





import functools
import gc
import inspect

import torch

from .imports import is_npu_available, is_xpu_available

def   a_   (			*lowerCAmelCase_				:      Union[str, Any]     ):
   if not isinstance(lowerCAmelCase_,     lowerCAmelCase_     ):
      __lowerCAmelCase							     =     list(lowerCAmelCase_     )
   for i in range(len(lowerCAmelCase_     )     ):
      __lowerCAmelCase							     =     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   a_   (			lowerCAmelCase_				:      Exception     ):
   __lowerCAmelCase							     =     [
       'CUDA out of memory.',  # CUDA OOM
       'cuDNN error: CUDNN_STATUS_NOT_SUPPORTED.',  # CUDNN SNAFU
       'DefaultCPUAllocator: can\'t allocate memory',  # CPU OOM
   ]
   if isinstance(lowerCAmelCase_,     lowerCAmelCase_     ) and len(exception.args     ) == 1:
      return any(err in exception.args[0] for err in _statements     )
   return False




def   a_   (			lowerCAmelCase_				:      callable = None,     lowerCAmelCase_				:      int = 128     ):
   if function is None:
      return functools.partial(lowerCAmelCase_,     starting_batch_size=lowerCAmelCase_     )

   __lowerCAmelCase							     =     starting_batch_size

   def decorator(*lowerCAmelCase_				:      Dict,     **lowerCAmelCase_				:      Dict     ):
      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()
      __lowerCAmelCase							     =     list(inspect.signature(lowerCAmelCase_     ).parameters.keys()     )
      # Guard against user error
      if len(lowerCAmelCase_     ) < (len(lowerCAmelCase_     ) + 1):
         __lowerCAmelCase							     =     ', '.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(lowerCAmelCase_,     *lowerCAmelCase_,     **lowerCAmelCase_     )
         except Exception as e:
            if should_reduce_batch_size(lowerCAmelCase_     ):
               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








from collections.abc import Sequence

def   a_   (			lowerCAmelCase_				:      Sequence[float],     lowerCAmelCase_				:      bool = False     ):
   if not arr:
      return 0

   __lowerCAmelCase							     =     0 if allow_empty_subarrays else float('-inf'     )
   __lowerCAmelCase							     =     0.0
   for num in arr:
      __lowerCAmelCase							     =     max(0 if allow_empty_subarrays else num,     curr_sum + num     )
      __lowerCAmelCase							     =     max(lowerCAmelCase_,     lowerCAmelCase_     )

   return max_sum


if __name__ == "__main__":
     from doctest import testmod

     testmod()

     _snake_case  :   Optional[Any]						   =  [-2, 1, -3, 4, -1, 2, 1, -5, 4]
     print(F"""{max_subarray_sum(nums) = }""")

