| 151 | namespace { |
| 152 | |
| 153 | Status DynamicStitchShapeFunction(InferenceContext* c) { |
| 154 | int32 num_partitions; |
| 155 | TF_RETURN_IF_ERROR(c->GetAttr("N", &num_partitions)); |
| 156 | |
| 157 | bool all_indices_constant = true; |
| 158 | int32 max_index = 0; |
| 159 | ShapeHandle extra_shape = c->UnknownShape(); |
| 160 | for (int i = 0; i < num_partitions; ++i) { |
| 161 | const Tensor* indices_t = c->input_tensor(i); |
| 162 | if (indices_t == nullptr) { |
| 163 | all_indices_constant = false; |
| 164 | } |
| 165 | |
| 166 | ShapeHandle indices_shape = c->input(i); |
| 167 | ShapeHandle data_shape = c->input(i + num_partitions); |
| 168 | if (!c->RankKnown(indices_shape)) { |
| 169 | continue; |
| 170 | } |
| 171 | const int64 indices_rank = c->Rank(indices_shape); |
| 172 | |
| 173 | // Assert that data_shape starts with indices_shape. |
| 174 | ShapeHandle unused; |
| 175 | TF_RETURN_IF_ERROR( |
| 176 | c->MergePrefix(data_shape, indices_shape, &unused, &unused)); |
| 177 | |
| 178 | // The rest belongs to output. |
| 179 | ShapeHandle rest; |
| 180 | TF_RETURN_IF_ERROR(c->Subshape(data_shape, indices_rank, &rest)); |
| 181 | TF_RETURN_IF_ERROR(c->Merge(extra_shape, rest, &extra_shape)); |
| 182 | |
| 183 | if (indices_t != nullptr) { |
| 184 | // The length is based on the highest index from flattened indices. |
| 185 | const int32* indices = indices_t->flat<int32>().data(); |
| 186 | int64 count = indices_t->NumElements(); |
| 187 | for (int64 i = 0; i < count; ++i) { |
| 188 | if (indices[i] > max_index) { |
| 189 | max_index = indices[i]; |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | ShapeHandle output_shape = c->Vector( |
| 196 | all_indices_constant ? c->MakeDim(max_index + 1) : c->UnknownDim()); |
| 197 | TF_RETURN_IF_ERROR(c->Concatenate(output_shape, extra_shape, &output_shape)); |
| 198 | c->set_output(0, output_shape); |
| 199 | return Status::OK(); |
| 200 | } |
| 201 | |
| 202 | } // namespace |
| 203 |
nothing calls this directly
no test coverage detected