blob: 226af96fe3c82945a3cd99db4a2b2c187eac7513 [file] [log] [blame]
Moritz Pflanzer6db73ce2017-07-19 10:18:42 +01001/*
2 * Copyright (c) 2017 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 "NormalizationLayer.h"
25
Georgios Pinitas583137c2017-08-31 18:12:42 +010026#include "arm_compute/core/Types.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010027#include "tests/validation/FixedPoint.h"
Moritz Pflanzer6db73ce2017-07-19 10:18:42 +010028
29namespace arm_compute
30{
31namespace test
32{
33namespace validation
34{
35namespace reference
36{
37template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
38SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info)
39{
40 // Create reference
41 SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
42
43 // Compute reference
44 const uint32_t norm_size = info.norm_size();
45 NormType type = info.type();
46 float beta = info.beta();
47 uint32_t kappa = info.kappa();
48
49 const int cols = src.shape()[0];
50 const int rows = src.shape()[1];
51 const int depth = src.shape()[2];
52 int upper_dims = src.shape().total_size() / (cols * rows);
53
54 float coeff = info.scale_coeff();
55 int radius_cols = norm_size / 2;
56
57 // IN_MAP_1D and CROSS_MAP normalize over a single axis only
58 int radius_rows = (NormType::IN_MAP_2D == type) ? norm_size / 2 : 0;
59
60 if(type == NormType::CROSS_MAP)
61 {
62 // Remove also depth from upper dimensions since it is the dimension we
63 // want to use for normalization
64 upper_dims /= depth;
65
66 for(int r = 0; r < upper_dims; ++r)
67 {
68 for(int i = 0; i < rows; ++i)
69 {
70 for(int k = 0; k < cols; ++k)
71 {
72 for(int l = 0; l < depth; ++l)
73 {
74 float accumulated_scale = 0.f;
75
76 for(int j = -radius_cols; j <= radius_cols; ++j)
77 {
78 const int z = l + j;
79
80 if(z >= 0 && z < depth)
81 {
82 const T value = src[k + i * cols + z * rows * cols + r * cols * rows * depth];
83 accumulated_scale += value * value;
84 }
85 }
86
87 dst[k + i * cols + l * rows * cols + r * cols * rows * depth] = kappa + accumulated_scale * coeff;
88 }
89 }
90 }
91 }
92 }
93 else
94 {
95 for(int r = 0; r < upper_dims; ++r)
96 {
97 for(int i = 0; i < rows; ++i)
98 {
99 for(int k = 0; k < cols; ++k)
100 {
101 float accumulated_scale = 0.f;
102
103 for(int j = -radius_rows; j <= radius_rows; ++j)
104 {
105 const int y = i + j;
106 for(int l = -radius_cols; l <= radius_cols; ++l)
107 {
108 const int x = k + l;
109
110 if((x >= 0 && y >= 0) && (x < cols && y < rows))
111 {
112 const T value = src[x + y * cols + r * cols * rows];
113 accumulated_scale += value * value;
114 }
115 }
116 }
117
118 dst[k + i * cols + r * cols * rows] = kappa + accumulated_scale * coeff;
119 }
120 }
121 }
122 }
123
124 if(beta == 1.f)
125 {
126 for(int i = 0; i < dst.num_elements(); ++i)
127 {
128 dst[i] = src[i] / dst[i];
129 }
130 }
131 else if(beta == 0.5f)
132 {
133 for(int i = 0; i < dst.num_elements(); ++i)
134 {
135 dst[i] = src[i] / std::sqrt(dst[i]);
136 }
137 }
138 else
139 {
140 for(int i = 0; i < dst.num_elements(); ++i)
141 {
142 dst[i] = src[i] * std::exp(std::log(dst[i]) * -beta);
143 }
144 }
145
146 return dst;
147}
148
149template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
150SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info)
151{
152 using namespace fixed_point_arithmetic;
153
154 // Create reference
155 SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
156
157 // Compute reference
158 const int fixed_point_position = src.fixed_point_position();
159
160 const uint32_t norm_size = info.norm_size();
161 NormType type = info.type();
162 fixed_point<T> beta(info.beta(), fixed_point_position);
163 fixed_point<T> kappa(info.kappa(), fixed_point_position);
164
165 const int cols = src.shape()[0];
166 const int rows = src.shape()[1];
167 const int depth = src.shape()[2];
168 int upper_dims = src.shape().total_size() / (cols * rows);
169
170 fixed_point<T> coeff(info.scale_coeff(), fixed_point_position);
171 int radius_cols = norm_size / 2;
172
173 // IN_MAP_1D and CROSS_MAP normalize over a single axis only
174 int radius_rows = (NormType::IN_MAP_2D == type) ? norm_size / 2 : 0;
175
176 if(type == NormType::CROSS_MAP)
177 {
178 // Remove also depth from upper dimensions since it is the dimension we
179 // want to use for normalization
180 upper_dims /= depth;
181
182 for(int r = 0; r < upper_dims; ++r)
183 {
184 for(int i = 0; i < rows; ++i)
185 {
186 for(int k = 0; k < cols; ++k)
187 {
188 for(int l = 0; l < depth; ++l)
189 {
190 fixed_point<T> accumulated_scale(0.f, fixed_point_position);
191
192 for(int j = -radius_cols; j <= radius_cols; ++j)
193 {
194 const int z = l + j;
195
196 if(z >= 0 && z < depth)
197 {
198 const T value = src[k + i * cols + z * rows * cols + r * cols * rows * depth];
199 const fixed_point<T> fp_value(value, fixed_point_position, true);
200 accumulated_scale = add(accumulated_scale, mul(fp_value, fp_value));
201 }
202 }
203
204 accumulated_scale = add(kappa, mul(accumulated_scale, coeff));
205 dst[k + i * cols + l * rows * cols + r * cols * rows * depth] = accumulated_scale.raw();
206 }
207 }
208 }
209 }
210 }
211 else
212 {
213 for(int r = 0; r < upper_dims; ++r)
214 {
215 for(int i = 0; i < rows; ++i)
216 {
217 for(int k = 0; k < cols; ++k)
218 {
219 fixed_point<T> accumulated_scale(0.f, fixed_point_position);
220
221 for(int j = -radius_rows; j <= radius_rows; ++j)
222 {
223 const int y = i + j;
224
225 for(int l = -radius_cols; l <= radius_cols; ++l)
226 {
227 const int x = k + l;
228
229 if((x >= 0 && y >= 0) && (x < cols && y < rows))
230 {
231 const T value = src[x + y * cols + r * cols * rows];
232 const fixed_point<T> fp_value(value, fixed_point_position, true);
233 accumulated_scale = add(accumulated_scale, mul(fp_value, fp_value));
234 }
235 }
236 }
237
238 accumulated_scale = add(kappa, mul(accumulated_scale, coeff));
239 dst[k + i * cols + r * cols * rows] = accumulated_scale.raw();
240 }
241 }
242 }
243 }
244
245 if(info.beta() == 1.f)
246 {
247 for(int i = 0; i < dst.num_elements(); ++i)
248 {
249 fixed_point<T> res = div(fixed_point<T>(src[i], fixed_point_position, true), fixed_point<T>(dst[i], fixed_point_position, true));
250 dst[i] = res.raw();
251 }
252 }
253 else
254 {
255 const fixed_point<T> beta(info.beta(), fixed_point_position);
256
257 for(int i = 0; i < dst.num_elements(); ++i)
258 {
259 fixed_point<T> res = pow(fixed_point<T>(dst[i], fixed_point_position, true), beta);
260 res = div(fixed_point<T>(src[i], fixed_point_position, true), res);
261 dst[i] = res.raw();
262 }
263 }
264
265 return dst;
266}
267
268template SimpleTensor<float> normalization_layer(const SimpleTensor<float> &src, NormalizationLayerInfo info);
Georgios Pinitas583137c2017-08-31 18:12:42 +0100269template SimpleTensor<half> normalization_layer(const SimpleTensor<half> &src, NormalizationLayerInfo info);
Moritz Pflanzer6db73ce2017-07-19 10:18:42 +0100270template SimpleTensor<qint8_t> normalization_layer(const SimpleTensor<qint8_t> &src, NormalizationLayerInfo info);
Michele Di Giorgiod5e65c72017-07-26 17:09:17 +0100271template SimpleTensor<qint16_t> normalization_layer(const SimpleTensor<qint16_t> &src, NormalizationLayerInfo info);
Moritz Pflanzer6db73ce2017-07-19 10:18:42 +0100272} // namespace reference
273} // namespace validation
274} // namespace test
275} // namespace arm_compute