| 525 | // componentwise multiplication functor instead. |
| 526 | template <typename Device, typename T> |
| 527 | Status ContractOperands(OpKernelContext* ctx, absl::Span<const Tensor> inputs, |
| 528 | absl::Span<const bool> swap_free_and_contract, |
| 529 | Tensor* output) { |
| 530 | if (inputs.size() == 1) return CopyFrom(inputs[0], inputs[0].shape(), output); |
| 531 | MatMulBCast bcast(inputs[0].shape().dim_sizes(), |
| 532 | inputs[1].shape().dim_sizes()); |
| 533 | if (!bcast.IsValid()) { |
| 534 | return errors::InvalidArgument( |
| 535 | "Invalid broadcasting dimensions: ", inputs[0].shape().DebugString(), |
| 536 | " vs. ", inputs[1].shape().DebugString()); |
| 537 | } |
| 538 | Tensor lhs; |
| 539 | TF_RETURN_IF_ERROR(ReshapeToRank3(inputs[0], bcast.x_batch_size(), &lhs)); |
| 540 | Tensor rhs; |
| 541 | TF_RETURN_IF_ERROR(ReshapeToRank3(inputs[1], bcast.y_batch_size(), &rhs)); |
| 542 | TensorShape output_shape = bcast.output_batch_shape(); |
| 543 | for (int i = 0; i < inputs.size(); ++i) { |
| 544 | const int64 free_axis = |
| 545 | inputs[i].dims() - (swap_free_and_contract[i] ? 1 : 2); |
| 546 | output_shape.AddDim(inputs[i].dim_size(free_axis)); |
| 547 | } |
| 548 | |
| 549 | bool trans_x = swap_free_and_contract[0]; |
| 550 | bool trans_y = !swap_free_and_contract[1]; |
| 551 | |
| 552 | TF_RETURN_IF_ERROR( |
| 553 | ctx->allocate_temp(DataTypeToEnum<T>::value, output_shape, output)); |
| 554 | Tensor output_reshaped; |
| 555 | TF_RETURN_IF_ERROR( |
| 556 | ReshapeToRank3(*output, bcast.output_batch_size(), &output_reshaped)); |
| 557 | LaunchBatchMatMul<Device, T>::Launch(ctx, lhs, rhs, false, false, trans_x, |
| 558 | trans_y, bcast, &output_reshaped); |
| 559 | return Status::OK(); |
| 560 | } |
| 561 | } // namespace |
| 562 | |
| 563 | template <typename Device, typename T> |
nothing calls this directly
no test coverage detected