1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
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
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include "Operations.h"
18#include "OperationsUtils.h"
19
20#include "internal/optimized/optimized_ops.h"
21
22namespace android {
23namespace nn {
24
25#define ANDROID_NN_POOLING_PARAMETERS                                           \
26    uint32_t height       = getSizeOfDimension(inputShape, 1);                  \
27    uint32_t width        = getSizeOfDimension(inputShape, 2);                  \
28    uint32_t outHeight    = getSizeOfDimension(outputShape, 1);                 \
29    uint32_t outWidth     = getSizeOfDimension(outputShape, 2);                 \
30                                                                                \
31    uint32_t paddingHeight = (uint32_t)padding_top;                             \
32    uint32_t paddingWidth = (uint32_t)padding_left;
33
34bool averagePoolFloat32(const float* inputData, const Shape& inputShape,
35                        int32_t padding_left, int32_t padding_right,
36                        int32_t padding_top, int32_t padding_bottom,
37                        int32_t stride_width, int32_t stride_height,
38                        int32_t filter_width, int32_t filter_height, int32_t activation,
39                        float* outputData, const Shape& outputShape) {
40
41    ANDROID_NN_POOLING_PARAMETERS
42
43    #define ANDROID_NN_AVERAGE_POOL(activation)                                \
44        optimized_ops::AveragePool<FusedActivationFunctionType::activation>(   \
45            inputData, convertShapeToDims(inputShape),                         \
46            stride_width, stride_height, paddingWidth, paddingHeight,          \
47            filter_width, filter_height,                                       \
48            outputData, convertShapeToDims(outputShape))
49
50    ANDROID_NN_MACRO_DISPATCH(ANDROID_NN_AVERAGE_POOL)
51    #undef ANDROID_NN_AVERAGE_POOL
52
53    return true;
54}
55
56bool averagePoolQuant8(const uint8_t* inputData, const Shape& inputShape,
57                       int32_t padding_left, int32_t padding_right,
58                       int32_t padding_top, int32_t padding_bottom,
59                       int32_t stride_width, int32_t stride_height,
60                       int32_t filter_width, int32_t filter_height, int32_t activation,
61                       uint8_t* outputData, const Shape& outputShape) {
62
63    ANDROID_NN_POOLING_PARAMETERS
64
65    int32_t output_activation_min = 0;
66    int32_t output_activation_max = 0;
67
68    CalculateActivationRangeUint8(activation, outputShape,
69                                  &output_activation_min,
70                                  &output_activation_max);
71
72    #define ANDROID_NN_AVERAGE_POOL(activation)                                \
73        optimized_ops::AveragePool<FusedActivationFunctionType::activation>(   \
74            inputData, convertShapeToDims(inputShape),                         \
75            stride_width, stride_height, paddingWidth, paddingHeight,          \
76            filter_width, filter_height,                                       \
77            output_activation_min, output_activation_max,                      \
78            outputData, convertShapeToDims(outputShape))
79
80    ANDROID_NN_MACRO_DISPATCH(ANDROID_NN_AVERAGE_POOL)
81    #undef ANDROID_NN_AVERAGE_POOL
82
83    return true;
84}
85
86bool l2PoolFloat32(const float* inputData, const Shape& inputShape,
87                   int32_t padding_left, int32_t padding_right,
88                   int32_t padding_top, int32_t padding_bottom,
89                   int32_t stride_width, int32_t stride_height,
90                   int32_t filter_width, int32_t filter_height, int32_t activation,
91                   float* outputData, const Shape& outputShape) {
92
93    ANDROID_NN_POOLING_PARAMETERS
94
95    #define ANDROID_NN_L2_POOL(activation)                                     \
96        optimized_ops::L2Pool<FusedActivationFunctionType::activation>(        \
97            inputData, convertShapeToDims(inputShape),                         \
98            stride_width, stride_height, paddingWidth, paddingHeight,          \
99            filter_width, filter_height,                                       \
100            outputData, convertShapeToDims(outputShape))
101
102    ANDROID_NN_MACRO_DISPATCH(ANDROID_NN_L2_POOL)
103    #undef ANDROID_NN_L2_POOL
104
105    return true;
106}
107
108bool maxPoolFloat32(const float* inputData, const Shape& inputShape,
109                    int32_t padding_left, int32_t padding_right,
110                    int32_t padding_top, int32_t padding_bottom,
111                    int32_t stride_width, int32_t stride_height,
112                    int32_t filter_width, int32_t filter_height, int32_t activation,
113                    float* outputData, const Shape& outputShape) {
114
115    ANDROID_NN_POOLING_PARAMETERS
116
117    #define ANDROID_NN_MAX_POOL(activation)                                    \
118        optimized_ops::MaxPool<FusedActivationFunctionType::activation>(       \
119            inputData, convertShapeToDims(inputShape),                         \
120            stride_width, stride_height, paddingWidth, paddingHeight,          \
121            filter_width, filter_height,                                       \
122            outputData, convertShapeToDims(outputShape))
123
124    ANDROID_NN_MACRO_DISPATCH(ANDROID_NN_MAX_POOL)
125    #undef ANDROID_NN_MAX_POOL
126
127    return true;
128}
129
130bool maxPoolQuant8(const uint8_t* inputData, const Shape& inputShape,
131                   int32_t padding_left, int32_t padding_right,
132                   int32_t padding_top, int32_t padding_bottom,
133                   int32_t stride_width, int32_t stride_height,
134                   int32_t filter_width, int32_t filter_height, int32_t activation,
135                   uint8_t* outputData, const Shape& outputShape) {
136
137    ANDROID_NN_POOLING_PARAMETERS
138
139    int32_t output_activation_min = 0;
140    int32_t output_activation_max = 0;
141
142    CalculateActivationRangeUint8(activation, outputShape,
143                                  &output_activation_min,
144                                  &output_activation_max);
145
146    #define ANDROID_NN_MAX_POOL(activation)                                    \
147        optimized_ops::MaxPool<FusedActivationFunctionType::activation>(       \
148            inputData, convertShapeToDims(inputShape),                         \
149            stride_width, stride_height, paddingWidth, paddingHeight,          \
150            filter_width, filter_height,                                       \
151            output_activation_min, output_activation_max,                      \
152            outputData, convertShapeToDims(outputShape))
153
154    ANDROID_NN_MACRO_DISPATCH(ANDROID_NN_MAX_POOL)
155    #undef ANDROID_NN_MAX_POOL
156
157    return true;
158}
159
160#undef ANDROID_NN_POOLING_PARAMETERS
161}  // namespace nn
162}  // namespace android
163