'''simple docstring'''





import inspect
import warnings

import torch

from .state import AcceleratorState, GradientState
from .utils import DistributedType, honor_type, is_tpu_available


if is_tpu_available(check_device=False):
				import torch_xla.core.xla_model as xm


def 					__lowerCAmelCase			(  _A ,_A					):



							"""simple docstring"""


							if isinstance(_A ,(list, tuple)					):
														return honor_type(_A ,(move_to_device(_A ,_A					) for t in state)					)
							elif isinstance(_A ,_A					):
														return type(_A					)({k: move_to_device(_A ,_A					) for k, v in state.items()}					)
							elif isinstance(_A ,torch.Tensor					):
														return state.to(_A					)
							return state







class _lowercase					(       torch.optim.Optimizer						):





							"""simple docstring"""




							def __init__(    self     ,   UpperCAmelCase     ,   UpperCAmelCase=True     ,   UpperCAmelCase=None  ):







														'''simple docstring'''






														_lowercase				=	optimizer
														_lowercase				=	scaler
														_lowercase				=	AcceleratorState()
														_lowercase				=	GradientState()
														_lowercase				=	device_placement
														_lowercase				=	False
														_lowercase				=	None

														# Handle device placement
														if device_placement:
																					_lowercase				=	self.optimizer.state_dict()
																					if self.accelerator_state.distributed_type == DistributedType.TPU:
																												xm.send_cpu_data_to_device(UpperCAmelCase     ,   self.accelerator_state.device  )
																					else:
																												_lowercase				=	move_to_device(UpperCAmelCase     ,   self.accelerator_state.device  )
																					self.optimizer.load_state_dict(UpperCAmelCase  )



							@property
							def     _UpperCAmelCase       (    self  ):







														'''simple docstring'''






														return self.optimizer.state



							@state.setter
							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														_lowercase				=	state



							@property
							def     _UpperCAmelCase       (    self  ):







														'''simple docstring'''






														return self.optimizer.param_groups



							@param_groups.setter
							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														_lowercase				=	param_groups



							@property
							def     _UpperCAmelCase       (    self  ):







														'''simple docstring'''






														return self.optimizer.defaults



							@defaults.setter
							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														_lowercase				=	defaults



							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														self.optimizer.add_param_group(UpperCAmelCase  )



							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														if self.accelerator_state.distributed_type == DistributedType.TPU and self.device_placement:
																					xm.send_cpu_data_to_device(UpperCAmelCase     ,   self.accelerator_state.device  )
														self.optimizer.load_state_dict(UpperCAmelCase  )



							def     _UpperCAmelCase       (    self  ):







														'''simple docstring'''






														return self.optimizer.state_dict()



							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase=None  ):







														'''simple docstring'''






														if self.gradient_state.sync_gradients:
																					_lowercase				=	"""set_to_none""" in inspect.signature(self.optimizer.zero_grad  ).parameters
																					if accept_arg:
																												if set_to_none is None:
																																			_lowercase				=	False
																												self.optimizer.zero_grad(set_to_none=UpperCAmelCase  )
																					else:
																												if set_to_none is not None:
																																			raise ValueError("""`set_to_none` for Optimizer.zero_grad` is not supported by this optimizer."""  )
																												self.optimizer.zero_grad()



							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase=None  ):







														'''simple docstring'''






														if self.gradient_state.sync_gradients:
																					if self.accelerator_state.distributed_type == DistributedType.TPU:
																												_lowercase				=	{"""closure""": closure} if closure is not None else {}
																												xm.optimizer_step(self.optimizer     ,   optimizer_args=UpperCAmelCase  )
																					elif self.scaler is not None:
																												_lowercase				=	False
																												if self._last_scale is None:
																																			# `get_scale` is an async operation requiring full synchronization
																																			# on CPU and GPUs before finishing. As a result, we store away
																																			# the prior one to reduce the call overhead
																																			_lowercase				=	self.scaler.get_scale()
																																			_lowercase				=	True
																												self.scaler.step(self.optimizer     ,   UpperCAmelCase  )
																												self.scaler.update()
																												_lowercase				=	self.scaler.get_scale()
																												if not new_scale:
																																			# If we reduced the loss scale, it means the optimizer step was skipped because of gradient overflow.
																																			_lowercase				=	scale_after < self._last_scale
																												_lowercase				=	scale_after

																					else:
																												self.optimizer.step(UpperCAmelCase  )



							def     _UpperCAmelCase       (    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														for param_group in self.optimizer.param_groups:
																					_lowercase				=	[parameters_map.get(UpperCAmelCase     ,   UpperCAmelCase  ) for p in param_group["""params"""]]



							@property
							def     _UpperCAmelCase       (    self  ):







														'''simple docstring'''






														warnings.warn(
														    """The `is_overflow` property is deprecated and will be removed in version 1.0 of Accelerate use """
														    """`optimizer.step_was_skipped` instead."""     ,   UpperCAmelCase     ,   )
														return self._is_overflow



							@property
							def     _UpperCAmelCase       (    self  ):







														'''simple docstring'''






														return self._is_overflow



							def __getstate__(    self  ):







														'''simple docstring'''






														return self.__dict__.copy()



							def __setstate__(    self     ,   UpperCAmelCase  ):







														'''simple docstring'''






														self.__dict__.update(UpperCAmelCase  )



import math
from timeit import timeit


def 					__lowerCAmelCase			(  _A					):



							"""simple docstring"""


							_lowercase				=	0
							_lowercase				=	abs(_A					)
							while True:
														_lowercase				=	n // 10
														digits += 1
														if n == 0:
																					break
							return digits


def 					__lowerCAmelCase			(  _A					):



							"""simple docstring"""


							return 1 if n == 0 else math.floor(math.log(abs(_A					) ,10					) + 1					)


def 					__lowerCAmelCase			(  _A					):



							"""simple docstring"""


							return len(str(abs(_A					)					)					)


def 					__lowerCAmelCase			(  ):



							"""simple docstring"""


							from collections.abc import Callable

							def benchmark_a_function(_A ,_A					) -> None:
														_lowercase				=	f'''{func.__name__}({value})'''
														_lowercase				=	timeit(f'''__main__.{call}''' ,setup="""import __main__"""					)
														print(f'''{call}: {func(_A					)} -- {timing} seconds'''					)

							for value in (262_144, 1_125_899_906_842_624, 1_267_650_600_228_229_401_496_703_205_376):
														for func in (num_digits, num_digits_fast, num_digits_faster):
																					benchmark_a_function(_A ,_A					)
														print()


if __name__ == "__main__":
				import doctest

				doctest.testmod()
				benchmark()


