| 119 | } |
| 120 | |
| 121 | void Compute(OpKernelContext* context) override { |
| 122 | const Tensor& input = context->input(0); |
| 123 | const Tensor& filter = context->input(1); |
| 124 | |
| 125 | // Determine relevant sizes from input and filters. |
| 126 | int stride_rows = 0, stride_cols = 0; |
| 127 | int rate_rows = 0, rate_cols = 0; |
| 128 | int64 pad_top = 0, pad_left = 0; |
| 129 | int64 out_rows = 0, out_cols = 0; |
| 130 | ParseSizes(context, strides_, rates_, padding_, &stride_rows, &stride_cols, |
| 131 | &rate_rows, &rate_cols, &pad_top, &pad_left, &out_rows, |
| 132 | &out_cols); |
| 133 | |
| 134 | // Output tensor is of the following dimensions: |
| 135 | // [ batch, out_rows, out_cols, depth ] |
| 136 | const int batch = input.dim_size(0); |
| 137 | const int depth = input.dim_size(3); |
| 138 | const std::vector<int64> out_sizes = {batch, out_rows, out_cols, depth}; |
| 139 | TensorShape out_shape(out_sizes); |
| 140 | |
| 141 | Tensor* output = nullptr; |
| 142 | OP_REQUIRES_OK(context, context->allocate_output(0, out_shape, &output)); |
| 143 | |
| 144 | // If there is nothing to compute, return. |
| 145 | if (out_shape.num_elements() == 0) { |
| 146 | return; |
| 147 | } |
| 148 | |
| 149 | functor::Dilation<Device, T>()( |
| 150 | context->eigen_device<Device>(), input.tensor<T, 4>(), |
| 151 | filter.tensor<T, 3>(), stride_rows, stride_cols, rate_rows, rate_cols, |
| 152 | pad_top, pad_left, output->tensor<T, 4>()); |
| 153 | } |
| 154 | |
| 155 | std::vector<int32> strides_; |
| 156 | std::vector<int32> rates_; |
nothing calls this directly
no test coverage detected