2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "ir/Padding.h"
19 #include "util/Utils.h"
31 inline ExplicitPadding validPadding(void)
34 // ANEURALNETWORKS_PADDING_VALID
36 // VALID padding. No padding.
38 // When the input size is not evenly divisible by the filter size,
39 // the input at the end that could not fill the whole filter tile
40 // will simply be ignored.
42 ExplicitPadding padding;
52 inline ExplicitPadding samePaddingUsingIFM(const FeatureShape &ifm_shape, const Stride &stride,
53 uint32_t kw, uint32_t kh)
55 ExplicitPadding padding;
57 // ANEURALNETWORKS_PADDING_SAME (from NNAPI spec)
59 // SAME padding. Padding on both ends are the "same":
61 // padding_to_beginning = total_padding / 2
62 // padding_to_end = (total_padding + 1)/2.
64 const int32_t vertical_expected_output = (ifm_shape.H + stride.vertical - 1) / stride.vertical;
65 const int32_t horizontal_expected_output =
66 (ifm_shape.W + stride.horizontal - 1) / stride.horizontal;
68 const int32_t vertical_needed_input = (vertical_expected_output - 1) * stride.vertical + kh;
69 const int32_t vertical_total_padding = std::max(0, vertical_needed_input - ifm_shape.H);
71 const int32_t horizontal_needed_input = (horizontal_expected_output - 1) * stride.horizontal + kw;
72 const int32_t horizontal_total_padding = std::max(0, horizontal_needed_input - ifm_shape.W);
74 padding.top = vertical_total_padding / 2;
75 padding.bottom = (vertical_total_padding + 1) / 2;
76 padding.left = horizontal_total_padding / 2;
77 padding.right = (horizontal_total_padding + 1) / 2;
82 inline ExplicitPadding samePadding(const FeatureShape &ifm_shape, const FeatureShape &ofm_shape,
83 const Stride &stride, uint32_t kw, uint32_t kh)
85 const int32_t vertical_expected_output = (ifm_shape.H + stride.vertical - 1) / stride.vertical;
86 const int32_t horizontal_expected_output =
87 (ifm_shape.W + stride.horizontal - 1) / stride.horizontal;
88 assert(vertical_expected_output == ofm_shape.H);
89 assert(horizontal_expected_output == ofm_shape.W);
91 UNUSED_RELEASE(ofm_shape);
92 UNUSED_RELEASE(vertical_expected_output);
93 UNUSED_RELEASE(horizontal_expected_output);
95 return samePaddingUsingIFM(ifm_shape, stride, kw, kh);
100 inline std::string to_string(const PaddingType type)
104 case PaddingType::EXPLICIT:
105 return "Padding::EXPLICIT";
106 case PaddingType::SAME:
107 return "Padding::SAME";
108 case PaddingType::VALID:
109 return "Padding::VALID";
111 throw std::runtime_error{"Fail to convert string: wrong padding type"};
115 Padding::Padding(void) : type{PaddingType::EXPLICIT}, param{0, 0, 0, 0}
120 Padding::Padding(PaddingType paddingType) : type{paddingType}, param{0, 0, 0, 0}
122 assert(paddingType != PaddingType::EXPLICIT);
125 Padding::Padding(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom)
126 : type{PaddingType::EXPLICIT}, param{left, right, top, bottom}
131 const ExplicitPadding calculatePadding(const Padding &padding, const FeatureShape &ifm_shape,
132 const FeatureShape &ofm_shape, const Stride &stride,
133 uint32_t kw, uint32_t kh)
135 if (padding.type == PaddingType::EXPLICIT)
137 return padding.param;
139 else if (padding.type == PaddingType::SAME)
141 return samePadding(ifm_shape, ofm_shape, stride, kw, kh);
143 else if (padding.type == PaddingType::VALID)
145 return validPadding();
149 throw std::runtime_error{"Cannot handle padding type"};