
import random
import unittest

import torch

from diffusers import IFImgaImgPipeline
from diffusers.utils import floats_tensor
from diffusers.utils.import_utils import is_xformers_available
from diffusers.utils.testing_utils import skip_mps, torch_device

from ..pipeline_params import (
    TEXT_GUIDED_IMAGE_VARIATION_BATCH_PARAMS,
    TEXT_GUIDED_IMAGE_VARIATION_PARAMS,
)
from ..test_pipelines_common import PipelineTesterMixin
from . import IFPipelineTesterMixin





@skip_mps
class      _lowerCAmelCase (     __a ,				__a ,				unittest.TestCase	):
				_lowercase      		=IFImgaImgPipeline
				_lowercase      		=TEXT_GUIDED_IMAGE_VARIATION_PARAMS - {'''width''', '''height'''}
				_lowercase      		=TEXT_GUIDED_IMAGE_VARIATION_BATCH_PARAMS
				_lowercase      		=PipelineTesterMixin.required_optional_params - {'''latents'''}




				def 					__a						( self					)    ->				Any:
							return self._get_dummy_components()




				def 					__a						( self    ,    _UpperCamelCase    ,    _UpperCamelCase=0					)    ->				Dict:
							if str(_UpperCamelCase					).startswith("mps"					):
										lowerCAmelCase_      =     torch.manual_seed(_UpperCamelCase					)
							else:
										lowerCAmelCase_      =     torch.Generator(device=_UpperCamelCase					).manual_seed(_UpperCamelCase					)

							lowerCAmelCase_      =     floats_tensor((1, 3, 32, 32)    ,    rng=random.Random(_UpperCamelCase					)					).to(_UpperCamelCase					)

							lowerCAmelCase_      =     {
							    "prompt": "A painting of a squirrel eating a burger",
							    "image": image,
							    "generator": generator,
							    "num_inference_steps": 2,
							    "output_type": "numpy",
							}

							return inputs




				def 					__a						( self					)    ->				List[Any]:
							self._test_save_load_optional_components()




				@unittest.skipIf(
				    torch_device != "cuda" or not is_xformers_available()    ,    reason="XFormers attention is only available with CUDA and `xformers` installed"    ,    )
				def 					__a						( self					)    ->				str:
							self._test_xformers_attention_forwardGenerator_pass(expected_max_diff=1e-3					)




				@unittest.skipIf(torch_device != "cuda"    ,    reason="float16 requires CUDA"					)
				def 					__a						( self					)    ->				str:
							# Due to non-determinism in save load of the hf-internal-testing/tiny-random-t5 text encoder
							super().test_save_load_floataa(expected_max_diff=1e-1					)




				@unittest.skipIf(torch_device != "cuda"    ,    reason="float16 requires CUDA"					)
				def 					__a						( self					)    ->				Tuple:
							super().test_floataa_inference(expected_max_diff=1e-1					)




				def 					__a						( self					)    ->				Optional[Any]:
							self._test_attention_slicing_forward_pass(expected_max_diff=1e-2					)




				def 					__a						( self					)    ->				Tuple:
							self._test_save_load_local()




				def 					__a						( self					)    ->				List[Any]:
							self._test_inference_batch_single_identical(
							    expected_max_diff=1e-2    ,    )





class      _lowerCAmelCase :




				def __init__( self					)    ->				None:
							# numbermap keys are the number and its values are lists of indexes sorted
							# in ascending order
							lowerCAmelCase_      =     {}
							# indexmap keys are an index and it's values are the number at that index
							lowerCAmelCase_      =     {}




				def 					__a						( self    ,    _UpperCamelCase    ,    _UpperCamelCase					)    ->				list[int]:
							if isinstance(_UpperCamelCase    ,    (range, str)					):
										lowerCAmelCase_      =     list(_UpperCamelCase					)
							elif not isinstance(_UpperCamelCase    ,    _UpperCamelCase					):
										raise TypeError(
										    "binary_search_delete() only accepts either a list, range or str"					)

							lowerCAmelCase_      =     0
							lowerCAmelCase_      =     len(_UpperCamelCase					) - 1

							while low <= high:
										lowerCAmelCase_      =     (low + high) // 2
										if array[mid] == item:
													array.pop(_UpperCamelCase					)
													return array
										elif array[mid] < item:
													lowerCAmelCase_      =     mid + 1
										else:
													lowerCAmelCase_      =     mid - 1
							raise ValueError(
							    "Either the item is not in the array or the array was unsorted"					)




				def 					__a						( self    ,    _UpperCamelCase    ,    _UpperCamelCase					)    ->				list[int]:
							if isinstance(_UpperCamelCase    ,    (range, str)					):
										lowerCAmelCase_      =     list(_UpperCamelCase					)
							elif not isinstance(_UpperCamelCase    ,    _UpperCamelCase					):
										raise TypeError(
										    "binary_search_insert() only accepts either a list, range or str"					)

							lowerCAmelCase_      =     0
							lowerCAmelCase_      =     len(_UpperCamelCase					) - 1

							while low <= high:
										lowerCAmelCase_      =     (low + high) // 2
										if array[mid] == index:
													# If the item already exists in the array,
													# insert it after the existing item
													array.insert(mid + 1    ,    _UpperCamelCase					)
													return array
										elif array[mid] < index:
													lowerCAmelCase_      =     mid + 1
										else:
													lowerCAmelCase_      =     mid - 1

        # If the item doesn't exist in the array, insert it at the appropriate position
							array.insert(_UpperCamelCase    ,    _UpperCamelCase					)
							return array




				def 					__a						( self    ,    _UpperCamelCase    ,    _UpperCamelCase					)    ->				None:
							# Remove previous index
							if index in self.indexmap:
										lowerCAmelCase_      =     self.indexmap[index]
										if len(self.numbermap[n]					) == 1:
													del self.numbermap[n]
										else:
													lowerCAmelCase_      =     self.binary_search_delete(self.numbermap[n]    ,    _UpperCamelCase					)

        # Set new index
							lowerCAmelCase_      =     number

							# Number not seen before or empty so insert number value
							if number not in self.numbermap:
										lowerCAmelCase_      =     [index]

							# Here we need to perform a binary search insertion in order to insert
							# The item in the correct place
							else:
										lowerCAmelCase_      =     self.binary_search_insert(
										    self.numbermap[number]    ,    _UpperCamelCase					)




				def 					__a						( self    ,    _UpperCamelCase					)    ->				int:
							return self.numbermap.get(_UpperCamelCase    ,    [-1]					)[0]


if __name__ == "__main__":
			import doctest

			doctest.testmod()



