| 492 | } |
| 493 | |
| 494 | Status ShapeRefiner::ConstantPartialShape(InferenceContext* target_context, |
| 495 | const Node* node, int dst_idx, |
| 496 | ShapeHandle* result) { |
| 497 | const Edge* input_edge; |
| 498 | TF_RETURN_IF_ERROR(node->input_edge(dst_idx, &input_edge)); |
| 499 | |
| 500 | InferenceContext* src_context = GetContext(input_edge->src()); |
| 501 | if (src_context == nullptr) return errors::Internal("Missing src context"); |
| 502 | ShapeHandle src_shape = src_context->output(input_edge->src_output()); |
| 503 | |
| 504 | if (src_context->Value(src_context->Rank(src_shape)) == 0) { |
| 505 | Tensor t; |
| 506 | bool evaluated = false; |
| 507 | TF_RETURN_IF_ERROR( |
| 508 | EvaluateConstantTensorForEdge(node, dst_idx, &evaluated, &t)); |
| 509 | if (!evaluated) { |
| 510 | return errors::InvalidArgument( |
| 511 | "Received a shape scalar with unknown static value. A static value " |
| 512 | "of '-1' is required to represent an unknown shape."); |
| 513 | } |
| 514 | if (t.dims() == 0) { |
| 515 | if (t.dtype() == DT_INT32 && t.scalar<int32>()() == -1) { |
| 516 | *result = target_context->UnknownShape(); |
| 517 | return Status::OK(); |
| 518 | } else if (t.dtype() == DT_INT64 && t.scalar<int64>()() == -1) { |
| 519 | *result = target_context->UnknownShape(); |
| 520 | return Status::OK(); |
| 521 | } |
| 522 | } |
| 523 | return errors::InvalidArgument( |
| 524 | "Received an invalid shape scalar with a static value that is not " |
| 525 | "'-1': ", |
| 526 | t.DebugString()); |
| 527 | } |
| 528 | |
| 529 | TF_RETURN_IF_ERROR(src_context->WithRank(src_shape, 1, &src_shape)); |
| 530 | |
| 531 | const string& src_op = input_edge->src()->type_string(); |
| 532 | if (src_context->Value(src_context->Dim(src_shape, 0)) == 0) { |
| 533 | // Source tensor is a vector of length 0, so the shape it |
| 534 | // represents is as scalar. |
| 535 | *result = target_context->Scalar(); |
| 536 | } else if (src_op == "Shape") { |
| 537 | *result = src_context->input(0); |
| 538 | } else if (src_op == "ShapeN") { |
| 539 | *result = src_context->input(input_edge->src_output()); |
| 540 | } else if (src_op == "Pack") { |
| 541 | std::vector<DimensionHandle> dims; |
| 542 | // Pack is concatenating its input scalars to form the shape tensor vector. |
| 543 | for (int i = 0; i < src_context->num_inputs(); ++i) { |
| 544 | int64 size; |
| 545 | bool evaluated; |
| 546 | TF_RETURN_IF_ERROR(EvaluateConstantIntScalarEdge(input_edge->src(), i, |
| 547 | &evaluated, &size)); |
| 548 | if (evaluated) { |
| 549 | dims.push_back(size < 0 ? target_context->UnknownDim() |
| 550 | : target_context->MakeDim(size)); |
| 551 | } else { |
nothing calls this directly
no test coverage detected