| 480 | } |
| 481 | |
| 482 | void Compute(OpKernelContext* context) override { |
| 483 | // Input tensor is of the following dimensions: |
| 484 | // [ batch, in_rows, in_cols, in_depth ] |
| 485 | const Tensor& input = context->input(0); |
| 486 | |
| 487 | // Input filter is of the following dimensions: |
| 488 | // [ filter_rows, filter_cols, in_depth, out_depth] |
| 489 | const Tensor& filter = context->input(1); |
| 490 | |
| 491 | // For 2D convolution, there should be 4 dimensions. |
| 492 | OP_REQUIRES(context, input.dims() == 4, |
| 493 | errors::InvalidArgument("input must be 4-dimensional", |
| 494 | input.shape().DebugString())); |
| 495 | OP_REQUIRES(context, filter.dims() == 4, |
| 496 | errors::InvalidArgument("filter must be 4-dimensional: ", |
| 497 | filter.shape().DebugString())); |
| 498 | |
| 499 | const float min_input = context->input(2).flat<float>()(0); |
| 500 | const float max_input = context->input(3).flat<float>()(0); |
| 501 | const float min_filter = context->input(4).flat<float>()(0); |
| 502 | const float max_filter = context->input(5).flat<float>()(0); |
| 503 | const int32 offset_input = |
| 504 | FloatToQuantizedUnclamped<T1>(0.0f, min_input, max_input); |
| 505 | const int32 offset_filter = |
| 506 | FloatToQuantizedUnclamped<T2>(0.0f, min_filter, max_filter); |
| 507 | const int32 offset_output = 0; |
| 508 | const int32 mult_output = 1; |
| 509 | const int32 shift_output = 0; |
| 510 | |
| 511 | // The last dimension for input is in_depth. It must be the same as the |
| 512 | // filter's in_depth. |
| 513 | const int64 in_depth = input.dim_size(3); |
| 514 | OP_REQUIRES(context, in_depth == filter.dim_size(2), |
| 515 | errors::InvalidArgument( |
| 516 | "input and filter must have the same depth: ", in_depth, |
| 517 | " vs ", filter.dim_size(2))); |
| 518 | |
| 519 | // The last dimension for filter is out_depth. |
| 520 | const int64 out_depth = filter.dim_size(3); |
| 521 | |
| 522 | // The second dimension for input is rows/height. |
| 523 | // The first dimension for filter is rows/height. |
| 524 | const int64 input_rows = input.dim_size(1); |
| 525 | const int64 filter_rows = filter.dim_size(0); |
| 526 | |
| 527 | // The third dimension for input is columns/width. |
| 528 | // The second dimension for filter is columns/width. |
| 529 | const int64 input_cols = input.dim_size(2); |
| 530 | const int64 filter_cols = filter.dim_size(1); |
| 531 | |
| 532 | // The first dimension for input is batch. |
| 533 | const int64 batch = input.dim_size(0); |
| 534 | |
| 535 | // For now we take the stride from the second dimension only (we |
| 536 | // assume row = col stride, and do not support striding on the |
| 537 | // batch or depth dimension). |
| 538 | const int stride = strides_[1]; |
| 539 |
nothing calls this directly
no test coverage detected