
    ɯwgi                        d dl mZ d dlZd dlmZmZmZmZmZm	Z	 d dl
Z
d dlmZ ddlmZmZmZmZmZ dgZej*                  Z ej,                  d      	 	 	 	 	 	 	 	 dd	       Z	 	 	 	 	 	 	 	 dd
Zy)    )annotationsN)CallableDictListSequenceTupleUnion)dim   )	_ellipsisAnonymousAxiscomma_separateparse_patternvalidate_rearrange_expressions	rearrange   c                l   t        ||      \  }}t        |||       t        d |j                  D              }|j                  rO| t        |j                        dz
  z
  }t        |j                        dz
  }||z   x}| kD  rUt        d| d|  d      d}t        |j                        }t        |j                        x}| k7  rt        d| d|  d      ||z   |z   }	|	dk(  rd S t        d	 t        |	      D              i g }
d|j                  D ]  }t        |t              rf|D ]"  }t        |t              sJ    f|<   dz  $ |r=t        d
      }   f|<   |
j                  |       |j                  |       dz  y|t        k(  r-t        }t        fdt        |      D              |<   |z  t        d|        	 	 	 	 dfd} ||j                        } ||j                        }t        fd|
D              }t        fd|j!                         D              }d}d| dt#               d|	 d|rdj%                  d |D              ndz   dt#        |       dt#        |       dz   |rdt#        |g       dndz   }t'        |       t)               |   S )az  Translate an `einops`-style pattern into a callable that performs the rearrange using first-class dimensions.

    Since the an equivalent result is computed for tensors with the same number of dimensions, with the same pattern and
    specified axes lengths, this function can be memoized.

    Args:
        tensor_ndim (int): the number of dimensions in the tensor to rearrange
        pattern (str): the `einops`-style rearrangement pattern
        axes_lengths (int): any additional length specifications for dimensions

    Returns:
        Callable[[torch.Tensor], torch.Tensor]: a callable that performs the rearrangement
    c              3  "   K   | ]  }|  	 y wN ).0r
   s     _/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/functorch/einops/rearrange.py	<genexpr>z-_create_rearrange_callable.<locals>.<genexpr>+   s     :##g:s   r   z!Number of dimensions in pattern (zH) must be less than or equal to the number of dimensions in the tensor ()r   z;) must be equal to the number of dimensions in the tensor (c                    | S r   r   )tensors    r   <lambda>z,_create_rearrange_callable.<locals>.<lambda>B   s    f     c              3  &   K   | ]	  }d |   yw)dNr   )r   is     r   r   z-_create_rearrange_callable.<locals>.<genexpr>D   s     -M!!g-Ms   1c              3  .   K   | ]  }|z        y wr   r   )r   jdims_ifirst_class_dimss     r   r   z-_create_rearrange_callable.<locals>.<genexpr>Z   s       312 !,3   Unexpected dimension: c                    g }| D ]e  }t        |t              r$|j                  t        fd|D                     7|t        k(  r|j                  t                  Yt        d|        |S )z|Convert a `ParsedExpression.composition` into a `Tensor.__getitem__` index of strings representing first
        class dims.c              3  6   K   | ]  }|   D ]  }|   y wr   r   )r   
identifierr
   identifier_dim_maps      r   r   zJ_create_rearrange_callable.<locals>.composition_to_dims.<locals>.<genexpr>j   s3      &#5j#A   s   r(   )
isinstancelistappendtupler   extend
ValueError)compositiondim_composition	dimensionr,   s      r   composition_to_dimsz7_create_rearrange_callable.<locals>.composition_to_dimsa   s    
 >@$ 	GI)T*&& *3  i'&&'9)'DE #9)!EFF	G r   c              3  .   K   | ]  }|   d      ywr   Nr   )r   axisr,   s     r   r   z-_create_rearrange_callable.<locals>.<genexpr>x   s     Hd(.q1Hr'   c              3  8   K   | ]  \  }}|   d    |f  ywr8   r   )r   r9   lengthr,   s      r   r   z-_create_rearrange_callable.<locals>.<genexpr>y   s*      2>$	D	!!	$f-s   do_rearrangezdef z(tensor):
    z = dims(z)
 c              3  4   K   | ]  \  }}d | d| d  yw)z    z.size = 
Nr   )r   r
   r;   s      r   r   z-_create_rearrange_callable.<locals>.<genexpr>   s(      3@C$se8F82.s   z    tensor = tensor[z].order(z    return tensor.sum(z, keepdim=False)
z    return tensor
)r3   z5Sequence[Union[List[Union[str, AnonymousAxis]], str]]returnz!List[Union[str, Tuple[str, ...]]])r   r   sumr3   has_ellipsislenidentifiersr2   r0   ranger-   r.   strr   r/   r   itemsr   joinexeclocals)tensor_ndimpatternaxes_lengthsleftrightn_anon_dimsn_ellipsis_dimsn_named_dimspattern_ndimn_dims	anon_axesr5   r+   	anon_axisr6   	left_dims
right_dims	anon_dimsspecified_lengthscustom_rearrange_callable_namecustom_rearrange_callable_coder%   r&   r,   s                        @@@r   _create_rearrange_callabler]      s`   "  6KD%"4=:)9)9::K%T-=-=)>)BC4++,q0',66L+E3L> B--8M< 
 4++, 0 011LkA3L> B*m1.  O+k9F{$$(--MuV}-M(MKM%'I F%% C	i&' 
!*c2222B62J1L":.!	
 )#.	1A&1I0K"9-  +  +!)#"J-2 36;O6L3 .z* o%F5i[ABB+C.J	** $D$4$45I$U%6%67JHiHHI BNBTBTBV  &4" 12 3!"234HVHCI ! GG DU  
	
 !	!: ;8NS]D^C__b
c	d  %^YK%@$AAST&	
 #( 		'(8233r   c                    t        | t        j                        st        j                  |       } t	        | j
                  |fi |} ||       S )a  A native implementation of `einops.rearrange`, a reader-friendly smart element reordering for multidimensional
    tensors. This operation includes functionality of transpose (axes permutation), reshape (view), squeeze, unsqueeze,
    stack, concatenate and other operations.

    See: https://einops.rocks/api/rearrange/

    Args:
        tensor (Tensor or sequence of Tensor): the tensor(s) to rearrange
        pattern (str): the rearrangement pattern
        axes_lengths (int): any additional length specifications for dimensions

    Returns:
        Tensor: the rearranged tensor

    Examples:
        >>> # suppose we have a set of 32 images in "h w c" format (height-width-channel)
        >>> images = torch.randn((32, 30, 40, 3))

        >>> # stack along first (batch) axis, output is a single array
        >>> rearrange(images, 'b h w c -> b h w c').shape
        torch.Size([32, 30, 40, 3])

        >>> # concatenate images along height (vertical axis), 960 = 32 * 30
        >>> rearrange(images, 'b h w c -> (b h) w c').shape
        torch.Size([960, 40, 3])

        >>> # concatenated images along horizontal axis, 1280 = 32 * 40
        >>> rearrange(images, 'b h w c -> h (b w) c').shape
        torch.Size([30, 1280, 3])

        >>> # reordered axes to "b c h w" format for deep learning
        >>> rearrange(images, 'b h w c -> b c h w').shape
        torch.Size([32, 3, 30, 40])

        >>> # flattened each image into a vector, 3600 = 30 * 40 * 3
        >>> rearrange(images, 'b h w c -> b (c h w)').shape
        torch.Size([32, 3600])

        >>> # split each image into 4 smaller (top-left, top-right, bottom-left, bottom-right), 128 = 32 * 2 * 2
        >>> rearrange(images, 'b (h1 h) (w1 w) c -> (b h1 w1) h w c', h1=2, w1=2).shape
        torch.Size([128, 15, 20, 3])

        >>> # space-to-depth operation
        >>> rearrange(images, 'b (h h1) (w w1) c -> b h w (c h1 w1)', h1=2, w1=2).shape
        torch.Size([32, 15, 20, 12])
    )r-   torchTensorstackr]   ndim)r   rL   rM   rearrange_callables       r   r   r      sJ    f fell+V$3W , f%%r   )rK   intrL   rF   rM   rd   r@   z&Callable[[torch.Tensor], torch.Tensor])r   zAUnion[torch.Tensor, List[torch.Tensor], Tuple[torch.Tensor, ...]]rL   rF   rM   rd   r@   ztorch.Tensor)
__future__r   	functoolstypingr   r   r   r   r   r	   r_   functorch._Cr
   _C_parsingr   r   r   r   r   __all__dims	lru_cacher]   r   r   r   r   <module>rn      s    "  ? ?  "  -	ww S{4{4"{447{4+{4 {4|:&M:&:& :& 	:&r   