o
    Ei>                     @   s  d dl Z ddlmZ d dlmZ d dlZd dlmZm	Z	 d dl
mZ e jdd dd^d	d
Ze jddddZe jje jdd dddddede jdede	e jedf dedejde jfddZee_e jjddddede jde	e jedf dedejde jfddZdd Ze jjddddede jde	e jedf dedejde jfddZd d! Ze jjddddede jde	e jedf dedejde jfd"d#Zd$d% Ze jjddddede jde	e jedf dedejde jfd&d'Zd(d) Ze jjddddede jde	e jedf dedejde jfd*d+Z d,d- Z!e jjddddede jde	e jedf dedejde jfd.d/Z"d0d1 Z#e jjddddede jde	e jedf dedejde jfd2d3Z$d4d5 Z%e jjddddede jde	e jedf dedejde jfd6d7Z&d8d9 Z'e jjddddede jde	e jedf dedejde jfd:d;Z(d<d= Z)e jjddddede jde	e jedf dedejde jfd>d?Z*d@dA Z+e jjddddede jde	e jedf dedejde jfdBdCZ,dDdE Z-e jjddddede jde	e jedf dedejde jfdFdGZ.dHdI Z/e jjddddede jde	e jedf dedejde jfdJdKZ0dLdM Z1e jjddddede jde	e jedf dedejde jfdNdOZ2dPdQ Z3e jjddddede jde	e jedf dedejde jfdRdSZ4dTdU Z5e jjddddede jde	e jedf dedejde jfdVdWZ6dXdY Z7e jjddddede jde	e jedf dedejde jfdZd[Z8d\d] Z9dS )_    N   )util)partial)CallableUnionc                    s   d fdd	S )Nc                    s    | fdd|D ||S )Nc                       g | ]} |qS  r   .0xtr   P/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/einx/op/elementwise.py
<listcomp>       .<lambda>.<locals>.<lambda>.<locals>.<listcomp>r   )exprs_in
tensors_inexpr_outopbackendcr   r   r   <lambda>
   s    <lambda>.<locals>.<lambda>Nr   r   r   r   r   r   r   
   s    r   )tracec           	         s   t | |g D ]}| D ]}t|tjjjrtdqqtdd | D r(J tdd | D r5J dd  fddt	|| D } 
|}tj| ||g d	\}}t|d
kret|d
ksgJ |d |d fS )NzConcatenation not allowedc                 s   s,    | ]}|  D ]
}tjj|V  qqd S r   )alleinxexprstage3	is_marked)r
   rootr    r   r   r   	<genexpr>   s   * z%elementwise_stage3.<locals>.<genexpr>c                 s   s    | ]
}t jj|V  qd S r   )r   r    r!   r"   r
   r    r   r   r   r$      s    c                 S   s   | dkrdS | dkrdS | S )Naddbiasmultiplyscaler   )sr   r   r   get_name   s
   z$elementwise_stage3.<locals>.get_namec              
      s8   g | ]\}}t jj||j ttd qS ))nameinit)r   tracercall_factoryshaper   
_op_to_str)r
   tensorr    r   r+   r   r   r   r       s    z&elementwise_stage3.<locals>.<listcomp>r   r   r   )listr   
isinstancer   r    r!   Concatenation
ValueErroranyzipall_to_tensorvmap_with_axis_stage3len)	r   r   r   r   r   r#   r    tensors_out	exprs_outr   r3   r   elementwise_stage3	   s$   


r@   T)csec             	   O   s(  t jj| |\} }t jj| }t|d dkrHt|dkrHt jjt jj	t jj
|d d t jj|d d ggt|dd   }t|dkr|d }dd |D }t }t|D ]\}}	t|D ]\}
}||
krw||	sw nqh|||  q`t|dkrtd| dtt| }t jj|d t jj	|gg}t|d t|krtdt|d  d	t| t|d dkrtd
t|d  t jjdd t|d |D t j|d d g dd | D  |ddd t|d d  }|d d |d }}||fS )Nr   r      c                 S   s   g | ]}d d |  D qS )c                 S   s"   h | ]}t |tjjjr|jqS r   )r6   r   r    stage1	NamedAxisr,   r%   r   r   r   	<setcomp>M   s   " z#parse.<locals>.<listcomp>.<setcomp>)r   )r
   r#   r   r   r   r   L   s    zparse.<locals>.<listcomp>z9Could not implicitly determine output expression for op ''z	Expected z input tensors, but got z&Expected 1 output expression, but got c                 S   s   g | ]\}}t j||qS r   )r   r    Equation)r
   expr_intensor_shaper   r   r   r   e   s    c                 S   s4   g | ]\}}t jj|t|d tjf dddqS ).N)depth1depth2)r   r    rG   npasarraynewaxis)r
   kvr   r   r   r   n   s    "F)rA   
cse_concat)r   r   r   !_clean_description_and_parametersr    rC   parse_opr=   OpArgsdemark
get_markedr5   set	enumerateissubsetr&   r8   nextiter__deepcopy__solver:   rG   items)descriptionrA   tensor_shapes
parametersr   
input_argsin_axis_namesvalid_parentsiparentjchildr   exprsr   r   r   r   parse3   sn   " 
	rl   c                    s   d d fdd
S )Nr4   c                   s$    | gfdd|D R i |S )Nc                    r   r   r   r	   r   r   r   r   }   r   r   r   )ra   r   tensorskwargsr   r   r   r   |   s    r   r   r   r   r   r   r   |   r   )r   rA   ra   rm   r   r   rA   rc   returnc          	      O   sB   t | gdd |D R d|i|\}}t|||||d\}}|S )a~  Applies an element-by-element operation over the given tensors.

    It supports the following shorthand notation:

    * The output is determined implicitly if one of the input expressions contains the named axes
      of all other inputs and if this choice is unique.

      | Example: ``a b, a`` expands to ``a b, a -> a b``.
      | Example: ``b a, b, a`` expands to ``b a, b, a -> b a``.
      | Example: ``a b, b a`` raises an exception.
      | Example: ``a b, a b`` expands to ``a b, a b -> a b``.

    * Bracket notation can be used when passing two input tensors to indicate that the second
      input is a subexpression of the first.

      Example: ``a [b]`` expands to ``a b, b``.

    Args:
        description: Description string for the operation in einx notation.
        tensors: Input tensors or tensor factories matching the description string.
        op: Backend elemebt-by-element operation. Must accept the same number of tensors
            as specified in the description string and comply with numpy broadcasting rules.
            If ``op`` is a string, retrieves the attribute of ``backend`` with the same name.
        backend: Backend to use for all operations. If None, determines the backend from
            the input tensors. Defaults to None.
        cse: Whether to apply common subexpression elimination to the expressions. Defaults
            to True.
        graph: Whether to return the graph representation of the operation instead of
            computing the result. Defaults to False.
        **parameters: Additional parameters that specify values for single axes, e.g. ``a=4``.

    Returns:
        The result of the elementwise operation if ``graph=False``, otherwise the graph
        representation of the operation.

    Examples:
        Compute a sum of two vectors:

        >>> a, b = np.random.uniform(size=(10,)), np.random.uniform(size=(10,))
        >>> einx.elementwise("a, a -> a", a, b, op=np.add).shape
        (10,)

        Add a vector on all columns of a matrix:

        >>> a, b = np.random.uniform(size=(10, 10)), np.random.uniform(size=(10,))
        >>> einx.add("a b, a -> a b", a, b).shape
        (10, 10,)

        Subtract a vector from all rows of a matrix:

        >>> a, b = np.random.uniform(size=(10, 10)), np.random.uniform(size=(10,))
        >>> einx.subtract("a b, b -> a b", a, b).shape
        (10, 10,)

        Select from one of two choices according to a boolean mask:

        >>> x, mask = (
        ...     np.random.uniform(size=(10, 10)),
        ...     np.random.uniform(size=(10,)),
        ... )
        >>> einx.where("a, a b, -> a b", mask, x, 0).shape
        (10, 10,)

        Add a bias onto all channels of a tensor:

        >>> x, w = (
        ...     np.random.uniform(size=(4, 16, 16, 64)),
        ...     np.random.uniform(size=(64,)),
        ... )
        >>> einx.add("b... [c]", x, w).shape
        (4, 16, 16, 64)
    c                 S   s   g | ]}t j|qS r   )r   r.   	get_shape)r
   r2   r   r   r   r      s    zelementwise.<locals>.<listcomp>rA   )r   r   )rl   r@   )	ra   r   r   rA   rm   rc   r   r   r2   r   r   r   elementwisez   s   V
rq   c                O      t | g|R d||d|S )z<Specialization of :func:`einx.elementwise` with ``op="add"``r&   r   r   rA   rq   ra   r   rA   rm   rc   r   r   r   r&         	r&   c                  O      t | ddi|S )Nr   r&   r@   argsrn   r   r   r   
add_stage3      r{   c                O   rr   )zASpecialization of :func:`einx.elementwise` with ``op="subtract"``subtractrs   rt   ru   r   r   r   r}      rv   r}   c                  O   rw   )Nr   r}   rx   ry   r   r   r   subtract_stage3   r|   r~   c                O   rr   )zASpecialization of :func:`einx.elementwise` with ``op="multiply"``r(   rs   rt   ru   r   r   r   r(      rv   r(   c                  O   rw   )Nr   r(   rx   ry   r   r   r   multiply_stage3  r|   r   c                O   rr   )zDSpecialization of :func:`einx.elementwise` with ``op="true_divide"``true_dividers   rt   ru   r   r   r   r   
     	r   c                  O   rw   )Nr   r   rx   ry   r   r   r   true_divide_stage3  r|   r   c                O   rr   )zESpecialization of :func:`einx.elementwise` with ``op="floor_divide"``floor_dividers   rt   ru   r   r   r   r     r   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   floor_divide_stage3*  r|   r   c                O   rr   )z?Specialization of :func:`einx.elementwise` with ``op="divide"``dividers   rt   ru   r   r   r   r   .  rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   divide_stage3:  r|   r   c                O   rr   )zDSpecialization of :func:`einx.elementwise` with ``op="logical_and"``logical_andrs   rt   ru   r   r   r   r   >  r   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   logical_and_stage3L  r|   r   c                O   rr   )zCSpecialization of :func:`einx.elementwise` with ``op="logical_or"``
logical_orrs   rt   ru   r   r   r   r   P  r   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   logical_or_stage3^  r|   r   c                O   rr   )z>Specialization of :func:`einx.elementwise` with ``op="where"``wherers   rt   ru   r   r   r   r   b  rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   where_stage3n  r|   r   c                O   rr   )z=Specialization of :func:`einx.elementwise` with ``op="less"``lessrs   rt   ru   r   r   r   r   r  rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   less_stage3~  r|   r   c                O   rr   )zCSpecialization of :func:`einx.elementwise` with ``op="less_equal"``
less_equalrs   rt   ru   r   r   r   r     r   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   less_equal_stage3  r|   r   c                O   rr   )z@Specialization of :func:`einx.elementwise` with ``op="greater"``greaterrs   rt   ru   r   r   r   r     rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   greater_stage3  r|   r   c                O   rr   )zFSpecialization of :func:`einx.elementwise` with ``op="greater_equal"``greater_equalrs   rt   ru   r   r   r   r     r   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   greater_equal_stage3  r|   r   c                O   rr   )z>Specialization of :func:`einx.elementwise` with ``op="equal"``equalrs   rt   ru   r   r   r   r     rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   equal_stage3  r|   r   c                O   rr   )zBSpecialization of :func:`einx.elementwise` with ``op="not_equal"``	not_equalrs   rt   ru   r   r   r   r     r   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   not_equal_stage3  r|   r   c                O   rr   )z@Specialization of :func:`einx.elementwise` with ``op="maximum"``maximumrs   rt   ru   r   r   r   r     rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   maximum_stage3  r|   r   c                O   rr   )z@Specialization of :func:`einx.elementwise` with ``op="minimum"``minimumrs   rt   ru   r   r   r   r     rv   r   c                  O   rw   )Nr   r   rx   ry   r   r   r   minimum_stage3  r|   r   r   ):r    r   	functoolsr   numpyrL   typingr   r   numpy.typingnptjitr@   	lru_cacherl   traceback_utilfilterstrTensorBackendbool	ArrayLikerq   r&   r{   r}   r~   r(   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s   %F	W