| 48 | explicit PadOp(OpKernelConstruction* context) : OpKernel(context) {} |
| 49 | |
| 50 | void Compute(OpKernelContext* context) override { |
| 51 | const Tensor& in0 = context->input(0); |
| 52 | const Tensor& in1 = context->input(1); |
| 53 | const int dims = in0.dims(); |
| 54 | static const int kMinDims = 0; |
| 55 | static const int kMaxDims = 6; |
| 56 | OP_REQUIRES(context, kMinDims <= dims && dims <= kMaxDims, |
| 57 | errors::Unimplemented("inputs rank not in [", kMinDims, ",", |
| 58 | kMaxDims, "]: ", dims)); |
| 59 | OP_REQUIRES( |
| 60 | context, |
| 61 | TensorShapeUtils::IsMatrix(in1.shape()) && in1.dim_size(1) == 2, |
| 62 | errors::InvalidArgument("paddings must be a matrix with 2 columns: ", |
| 63 | in1.shape().DebugString())); |
| 64 | const int fixed_dims = |
| 65 | (allow_legacy_scalars() && dims == 0 && in1.dim_size(0) == 1) ? 1 |
| 66 | : dims; |
| 67 | OP_REQUIRES( |
| 68 | context, fixed_dims == in1.dim_size(0), |
| 69 | errors::InvalidArgument( |
| 70 | "The first dimension of paddings must be the rank of inputs", |
| 71 | in1.shape().DebugString(), " ", in0.shape().DebugString())); |
| 72 | |
| 73 | T pad_value = T(); |
| 74 | if (context->num_inputs() == 3) { |
| 75 | const Tensor& constant_values = context->input(2); |
| 76 | OP_REQUIRES( |
| 77 | context, TensorShapeUtils::IsScalar(constant_values.shape()), |
| 78 | errors::InvalidArgument("constant_values must be a scalar. Found: ", |
| 79 | constant_values.shape().DebugString())); |
| 80 | pad_value = context->input(2).scalar<T>()(); |
| 81 | } |
| 82 | |
| 83 | // Compute the shape of the output tensor, and allocate it. |
| 84 | TensorShape output_shape; |
| 85 | typename TTypes<Tpadding>::ConstMatrix paddings = in1.matrix<Tpadding>(); |
| 86 | for (int d = 0; d < fixed_dims; ++d) { |
| 87 | const Tpadding before_d = |
| 88 | paddings(d, 0); // Pad before existing elements. |
| 89 | const Tpadding after_d = paddings(d, 1); // Pad after existing elements. |
| 90 | OP_REQUIRES(context, before_d >= 0 && after_d >= 0, |
| 91 | errors::InvalidArgument("Paddings must be non-negative: ", |
| 92 | before_d, " ", after_d)); |
| 93 | const int64 size_d = |
| 94 | (allow_legacy_scalars() && d == in0.dims()) ? 1 : in0.dim_size(d); |
| 95 | OP_REQUIRES_OK( |
| 96 | context, output_shape.AddDimWithStatus(before_d + size_d + after_d)); |
| 97 | } |
| 98 | |
| 99 | // If there is no padding to be done, forward the input to output. |
| 100 | if (output_shape.num_elements() == in0.NumElements()) { |
| 101 | // When num_elements == 0, shape may have changed. |
| 102 | Tensor out; |
| 103 | CHECK(out.CopyFrom(in0, output_shape)); |
| 104 | context->set_output(0, out); |
| 105 | return; |
| 106 | } |
| 107 |
nothing calls this directly
no test coverage detected