| 825 | } |
| 826 | |
| 827 | void Compute(OpKernelContext* ctx) override { |
| 828 | OP_REQUIRES_OK(ctx, SetupFlowControlInputs(ctx, false)); |
| 829 | |
| 830 | TensorArray* tensor_array = nullptr; |
| 831 | OP_REQUIRES_OK(ctx, GetTensorArray(ctx, &tensor_array)); |
| 832 | core::ScopedUnref unref(tensor_array); |
| 833 | OP_REQUIRES( |
| 834 | ctx, dtype_ == tensor_array->ElemType(), |
| 835 | errors::InvalidArgument( |
| 836 | "TensorArray dtype is ", DataTypeString(tensor_array->ElemType()), |
| 837 | " but Op requested dtype ", DataTypeString(dtype_), ".")); |
| 838 | |
| 839 | int32 array_size; |
| 840 | OP_REQUIRES_OK(ctx, tensor_array->PackOrConcatSize(&array_size)); |
| 841 | |
| 842 | // If there are no elements, return a zero-element Tensor with |
| 843 | // shape [0] + element_shape_except0_ |
| 844 | if (array_size == 0) { |
| 845 | OP_REQUIRES( |
| 846 | ctx, element_shape_except0_.IsFullyDefined(), |
| 847 | errors::Unimplemented( |
| 848 | "TensorArray has size zero, but element_shape_except0 ", |
| 849 | element_shape_except0_.DebugString(), |
| 850 | " is not fully defined. " |
| 851 | "Currently only static shapes are supported when concatenating " |
| 852 | "zero-size TensorArrays.")); |
| 853 | TensorShape empty_shape; |
| 854 | element_shape_except0_.AsTensorShape(&empty_shape); |
| 855 | empty_shape.InsertDim(0, 0); |
| 856 | Tensor* empty_unused; |
| 857 | OP_REQUIRES_OK(ctx, ctx->allocate_output(0, empty_shape, &empty_unused)); |
| 858 | OP_REQUIRES_OK(ctx, ctx->allocate_output(1, {0}, &empty_unused)); |
| 859 | return; |
| 860 | } |
| 861 | |
| 862 | // Read all the PersistentTensors into a vector to keep track of |
| 863 | // their memory. |
| 864 | std::vector<PersistentTensor> values; |
| 865 | std::vector<int32> indices(array_size); |
| 866 | std::iota(indices.begin(), indices.end(), 0); |
| 867 | Status s = tensor_array->ReadMany<Device, T>(ctx, indices, &values); |
| 868 | OP_REQUIRES_OK(ctx, s); |
| 869 | |
| 870 | std::vector<const Tensor*> value_tensors; |
| 871 | value_tensors.resize(values.size()); |
| 872 | |
| 873 | Tensor* lengths_tensor = nullptr; |
| 874 | OP_REQUIRES_OK(ctx, ctx->allocate_output( |
| 875 | 1, TensorShape({static_cast<int64>(values.size())}), |
| 876 | &lengths_tensor)); |
| 877 | auto lengths_tensor_t = lengths_tensor->vec<int64>(); |
| 878 | |
| 879 | TensorShape output_shape; |
| 880 | TensorShape output_shape_except0; |
| 881 | for (std::size_t i = 0; i < values.size(); ++i) { |
| 882 | value_tensors[i] = values[i].AccessTensor(ctx); |
| 883 | TensorShape value_shape_t = value_tensors[i]->shape(); |
| 884 |
nothing calls this directly
no test coverage detected