| 425 | } |
| 426 | |
| 427 | void Compute(OpKernelContext* c) override { |
| 428 | // Check that the input Variant tensor is indeed a TensorList and has the |
| 429 | // correct element type. |
| 430 | const TensorList* tensor_list = nullptr; |
| 431 | OP_REQUIRES_OK(c, GetInputList(c, 0, &tensor_list)); |
| 432 | OP_REQUIRES( |
| 433 | c, element_dtype_ == tensor_list->element_dtype, |
| 434 | errors::InvalidArgument( |
| 435 | "Invalid data types; op elements ", DataTypeString(element_dtype_), |
| 436 | " but list elements ", DataTypeString(tensor_list->element_dtype))); |
| 437 | // The leading dimension of all list elements if they are all the same. |
| 438 | // This is used as the leading dim of uninitialized tensors in the list |
| 439 | // if leading_dims is not provided. |
| 440 | int64 first_dim = -1; |
| 441 | if (c->num_inputs() > 1) { |
| 442 | // TensorListConcatV2 |
| 443 | PartialTensorShape element_shape; |
| 444 | OP_REQUIRES_OK( |
| 445 | c, GetElementShapeFromInput(c, *tensor_list, 1, &element_shape)); |
| 446 | OP_REQUIRES(c, element_shape.unknown_rank() || element_shape.dims() >= 1, |
| 447 | errors::InvalidArgument( |
| 448 | "Concat requires elements to be at least vectors, ", |
| 449 | "found scalars instead.")); |
| 450 | // Split `element_shape` into `first_dim` and |
| 451 | // `element_shape_except_first_dim_`. |
| 452 | first_dim = element_shape.dim_size(0); |
| 453 | element_shape_except_first_dim_ = element_shape; |
| 454 | element_shape_except_first_dim_.RemoveDim(0); |
| 455 | } |
| 456 | // If the TensorList is empty, element_shape_except_first_dim_ must be fully |
| 457 | // defined. |
| 458 | OP_REQUIRES(c, |
| 459 | !tensor_list->tensors().empty() || |
| 460 | element_shape_except_first_dim_.IsFullyDefined(), |
| 461 | errors::InvalidArgument( |
| 462 | "All except the first dimension must be fully defined ", |
| 463 | "when concating an empty tensor list. element_shape: ", |
| 464 | element_shape_except_first_dim_.DebugString())); |
| 465 | // 1. Check that `element_shape_except_first_dim_` input tensor is |
| 466 | // compatible with the shapes of element tensors. |
| 467 | // 2. Check that the elements have the same shape except the first dim. |
| 468 | // 3. If `first_dim` is known, check that it is compatible with the leading |
| 469 | // dims of all elements. |
| 470 | // 4. If `first_dim` is unknown (-1), check whether all initialized |
| 471 | // elements have the same leading dim and if so set `first_dim` to that |
| 472 | // value. |
| 473 | if (!tensor_list->element_shape.IsFullyDefined()) { |
| 474 | bool check_dim = (first_dim == -1); |
| 475 | int64 inferred_first_dim = first_dim; |
| 476 | for (int i = 0; i < tensor_list->tensors().size(); ++i) { |
| 477 | const Tensor& t = tensor_list->tensors()[i]; |
| 478 | if (t.dtype() != DT_INVALID) { |
| 479 | PartialTensorShape tmp = element_shape_except_first_dim_; |
| 480 | OP_REQUIRES( |
| 481 | c, TensorShapeUtils::IsVectorOrHigher(t.shape()), |
| 482 | errors::InvalidArgument("Concat saw a scalar shape at index ", i, |
| 483 | " but requires at least vectors.")); |
| 484 | TensorShape shape_except_first_dim = TensorShape( |
nothing calls this directly
no test coverage detected