o
     iU                  
   @   s2  d dl mZmZmZmZmZ d dlZddlmZ deej	 de
deeee
ejf df  fd	d
Zdeeej	df eej	 f de
deej	 fddZdeeej	df eej	 f de
dej	fddZG dd dejjZG dd dejjZdej	de
deej	df fddZdeej	 de
dej	fddZdS )    )ListOptionalSequenceTupleUnionN   )_get_storage_basetensorsdimreturn.c                 C   s,  t | dks|| d jkrdS g }t| d jd D ](}||kr0|| d  | d    q||kr8|d8 }|| d | qd}t| dd D ]D\}}|j| d jkr\ dS | | d  kri dS | | d  |d ||   kr~ dS |du rt| d }t||kr dS qMt	|S )z
    If the tensors are already stacked on dimension :code:`dim`,         returns the strides of the stacked tensors.         Otherwise returns :code:`None`.
    r   r   N)
lenndimrangeappendstorage_offsetstride	enumerateshaper   tuple)r	   r
   final_strideistorage_data_ptrx r   G/home/ubuntu/.local/lib/python3.10/site-packages/xformers/ops/unbind.pyget_stack_strides   s8   r   c                 C   sD   t | |}|d ur t| d j}||t|  | d ||S d S )Nr   )r   listr   insertr   
as_strided)r	   r
   stridesinput_shaper   r   r   _stack_or_none_fw;   s   
r!   c                 C   s$   t | |}|d u rtj| |d}|S N)r
   )r!   torchstack)r	   r
   outr   r   r   	_stack_fwG   s   
r&   c                   @   s<   e Zd ZdZedejdefddZe	dejfddZ
d	S )
_Unbindz
    See function `unbind`
    r   r
   c                 C   s   || _ ||S N)r
   unbind)ctxr   r
   r   r   r   forwardV   s   
z_Unbind.forwardr	   c                 G   s   t ||jd fS r(   )r&   r
   )clsr*   r	   r   r   r   backward\   s   z_Unbind.backwardN)__name__
__module____qualname____doc__staticmethodr#   Tensorintr+   classmethodr-   r   r   r   r   r'   Q       r'   c                   @   s<   e Zd ZdZededejfddZe	dejfddZ
d	S )
_StackOrNonez&
    See function `stack_or_none`
    r
   r	   c                 G   s   || _ t||dS r"   )r
   r!   )r*   r
   r	   r   r   r   r+   g   s   z_StackOrNone.forwardgradc                 C   s   d g|j |jdR S r"   )r)   r
   )r,   r*   r8   r   r   r   r-   m   s   z_StackOrNone.backwardN)r.   r/   r0   r1   r2   r4   r#   r3   r+   r5   r-   r   r   r   r   r7   b   r6   r7   r   c                 C   s   t | |S )z
    Does exactly the same as :attr:`torch.unbind` for the forward.
    In backward, avoids a :attr:`torch.cat` if the gradients
    are already multiple views of the same storage
    )r'   apply)r   r
   r   r   r   r)   s   s   r)   c                 C   s   t j|g| R  S )z
    Does exactly the same as :attr:`torch.stack` if the tensors can be concatenated
    without any memory operation. Otherwise returns None.
    )r7   r9   )r	   r
   r   r   r   stack_or_none|   s   r:   )typingr   r   r   r   r   r#   commonr   r3   r4   SymIntr   r!   r&   autogradFunctionr'   r7   r)   r:   r   r   r   r   <module>   s8   
.


""	