o
     i                     @   s  d dl mZmZ d dlZd dlmZmZmZmZ ddl	m
Z
mZ eG dd de
ZeG dd	 d	e
ZeG d
d de
ZG dd dejjZ		ddejdejdejdeej dedejfddZG dd dejjZdeej deej dejfddZdS )    )OptionalSequenceN)index_select_cat_bwdindex_select_cat_fwdscaled_index_add_bwdscaled_index_add_fwd   )BaseOperatorregister_operatorc                   @      e Zd ZeZdZdZdS )ScaledIndexAddFwindexingscaled_index_addFN)__name__
__module____qualname__r   OPERATOROPERATOR_CATEGORYNAME r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/xformers/ops/indexing.pyr          r   c                   @   r   )ScaledIndexAddBwr   scaled_index_addBN)r   r   r   r   r   r   r   r   r   r   r   r      r   r   c                   @   r   )IndexSelectr   index_selectN)r   r   r   r   r   r   r   r   r   r   r   r   $   r   r   c                   @   sV   e Zd Zedejdejdejdeej dedejfddZeej	j
jd	d
 ZdS )_ScaledIndexAddxindexsourcescalingalphareturnc                 C   sL   t d urt ||||| ntd| | | ||| |j| _|| _|S )N:Triton is needed for forward pass but it is not available!)r   RuntimeError
mark_dirtysave_for_backwardshapesource_shaper!   )ctxr   r   r   r    r!   r   r   r   forward,   s   

z_ScaledIndexAdd.forwardc                 C   sn   | j \}}}t|}|d u rd n
tj| j|j|jd}td ur,t||||||| j nt	d|d ||d fS )Ndtypedevice;Triton is needed for backward pass but it is not available!)
saved_tensorstorch
empty_likeemptyr(   r,   r-   r   r!   r$   )r)   grad_outputr   r    r   grad_sourcegrad_scalingr   r   r   backwardC   s6   

z_ScaledIndexAdd.backwardN)r   r   r   staticmethodr0   Tensorr   floatr*   autogradfunctiononce_differentiabler6   r   r   r   r   r   +   s$    r         ?inputr   r   r    r!   r"   c                 C   s   t | ||||S )a  
    In-place scaling+index_add

    Indices in ``index`` are assumed to be unique

    The max index in ``index`` is assumed to be less than the size of dim0 of ``input``.

    :Note:

        The FW pass is done in-place (``input`` is modified)

    :Equivalent pytorch code:

    .. code-block:: python

        return torch.index_add(input, dim=0, source=scaling * src, index=indices, alpha=alpha)
    )r   apply)r>   r   r   r    r!   r   r   r   scaled_index_addh   s   r@   c                   @   s<   e Zd ZedejdejfddZeejjj	dd Z
dS )_IndexSelectCatargsr"   c                 G   s   t |d dks
J |d t |d  }|t |d d  }d}t||D ]\}}|j\}}|jd }	||	| 7 }q%tj|g|d j|d jd}
d}t||D ]0\}}|jd }	|jd }td urvt|
|||	|   |	|g|| nt	d||	| 7 }qP| j
|  dd |D | _|
S )N   r   r+   r   r#   c                 S   s   g | ]}|j qS r   )r'   ).0r   r   r   r   
<listcomp>   s    z+_IndexSelectCat.forward.<locals>.<listcomp>)lenzipr'   r0   r2   r,   r-   r   viewr$   r&   source_shapes)r)   rB   sourcesindicesoutput_numelr   r   num_rowsnum_colsnum_indicesoutputprocessed_numelr   r   r   r*      s>   





z_IndexSelectCat.forwardc                 C   s   | j }g }d}t| j|D ]B\}}|\}}|jd }	||||	|   |	|g}
||	| 7 }tj||g|j|jd}t	d urFt	|||
 nt
d|| qg |d gt| R S )Nr   r+   r.   )r/   rG   rI   r'   reshaper0   zerosr,   r-   r   r$   appendrF   )r)   r3   rK   	gradientsrQ   r(   r   rM   rN   rO   grad_output_slicegrad_source_slicer   r   r   r6      s8   

z_IndexSelectCat.backwardN)r   r   r   r7   r0   r8   r*   r:   r;   r<   r6   r   r   r   r   rA      s    +rA   rJ   rK   c                 C   s   t jg | |R  S )aD  
    Indices in ``index`` are assumed to be unique
    In each (index, source) pair, the max index in ``index`` is assumed to be less than the size of dim0 of ``source``

    :Example:

    Given:
    - ``sources[0]`` of shape ``[S0, D0]``
    - ``indices[0]`` of shape ``[I0]``
    - ``sources[1]`` of shape ``[S1, D1]``
    - ``indices[1]`` of shape ``[I1]``
    returns a ``torch.Tensor`` of shape ``[I0 * D0 + I1 * D1]``

    :Equivalent pytorch code:

    .. code-block:: python

        return torch.cat([s[i.long()].flatten() for s, i in zip(sources, indices)], dim=0)
    )rA   r?   )rJ   rK   r   r   r   index_select_cat   s   rX   )Nr=   )typingr   r   r0   xformers.ops._tritonr   r   r   r   commonr	   r
   r   r   r   r:   Functionr   r8   r9   r@   rA   rX   r   r   r   r   <module>   sD   A
S