| // Adapted from interp.cpp from Caffe util by Pauline Luc |
| // Originally developed by George Papandreou |
| |
| #include <ATen/ATen.h> |
| #include <ATen/NativeFunctions.h> |
| #include <ATen/native/UpSample.h> |
| |
| namespace at { |
| namespace meta { |
| |
| TORCH_META_FUNC(upsample_linear1d) ( |
| const Tensor& input, |
| IntArrayRef output_size, |
| bool align_corners, |
| c10::optional<double> scales |
| ) { |
| auto full_output_size = native::upsample_1d_common_check(input.sizes(), output_size); |
| |
| // Allow for empty batch size but not other dimensions |
| TORCH_CHECK( |
| (input.size(1) != 0 && input.size(2) != 0) && input.dim() == 3, |
| "Non-empty 3D data tensor expected but got a tensor with sizes ", |
| input.sizes()); |
| |
| set_output(full_output_size, input.options()); |
| } |
| |
| TORCH_META_FUNC(upsample_linear1d_backward) ( |
| const Tensor& grad_output, |
| IntArrayRef output_size, |
| IntArrayRef input_size, |
| bool align_corners, |
| c10::optional<double> scales |
| ) { |
| auto full_output_size = native::upsample_1d_common_check(input_size, output_size); |
| |
| TORCH_CHECK( |
| input_size.size() == 3, |
| "It is expected input_size equals to 3, but got size ", |
| input_size.size()); |
| |
| check_dim_size(grad_output, 3, 0, full_output_size[0]); |
| check_dim_size(grad_output, 3, 1, full_output_size[1]); |
| check_dim_size(grad_output, 3, 2, full_output_size[2]); |
| |
| set_output(input_size, grad_output.options()); |
| } |
| |
| } // namespace meta |
| |
| namespace native { |
| |
| TORCH_IMPL_FUNC(upsample_linear1d_out_cpu) ( |
| const Tensor& input, |
| IntArrayRef output_size, |
| bool align_corners, |
| c10::optional<double> scales, |
| const Tensor& output |
| ) { |
| upsample_linear1d_kernel(kCPU, output, input, align_corners, scales); |
| } |
| |
| TORCH_IMPL_FUNC(upsample_linear1d_backward_out_cpu) ( |
| const Tensor& grad_output, |
| IntArrayRef output_size, |
| IntArrayRef input_size, |
| bool align_corners, |
| c10::optional<double> scales, |
| const Tensor& grad_input |
| ) { |
| grad_input.zero_(); |
| upsample_linear1d_backward_kernel(kCPU, grad_input, grad_output, align_corners, scales); |
| } |
| |
| // vec variants |
| |
| using at::native::upsample::compute_output_size; |
| using at::native::upsample::get_scale_value; |
| |
| Tensor upsample_linear1d( |
| const Tensor& input, |
| c10::optional<IntArrayRef> output_size, |
| bool align_corners, |
| c10::optional<ArrayRef<double>> scale_factors) { |
| auto osize = compute_output_size(input.sizes(), output_size, scale_factors); |
| auto scale_w = get_scale_value(scale_factors, 0); |
| return at::upsample_linear1d(input, osize, align_corners, scale_w); |
| } |
| |
| Tensor upsample_linear1d_backward( |
| const Tensor& grad_output, |
| c10::optional<IntArrayRef> output_size, |
| IntArrayRef input_size, |
| bool align_corners, |
| c10::optional<ArrayRef<double>> scale_factors) { |
| auto osize = compute_output_size(input_size, output_size, scale_factors); |
| auto scale_w = get_scale_value(scale_factors, 0); |
| return at::upsample_linear1d_backward(grad_output, osize, input_size, align_corners, scale_w); |
| } |
| |
| DEFINE_DISPATCH(upsample_linear1d_kernel); |
| DEFINE_DISPATCH(upsample_linear1d_backward_kernel); |
| |
| } // namespace native |
| } // namespace at |