"""simple docstring"""


import inspect
from typing import Callable, List, Optional, Set, Tuple, Union

import torch
from packaging import version
from safetensors.torch import storage_ptr, storage_size
from torch import nn

from .utils import logging


__UpperCamelCase										=     [nn.LayerNorm]

__UpperCamelCase										=     logging.get_logger(__name__)

__UpperCamelCase										=     version.parse(version.parse(torch.__version__).base_version)

__UpperCamelCase										=     parsed_torch_version_base >= version.parse('''2.0''')
__UpperCamelCase										=     parsed_torch_version_base >= version.parse('''1.12''')
__UpperCamelCase										=     parsed_torch_version_base >= version.parse('''1.11''')
__UpperCamelCase										=     parsed_torch_version_base < version.parse('''1.11''')







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase		,   self   )							-> List[str]:
     from torch import _softmax_backward_data

     if is_torch_less_than_1_11:
          return _softmax_backward_data(UpperCAmelCase		,   UpperCAmelCase		,   parent.dim		,   self   )
     else:
          return _softmax_backward_data(UpperCAmelCase		,   UpperCAmelCase		,   parent.dim		,   self.dtype   )







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase = 0   )							-> nn.Linear:
     snake_case_   			=   index.to(layer.weight.device   )
     snake_case_   			=   layer.weight.index_select(UpperCAmelCase		,   UpperCAmelCase   ).clone().detach()
     if layer.bias is not None:
          if dim == 1:
               snake_case_   			=   layer.bias.clone().detach()
          else:
               snake_case_   			=   layer.bias[index].clone().detach()
     snake_case_   			=   list(layer.weight.size()   )
     snake_case_   			=   len(UpperCAmelCase   )
     snake_case_   			=   nn.Linear(new_size[1]		,   new_size[0]		,   bias=layer.bias is not None   ).to(layer.weight.device   )
     snake_case_   			=   False
     new_layer.weight.copy_(W.contiguous()   )
     snake_case_   			=   True
     if layer.bias is not None:
          snake_case_   			=   False
          new_layer.bias.copy_(b.contiguous()   )
          snake_case_   			=   True
     return new_layer




class 					UpperCamelCase   (							nn.Module  ):







       def __init__(					self,				lowerCAmelCase__,				lowerCAmelCase__) -> Any:
            super().__init__()
            snake_case_   			=   nf
            snake_case_   			=   nn.Parameter(torch.empty(lowerCAmelCase__,				lowerCAmelCase__))
            snake_case_   			=   nn.Parameter(torch.zeros(lowerCAmelCase__))
            nn.init.normal_(self.weight,				std=0.02)







       def 						a_		(					self,				lowerCAmelCase__) -> Optional[int]:
            snake_case_   			=   x.size()[:-1] + (self.nf,)
            snake_case_   			=   torch.addmm(self.bias,				x.view(-1,				x.size(-1)),				self.weight)
            snake_case_   			=   x.view(lowerCAmelCase__)
            return x







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase = 1   )							-> ConvaD:
     snake_case_   			=   index.to(layer.weight.device   )
     snake_case_   			=   layer.weight.index_select(UpperCAmelCase		,   UpperCAmelCase   ).clone().detach()
     if dim == 0:
          snake_case_   			=   layer.bias.clone().detach()
     else:
          snake_case_   			=   layer.bias[index].clone().detach()
     snake_case_   			=   list(layer.weight.size()   )
     snake_case_   			=   len(UpperCAmelCase   )
     snake_case_   			=   ConvaD(new_size[1]		,   new_size[0]   ).to(layer.weight.device   )
     snake_case_   			=   False
     new_layer.weight.copy_(W.contiguous()   )
     snake_case_   			=   True
     snake_case_   			=   False
     new_layer.bias.copy_(b.contiguous()   )
     snake_case_   			=   True
     return new_layer







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase = None   )							-> Union[nn.Linear, ConvaD]:
     if isinstance(UpperCAmelCase		,   nn.Linear   ):
          return prune_linear_layer(UpperCAmelCase		,   UpperCAmelCase		,   dim=0 if dim is None else dim   )
     elif isinstance(UpperCAmelCase		,   UpperCAmelCase   ):
          return prune_convad_layer(UpperCAmelCase		,   UpperCAmelCase		,   dim=1 if dim is None else dim   )
     else:
          raise ValueError(f'Can\'t prune layer of class {layer.__class__}'   )







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase		,   *UpperCAmelCase   )							-> torch.Tensor:
     assert len(UpperCAmelCase   ) > 0, f'{input_tensors} has to be a tuple/list of tensors'

     # inspect.signature exist since python 3.5 and is a python method -> no problem with backward compatibility
     snake_case_   			=   len(inspect.signature(UpperCAmelCase   ).parameters   )
     if num_args_in_forward_chunk_fn != len(UpperCAmelCase   ):
          raise ValueError(
              f'forward_chunk_fn expects {num_args_in_forward_chunk_fn} arguments, but only {len(UpperCAmelCase   )} input '
              'tensors are given'   )

     if chunk_size > 0:
          snake_case_   			=   input_tensors[0].shape[chunk_dim]
          for input_tensor in input_tensors:
               if input_tensor.shape[chunk_dim] != tensor_shape:
                    raise ValueError(
                        f'All input tenors have to be of the same shape: {tensor_shape}, '
                        f'found shape {input_tensor.shape[chunk_dim]}'   )

          if input_tensors[0].shape[chunk_dim] % chunk_size != 0:
               raise ValueError(
                   f'The dimension to be chunked {input_tensors[0].shape[chunk_dim]} has to be a multiple of the chunk '
                   f'size {chunk_size}'   )

          snake_case_   			=   input_tensors[0].shape[chunk_dim] // chunk_size

          # chunk input tensor into tuples
          snake_case_   			=   tuple(input_tensor.chunk(UpperCAmelCase		,   dim=UpperCAmelCase   ) for input_tensor in input_tensors   )
          # apply forward fn to every tuple
          snake_case_   			=   tuple(forward_fn(*UpperCAmelCase   ) for input_tensors_chunk in zip(*UpperCAmelCase   )   )
          # concatenate output at same dimension
          return torch.cat(UpperCAmelCase		,   dim=UpperCAmelCase   )

     return forward_fn(*UpperCAmelCase   )







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase		,   UpperCAmelCase   )							-> Tuple[Set[int], torch.LongTensor]:
     snake_case_   			=   torch.ones(UpperCAmelCase		,   UpperCAmelCase   )
     snake_case_   			=   set(UpperCAmelCase   ) - already_pruned_heads  # Convert to set and remove already pruned heads
     for head in heads:
          # Compute how many pruned heads are before the head and move the index accordingly
          snake_case_   			=   head - sum(1 if h < head else 0 for h in already_pruned_heads   )
          snake_case_   			=   0
     snake_case_   			=   mask.view(-1   ).contiguous().eq(1   )
     snake_case_   			=   torch.arange(len(UpperCAmelCase   )   )[mask].long()
     return heads, index







def    UpperCAmelCase       (						*UpperCAmelCase		,   UpperCAmelCase = None   )							-> Tuple[torch.Tensor, ...]:
     return torch.meshgrid(*UpperCAmelCase		,   indexing=UpperCAmelCase   )







def    UpperCAmelCase       (						UpperCAmelCase   )							-> Tuple[torch.device, int, int]:
     return tensor.device, storage_ptr(UpperCAmelCase   ), storage_size(UpperCAmelCase   )


"""simple docstring"""


from math import factorial







def    UpperCAmelCase       (						UpperCAmelCase		,   UpperCAmelCase   )							-> List[str]:
     return factorial(UpperCAmelCase   ) / (factorial(UpperCAmelCase   ) * factorial(n - r   ))







def    UpperCAmelCase       (						)							-> Optional[Any]:
     snake_case_   			=   0

     for i in range(1		,   101   ):
          for j in range(1		,   i + 1   ):
               if combinations(UpperCAmelCase		,   UpperCAmelCase   ) > 1e6:
                    total += 1
     return total


if __name__ == "__main__":
    print(solution())

