| 39 | } |
| 40 | |
| 41 | void Compute(OpKernelContext* context) override { |
| 42 | OpInputList inds; |
| 43 | OP_REQUIRES_OK(context, context->input_list("indices", &inds)); |
| 44 | const int N = inds.size(); |
| 45 | for (int i = 0; i < N; i++) { |
| 46 | OP_REQUIRES(context, TensorShapeUtils::IsMatrix(inds[i].shape()), |
| 47 | errors::InvalidArgument( |
| 48 | "Input indices should be a matrix but received shape ", |
| 49 | inds[i].shape().DebugString(), " at position ", i)); |
| 50 | } |
| 51 | |
| 52 | OpInputList vals; |
| 53 | OP_REQUIRES_OK(context, context->input_list("values", &vals)); |
| 54 | OP_REQUIRES(context, vals.size() == N, |
| 55 | errors::InvalidArgument("Expected ", N, " input values, got ", |
| 56 | vals.size())); |
| 57 | for (int i = 0; i < N; i++) { |
| 58 | OP_REQUIRES(context, TensorShapeUtils::IsVector(vals[i].shape()), |
| 59 | errors::InvalidArgument( |
| 60 | "Input values should be a vector but received shape ", |
| 61 | vals[i].shape().DebugString(), " at position ", i)); |
| 62 | } |
| 63 | |
| 64 | OpInputList shapes; |
| 65 | OP_REQUIRES_OK(context, context->input_list("shapes", &shapes)); |
| 66 | OP_REQUIRES(context, shapes.size() == N, |
| 67 | errors::InvalidArgument("Expected ", N, " input shapes, got ", |
| 68 | shapes.size())); |
| 69 | for (int i = 0; i < N; i++) { |
| 70 | OP_REQUIRES(context, TensorShapeUtils::IsVector(shapes[i].shape()), |
| 71 | errors::InvalidArgument( |
| 72 | "Input shapes should be a vector but received shape ", |
| 73 | shapes[i].shape().DebugString(), " at position ", i)); |
| 74 | } |
| 75 | |
| 76 | const TensorShape input_shape(shapes[0].vec<int64>()); |
| 77 | const int input_rank = input_shape.dims(); |
| 78 | const int concat_dim = (concat_dim_attr_ < 0) |
| 79 | ? input_rank + concat_dim_attr_ |
| 80 | : concat_dim_attr_; |
| 81 | OP_REQUIRES(context, concat_dim >= 0 && concat_dim < input_rank, |
| 82 | errors::InvalidArgument("Concat dimension must be in range [", |
| 83 | -input_rank, ", ", input_rank, |
| 84 | "), got ", concat_dim_attr_)); |
| 85 | for (int i = 1; i < N; ++i) { |
| 86 | const TensorShape current_shape(shapes[i].vec<int64>()); |
| 87 | OP_REQUIRES( |
| 88 | context, current_shape.dims() == input_rank, |
| 89 | errors::InvalidArgument( |
| 90 | "Ranks of all input tensors must match: expected ", input_rank, |
| 91 | " but got ", current_shape.dims(), " at position ", i)); |
| 92 | for (int j = 0; j < input_rank; ++j) { |
| 93 | if (j != concat_dim) { |
| 94 | OP_REQUIRES( |
| 95 | context, input_shape.dim_size(j) == current_shape.dim_size(j), |
| 96 | errors::InvalidArgument( |
| 97 | "Input shapes must match: expected ", input_shape.dim_size(j), |
| 98 | " for dimension ", j, " but got ", current_shape.dim_size(j), |
nothing calls this directly
no test coverage detected