



import functools
import gc
import inspect

import torch

from .imports import is_npu_available, is_xpu_available



def __lowerCAmelCase (     *SCREAMING_SNAKE_CASE_  ):

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




def __lowerCAmelCase (     SCREAMING_SNAKE_CASE_ = None						,  SCREAMING_SNAKE_CASE_ = 128  ):

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

			lowercase__					  =				starting_batch_size

			def decorator(*SCREAMING_SNAKE_CASE_						,  **SCREAMING_SNAKE_CASE_  ):
						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()
						lowercase__					  =				list(inspect.signature(SCREAMING_SNAKE_CASE_  ).parameters.keys()  )
						# Guard against user error
						if len(SCREAMING_SNAKE_CASE_  ) < (len(SCREAMING_SNAKE_CASE_  ) + 1):
									lowercase__					  =				", ".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(SCREAMING_SNAKE_CASE_						,  *SCREAMING_SNAKE_CASE_						,  **SCREAMING_SNAKE_CASE_  )
									except Exception as e:
												if should_reduce_batch_size(SCREAMING_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 __lowerCAmelCase (     SCREAMING_SNAKE_CASE_  ):
			if upper_limit < 0:
						raise ValueError("Limit for the Catalan sequence must be ≥ 0"  )

			lowercase__					  =				[0] * (upper_limit + 1)

			# Base case: C(0) = C(1) = 1
			lowercase__					  =				1
			if upper_limit > 0:
						lowercase__					  =				1

			# Recurrence relation: C(i) = sum(C(j).C(i-j-1)), from j = 0 to i
			for i in range(2						,  upper_limit + 1  ):
						for j in range(SCREAMING_SNAKE_CASE_  ):
									catalan_list[i] += catalan_list[j] * catalan_list[i - j - 1]

			return catalan_list


if __name__ == "__main__":
							print("""\n********* Catalan Numbers Using Dynamic Programming ************\n""")
							print("""\n*** Enter -1 at any time to quit ***""")
							print("""\nEnter the upper limit (≥ 0) for the Catalan number sequence: """, end="""""")
							try:
														while True:
																					lowercase_								=     int(input().strip())
																					if N < 0:
																												print("""\n********* Goodbye!! ************""")
																												break
																					else:
																												print(F'The Catalan numbers from 0 through {N} are:')
																												print(catalan_numbers(N))
																												print("""Try another upper limit for the sequence: """, end="""""")
							except (NameError, ValueError):
														print("""\n********* Invalid input, goodbye! ************\n""")

							import doctest

							doctest.testmod()




