| 183 | explicit TileOp(OpKernelConstruction* context) : OpKernel(context) {} |
| 184 | |
| 185 | void Compute(OpKernelContext* context) override { |
| 186 | const Tensor& input = context->input(0); |
| 187 | const Tensor& multiples = context->input(1); |
| 188 | |
| 189 | OP_REQUIRES( |
| 190 | context, IsLegacyVector(multiples.shape()), |
| 191 | errors::InvalidArgument("Expected multiples to be 1-D, but got shape ", |
| 192 | multiples.shape().DebugString())); |
| 193 | OP_REQUIRES(context, input.dims() == multiples.NumElements(), |
| 194 | errors::InvalidArgument( |
| 195 | "Expected multiples argument to be a vector of length ", |
| 196 | input.dims(), " but got length ", multiples.dim_size(0))); |
| 197 | const int input_dims = input.dims(); |
| 198 | |
| 199 | // Eigen doesn't support scalars on the GPU, so handle 0-D specially |
| 200 | if (input_dims == 0) { |
| 201 | context->set_output(0, input); |
| 202 | return; |
| 203 | } |
| 204 | |
| 205 | const gtl::ArraySlice<Tmultiples> multiples_array( |
| 206 | multiples.flat<Tmultiples>().data(), input_dims); |
| 207 | TensorShape output_shape; |
| 208 | for (int i = 0; i < input_dims; ++i) { |
| 209 | OP_REQUIRES( |
| 210 | context, multiples_array[i] >= 0, |
| 211 | errors::InvalidArgument("Expected multiples[", i, "] >= 0, but got ", |
| 212 | multiples_array[i])); |
| 213 | OP_REQUIRES_OK( |
| 214 | context, |
| 215 | output_shape.AddDimWithStatus(input.dim_size(i) * multiples_array[i])); |
| 216 | } |
| 217 | if (output_shape == input.shape()) { |
| 218 | context->set_output(0, input); |
| 219 | return; |
| 220 | } |
| 221 | Tensor* result = nullptr; |
| 222 | OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &result)); |
| 223 | |
| 224 | // If there's no output, there's nothing to do. |
| 225 | if (output_shape.num_elements() == 0) return; |
| 226 | |
| 227 | #define HANDLE_TYPE(DT) \ |
| 228 | if (context->input(0).dtype() == DT) { \ |
| 229 | HandleCase<DT>(context, multiples_array, result); \ |
| 230 | return; \ |
| 231 | } |
| 232 | |
| 233 | #define HANDLE_TYPE_NAME(T) HANDLE_TYPE(DataTypeToEnum<T>::value) |
| 234 | |
| 235 | // Invoke macro using TF_CALL_* so type-filtering for platform applies. |
| 236 | TF_CALL_bool(HANDLE_TYPE_NAME); |
| 237 | TF_CALL_bfloat16(HANDLE_TYPE_NAME); |
| 238 | TF_CALL_float(HANDLE_TYPE_NAME); |
| 239 | TF_CALL_double(HANDLE_TYPE_NAME); |
| 240 | TF_CALL_uint8(HANDLE_TYPE_NAME); |
| 241 | TF_CALL_int8(HANDLE_TYPE_NAME); |
| 242 | TF_CALL_int32(HANDLE_TYPE_NAME); |
nothing calls this directly
no test coverage detected