
    ɯwg/                        U d Z ddlmZ ddlZddlZddlmZmZmZm	Z	m
Z
mZmZ dZded<    G d d	      Z G d
 d      Z	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZddZy)a  Adapted from https://github.com/arogozhnikov/einops/blob/36c7bb16e57d6e57f8f3050f9e07abdf3f00469f/einops/parsing.py.

MIT License

Copyright (c) 2018 Alex Rogozhnikov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
    )annotationsN)
CollectionListMappingOptionalSetTupleUnionu   …str	_ellipsisc                       e Zd ZdZddZddZy)AnonymousAxiszUsed by `ParsedExpression` to represent an axis with a size (> 1), but no associated identifier.

    Note: Different instances of this class are not equal to each other, even if they have the same value.
    c                r    t        |      | _        | j                  dk  rt        d| j                         y )N   z0Anonymous axis should have positive length, not )intvalue
ValueError)selfr   s     ^/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/functorch/einops/_parsing.py__init__zAnonymousAxis.__init__)   s8    Z
::>B4::,O      c                     | j                    dS )Nz-axis)r   )r   s    r   __repr__zAnonymousAxis.__repr__0   s    **U##r   N)r   r   returnNone)r   r   )__name__
__module____qualname____doc__r   r    r   r   r   r   #   s    
$r   r   c                  `    e Zd ZdZddd	 	 	 	 	 	 	 ddZe	 d		 	 	 	 	 d
d       Zedd       Zy)ParsedExpressionz`Structure containing information about one side of an `einops`-style pattern (e.g. 'b c (h w)').F)allow_underscoreallow_duplicatesc                   d _         d _        t                _        d _        g  _        d|v rid|vrt        d      t        j                  |d      dk7  st        j                  |d      dk7  rt        d      |j                  dt              }d	 _         dd fd
}d}|D ]  }|dv rR| ||       d}|dk(  rt        d      g (|dk(  s.t        d       j
                  j                         dYt        j                  |      s
|dt        fv r||}}||z  }t        d| d       t        d| d      |	 ||       yy)a\  Parse the expression and store relevant metadata.

        Args:
            expression (str): the `einops`-pattern to parse
            allow_underscore (bool): whether to allow axis identifier names to begin with an underscore
            allow_duplicates (bool): whether to allow an identifier to appear more than once in the expression
        FN.z...z6Expression may contain dots only inside ellipsis (...)r      zUExpression may contain dots only inside ellipsis (...); only one ellipsis for tensor Tc                   | j                   v rr| dk(  sst        d|  d      | t        k(  rej                   j                  t               'j                  j                  t               d_        y j                  t               d_        y t        j                  |       }|r.t        |       dk(  r j                  j                  g        y 	 y j                  |       \  }}|s|st        d|  d	|       |rt        |       n| }j                   j                  |       |rd_        j                  j                  |g       y j                  |       y )
N_z2Indexing expression contains duplicate dimension ''FTr   )r#   zInvalid axis identifier: 
)identifiersr   r   addcompositionappendhas_ellipsis_parenthesizedr   	isdecimalr   check_axis_name_return_reasonr   has_non_unitary_anonymous_axes)	x	is_numberis_axis_namereason	axis_namer$   r#   bracket_groupr   s	        r   add_axis_namez0ParsedExpression.__init__.<locals>.add_axis_nameZ   sj   D$$$(Q#X?O$LQCqQ  I~  $$Y/ ($$++I66;D3!((36:D3MM!,	Q1$,((//3  '+'I'I(8 (J ($f "\$'@2fX%NOO(1M!$q    $$Y/:>D7 ($$++YK8!((3r   z() (zDAxis composition is one-level (brackets inside brackets not allowed))zBrackets are not balancedr)   zUnknown character 'r*   z'Imbalanced parentheses in expression: ')r4   r   r   r   )has_ellipsisr0   setr,   r3   r.   r   r   countreplacer   r/   isalnum)r   
expressionr#   r$   r:   current_identifiercharr9   s   ` ``   @r   r   zParsedExpression.__init__7   s    #(:>';>549+NP*J& L  yyU+q0CIIj#4NRS4S k  $++E9=J $DCG%	4 %	4N " 	@Du}%1!"45%)"3;$0(b  %'MS[$,()DEE$$++M:$(MT"dsI.>&>%-)-&&$.& #6tfA!>??-	@0 $FzlRSTUU),- *r   c                   t         j                  |       sy| d   dk(  s| d   dk(  r	| dk(  r|ryyt        j                  |       rt	        j
                  d|  t               | dv rt	        j
                  d	t               y)
a  Check if the given axis name is valid, and a message explaining why if not.

        Valid axes names are python identifiers except keywords, and should not start or end with an underscore.

        Args:
            name (str): the axis name to check
            allow_underscore (bool): whether axis names are allowed to start with an underscore

        Returns:
            Tuple[bool, str]: whether the axis name is valid, a message explaining why if not
        )Fznot a valid python identifierr   r)   )T )Fz8axis name should should not start or end with underscorez7It is discouraged to use axes names that are keywords: )axiszQIt is discouraged to use 'axis' as an axis name and will raise an error in future)r   isidentifierkeyword	iskeywordwarningswarnRuntimeWarningFutureWarning)namer#   s     r   r2   z.ParsedExpression.check_axis_name_return_reason   s     %9!W^tBx3s{/T  &MdVT" xg! r   c                6    t         j                  |       \  }}|S )zCheck if the name is a valid axis name.

        Args:
            name (str): the axis name to check

        Returns:
            bool: whether the axis name is valid
        )r"   r2   )rP   is_validr)   s      r   check_axis_namez ParsedExpression.check_axis_name   s     'DDTJ!r   N)rB   r   r#   boolr$   rT   r   r   )F)rP   r   r#   rT   r   zTuple[bool, str])rP   r   r   rT   )r   r   r   r   r   staticmethodr2   rS   r    r   r   r"   r"   4   s    j "'!&f.f. 	f.
 f. 
f.P ,1%)	 B 
 
r   r"   c                `   	 | j                  d      \  }}t        |v rt        dt         d      t        |      }t        |      }|j                  s|j                  rt        d|        |j                  r|j
                  rt        d|        ||fS # t        $ r t        d      dw xY w)a  Parse an `einops`-style pattern into a left-hand side and right-hand side `ParsedExpression` object.

    Args:
        pattern (str): the `einops`-style rearrangement pattern
        axes_lengths (Mapping[str, int]): any additional length specifications for dimensions

    Returns:
       Tuple[ParsedExpression, ParsedExpression]: a tuple containing the left-hand side and right-hand side expressions
    z->z,Pattern must contain a single '->' separatorNr*   z#' is not an allowed axis identifierz=Ellipsis found in right side, but not left side of a pattern z9Ellipsis is parenthesis in the left side is not allowed: )splitr   r   r"   r=   r0   )patternaxes_lengthsleft_str	right_strleftrights         r   parse_patternr^      s    S%mmD1) L 1YK'JKLLH%DY'E!3!3KG9U
 	
 T<<GyQ
 	
 ;%  SGHdRSs   B B-c                   |j                         D ]#  }t        |      x}t        ust        d|        | j                  s|j                  rt        d      t        j                  | j                  |j                        }t        |      dkD  rt        d|       |j                         | j                  z
  }t        |      dkD  rt        d|       y)a4  Perform expression validations that are specific to the `rearrange` operation.

    Args:
        left (ParsedExpression): left-hand side expression
        right (ParsedExpression): right-hand side expression
        axes_lengths (Mapping[str, int]): any additional length specifications for dimensions
    z.rearrange axis lengths must be integers, got: z.rearrange only supports unnamed axes of size 1r   zJIdentifiers only on one side of rearrange expression (should be on both): z/Identifiers not found in rearrange expression: N)valuestyper   	TypeErrorr3   r   r>   symmetric_differencer,   lenkeys)r\   r]   rY   lengthlength_type
differenceunmatched_axess          r   validate_rearrange_expressionsrj      s     %%' <'K3@N  **e.R.RIJJ))$*:*:E<M<MNJ
:XYcXde
 	
 "&&(4+;+;;N
>Q=n=MN
 	
 r   c                2    dj                  d | D              S )aJ  Convert a collection of strings representing first class dims into a comma-separated string.

    Args:
        collection (Collection[Union[str, Collection[str]]]): the collection of strings to convert

    Returns:
        str: the comma-separated string

    Examples:
        >>> comma_separate(('d0',))
        'd0'

        >>> comma_separate(('d0', 'd1', 'd2', 'd3'))
        'd0, d1, d2, d3'

        >>> comma_separate([('d1', 'd4')])
        '(d1, d4)'

        >>> comma_separate([('d0',), (), ('d1',), ('d2',), ('d3', 'd4')])
        '(d0,), (), (d1,), (d2,), (d3, d4)'
    z, c              3     K   | ]7  }t        |t              r|n d t        |       t        |      dk(  rdnd d 9 yw)r;   r   ,rG   r<   N)
isinstancer   comma_separaterd   ).0items     r   	<genexpr>z!comma_separate.<locals>.<genexpr>*  sO        dC  	%&c$i1ns"&EQG	Hs   =?)join)
collections    r   ro   ro     s$    , 99  	  r   )rX   r   rY   Mapping[str, int]r   z)Tuple[ParsedExpression, ParsedExpression])r\   r"   r]   r"   rY   ru   r   r   )rt   z'Collection[Union[str, Collection[str]]]r   r   )r   
__future__r   rJ   rL   typingr   r   r   r   r   r	   r
   r   __annotations__r   r"   r^   rj   ro   r    r   r   <module>ry      s   0 #   I I I 	3 $ $"X Xv"" 1"."J


#3
CT
	
@r   