
import logging
import math
from functools import partial
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union

import torch

from .tensor_utils import tensor_tree_map, tree_map






def    lowerCamelCase__				(				__lowerCAmelCase  :  Union[dict, list, tuple, torch.Tensor]				):




			"""simple docstring"""


			lowerCAmelCase_						=	[]
			if isinstance(__lowerCAmelCase    ,							__lowerCAmelCase				):
						for v in tree.values():
									shapes.extend(_fetch_dims(__lowerCAmelCase				)				)
			elif isinstance(__lowerCAmelCase    ,							(list, tuple)				):
						for t in tree:
									shapes.extend(_fetch_dims(__lowerCAmelCase				)				)
			elif isinstance(__lowerCAmelCase    ,							torch.Tensor				):
						shapes.append(tree.shape				)
			else:
						raise ValueError("Not supported"				)

			return shapes






@torch.jit.ignore
def    lowerCamelCase__				(				__lowerCAmelCase  :  int    ,							__lowerCAmelCase  :  Tuple[int, ...]				):




			"""simple docstring"""


			lowerCAmelCase_						=	[]
			for d in reversed(__lowerCAmelCase				):
						idx.append(flat_idx % d				)
						lowerCAmelCase_						=	flat_idx // d

			return tuple(reversed(__lowerCAmelCase				)				)






@torch.jit.ignore
def    lowerCamelCase__				(				__lowerCAmelCase  :  Sequence[int]    ,							__lowerCAmelCase  :  Sequence[int]    ,							__lowerCAmelCase  :  Sequence[int]    ,							__lowerCAmelCase  :  Optional[Sequence[bool]] = None    ,							__lowerCAmelCase  :  Optional[Sequence[bool]] = None    ,							):




			"""simple docstring"""


			def reduce_edge_list(__lowerCAmelCase  :  List[bool]				) -> None:
						lowerCAmelCase_						=	True
						for i in range(len(__lowerCAmelCase				)				):
									lowerCAmelCase_						=	-1 * (i + 1)
									l[reversed_idx] &= tally
									lowerCAmelCase_						=	l[reversed_idx]

			if start_edges is None:
						lowerCAmelCase_						=	[s == 0 for s in start]
						reduce_edge_list(__lowerCAmelCase				)
			if end_edges is None:
						lowerCAmelCase_						=	[e == (d - 1) for e, d in zip(__lowerCAmelCase    ,							__lowerCAmelCase				)]
						reduce_edge_list(__lowerCAmelCase				)

			# Base cases. Either start/end are empty and we're done, or the final,
			# one-dimensional tensor can be simply sliced
			if len(__lowerCAmelCase				) == 0:
						return [()]
			elif len(__lowerCAmelCase				) == 1:
						return [(slice(start[0]    ,							end[0] + 1				),)]

			lowerCAmelCase_						=	[]
			lowerCAmelCase_						=	[]

			# Dimensions common to start and end can be selected directly
			for s, e in zip(__lowerCAmelCase    ,							__lowerCAmelCase				):
						if s == e:
									path_list.append(slice(__lowerCAmelCase    ,							s + 1				)				)
						else:
									break

			lowerCAmelCase_						=	tuple(__lowerCAmelCase				)
			lowerCAmelCase_						=	len(__lowerCAmelCase				)

			# start == end, and we're done
			if divergence_idx == len(__lowerCAmelCase				):
						return [path]

			def upper() -> Tuple[Tuple[slice, ...], ...]:
						assert start_edges is not None
						assert end_edges is not None

						lowerCAmelCase_						=	start[divergence_idx]
						return tuple(
						    path + (slice(__lowerCAmelCase    ,							sdi + 1				),) + s
						    for s in _get_minimal_slice_set(
						        start[divergence_idx + 1 :]    ,							[d - 1 for d in dims[divergence_idx + 1 :]]    ,							dims[divergence_idx + 1 :]    ,							start_edges=start_edges[divergence_idx + 1 :]    ,							end_edges=[True for _ in end_edges[divergence_idx + 1 :]]    ,							)				)

			def lower() -> Tuple[Tuple[slice, ...], ...]:
						assert start_edges is not None
						assert end_edges is not None

						lowerCAmelCase_						=	end[divergence_idx]
						return tuple(
						    path + (slice(__lowerCAmelCase    ,							edi + 1				),) + s
						    for s in _get_minimal_slice_set(
						        [0 for _ in start[divergence_idx + 1 :]]    ,							end[divergence_idx + 1 :]    ,							dims[divergence_idx + 1 :]    ,							start_edges=[True for _ in start_edges[divergence_idx + 1 :]]    ,							end_edges=end_edges[divergence_idx + 1 :]    ,							)				)

			# If both start and end are at the edges of the subtree rooted at
			# divergence_idx, we can just select the whole subtree at once
			if start_edges[divergence_idx] and end_edges[divergence_idx]:
						slices.append(path + (slice(start[divergence_idx]    ,							end[divergence_idx] + 1				),)				)
			# If just start is at the edge, we can grab almost all of the subtree,
			# treating only the ragged bottom edge as an edge case
			elif start_edges[divergence_idx]:
						slices.append(path + (slice(start[divergence_idx]    ,							end[divergence_idx]				),)				)
						slices.extend(lower()				)
			# Analogous to the previous case, but the top is ragged this time
			elif end_edges[divergence_idx]:
						slices.extend(upper()				)
						slices.append(path + (slice(start[divergence_idx] + 1    ,							end[divergence_idx] + 1				),)				)
			# If both sides of the range are ragged, we need to handle both sides
			# separately. If there's contiguous meat in between them, we can index it
			# in one big chunk
			else:
						slices.extend(upper()				)
						lowerCAmelCase_						=	end[divergence_idx] - start[divergence_idx]
						if middle_ground > 1:
									slices.append(path + (slice(start[divergence_idx] + 1    ,							end[divergence_idx]				),)				)
						slices.extend(lower()				)

			return slices






@torch.jit.ignore
def    lowerCamelCase__				(				__lowerCAmelCase  :  torch.Tensor    ,							__lowerCAmelCase  :  int    ,							__lowerCAmelCase  :  int    ,							__lowerCAmelCase  :  int				):




			"""simple docstring"""


			lowerCAmelCase_						=	t.shape[:no_batch_dims]
			lowerCAmelCase_						=	list(_flat_idx_to_idx(__lowerCAmelCase    ,							__lowerCAmelCase				)				)
			# _get_minimal_slice_set is inclusive
			lowerCAmelCase_						=	list(_flat_idx_to_idx(flat_end - 1    ,							__lowerCAmelCase				)				)

			# Get an ordered list of slices to perform
			lowerCAmelCase_						=	_get_minimal_slice_set(
			    __lowerCAmelCase    ,							__lowerCAmelCase    ,							__lowerCAmelCase    ,							)

			lowerCAmelCase_						=	[t[s] for s in slices]

			return torch.cat([s.view((-1,) + t.shape[no_batch_dims:]				) for s in sliced_tensors]				)






def    lowerCamelCase__				(				__lowerCAmelCase  :  Callable    ,							__lowerCAmelCase  :  Dict[str, Any]    ,							__lowerCAmelCase  :  int    ,							__lowerCAmelCase  :  int    ,							__lowerCAmelCase  :  bool = False    ,							__lowerCAmelCase  :  Any = None    ,							__lowerCAmelCase  :  bool = False    ,							):




			"""simple docstring"""


			if not (len(__lowerCAmelCase				) > 0):
						raise ValueError("Must provide at least one input"				)

			lowerCAmelCase_						=	[shape[:no_batch_dims] for shape in _fetch_dims(__lowerCAmelCase				)]
			lowerCAmelCase_						=	tuple([max(__lowerCAmelCase				) for s in zip(*__lowerCAmelCase				)]				)

			def _prep_inputs(__lowerCAmelCase  :  torch.Tensor				) -> torch.Tensor:
						if not low_mem:
									if not sum(t.shape[:no_batch_dims]				) == no_batch_dims:
												lowerCAmelCase_						=	t.expand(orig_batch_dims + t.shape[no_batch_dims:]				)
									lowerCAmelCase_						=	t.reshape(-1    ,							*t.shape[no_batch_dims:]				)
						else:
									lowerCAmelCase_						=	t.expand(orig_batch_dims + t.shape[no_batch_dims:]				)
						return t

			lowerCAmelCase_						=	tensor_tree_map(_prep_inputs    ,							__lowerCAmelCase				)
			lowerCAmelCase_						=	None
			if _out is not None:
						lowerCAmelCase_						=	tensor_tree_map(lambda __lowerCAmelCase				: t.view([-1] + list(t.shape[no_batch_dims:]				)				)    ,							_out				)

			lowerCAmelCase_						=	1
			for d in orig_batch_dims:
						flat_batch_dim *= d

			lowerCAmelCase_						=	flat_batch_dim // chunk_size + (flat_batch_dim % chunk_size != 0)

			def _select_chunk(__lowerCAmelCase  :  torch.Tensor				) -> torch.Tensor:
						return t[i : i + chunk_size] if t.shape[0] != 1 else t

			lowerCAmelCase_						=	0
			lowerCAmelCase_						=	prepped_outputs
			for _ in range(__lowerCAmelCase				):
						# Chunk the input
						if not low_mem:
									lowerCAmelCase_						=	_select_chunk
						else:
									lowerCAmelCase_						=	partial(
									    _chunk_slice    ,							flat_start=__lowerCAmelCase    ,							flat_end=min(__lowerCAmelCase    ,							i + chunk_size				)    ,							no_batch_dims=len(__lowerCAmelCase				)    ,							)

						lowerCAmelCase_						=	tensor_tree_map(__lowerCAmelCase    ,							__lowerCAmelCase				)

						# Run the layer on the chunk
						lowerCAmelCase_						=	layer(**__lowerCAmelCase				)

						# Allocate space for the output
						if out is None:
									lowerCAmelCase_						=	tensor_tree_map(lambda __lowerCAmelCase				: t.new_zeros((flat_batch_dim,) + t.shape[1:]				)    ,							__lowerCAmelCase				)

						# Put the chunk in its pre-allocated space
						if isinstance(__lowerCAmelCase    ,							__lowerCAmelCase				):

									def assign(__lowerCAmelCase  :  dict    ,							__lowerCAmelCase  :  dict				) -> None:
												for k, v in da.items():
															if isinstance(__lowerCAmelCase    ,							__lowerCAmelCase				):
																		assign(__lowerCAmelCase    ,							da[k]				)
															else:
																		if _add_into_out:
																					v[i : i + chunk_size] += da[k]
																		else:
																					lowerCAmelCase_						=	da[k]

									assign(__lowerCAmelCase    ,							__lowerCAmelCase				)
						elif isinstance(__lowerCAmelCase    ,							__lowerCAmelCase				):
									for xa, xa in zip(__lowerCAmelCase    ,							__lowerCAmelCase				):
												if _add_into_out:
															xa[i : i + chunk_size] += xa
												else:
															lowerCAmelCase_						=	xa
						elif isinstance(__lowerCAmelCase    ,							torch.Tensor				):
									if _add_into_out:
												out[i : i + chunk_size] += output_chunk
									else:
												lowerCAmelCase_						=	output_chunk
						else:
									raise ValueError("Not supported"				)

						i += chunk_size

			lowerCAmelCase_						=	tensor_tree_map(lambda __lowerCAmelCase				: t.view(orig_batch_dims + t.shape[1:]				)    ,							__lowerCAmelCase				)

			return out





class 	_lowerCAmelCase					:




				def __init__(					self				,				_UpperCamelCase = 512				,				)				->      Optional[Any]:
							lowerCAmelCase_						=	max_chunk_size
							lowerCAmelCase_						=	None
							lowerCAmelCase_						=	None




				def      __a						(					self				,				_UpperCamelCase				,				_UpperCamelCase				,				_UpperCamelCase     )				->      int:
							logging.info("Tuning chunk size..."     )

							if min_chunk_size >= self.max_chunk_size:
										return min_chunk_size

							lowerCAmelCase_						=	[2**l for l in range(int(math.log(self.max_chunk_size				,				2     )     ) + 1     )]
							lowerCAmelCase_						=	[c for c in candidates if c > min_chunk_size]
							lowerCAmelCase_						=	[min_chunk_size] + candidates
							candidates[-1] += 4

							def test_chunk_size(_UpperCamelCase     ) -> bool:
										try:
													with torch.no_grad():
																fn(*_UpperCamelCase				,				chunk_size=_UpperCamelCase     )
													return True
										except RuntimeError:
													return False

							lowerCAmelCase_						=	0
							lowerCAmelCase_						=	len(_UpperCamelCase     ) - 1
							while i > min_viable_chunk_size_index:
										lowerCAmelCase_						=	test_chunk_size(candidates[i]     )
										if not viable:
													lowerCAmelCase_						=	(min_viable_chunk_size_index + i) // 2
										else:
													lowerCAmelCase_						=	i
													lowerCAmelCase_						=	(i + len(_UpperCamelCase     ) - 1) // 2

							return candidates[min_viable_chunk_size_index]




				def      __a						(					self				,				_UpperCamelCase				,				_UpperCamelCase     )				->      bool:
							lowerCAmelCase_						=	True
							for aa, aa in zip(_UpperCamelCase				,				_UpperCamelCase     ):
										assert type(_UpperCamelCase     ) == type(_UpperCamelCase     )
										if isinstance(_UpperCamelCase				,				(list, tuple)     ):
													consistent &= self._compare_arg_caches(_UpperCamelCase				,				_UpperCamelCase     )
										elif isinstance(_UpperCamelCase				,				_UpperCamelCase     ):
													lowerCAmelCase_						=	[v for _, v in sorted(aa.items()				,				key=lambda _UpperCamelCase     : x[0]     )]
													lowerCAmelCase_						=	[v for _, v in sorted(aa.items()				,				key=lambda _UpperCamelCase     : x[0]     )]
													consistent &= self._compare_arg_caches(_UpperCamelCase				,				_UpperCamelCase     )
										else:
													consistent &= aa == aa

							return consistent




				def      __a						(					self				,				_UpperCamelCase				,				_UpperCamelCase				,				_UpperCamelCase				,				)				->      int:
							lowerCAmelCase_						=	True
							lowerCAmelCase_						=	tree_map(lambda _UpperCamelCase     : a.shape if isinstance(_UpperCamelCase				,				torch.Tensor     ) else a				,				_UpperCamelCase				,				_UpperCamelCase     )
							if self.cached_arg_data is not None:
										# If args have changed shape/value, we need to re-tune
										assert len(self.cached_arg_data     ) == len(_UpperCamelCase     )
										lowerCAmelCase_						=	self._compare_arg_caches(self.cached_arg_data				,				_UpperCamelCase     )
							else:
										# Otherwise, we can reuse the precomputed value
										lowerCAmelCase_						=	False

							if not consistent:
										lowerCAmelCase_						=	self._determine_favorable_chunk_size(
										    _UpperCamelCase				,				_UpperCamelCase				,				_UpperCamelCase				,				)
										lowerCAmelCase_						=	arg_data

							assert self.cached_chunk_size is not None

							return self.cached_chunk_size





from typing import TYPE_CHECKING

from ...utils import (
    OptionalDependencyNotAvailable,
    _LazyModule,
    is_sentencepiece_available,
    is_speech_available,
    is_tf_available,
    is_torch_available,
)


_A   =     {
    "configuration_speech_to_text": ["SPEECH_TO_TEXT_PRETRAINED_CONFIG_ARCHIVE_MAP", "Speech2TextConfig"],
    "processing_speech_to_text": ["Speech2TextProcessor"],
}

try:
			if not is_sentencepiece_available():
						raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
			pass
else:
			_A   =     ["Speech2TextTokenizer"]

try:
			if not is_speech_available():
						raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
			pass
else:
			_A   =     ["Speech2TextFeatureExtractor"]

try:
			if not is_tf_available():
						raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
			pass
else:
			_A   =     [
			    "TF_SPEECH_TO_TEXT_PRETRAINED_MODEL_ARCHIVE_LIST",
			    "TFSpeech2TextForConditionalGeneration",
			    "TFSpeech2TextModel",
			    "TFSpeech2TextPreTrainedModel",
			]

try:
			if not is_torch_available():
						raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
			pass
else:
			_A   =     [
			    "SPEECH_TO_TEXT_PRETRAINED_MODEL_ARCHIVE_LIST",
			    "Speech2TextForConditionalGeneration",
			    "Speech2TextModel",
			    "Speech2TextPreTrainedModel",
			]


if TYPE_CHECKING:
			from .configuration_speech_to_text import SPEECH_TO_TEXT_PRETRAINED_CONFIG_ARCHIVE_MAP, SpeechaTextConfig
			from .processing_speech_to_text import SpeechaTextProcessor

			try:
						if not is_sentencepiece_available():
									raise OptionalDependencyNotAvailable()
			except OptionalDependencyNotAvailable:
						pass
			else:
						from .tokenization_speech_to_text import SpeechaTextTokenizer

			try:
						if not is_speech_available():
									raise OptionalDependencyNotAvailable()
			except OptionalDependencyNotAvailable:
						pass
			else:
						from .feature_extraction_speech_to_text import SpeechaTextFeatureExtractor

			try:
						if not is_tf_available():
									raise OptionalDependencyNotAvailable()
			except OptionalDependencyNotAvailable:
						pass
			else:
						from .modeling_tf_speech_to_text import (
						    TF_SPEECH_TO_TEXT_PRETRAINED_MODEL_ARCHIVE_LIST,
						    TFSpeechaTextForConditionalGeneration,
						    TFSpeechaTextModel,
						    TFSpeechaTextPreTrainedModel,
						)

			try:
						if not is_torch_available():
									raise OptionalDependencyNotAvailable()
			except OptionalDependencyNotAvailable:
						pass
			else:
						from .modeling_speech_to_text import (
						    SPEECH_TO_TEXT_PRETRAINED_MODEL_ARCHIVE_LIST,
						    SpeechaTextForConditionalGeneration,
						    SpeechaTextModel,
						    SpeechaTextPreTrainedModel,
						)

else:
			import sys

			_A   =     _LazyModule(__name__, globals()["__file__"], _import_structure, module_spec=__spec__)



