//  [python]
def test_upsamplingBiMode2d_consistency(
        self,
        device,
        memory_format,
        mode,
        antialias,
        align_corners,
        num_channels,
        output_size,
        check_as_unsqueezed_3d_tensor,
        non_contig,
        batch_size,
    ):
        # Check output value consistency between resized_input_uint8 and resized input_float
        if torch.device(device).type == "npu":
            raise SkipTest("NPU implementation is not yet supporting uint8")

        torch.manual_seed(0)

        input_ui8 = torch.randint(0, 256, size=(batch_size, num_channels, 400, 400), dtype=torch.uint8, device=device)
        input_ui8 = input_ui8.contiguous(memory_format=memory_format)

        if non_contig == "sliced":
            input_ui8 = input_ui8[:, :, 10:-10, 10:-10]
        elif non_contig == "restrided":
            input_ui8 = input_ui8[:, :, ::2, ::2]

        if batch_size == 1 and check_as_unsqueezed_3d_tensor:
            input_ui8 = input_ui8[0, ...]
            input_ui8 = input_ui8[None, ...]

        input_f32 = input_ui8.float()

        output_f32 = F.interpolate(
            input_f32, size=(output_size, output_size), mode=mode, align_corners=align_corners, antialias=antialias
        ).round().clip(0, 255)
        output_ui8 = F.interpolate(
            input_ui8, size=(output_size, output_size), mode=mode, align_corners=align_corners, antialias=antialias
        )

        if non_contig is False:
            self.assertTrue(input_ui8.is_contiguous(memory_format=memory_format))

        if batch_size == 1 and check_as_unsqueezed_3d_tensor and memory_format == torch.channels_last:
            self.assertTrue(output_ui8.is_contiguous())
            self.assertTrue(output_f32.is_contiguous())
        else:
            self.assertTrue(output_ui8.is_contiguous(memory_format=memory_format))
            self.assertTrue(output_f32.is_contiguous(memory_format=memory_format))

        diff = (output_f32 - output_ui8.float()).abs()
        if mode == "bilinear":
            torch.testing.assert_close(output_f32, output_ui8.float(), rtol=0, atol=1)
        else:
            # - tolerances for bicubic mode are in general higher than for
            #   bilinear mode, because the bicubic kernel may create
            #   [intermediate] values outside of the [0, 255] range, which need
            #   to be clipped in uint8 path, but not in float path. This isn't
            #   an issue with bilinear kernel.
            # - Also in bicubic mode, when antialias=False, we have to use
            #   bigger tolerances than when antialias=True. This is partially
            #   due to the fact that when False, the float path uses the -0.75
            #   constant while the uint8 path uses the -0.5 constant in the
            #   bicubic kernel (when True, they both use -0.5). This difference
            #   in constants exists for historical reasons. Should both paths
            #   use the -0.5 constant, we would have closer results and we would
            #   be able to lower the tolerances.

            max_diff = 30 if antialias else 44
            assert diff.max() < max_diff

            threshold = 2
            percent = 3 if antialias else 40
            assert (diff > threshold).float().mean() < (percent / 100)

            threshold = 5
            percent = 1 if antialias else 20
            assert (diff > threshold).float().mean() < (percent / 100)

            mae = .4 if antialias else 3
            assert diff.mean() < mae