| 1578 | } |
| 1579 | |
| 1580 | Status ConcatShapeHelper(InferenceContext* c, int start_value_index, |
| 1581 | int end_value_index, int dim_index) { |
| 1582 | ShapeHandle unused; |
| 1583 | TF_RETURN_IF_ERROR(c->WithRank(c->input(dim_index), 0, &unused)); |
| 1584 | const Tensor* concat_dim_t = c->input_tensor(dim_index); |
| 1585 | if (concat_dim_t == nullptr) { |
| 1586 | // Return an unknown shape with same rank as inputs, or an unknown rank |
| 1587 | // if no input's rank is known. |
| 1588 | |
| 1589 | // Find rank. |
| 1590 | int32 rank = InferenceContext::kUnknownRank; |
| 1591 | for (int i = start_value_index; i < end_value_index; ++i) { |
| 1592 | if (rank == InferenceContext::kUnknownRank) rank = c->Rank(c->input(i)); |
| 1593 | if (rank != InferenceContext::kUnknownRank) { |
| 1594 | break; |
| 1595 | } |
| 1596 | } |
| 1597 | if (rank == InferenceContext::kUnknownRank) { |
| 1598 | c->set_output(0, c->UnknownShape()); |
| 1599 | return Status::OK(); |
| 1600 | } else if (rank == 0) { |
| 1601 | return errors::InvalidArgument( |
| 1602 | "Can't concatenate scalars (use tf.stack instead)"); |
| 1603 | } else { |
| 1604 | for (int i = start_value_index; i < end_value_index; ++i) { |
| 1605 | // Check that all the inputs are of the correct rank. |
| 1606 | TF_RETURN_IF_ERROR(c->WithRank(c->input(i), rank, &unused)); |
| 1607 | } |
| 1608 | } |
| 1609 | // Build result of <rank> different unknown dims. |
| 1610 | std::vector<DimensionHandle> dims; |
| 1611 | dims.reserve(rank); |
| 1612 | for (int i = 0; i < rank; ++i) dims.push_back(c->UnknownDim()); |
| 1613 | c->set_output(0, c->MakeShape(dims)); |
| 1614 | return Status::OK(); |
| 1615 | } |
| 1616 | |
| 1617 | // Merge all the non-concat dims, and sum the concat dim to make an output |
| 1618 | // shape. |
| 1619 | const int32 concat_dim = concat_dim_t->scalar<int32>()(); |
| 1620 | |
| 1621 | // Minimum required number of dimensions. |
| 1622 | const int64 min_rank = concat_dim < 0 ? -concat_dim : concat_dim + 1; |
| 1623 | |
| 1624 | ShapeHandle output_before; |
| 1625 | ShapeHandle output_after; |
| 1626 | |
| 1627 | ShapeHandle input = c->input(end_value_index - 1); |
| 1628 | TF_RETURN_IF_ERROR(c->WithRankAtLeast(input, min_rank, &input)); |
| 1629 | TF_RETURN_IF_ERROR(c->Subshape(input, 0, concat_dim, &output_before)); |
| 1630 | DimensionHandle output_middle = c->Dim(input, concat_dim); |
| 1631 | if (concat_dim == -1) { |
| 1632 | output_after = c->Scalar(); // no dimensions. |
| 1633 | } else { |
| 1634 | TF_RETURN_IF_ERROR(c->Subshape(input, concat_dim + 1, &output_after)); |
| 1635 | } |
| 1636 | |
| 1637 | for (int i = end_value_index - 2; i >= start_value_index; --i) { |
no test coverage detected