| 1307 | } |
| 1308 | |
| 1309 | Status MaxPoolV2Shape(shape_inference::InferenceContext* c, int num_inputs) { |
| 1310 | string data_format_str; |
| 1311 | TensorFormat data_format; |
| 1312 | Status s = c->GetAttr("data_format", &data_format_str); |
| 1313 | if (s.ok()) { |
| 1314 | FormatFromString(data_format_str, &data_format); |
| 1315 | } else { |
| 1316 | data_format = FORMAT_NHWC; |
| 1317 | } |
| 1318 | |
| 1319 | const int rank = (data_format == FORMAT_NCHW_VECT_C) ? 5 : 4; |
| 1320 | ShapeHandle input_shape; |
| 1321 | TF_RETURN_IF_ERROR(c->WithRank(c->input(0), rank, &input_shape)); |
| 1322 | |
| 1323 | TF_RETURN_IF_ERROR( |
| 1324 | CheckFormatConstraintsOnShape(data_format, input_shape, "input", c)); |
| 1325 | |
| 1326 | std::vector<int32> kernel_sizes; |
| 1327 | std::vector<int32> strides; |
| 1328 | |
| 1329 | if (c->num_inputs() + 2 == num_inputs) { |
| 1330 | TF_RETURN_IF_ERROR(c->GetAttr("ksize", &kernel_sizes)); |
| 1331 | |
| 1332 | TF_RETURN_IF_ERROR(c->GetAttr("strides", &strides)); |
| 1333 | } else { |
| 1334 | // Verify shape of ksize and strides input. |
| 1335 | ShapeHandle size; |
| 1336 | DimensionHandle unused; |
| 1337 | TF_RETURN_IF_ERROR(c->WithRank(c->input(c->num_inputs() - 2), 1, &size)); |
| 1338 | TF_RETURN_IF_ERROR(c->WithValue(c->Dim(size, 0), 4, &unused)); |
| 1339 | TF_RETURN_IF_ERROR(c->WithRank(c->input(c->num_inputs() - 1), 1, &size)); |
| 1340 | TF_RETURN_IF_ERROR(c->WithValue(c->Dim(size, 0), 4, &unused)); |
| 1341 | |
| 1342 | const Tensor* kernel_sizes_tensor = c->input_tensor(c->num_inputs() - 2); |
| 1343 | if (kernel_sizes_tensor == nullptr) { |
| 1344 | c->set_output(0, c->UnknownShape()); |
| 1345 | return Status::OK(); |
| 1346 | } |
| 1347 | kernel_sizes.resize(kernel_sizes_tensor->shape().num_elements()); |
| 1348 | auto kernel_sizes_vec = kernel_sizes_tensor->flat<int32>(); |
| 1349 | std::copy_n(&kernel_sizes_vec(0), kernel_sizes.size(), |
| 1350 | kernel_sizes.begin()); |
| 1351 | |
| 1352 | const Tensor* strides_tensor = c->input_tensor(c->num_inputs() - 1); |
| 1353 | if (strides_tensor == nullptr) { |
| 1354 | c->set_output(0, c->UnknownShape()); |
| 1355 | return Status::OK(); |
| 1356 | } |
| 1357 | strides.resize(strides_tensor->shape().num_elements()); |
| 1358 | auto strides_vec = strides_tensor->flat<int32>(); |
| 1359 | std::copy_n(&strides_vec(0), strides.size(), strides.begin()); |
| 1360 | } |
| 1361 | |
| 1362 | if (strides.size() != 4) { |
| 1363 | return errors::InvalidArgument( |
| 1364 | "MaxPool requires the stride attribute to contain 4 values, but " |
| 1365 | "got: ", |
| 1366 | strides.size()); |
no test coverage detected