| 483 | } |
| 484 | |
| 485 | Status BatchMatMulShape(shape_inference::InferenceContext* c) { |
| 486 | ShapeHandle a_shape; |
| 487 | ShapeHandle b_shape; |
| 488 | TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(0), 2, &a_shape)); |
| 489 | TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(1), 2, &b_shape)); |
| 490 | |
| 491 | // Determine output rows and cols. |
| 492 | bool adj_x; |
| 493 | bool adj_y; |
| 494 | TF_RETURN_IF_ERROR(c->GetAttr("adj_x", &adj_x)); |
| 495 | TF_RETURN_IF_ERROR(c->GetAttr("adj_y", &adj_y)); |
| 496 | DimensionHandle output_rows = c->Dim(a_shape, adj_x ? -1 : -2); |
| 497 | DimensionHandle output_cols = c->Dim(b_shape, adj_y ? -2 : -1); |
| 498 | |
| 499 | // Batch dims match between inputs. |
| 500 | ShapeHandle a_batch_dims; |
| 501 | ShapeHandle b_batch_dims; |
| 502 | ShapeHandle batch_dims; |
| 503 | TF_RETURN_IF_ERROR(c->Subshape(a_shape, 0, -2, &a_batch_dims)); |
| 504 | TF_RETURN_IF_ERROR(c->Subshape(b_shape, 0, -2, &b_batch_dims)); |
| 505 | TF_RETURN_IF_ERROR(c->Merge(a_batch_dims, b_batch_dims, &batch_dims)); |
| 506 | |
| 507 | // Assert inner dims match. |
| 508 | DimensionHandle unused; |
| 509 | TF_RETURN_IF_ERROR(c->Merge(c->Dim(a_shape, adj_x ? -2 : -1), |
| 510 | c->Dim(b_shape, adj_y ? -1 : -2), &unused)); |
| 511 | |
| 512 | ShapeHandle out; |
| 513 | TF_RETURN_IF_ERROR( |
| 514 | c->Concatenate(batch_dims, c->Matrix(output_rows, output_cols), &out)); |
| 515 | c->set_output(0, out); |
| 516 | return Status::OK(); |
| 517 | } |
| 518 | |
| 519 | // -------------------------------------------------------------------------- |
| 520 |
nothing calls this directly
no test coverage detected