o
    ij                     @   s  d dl m Z  d dlmZ d dlmZ ddlmZ ddlmZ ddl	Z	ddd	Z
e dd
dededeeB dB dejdeeedf B f
ddZde
d de_dd Zdd Ze ddddedededB deeB dB dejdefddZeddd e_e ddddedededB deeB dB dejdefd!d"Zed"d#d$e_e ddddedededB deeB dB dejdefd%d&Zed&d'd(e_e ddddedededB deeB dB dejdefd)d*Zed*d+d,e_e ddddedededB deeB dB dejdefd-d.Zed.d/d0e_e ddddedededB deeB dB dejdefd1d2Zed2d3d4e_e ddddedededB deeB dB dejdefd5d6Zed6d7d8e_e ddddedededB deeB dB dejdefd9d:Zed:d;d<e_e ddddedededB deeB dB dejdefd=d>Zed>d?d@e_e ddddedededB deeB dB dejdefdAdBZedBdCdDe_e ddddedededB deeB dB dejdefdEdFZedFdGdHe_e dd
dededeeB dB dejdef
dIdJZdKe
d dLe_dMdN Ze dd
dededeeB dB dejdef
dOdPZ edPdQdRdSe _e dd
dededeeB dB dejdef
dTdUZ!edUdVdWdSe!_e dd
dededeeB dB dejdef
dXdYZ"edYdZd[dSe"_e dd
dededeeB dB dejdef
d\d]Z#ed]d^d_dSe#_e dd
dededeeB dB dejdef
d`daZ$edadbd_dSe$_e dd
dededeeB dB dejdef
dcddZ%eddded_dSe%_e dd
dededeeB dB dejdef
dfdgZ&edgdhdidSe&_e dd
dededeeB dB dejdef
djdkZ'edkdldmdSe'_e dd
dednedoedpedeeB dB dejdefdqdrZ(edrdsdtdue(_e dd
dededeeB dB dejdef
dvdwZ)edwdxdydSe)_e dd
dededeeB dB dejdef
dzd{Z*ed{d|d}dSe*_e dd
dededeeB dB dejdef
d~dZ+eddddSe+_e dd
dededeeB dB dejdef
ddZ,eddddSe,_e dd
dededeeB dB dejdef
ddZ-eddddSe-_e dd
dededeeB dB dejdef
ddZ.eddddSe._e dd
dededeeB dB dejdef
ddZ/eddddSe/_e dd
dededeeB dB dejdef
ddZ0eddddSe0_e dd
dededeeB dB dejdef
ddZ1eddddSe1_e dd
dededeeB dB dejdef
ddZ2de
d de2_dd Z3e dd
dededeeB dB dejdef
ddZ4e3dddde4_e dd
dededeeB dB dejdef
ddZ5e3dddde5_e dd
dededeeB dB dejdef
ddZ6e3dddde6_e dd
dededeeB dB dejdef
ddZ7de
d de7_e dd
dededeeB dB dejdef
ddZ8de
d de8_e dd
dededeeB dB dejdef
ddZ9de
d de9_e dd
dededeeB dB dejdef
ddZ:de
d de:_e dd
dededeeB dB dejdef
ddZ;de
d de;_e dd
dededejdeeB dB dejdefddZ<de
dd de<_dd Z=e dd
dededeeB dB dejdef
ddĄZ>e=ddwe>_e dd
dededeeB dB dejdef
ddƄZ?e=dd{e?_ddȄ e@ D ZAdS )   )api)Tensor)Backend    N)Union c              	   C   s>   | rdnd}| r
dnd}d| rdnd d| d	| d
| d	S )Nr   syieszRArgs:
    description: Description string for the operation in einx notation.
    tensorz*tensorsz: Input tensorz or tensor factoraO   matching the description string.
    backend: Backend to use for all operations. If None, uses the :doc:`default backend </gettingstarted/backends>` for the given setting. Defaults to None.
    graph: Whether to return the compiled code representation of this operation instead of
        computing the result. Defaults to False.
    z
    **parameters: Additional parameters that specify dimension sizes, e.g. ``a=4``.

Returns:
    The result of the operation if ``graph=False``, otherwise the compiled code
    representation of the operation.
 )singlekwargsr   r
   r   r   J/home/ubuntu/.local/lib/python3.10/site-packages/einx/_src/frontend/ops.py_args_return	   s   
r   )backenddescriptiontensorsr   
parametersreturn.c                O      |j | g|R i |S N)idr   r   r   r   r   r   r   r         r   a  Compute the identity-map of values in the given tensor.

In the simplest case, the elementary operation has the signature ``[] -> []`` and returns the input as-is. If there are more than one
input/ output or concatenated inputs/ outputs, the ordered tuple of inputs is returned as-is.

F
c                 C   s2   | d| d|  d|  d|  d|  dt d dS )	NzB.

The elementary operation has the signature ``[...] -> []`` and z.

If there is no output expression, it is determined implicitly by removing all bracketed expressions from the input expression.
For example, the following operations compute the same output:

..  code-block:: python

    y = einx.z("a [b]", x)
    y = einx.a  ("a [b] -> a", x)

If there are no brackets in the expression, brackets are implicitly placed around all axes that do not appear in the output expression.
For example, the following operations compute the same output:

..  code-block:: python

    y = einx.z("a b -> a", x)
    y = einx.z("a [b] -> a", x)

Tr   r   )opline1outputr   r   r   _make_reduction_doc)   s   	
r    c                 C   s    | d urt jdtdd d S d S )NzThe 'keepdims' argument in einx reduction operations is deprecated and will be removed in a future version. Please use a flattened axis instead.
For example, instead of

    einx.{op}("a [b]", x, keepdims=True)

write

    einx.{op}("a ([b])", x).
   )
stacklevel)warningswarnDeprecationWarning)keepdimsr   r   r   _keepdims_warningB   s   
r'   )r&   r   r   r&   c                K       t | |j| |fd|i|S Nr&   )r'   sumr   r   r&   r   r   r   r   r   r*   M      r*   z-Compute the sum of values in the given tensorz2computes the sum of all values of the input tensorc                K   r(   r)   )r'   meanr+   r   r   r   r-   V   r,   r-   z.Compute the mean of values in the given tensorz3computes the mean of all values of the input tensorc                K   r(   r)   )r'   varr+   r   r   r   r.   _   r,   r.   z2Compute the variance of values in the given tensorz7computes the variance of all values of the input tensorc                K   r(   r)   )r'   stdr+   r   r   r   r/   h   r,   r/   z<Compute the standard deviation of values in the given tensorzAcomputes the standard deviation of all values of the input tensorc                K   r(   r)   )r'   prodr+   r   r   r   r0   s   r,   r0   z1Compute the product of values in the given tensorz6computes the product of all values of the input tensorc                K   r(   r)   )r'   count_nonzeror+   r   r   r   r1   |   s   r1   z*Counts non-zero values in the given tensorz<counts the number of all non-zero values of the input tensorc                K   r(   r)   )r'   anyr+   r   r   r   r2      r,   r2   zBCompute the logical disjunction (OR) of values in the given tensorzGcomputes the logical disjunction (OR) of all values of the input tensorc                K   r(   r)   )r'   allr+   r   r   r   r3      r,   r3   zCCompute the logical conjunction (AND) of values in the given tensorzHcomputes the logical conjunction (AND) of all values of the input tensorc                K   r(   r)   )r'   maxr+   r   r   r   r4      r,   r4   z1Compute the maximum of values in the given tensorz6computes the maximum of all values of the input tensorc                K   r(   r)   )r'   minr+   r   r   r   r5      r,   r5   z1Compute the minimum of values in the given tensorz6computes the minimum of all values of the input tensorc                K   r(   r)   )r'   	logsumexpr+   r   r   r   r6      r,   r6   z5Compute the log-sum-exp of values in the given tensorz:computes the log-sum-exp of all values of the input tensorc                O   r   r   )dotr   r   r   r   r7      r   r7   a  Compute the dot-product of values in the given tensors.

In the simplest case, the elementary operation has the signature ``[a], [a] -> []`` and computes the dot-product over the two input vectors.
If more than two tensors or more than two axes are passed to the elementary operation, the dot-product is applied sequentially in an unspecified
order to all pairs of dimensions with the same name.

If there are no brackets in the expression, brackets are placed implicitly around all axes that do not appear in the output expression. For example,
the following operations compute the same output:

..  code-block:: python

    z = einx.dot("a b, b c -> a c", x, y)
    z = einx.dot("a [b], [b] c -> a c", x, y)


    c                 C   s   |dkrd|  d|  d|  d|  d|  d}n|dkr.d	|  d
|  d|  d|  d|  d}nt d| d| d| dtd dS )N   z
    z = einx.z("a b, a", x, y)
    z = einx.z&("a b, a -> a b", x, y)

    z = einx.z ("a b, a b", x, y)
    z = einx.z(("a b, a b -> a b", x, y)

    z = einx.zP("a b, b a", x, y)
    # raises an exception due to ambiguous output expression
   z
    w = einx.z$("a b, a, b", x, y, z)
    w = einx.z,("a b, a, b -> a b", x, y, z)

    w = einx.z(("a b, a b, a b", x, y, z)
    w = einx.z0("a b, a b, a b -> a b", x, y, z)

    w = einx.zX("a b, b a, a b", x, y, z)
    # raises an exception due to ambiguous output expression
zInvalid nargsz.

The elementary operation a   .

If there is no output expression, one of the input expressions is implicitly used as output expression if it contains the axis names of all other
inputs and if this choice is unique. For example, the following pairs of operations compute the same output:

..  code-block:: python

    z

Fr   )
ValueErrorr   )r   r   r   nargscoder   r   r   _make_elwise_doc   s@   


	r>   c                O   r   r   )addr   r   r   r   r?      r   r?   z3Compute the sum of values of multiple given tensorsz:takes any number of scalars as input and returns their sumr9   c                O   r   r   )subtractr   r   r   r   r@     r   r@   z;Computes the difference between values of two given tensorszBtakes two scalars as input and subtracts the second from the firstc                O   r   r   )multiplyr   r   r   r   rA     r   rA   z7Compute the product of values of multiple given tensorsz>takes any number of scalars as input and returns their productc                O   r   r   )true_divider   r   r   r   rB     r   rB   z>Computes the true division between values of two given tensorsz>takes two scalars as input and divides the first by the secondc                O   r   r   )floor_divider   r   r   r   rC   "  r   rC   z?Computes the floor division between values of two given tensorsc                O   r   r   )divider   r   r   r   rD   ,  r   rD   z9Computes the division between values of two given tensorsc                O   r   r   )logical_andr   r   r   r   rE   6  r   rE   zICompute the logical conjunction (AND) of values of multiple given tensorszPtakes any number of scalars as input and returns their logical conjunction (AND)c                O   r   r   )
logical_orr   r   r   r   rF   C  r   rF   zHCompute the logical disjunction (OR) of values of multiple given tensorszOtakes any number of scalars as input and returns their logical disjunction (OR)maskxr	   c                K   s   |j | |||fi |S r   )where)r   rG   rH   r	   r   r   r   r   r   rI   P  r   rI   zDConditionally select values from two tensors based on a boolean maskzrtakes three scalars as input (mask, true_val, false_val) and returns true_val if mask is true, otherwise false_valr:   c                O   r   r   )maximumr   r   r   r   rJ   ]  r   rJ   z7Compute the maximum of values of multiple given tensorsz>takes any number of scalars as input and returns their maximumc                O   r   r   )minimumr   r   r   r   rK   g  r   rK   z7Compute the minimum of values of multiple given tensorsz>takes any number of scalars as input and returns their minimumc                O   r   r   )lessr   r   r   r   rL   q  r   rL   zEComputes the less-than comparison between values of two given tensorszatakes two scalars as input and returns true if the first is less than the second, otherwise falsec                O   r   r   )
less_equalr   r   r   r   rM   ~  r   rM   zNComputes the less-than-or-equal comparison between values of two given tensorszmtakes two scalars as input and returns true if the first is less than or equal to the second, otherwise falsec                O   r   r   )greaterr   r   r   r   rN     r   rN   zHComputes the greater-than comparison between values of two given tensorszdtakes two scalars as input and returns true if the first is greater than the second, otherwise falsec                O   r   r   )greater_equalr   r   r   r   rO     r   rO   zQComputes the greater-than-or-equal comparison between values of two given tensorszptakes two scalars as input and returns true if the first is greater than or equal to the second, otherwise falsec                O   r   r   )equalr   r   r   r   rP     r   rP   zDComputes the equality comparison between values of two given tensorszNtakes two scalars as input and returns true if they are equal, otherwise falsec                O   r   r   )	not_equalr   r   r   r   rQ     r   rQ   zHComputes the non-equality comparison between values of two given tensorszNtakes two scalars as input and returns false if they are equal, otherwise truec                O   r   r   )	logaddexpr   r   r   r   rR     r   rR   z;Compute the log-sum-exp of values of multiple given tensorszBtakes any number of scalars as input and returns their log-sum-expc                O   r   r   )get_atr   r   r   r   rS     r   rS   aA  Retrieves values from a tensor at the coordinates specified by another tensor.

The elementary operation has the signature ``[...] , [n] -> []``. The first argument is the n-dimensional value tensor, the second argument
specifies a single n-dimensional coordinate, and the result is the value at that coordinate.

For 1-dimensional value tensors, the elementary operation also accepts the signature ``[...] , [] -> []``. For example, the following two
operations compute the same output:

..  code-block:: python

    y = einx.get_at("[h], p [1] -> p", x, idx)
    y = einx.get_at("[h], p     -> p", x, idx[:, 0])

The elementary operation also accepts multiple coordinate tensors as input, in which case they are concatenated first. The length of the resulting
coordinate vector must equal the number of dimensions of the value tensor. For example, the following two operations compute the same output:

..  code-block:: python

    y = einx.get_at("[a b c d], p [n]           -> p", x, idx)
    y = einx.get_at("[a b c d], p, p [2], p [1] -> p", x, idx[:, 0], idx[:, 1:3], idx[:, 3:4])

c                 C   sD   | d| d| d|  d|  d|  d|  d|  d|  d	t d
 dS )Na   at the coordinates specified by an indexing tensor.

The elementary operation has the signature ``[...] , [n], [] -> [...]``. The first argument is the n-dimensional value tensor, the second argument
specifies a single n-dimensional coordinate, the third argument is the z: value, and the result is the value tensor with the value z
at that coordinate.

For 1-dimensional value tensors, the elementary operation also accepts the signature ``[...] , [], [] -> []``. For example, the following two
operations compute the same output:

..  code-block:: python

    y = einx.z@("p [h], p [1], p -> p [h]", x, idx,       update)
    y = einx.a  ("p [h], p,     p -> p [h]", x, idx[:, 0], update)

The elementary operation also accepts multiple coordinate tensors as input, in which case they are concatenated first. The length of the resulting
coordinate vector must equal the number of dimensions of the value tensor. The update tensor always is the last argument.
For example, the following two operations compute the same output:

..  code-block:: python

    y = einx.zf("p [a b c d], p [n],           p -> p", x, idx,                                 update)
    y = einx.a:  ("p [a b c d], p, p [2], p [1], p -> p", x, idx[:, 0], idx[:, 1:3], idx[:, 3:4], update)

If no output expression is given, it is implicitly chosen to be the same as the input expression of the value tensor. For example,
the following two operations compute the same output:

..  code-block:: python

    y = einx.z;("b [h w] c, b p [2], b p c", x, idx, update)
    y = einx.a  ("b [h w] c, b p [2], b p c -> b [h w] c", x, idx, update)

The order in which the updates are applied depends on the chosen backend. The operation also may or may not update the target tensor inplace.
Please check by inspecting the code representation (by passing ``graph=True``).

Fr8   r   )r   r   value1value2r   r   r   _update_at_doc  s&   "rV   c                O   r   r   )set_atr   r   r   r   rW     r   rW   z4Sets values in a target tensor from an update tensornewoverwrittenc                O   r   r   )add_atr   r   r   r   rZ     r   rZ   z4Adds values from an update tensor to a target tensoraddedc                O   r   r   )subtract_atr   r   r   r   r\     r   r\   z9Subtracts values from a target tensor by an update tensor
subtractedc                K      |j | |fi |S r   )softmaxr   r   r   r   r   r   r   r_   &     r_   a  Compute the softmax of values in the given tensor.

The elementary operation has the signature ``[...] -> [...]`` and computes the softmax over all input values.

If there is no output expression, it is chosen to be the same as the input expression. For example, the following operations compute the same output:

..  code-block:: python

    y = einx.softmax("a [b]", x)
    y = einx.softmax("a [b] -> a [b]", x)

Tc                K   r^   r   )log_softmaxr`   r   r   r   rb   :  ra   rb   a  Compute the log-softmax of values in the given tensor.

The elementary operation has the signature ``[...] -> [...]`` and computes the log-softmax over all input values.

If there is no output expression, it is chosen to be the same as the input expression. For example, the following operations compute the same output:

..  code-block:: python

    y = einx.log_softmax("a [b]", x)
    y = einx.log_softmax("a [b] -> a [b]", x)

c                K   r^   r   )sortr`   r   r   r   rc   N  ra   rc   a  Returns values in the given tensor sorted in ascending order.

The elementary operation has the signature ``[a] -> [a]`` and returns the values sorted along the single axis in ascending order.

If there is no output expression, it is chosen to be the same as the input expression. For example, the following operations compute the same output:

..  code-block:: python

    y = einx.sort("a [b]", x)
    y = einx.sort("a [b] -> a [b]", x)

c                K   r^   r   )argsortr`   r   r   r   rd   b  ra   rd   a  Returns the indices that would sort values in the given tensor in ascending order.

The elementary operation has the signature ``[a] -> [a]`` and returns the indices that would sort values along the single axis in ascending order.

If there is no output expression, it is chosen to be the same as the input expression. For example, the following operations compute the same output:

..  code-block:: python

    y = einx.argsort("a [b]", x)
    y = einx.argsort("a [b] -> a [b]", x)

c                K   r^   r   )flipr`   r   r   r   re   v  ra   re   a  Reverse the order of elements in the given tensor.

The elementary operation has the signature ``[...] -> [...]`` and reverses the order of elements along all axes.

If there is no output expression, it is chosen to be the same as the input expression. For example, the following operations compute the same output:

..  code-block:: python

    y = einx.flip("a [b]", x)
    y = einx.flip("a [b] -> a [b]", x)

shiftc                K   s   |j | |fd|i|S )Nrf   )roll)r   r   rf   r   r   r   r   r   rg     r   rg   a  Rolls the elements in the given tensor by the specified shift amounts.

The elementary operation has the signature ``[...] -> [...]`` and rolls elements separately along all axes. Elements that are rolled beyond the last position
are re-introduced at the first position.

If there is no output expression, it is chosen to be the same as the input expression. For example, the following operations compute the same output:

..  code-block:: python

    y = einx.roll("a [b]", x, shift=4)
    y = einx.roll("a [b] -> a [b]", x, shift=4)

zshift: Amounts by which elements are shifted along each axis. Can be a single integer or a list of integers matching the number of axes in the tensor.c                 C   s4   d| d| d|  d|  d|  d|  dt d d	S )
NzFind the coordinates of the z values in the given tensor.

The elementary operation has the signature ``[...] -> [n]``. It takes an n-dimensional tensor as input and returns the n-dimensional coordinate vector of
the z value.

For 1-dimensional tensors, the elementary operation also accepts the signature ``[a] -> []``. For example, the following two operations compute
the same output:

..  code-block:: python

    y = einx.argmaz$x("a [b] -> a [1]", x)
    y = einx.z("a [b] -> a ", x)

If no output is given, it is determined implicitly by replacing a single bracketed expression in the input with ``[n]``. For example, the
following two operations compute the same output:

..  code-block:: python

    y = einx.z("a [b c]", x)
    y = einx.z("a [b c] -> a [2]", x)

Tr   r   )r   findr   r   r   _make_argfind_doc  s   
ri   c                K   r^   r   )argmaxr`   r   r   r   rj     ra   rj   c                K   r^   r   )argminr`   r   r   r   rk     ra   rk   c                 C   s8   g | ]}|d    r|dvrtt | rt | qS )r   )r   nptr   r   r   Tuple)islowercallableglobals).0namer   r   r   
<listcomp>  s    $rs   )r   )Br   typesr   r   r   numpy.typingtypingrl   r   r#   r   str	ArrayLiketupler   __doc__r    r'   boolr*   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r>   r?   r@   rA   rB   rC   rD   rE   rF   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rV   rW   rZ   r\   r_   rb   rc   rd   re   rg   ri   rj   rk   diropsr   r   r   r   <module>   s   
<
	:::::
:::::0
)0000000080000000000
'0000
0
0
0
0
6
00
