blob: 700e8f8ccfe880aff91601361184bc55439a478b [file] [log] [blame]
Giuseppe Rossinid7647d42018-07-17 18:13:13 +01001/*
Georgios Pinitasd57891a2019-02-19 18:10:03 +00002 * Copyright (c) 2018-2019 ARM Limited.
Giuseppe Rossinid7647d42018-07-17 18:13:13 +01003 *
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 "PadLayer.h"
25
26#include "arm_compute/core/Types.h"
27#include "arm_compute/core/utils/misc/ShapeCalculator.h"
28#include "tests/validation/Helpers.h"
29
30namespace arm_compute
31{
32namespace test
33{
34namespace validation
35{
36namespace reference
37{
38template <typename T>
Usama Arif89890c62019-03-19 10:57:05 +000039SimpleTensor<T> pad_layer(const SimpleTensor<T> &src, const PaddingList &paddings, const PixelValue const_value, const PaddingMode mode)
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010040{
Usama Arif89890c62019-03-19 10:57:05 +000041 const DataType dst_data_type = src.data_type();
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010042
Usama Arif89890c62019-03-19 10:57:05 +000043 const TensorShape orig_shape = src.shape();
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010044
45 std::vector<PaddingInfo> paddings_extended = paddings;
46
Usama Arif89890c62019-03-19 10:57:05 +000047 for(size_t i = paddings.size(); i < TensorShape::num_max_dimensions; ++i)
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010048 {
49 paddings_extended.emplace_back(PaddingInfo{ 0, 0 });
50 }
51
Usama Arif89890c62019-03-19 10:57:05 +000052 const TensorShape padded_shape = misc::shape_calculator::compute_padded_shape(orig_shape, paddings);
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010053
54 SimpleTensor<T> dst(padded_shape, dst_data_type);
55
56 // Reference algorithm: loop over the different dimension of the input.
Usama Arif89890c62019-03-19 10:57:05 +000057 for(int idx = 0; idx < dst.num_elements(); ++idx)
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010058 {
Usama Arif89890c62019-03-19 10:57:05 +000059 const Coordinates coord = index2coord(padded_shape, idx);
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010060
61 const size_t i = coord.x();
62 const size_t j = coord.y();
63 const size_t k = coord.z();
64 const size_t l = coord[3];
65 const size_t m = coord[4];
66 const size_t n = coord[5];
67
Usama Arif89890c62019-03-19 10:57:05 +000068 const std::array<size_t, TensorShape::num_max_dimensions> dims = { { 0, 1, 2, 3, 4, 5 } };
69 const std::array<size_t, TensorShape::num_max_dimensions> coords = { { i, j, k, l, m, n } };
Giuseppe Rossinid7647d42018-07-17 18:13:13 +010070 auto is_padding_area = [&](size_t i)
71 {
72 return (coords[i] < paddings_extended[i].first || coords[i] > orig_shape[i] + paddings_extended[i].first - 1);
73 };
74
Usama Arif89890c62019-03-19 10:57:05 +000075 auto orig_coord_reflect = [&](size_t i)
76 {
77 if(is_padding_area(i))
78 {
79 if(coords[i] < paddings_extended[i].first)
80 {
81 return paddings_extended[i].first - coords[i];
82 }
83 else
84 {
85 return 2 * orig_shape[i] + paddings_extended[i].first - 2 - coords[i];
86 }
87 }
88 return coords[i] - paddings_extended[i].first;
89 };
90
91 auto orig_coord_symm = [&](size_t i)
92 {
93 if(is_padding_area(i))
94 {
95 if(coords[i] < paddings_extended[i].first)
96 {
97 return paddings_extended[i].first - coords[i] - 1;
98 }
99 else
100 {
101 return 2 * orig_shape[i] + paddings_extended[i].first - 1 - coords[i];
102 }
103 }
104 return coords[i] - paddings_extended[i].first;
105 };
106
107 // If the tuple [i,j,k,l,m] is in the padding area, then simply set the value
Giuseppe Rossinid7647d42018-07-17 18:13:13 +0100108 if(std::any_of(dims.begin(), dims.end(), is_padding_area))
109 {
Usama Arif89890c62019-03-19 10:57:05 +0000110 switch(mode)
111 {
112 case PaddingMode::CONSTANT:
113 const_value.get(dst[idx]);
114 break;
115 case PaddingMode::REFLECT:
116 {
117 const Coordinates orig_coords{ orig_coord_reflect(0),
Giorgio Arena205eed82019-08-14 10:13:50 +0100118 orig_coord_reflect(1),
119 orig_coord_reflect(2),
120 orig_coord_reflect(3),
121 orig_coord_reflect(4),
122 orig_coord_reflect(5) };
Usama Arif89890c62019-03-19 10:57:05 +0000123
124 const size_t idx_src = coord2index(orig_shape, orig_coords);
125 dst[idx] = src[idx_src];
126 break;
127 }
128 case PaddingMode::SYMMETRIC:
129 {
130 const Coordinates orig_coords{ orig_coord_symm(0),
Giorgio Arena205eed82019-08-14 10:13:50 +0100131 orig_coord_symm(1),
132 orig_coord_symm(2),
133 orig_coord_symm(3),
134 orig_coord_symm(4),
135 orig_coord_symm(5) };
Usama Arif89890c62019-03-19 10:57:05 +0000136
137 const size_t idx_src = coord2index(orig_shape, orig_coords);
138 dst[idx] = src[idx_src];
139 break;
140 }
141 default:
142 ARM_COMPUTE_ERROR("Padding mode not supported.");
143 break;
144 }
Giuseppe Rossinid7647d42018-07-17 18:13:13 +0100145 }
146 else
147 {
148 // If the tuple[i,j,k,l,m] is not in the padding area, then copy the input into the output
149
Giorgio Arena205eed82019-08-14 10:13:50 +0100150 const Coordinates orig_coords
151 {
152 i - paddings_extended[0].first,
153 j - paddings_extended[1].first,
154 k - paddings_extended[2].first,
155 l - paddings_extended[3].first,
156 m - paddings_extended[4].first,
157 n - paddings_extended[5].first
158 };
Giuseppe Rossinid7647d42018-07-17 18:13:13 +0100159
160 const size_t idx_src = coord2index(orig_shape, orig_coords);
161 dst[idx] = src[idx_src];
162 }
163 }
164
165 return dst;
166}
167
Usama Arif89890c62019-03-19 10:57:05 +0000168template SimpleTensor<float> pad_layer(const SimpleTensor<float> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
169template SimpleTensor<half> pad_layer(const SimpleTensor<half> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
Usama Arif89890c62019-03-19 10:57:05 +0000170template SimpleTensor<uint8_t> pad_layer(const SimpleTensor<uint8_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
171template SimpleTensor<int8_t> pad_layer(const SimpleTensor<int8_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
172template SimpleTensor<uint16_t> pad_layer(const SimpleTensor<uint16_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
173template SimpleTensor<int16_t> pad_layer(const SimpleTensor<int16_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
Giorgio Arena205eed82019-08-14 10:13:50 +0100174template SimpleTensor<uint32_t> pad_layer(const SimpleTensor<uint32_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
175template SimpleTensor<int32_t> pad_layer(const SimpleTensor<int32_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
Giuseppe Rossinid7647d42018-07-17 18:13:13 +0100176} // namespace reference
177} // namespace validation
178} // namespace test
179} // namespace arm_compute