| 3239 | } |
| 3240 | |
| 3241 | inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, |
| 3242 | const float* input_data, const RuntimeShape& output_shape, |
| 3243 | float* output_data) { |
| 3244 | gemmlowp::ScopedProfilingLabel label("MaxPool"); |
| 3245 | TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); |
| 3246 | TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); |
| 3247 | const int batches = MatchingDim(input_shape, 0, output_shape, 0); |
| 3248 | const int input_height = input_shape.Dims(1); |
| 3249 | const int input_width = input_shape.Dims(2); |
| 3250 | const int output_height = output_shape.Dims(1); |
| 3251 | const int output_width = output_shape.Dims(2); |
| 3252 | const int stride_height = params.stride_height; |
| 3253 | const int stride_width = params.stride_width; |
| 3254 | |
| 3255 | const auto in_mat = MapAsMatrixWithLastDimAsRows(input_data, input_shape); |
| 3256 | auto out_mat = MapAsMatrixWithLastDimAsRows(output_data, output_shape); |
| 3257 | // Prefill the output to minimum representable float value |
| 3258 | out_mat.setConstant(std::numeric_limits<float>::lowest()); |
| 3259 | for (int b = 0; b < batches; ++b) { |
| 3260 | for (int h = 0; h < input_height; ++h) { |
| 3261 | for (int w = 0; w < input_width; ++w) { |
| 3262 | // (h_start, h_end) * (w_start, w_end) is the range that the input |
| 3263 | // vector projects to. |
| 3264 | int hpad = h + params.padding_values.height; |
| 3265 | int wpad = w + params.padding_values.width; |
| 3266 | int h_start = (hpad < params.filter_height) |
| 3267 | ? 0 |
| 3268 | : (hpad - params.filter_height) / stride_height + 1; |
| 3269 | int h_end = std::min(hpad / stride_height + 1, output_height); |
| 3270 | int w_start = (wpad < params.filter_width) |
| 3271 | ? 0 |
| 3272 | : (wpad - params.filter_width) / stride_width + 1; |
| 3273 | int w_end = std::min(wpad / stride_width + 1, output_width); |
| 3274 | // compute elementwise sum |
| 3275 | for (int ph = h_start; ph < h_end; ++ph) { |
| 3276 | for (int pw = w_start; pw < w_end; ++pw) { |
| 3277 | int out_offset = NodeOffset(b, ph, pw, output_height, output_width); |
| 3278 | out_mat.col(out_offset) = |
| 3279 | out_mat.col(out_offset) |
| 3280 | .cwiseMax(in_mat.col( |
| 3281 | NodeOffset(b, h, w, input_height, input_width))); |
| 3282 | } |
| 3283 | } |
| 3284 | } |
| 3285 | } |
| 3286 | } |
| 3287 | const int flat_size = output_shape.FlatSize(); |
| 3288 | for (int i = 0; i < flat_size; ++i) { |
| 3289 | output_data[i] = ActivationFunctionWithMinMax(output_data[i], |
| 3290 | params.float_activation_min, |
| 3291 | params.float_activation_max); |
| 3292 | } |
| 3293 | } |
| 3294 | |
| 3295 | inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, |
| 3296 | const uint8* input_data, const RuntimeShape& output_shape, |
nothing calls this directly
no test coverage detected