






import functools
import gc
import inspect

import torch

from .imports import is_npu_available, is_xpu_available






def 	UpperCamelCase	(							*snake_case__  : List[Any]	):




     '''simple docstring'''






     if not isinstance(snake_case__						,snake_case__	):
          __snake_case      :Any 							=    list(snake_case__	)
     for i in range(len(snake_case__	)	):
          __snake_case      :Optional[int] 							=    None
     gc.collect()
     if is_xpu_available():
          torch.xpu.empty_cache()
     elif is_npu_available():
          torch.npu.empty_cache()
     else:
          torch.cuda.empty_cache()
     return objects






def 	UpperCamelCase	(							snake_case__  : Exception	):




     '''simple docstring'''






     __snake_case      :Any 							=    [
         """CUDA out of memory.""",  # CUDA OOM
         """cuDNN error: CUDNN_STATUS_NOT_SUPPORTED.""",  # CUDNN SNAFU
         """DefaultCPUAllocator: can't allocate memory""",  # CPU OOM
     ]
     if isinstance(snake_case__						,snake_case__	) and len(exception.args	) == 1:
          return any(err in exception.args[0] for err in _statements	)
     return False






def 	UpperCamelCase	(							snake_case__  : callable = None						,snake_case__  : int = 128	):




     '''simple docstring'''






     if function is None:
          return functools.partial(snake_case__						,starting_batch_size=snake_case__	)

     __snake_case      :Dict 							=    starting_batch_size

     def decorator(*snake_case__  : Dict						,**snake_case__  : Any	):
          nonlocal batch_size
          gc.collect()
          if is_xpu_available():
               torch.xpu.empty_cache()
          elif is_npu_available():
               torch.npu.empty_cache()
          else:
               torch.cuda.empty_cache()
          __snake_case      :str 							=    list(inspect.signature(snake_case__	).parameters.keys()	)
          # Guard against user error
          if len(snake_case__	) < (len(snake_case__	) + 1):
               __snake_case      :int 							=    """, """.join([f'''{arg}={value}''' for arg, value in zip(params[1:]						,args[1:]	)]	)
               raise TypeError(
                   f'''Batch size was passed into `{function.__name__}` as the first argument when called.'''
                   f'''Remove this as the decorator already does so: `{function.__name__}({arg_str})`'''	)
          while True:
               if batch_size == 0:
                    raise RuntimeError("""No executable batch size found, reached zero."""	)
               try:
                    return function(snake_case__						,*snake_case__						,**snake_case__	)
               except Exception as e:
                    if should_reduce_batch_size(snake_case__	):
                         gc.collect()
                         if is_xpu_available():
                              torch.xpu.empty_cache()
                         elif is_npu_available():
                              torch.npu.empty_cache()
                         else:
                              torch.cuda.empty_cache()
                         batch_size //= 2
                    else:
                         raise

     return decorator










def 	UpperCamelCase	(							snake_case__  : int	):




     '''simple docstring'''






     __snake_case      :List[Any] 							=    0
     while num > 0:
          digit_sum += num % 10
          num //= 10
     return digit_sum






def 	UpperCamelCase	(							snake_case__  : int = 100	):




     '''simple docstring'''






     __snake_case      :Tuple 							=    1
     __snake_case      :Dict 							=    2

     for i in range(2						,max_n + 1	):
          __snake_case      :Optional[int] 							=    pre_numerator
          __snake_case      :List[Any] 							=    2 * i // 3 if i % 3 == 0 else 1
          __snake_case      :Dict 							=    cur_numerator
          __snake_case      :Optional[Any] 							=    e_cont * pre_numerator + temp

     return sum_digits(snake_case__	)


if __name__ == "__main__":
     print(f'''{solution() = }''')


