//  [python]
def forward(self, x):
        H, W = x.shape[2:]
        x = self.check_image_size(x)

        self.mean = self.mean.type_as(x)
        x = (x - self.mean) * self.img_range

        if self.upsampler == "pixelshuffle":
            # for classical SR
            x = self.conv_first(x)
            x = self.conv_after_body(self.forward_features(x)) + x
            x = self.conv_before_upsample(x)
            x = self.conv_last(self.upsample(x))
        elif self.upsampler == "pixelshuffle_aux":
            bicubic = F.interpolate(
                x,
                size=(H * self.upscale, W * self.upscale),
                mode="bicubic",
                align_corners=False,
            )
            bicubic = self.conv_bicubic(bicubic)
            x = self.conv_first(x)
            x = self.conv_after_body(self.forward_features(x)) + x
            x = self.conv_before_upsample(x)
            aux = self.conv_aux(x)  # b, 3, LR_H, LR_W
            x = self.conv_after_aux(aux)
            x = (
                self.upsample(x)[:, :, : H * self.upscale, : W * self.upscale]
                + bicubic[:, :, : H * self.upscale, : W * self.upscale]
            )
            x = self.conv_last(x)
            aux = aux / self.img_range + self.mean
        elif self.upsampler == "pixelshuffle_hf":
            # for classical SR with HF
            x = self.conv_first(x)
            x = self.conv_after_body(self.forward_features(x)) + x
            x_before = self.conv_before_upsample(x)
            x_out = self.conv_last(self.upsample(x_before))

            x_hf = self.conv_first_hf(x_before)
            x_hf = self.conv_after_body_hf(self.forward_features_hf(x_hf)) + x_hf
            x_hf = self.conv_before_upsample_hf(x_hf)
            x_hf = self.conv_last_hf(self.upsample_hf(x_hf))
            x = x_out + x_hf
            x_hf = x_hf / self.img_range + self.mean

        elif self.upsampler == "pixelshuffledirect":
            # for lightweight SR
            x = self.conv_first(x)
            x = self.conv_after_body(self.forward_features(x)) + x
            x = self.upsample(x)
        elif self.upsampler == "nearest+conv":
            # for real-world SR
            x = self.conv_first(x)
            x = self.conv_after_body(self.forward_features(x)) + x
            x = self.conv_before_upsample(x)
            x = self.lrelu(
                self.conv_up1(
                    torch.nn.functional.interpolate(x, scale_factor=2, mode="nearest")
                )
            )
            x = self.lrelu(
                self.conv_up2(
                    torch.nn.functional.interpolate(x, scale_factor=2, mode="nearest")
                )
            )
            x = self.conv_last(self.lrelu(self.conv_hr(x)))
        else:
            # for image denoising and JPEG compression artifact reduction
            x_first = self.conv_first(x)
            res = self.conv_after_body(self.forward_features(x_first)) + x_first
            x = x + self.conv_last(res)

        x = x / self.img_range + self.mean
        if self.upsampler == "pixelshuffle_aux":
            # NOTE: I removed an "aux" output here. not sure what that was for
            return x[:, :, : H * self.upscale, : W * self.upscale]  # type: ignore

        elif self.upsampler == "pixelshuffle_hf":
            x_out = x_out / self.img_range + self.mean  # type: ignore
            return x_out[:, :, : H * self.upscale, : W * self.upscale], x[:, :, : H * self.upscale, : W * self.upscale], x_hf[:, :, : H * self.upscale, : W * self.upscale]  # type: ignore

        else:
            return x[:, :, : H * self.upscale, : W * self.upscale]