o
    ei6                     @  s  d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	 er(d dl
mZmZ d dlZd dlmZmZmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZ dZdZd adddZdddZ ddddZ!	ddd!d"Z"G d#d$ d$Z#	ddd&d'Z$	ddd)d*Z%G d+d, d,e&Z'G d-d. d.e&Z(dd/l)m*Z* dd4d5Z+G d6d7 d7Z,e,ej-fZ.G d8d de,Z/G d9d: d:e,Z-ddd?d@Z0dddCdDZ1ddEdFZ2G dGdH dHZ3ddMdNZ4ddPdQZ5ddVdWZ6d dXl7m8Z8 d dYl9m:Z: e:e,ej-e,j; e,`<dd\d]Z=dd^d_Z>e>d` e>da e>db e>dc e>dd e>de e>df e>dg e>dh e>di e>dj e>dk e>dldmdn e>dodmdn e>dpddq e>drddq e>dsddq e>dtddq e>duddq e>dvddq e>dwddq e>dxddq e>dydzd{ e>d|dzd{ e>d}ddq e>d~ddzd e>dddzd e>dddzd e>dddzd e>dddzd e>dddzd e>dddzd e>dddzd e>ddddzd e>dddzd e8ej?j@jAddzdZAdS )    )annotationsN)AnyOptionalTYPE_CHECKINGUnion)CallableSequence)tree_flattentree_maptree_unflatten   )_match_levelsDimEntryndim_of_levels)EnableAllLayers)_PyInstDecoder)
TensorInfoTopcodeOptional[str]returnboolc                 C  s   t | o| dS )z4Check if opcode is relevant for variable assignment.STORE_)r   
startswith)r    r   `/var/www/addictedbytheproject.nl/epg/venv/lib/python3.10/site-packages/functorch/dim/__init__.py_relevant_op   s   r   tensortorch.Tensorc                 C  s   | S )z8Handle tensor conversion for torch function integration.r   )r   r   r   r   handle_from_tensor!      r   namestrsizeOptional[int]Dimc                 C  s   t | |dur	|S dS )zCreate a new Dim object.N)r$   )r    r"   r   r   r   _create_dim&   s   r&   nsizesOptional[list[Optional[int]]]Union[Dim, tuple[Dim, ...]]c           	        sh  d}ddurt }| dur| }t }|du rtd|j}z|du r*td|j}|j}t|| tj	dkrD 
 dkrD      t 
 rQdn 
 d	kr_     |dkrmdkrktd
}|krsdd fdd}durt |krtd| dt  |dkr|dW ~S g }t|D ]	}||| qt|W ~S ~w )a  
    Create and return one or more Dim objects.

    Uses bytecode inspection to determine variable names when possible.

    Args:
        n (int, optional): The number of dimensions to create. Can be omitted if sizes is specified.
        sizes (List[Optional[int]], optional): A list the same size as the number of dimensions to be
          created, specifying each dimensions size, or None to leave the size unset.

    Returns:
        Union[Dim, Tuple[Dim, ...]]: Single Dim if n=1, tuple of Dims otherwise.

    Examples:
        >>> batch, channel, width, height = dims(4)
        >>> batch, channel, width, height = dims(sizes=[None, 3, 224, 224])
        >>> single_dim = dims(1)
    r%   r   NUnable to get current frameUnable to get caller frame      PRECALLr   UNPACK_SEQUENCEzTdims() must be assigned to a sequence of variable names or have argument n specifiediintr   r$   c                   sN   d }| k r
   }|sd|  }dn   d ur |  nd }t||S Ndr   )r    nextr&   )r2   r    r"   decoderfound_ndimsr(   r   r   	genobjectn   s   

zdims.<locals>.genobject	expected  sizes but found )r2   r3   r   r$   )leninspectcurrentframeRuntimeErrorf_backf_codef_lastir   sysversion_infor   r6   r   opargSyntaxError
ValueErrorrangeappendtuple)	r'   r(   specified_ndimsframecodelastir:   resultr2   r   r7   r   dims+   sX   

	rQ   c                   @  s   e Zd ZU dZded< ded< ded< 		d<d=ddZd>ddZd?ddZd@ddZdAddZ	dAddZ
dBd!d"ZedCd#d$ZdAd%d&ZdDd*d+ZdEd-d.ZdEd/d0Ze	1	dFdGd:d;ZdS )HDimLista(  
    A list of first-class dimensions that can be bound to tensor dimensions.

    A DimList can be in one of two states:
    1. Unbound: Created with just a name, no specific dimensions yet
    2. Bound: Either created with specific dimensions/sizes, or bound later via bind() or bind_len()
    r   _namez	list[Dim]_dimsr   _boundNlen_or_dimsOptional[Union[int, Sequence]]r    c                 C  s   || _ g | _d| _t|tr| | dS |durOg }t|D ](\}}t|tr@| j r2| j  | nd| }|t|| q|t| q| 	| dS dS )z
        Initialize a new DimList object.

        Args:
            len_or_dims: Optional length (int) or sequence of dimensions/sizes
            name: Optional name for the dimension list
        FNdim)
rS   rT   rU   
isinstancer3   bind_len	enumeraterJ   r$   	_set_dims)selfrV   r    rQ   r2   itemdim_namer   r   r   __init__   s   

zDimList.__init__rQ   listr   Nonec                 C  s   d| _ || _dS )z%Set the dimensions and mark as bound.TN)rU   rT   )r]   rQ   r   r   r   r\      s   
zDimList._set_dimsr"   r3   c                 C  s~   | j rt| j|krtdt| j d| dS d| _ g | _t|D ]}| jr/| j | nd| }| jt| q#dS )z
        Bind this DimList to a specific length.

        Args:
            size: Number of dimensions to bind to

        Raises:
            DimensionBindError: If already bound to a different size
        zDimlist has size z but it is being bound to size TrX   N)rU   r=   rT   DimensionBindErrorrI   rS   rJ   r$   )r]   r"   r2   r_   r   r   r   rZ      s   
zDimList.bind_lenr(   Sequence[int]c                 C  sT   t |dr
t |dstdt|}| | t|D ]\}}t|| j| _qdS )z
        Bind this DimList to specific sizes.

        Args:
            sizes: Sequence of sizes for each dimension

        Raises:
            ValueError: If sizes is not a sequence
        __len____getitem__zexpected a sequenceN)hasattrrH   r=   rZ   r[   r3   rT   r"   )r]   r(   r"   r2   dim_sizer   r   r   bind   s   

zDimList.bindc                 C  s   | j stdt| jS )NDimList not bound)rU   rc   r=   rT   r]   r   r   r   _size   s   
zDimList._sizec                 C     |   S )z7Return the size (number of dimensions) of this DimList.rl   rk   r   r   r   r"         zDimList.sizebc                 C  s
   || _ dS )z(Set the bound status (for internal use).NrU   )r]   rp   r   r   r   
_set_bound   s   
zDimList._set_boundc                 C     | j S )z&Property to check if DimList is bound.rq   rk   r   r   r   is_bound   s   zDimList.is_boundc                 C  rm   )z!Return the length of the DimList.)r"   rk   r   r   r   re      ro   zDimList.__len__keyUnion[int, slice]r*   c                 C  s   | j stdt|tr |dk s|t| jkrtd| j| S t|trG|t| j\}}}g }t	|||D ]
}|
| j|  q8t|S td)Nrj   r   zindex out of boundszexpected an int or a slice)rU   rc   rY   r3   r=   rT   
IndexErrorsliceindicesrI   rJ   rK   rH   )r]   ru   startstopsteprP   r2   r   r   r   rf      s   


zDimList.__getitem__r!   c                 C  s>   | j rdddd | jD  dS | jdurd| j S dS )	,Return string representation of the DimList.(z, c                 s  s    | ]}t |V  qd S N)repr).0rX   r   r   r   	<genexpr>  s    z#DimList.__repr__.<locals>.<genexpr>)N*z<unbound_dimlist>)rU   joinrT   rS   rk   r   r   r   __repr__  s
   
zDimList.__repr__c                 C  rm   )r}   )r   rk   r   r   r   __str__  ro   zDimList.__str__r   funcr   typesrK   argskwargsOptional[dict]r   c                 C  s   t ||||S r   )_Tensor__torch_function__)clsr   r   r   r   r   r   r   r     s   zDimList.__torch_function__NN)rV   rW   r    r   )rQ   ra   r   rb   )r"   r3   r   rb   )r(   rd   r   rb   r   r3   )rp   r   r   rb   r   r   )ru   rv   r   r*   r   r!   r   N
r   r   r   rK   r   rK   r   r   r   r   )__name__
__module____qualname____doc____annotations__r`   r\   rZ   ri   rl   r"   rr   propertyrt   re   rf   r   r   classmethodr   r   r   r   r   rR      s0   
 









rR   )Optional[Union[int, list[Optional[int]]]]c                 C  sb   t | d}|dur/t|tr|| |S |t| t|D ]\}}|dur.||j| _q |S )z>Create a DimList object with the given name and optional size.)r    N)rR   rY   r3   rZ   r=   r[   rT   r"   )r    r"   dimlistr2   sr   r   r   _create_dimlist(  s   


r   #Union[DimList, tuple[DimList, ...]]c                   s  d}d|durt |}| dur| }t }|du rtd|j}z|du r*td|j}|j}t|| tj	dkrD 
 dkrD      t 
 rQdn 
 d	kr_     |dkrmdkrktd
}|krsdd fdd}|durt ||krtd| dt | |dkr|d}t||dur|d W ~S dW ~S g }t|D ]}	||	}|dur||	 nd}
|t||
 qt|W ~S ~w )zt
    Create and return one or more DimList objects.

    Similar to dims() but creates DimList objects instead.
    r%   r   Nr+   r,   r-   r0   r   r1   zXdimlists() must be assigned to a sequence of variable names or have argument n specifiedr2   r3   r   r!   c                   s6   d }| k r
   }|sd|  }d|S    |S r4   )r    r6   )r2   r    r8   r9   r   r   r:   o  s   
zdimlists.<locals>.genobjectr;   r<   )r2   r3   r   r!   )r=   r>   r?   r@   rA   rB   rC   r   rD   rE   r   r6   r   rF   rG   rH   r   rI   rJ   rK   )r'   r(   rL   rM   rN   rO   r:   r    rP   r2   r"   r   r   r   dimlists9  sb   

r   c                   @     e Zd ZdS )DimensionMismatchErrorNr   r   r   r   r   r   r   r         r   c                   @  r   )rc   Nr   r   r   r   r   rc     r   rc   )op_propertiesr   r   r   rb   c                  O  st   ddl }g }| D ]#}t|dr$dtt|v r$|dt|j d q|t| qt|i |d|ji dS )z;Safe print that avoids recursive torch function dispatches.r   N	__class__torch<>file)rD   rg   r!   typerJ   r   printstderr)r   r   rD   	safe_argsargr   r   r   _safe_print  s   r   c                   @  s   e Zd Zd0ddZd1ddZed2d	d
Zed3ddZd2ddZe			d4d5ddZ
ed6ddZd7d"d#Zd8d%d&Zd9d+d,Zd:d.d/ZdS );r   r   	list[Any]c                 C     t d)Nz+_get_levels must be implemented by subclassNotImplementedErrorrk   r   r   r   _get_levels     z_Tensor._get_levelsOptional[torch.Tensor]c                 C  r   )Nz+_get_tensor must be implemented by subclassr   rk   r   r   r   _get_tensor  r   z_Tensor._get_tensorr3   c                 C  r   )Nz$ndim must be implemented by subclassr   rk   r   r   r   ndim  ro   z_Tensor.ndimtuple[Any, ...]c                 C  s   t dd |  D S )Nc                 s  s     | ]}|  s| V  qd S r   )is_positionalrX   r   lr   r   r   r         z_Tensor.dims.<locals>.<genexpr>)rK   r   rk   r   r   r   rQ     s   z_Tensor.dimsc                 C  rs   r   )r   rk   r   r   r   rX     s   z_Tensor.dimr   Nr   r   r   rK   r   r   r   r   c                 C  s<  |d u ri }t r|tjju rt|dkr|st|d ttjfrt|d ttjfrtj|d ddd}tj|d ddd}|r|r|j	d ur|j	d ur|j	
 dkr|j	
 dkr|j	 r|j	 r|jpi|j}g }|jD ]}	|	|vrz||	 qo|jD ]}	|	|vr||	 q~t||||S |tjju rddlm}
 |
| ||||S |tjju rddlm} t|dkr||d |d |d  d S td	t| |tjju r|d dS |tju rt|i |S |tju rt|i |S |tjju s|tjju s|tjju s|tju rt|i |S t||||S )
N   r   r   Fensure_batchedensure_present)getitemsetitemr.   z%Expected 3 args for __setitem__, got )DOT_OPTIMIZEDr   Tensor__mul__r=   rY   r   r   creater   rX   is_floating_point
has_devicelevelsrJ   create_delayedrf   functorch.dim._getsetitemr   __setitem__r   rH   re   r"   softmaxstacksplit_VFsplit_with_sizes_torch_function_fallback)r   r   r   r   r   lhs_inforhs_infor   r   levelr   r   r   r   r   r     sx   









z_Tensor.__torch_function__dictc                   s@  t o| tjv }t||f\}}d g }g |D ]C}t|| d}	||	 |	rZ|s3|	jdus3td du r=|	j	r=|	j
 |	jD ]}
t|
tsPtdt|
 |
vrY|
 q@q|rt|D ](\}}	|	r|	j
dur|	j
} dur||	j	s|| j}t||	j}t|||< qat||\}}| |i |}d fdd	}t|tjr||S t||S tbt|D ](\}}	|	r|	jdur|	j} dur|	j	s| j}||	j t|||< qt||\}}| |i |}d fd
d}t|tjr	||W  d   S t||W  d   S 1 sw   Y  dS )zGFallback torch function implementation for non-special-cased functions.NFz-Expected pointwise or batchedtensor to be setzExpected DimEntry, got objr   r   c                   s"   t | tjrt|  d uS | S r   )rY   r   r   from_positionalr   )device_holding_tensorresult_levelsr   r   wrap_tensorG  s
   
z5_Tensor._torch_function_fallback.<locals>.wrap_tensorc                   s    t | tjr|  d uS | S r   )rY   r   r   from_batchedr   )r   guardr   r   unwrap_tensorc  s   z7_Tensor._torch_function_fallback.<locals>.unwrap_tensor)r   r   r   r   )POINTWISE_OPTIMIZEr   	pointwiser	   r   r   rJ   batchedtensorAssertionErrorr   r   r   rY   r   r   r[   todevicer   r   r   r   r   r
   r   inplace_update_layers)r   r   r   r   is_pointwise	flat_argsspecinfosfinfor   r2   r   mlunflat_argsunflat_kwargsrP   r   batchedr   r   )r   r   r   r   r     sj   





&z _Tensor._torch_function_fallbackindexvaluerb   c                 C  s   ddl m} || ||S )z2Set values in tensor using first-class dimensions.r   r   )r   r   )r]   r   r   r   r   r   r   r   m  s   z_Tensor.__setitem__r$   c                 G  s  t j| ddd}|D ]/}t|ts9t| tjr(t| ts(tjj| g|R    S | tjjt	| f| f|   S q
|sK| tjjt	| f| f| S |j
}|du ra| tjjt	| f| f| S |j}g }g }g }|D ]B}	|D ]}
|
 s|
 |	u rtd|	 dqp|D ]}| s| |	u rtd|	 dq|t|	 ||	j |d ql|| t| }t| }|| || |||| }t|||j}|S )aq  
        Expand tensor by adding new dimensions or expanding existing dimensions.

        If all arguments are Dim objects, adds new named dimensions.
        Otherwise, falls back to regular tensor expansion behavior.

        Args:
            args: Either Dim objects for new dimensions or sizes for regular expansion

        Returns:
            New tensor with expanded dimensions

        Example:
            >>> i, j = dims()
            >>> t = torch.randn(3, 4)
            >>> expanded = t[i].expand(j, k)  # Add j, k dimensions
            >>> expanded2 = t[i].expand(2, 4)  # Regular expand with sizes
        Fr   Nzexpanding dimension z# already exists in tensor with dimsr   )r   r   rY   r$   r   r   r   expandr   r   r   r   r   rX   rc   rJ   r   r"   extendra   stride
as_stridedstorage_offsetr   r   )r]   r   r   r   datar   
new_levels	new_sizesnew_stridesr5   r   	new_level
orig_sizesorig_stridesexpanded_datarP   r   r   r   r   v  s\   






z_Tensor.expandrQ   CUnion[int, Dim, tuple[Union[int, Dim], ...], list[Union[int, Dim]]]ry   sUnion[int, slice, torch.Tensor, tuple[Union[int, slice, torch.Tensor], ...], list[Union[int, slice, torch.Tensor]]]c           %        sx  ddl m} ddlm}m} ddlm  dddd}d  fdd}d!fdd}g }	g }
t|tt	f}t|tt	f}|re|re|}|}t
|t
|krZtdt
| dt
| d|	| |
| n
|	| |
| tdd}g }g }g }tt
|	D ]}||	| dd\}}|r-t
|dkr|t  q||d }|| t
|dkrqt
|dkr||j g }tdt
|D ]-}||| }d}tt
|D ]}|| |kr|| d} nq|s|| || qd}tt
|D ]}|| |kr|} nq|du r|| qt|D ]\}}||d | | q|| q|||	|  qt
|dkr|jdu rHtd||j|j|}| }g } g }!tt
|D ]4}|| |v rt
| dkrw| ||  q^| d  || 9  < q^| ||  |!||  q^|| |_|!|_d}"|
D ]}#t|#tt	frd}" nq||g ||
|"}$||$S )"z<
        Index tensor using first-class dimensions.
        r   )r   )getsetitem_flatinvoke_getitem	_wrap_dimFr   r   check_firstr   r   tuple[Any, bool]c                 S  s   t | ttfrt| dfS dS )NT)NF)rY   rK   ra   )r   r  r   r   r   maybe_dimpack  s   z$_Tensor.index.<locals>.maybe_dimpackr   c                   s,    | j d}| rtdt|  |S )NFz)expected a dimension specifyer but found )r   is_none	TypeErrorr   )r   r5   r  r]   r   r   parse_dim_entry  s   z&_Tensor.index.<locals>.parse_dim_entryr5   rb   c                   sB   |   rtd|   j  d j dtdt|   d)N
dimension z not in tensor of z dimensionsz not in tensor)r   r  positionr   r   rX   )r5   rk   r   r   dim_not_present  s
   z&_Tensor.index.<locals>.dim_not_presentzdims (z) and indices (z) must have the same length)r  r   TNz2Cannot perform dimension flattening on None tensorr%   )F)r   r   r  r   r   r  )r   r   r   r   )r5   r   r   rb   )
_dim_entryr   _getsetitemr  r	  _wrapr  rY   rK   ra   r=   r  r   rJ   r   r   rI   r   r   popr[   insertr   r   r"   reshape)%r]   rQ   ry   r   r  r	  r  r  r  	dims_listindices_listlhs_listrhs_listdims_seqindices_seq	self_infor   
to_flattendims_list_flatr2   m
is_dimpackfirstrestjr5   removedk	first_idxr
rearrangedr(   r   reshape_levelshas_dimpacksidxr   r   r  r   r     s   





z_Tensor.indexr!   c                 C  s   |   |  | j}}}g }|D ]3}t|dr&| r&|| |  qt|dr3||  qt|dr?||j q|| q| dt	| dt	|
  S )Nr   rX   r   z
with dims=z sizes=)r   r   r   rg   r   rJ   r  rX   r   rK   r"   )r]   r   r   r   	dims_reprr   r   r   r   r   f  s   

 z_Tensor.__repr__r   r   r   r   r   )r   r   r   r   )
r   r   r   rK   r   rK   r   r   r   r   )r   r   r   r   r   rb   )r   r$   r   r   )rQ   r  ry   r  r   r   r   )r   r   r   r   r   r   r   rQ   rX   r   r   staticmethodr   r   r   r   r   r   r   r   r   r     s&    


\
Q
	
U r   c                   @  s   e Zd ZU ded< ded< ded< ded< ded< d%d&ddZed'ddZed(ddZed'ddZ	e	j
d)ddZ	ed*ddZd+ddZd+d d!Zd,d"d#ZejZd$S )-r$   r3   _levelr!   rS   rl   r   _range_batchtensorr%   r    r   r   rb   c                 C  s*   || _ || _t| _td7 ad | _d | _d S Nr   )rS   rl   _n_dims_createdr6  r7  r8  )r]   r    r   r   r   r   r`     s   
zDim.__init__c                 C  s   dS r9  r   rk   r   r   r   r     r   zDim.ndimr   r   r   c                 C     t || u S r   r   )r   r   r   r   r   check_exact     zDim.check_exactc                 C  s"   | j dkrtd| j d| j S )Nr%   r  z is unbound)rl   rH   rS   rk   r   r   r   r"     s   
zDim.sizevc                 C  sB   | j dkr
|| _ d S | j |krtdt|  d| j  d| d S )Nr%   zDim 'z*' previously bound to a dimension of size z$ cannot bind to a dimension of size )rl   rc   r   )r]   r?  r   r   r   r"     s   


c                 C  s
   | j dkS )z1Return True if this dimension is bound to a size.r%   rn   rk   r   r   r   rt     s   
zDim.is_boundr   c                 C  s   | j du rt| j| _ | j S )z
        Get a tensor representing the range [0, size) for this dimension.

        Returns:
            A 1D tensor with values [0, 1, 2, ..., size-1]
        N)r7  r   aranger"   rk   r   r   r   
_get_range  s   
zDim._get_rangec                 C  s*   | j du rtjj|  d| j| _ | j S )z
        Get a batched tensor representation of this dimension.

        Returns:
            A batched tensor created from the range tensor
        Nr   )r8  r   _C
_functorch_add_batch_dimrA  r6  rk   r   r   r   _get_batchtensor  s
   
zDim._get_batchtensorc                 C  rs   )z&String representation of a Dim object.)rS   rk   r   r   r   r        zDim.__repr__N)r%   )r    r!   r   r3   r   rb   r   )r   r   r   r   )r?  r3   r   rb   r   r   r   r   )r   r   r   r   r`   r   r   r   r=  r"   setterrt   rA  rE  r   object
__format__r   r   r   r   r$   y  s*   
 		



c                   @  s   e Zd ZU ded< ded< ded< ded< ded	< d
ed< ded< ed5ddZed6ddZed7ddZed8d"d#Z	d9d$d%Z
d:d'd(Zd;d)d*Zd9d+d,Zd<d/d0Zd=d2d3Zd4S )>r   r   _tensorr8  list[DimEntry]_levelsr   _has_devicez$Optional[Callable[[], torch.Tensor]]_delayedzOptional[Callable]_delayed_origzOptional[tuple]_delayed_argsr   r3   c                 C  s   t dd | jD S )Nc                 s  s     | ]}|  r
d ndV  qdS )r   r   N)r   r   r   r   r   r     r   zTensor.ndim.<locals>.<genexpr>)sumrM  rk   r   r   r   r     s   zTensor.ndimotherr   c                 C  r;  r   r<  )r   rS  r   r   r   r=    r>  zTensor.check_exactr   r   r   r   Union[_Tensor, torch.Tensor]c                 C  s   d}d}|D ]'}|  r)|dks$|d | ks$td| d|  | }q|d7 }q|dks=|dks=td| |sA|S |  }||_||_||_d|_d|_d|_d|_	|
 t|krptd|
  d	t| d
|S )a0  
        Create a functorch Tensor from a regular PyTorch tensor with specified dimension levels.

        This is the primary way to create Tensor objects with first-class dimensions.

        Args:
            tensor: The underlying PyTorch tensor
            levels: List of DimEntry objects specifying the dimension structure
            has_device: Whether the tensor is on a device (not CPU)

        Returns:
            A new Tensor instance with the specified dimensions, or a regular torch.Tensor
            if there are no named dimensions
        r   r   z/Positional dimensions must be consecutive, got z then r%   z0Final positional dimension must be 0 or -1, got NzTensor has z dimensions but z levels provided)r   r  r   rK  rM  rN  r8  rO  rP  rQ  rX   r=   )r   r   r   r   	seen_dimslastr   rP   r   r   r   r     s:   

zTensor.from_positionalorigr   r   rK   r   c                   sD   |  }d|_ ||_||_d|_|_ |_d fdd}||_|S )zP
        Create a delayed tensor that defers the operation until later.
        Nr   r   c                    s:   g }  D ]}t |dr| |  q| | q|  S )Nr   )rg   rJ   r   )unwrapped_argsr   r   rW  r   r   evaluate_delayed'  s   
z/Tensor.create_delayed.<locals>.evaluate_delayedrG  )rK  rM  rN  r8  rP  rQ  rO  )r   rW  r   r   r   rP   rZ  r   rY  r   r     s   	zTensor.create_delayedc                 C  s@   t | dr| jdur| jdu r|  | _d| _d| _d| _| jS )zAGet the underlying tensor, handling delayed operations if needed.rO  N)rg   rO  rK  rP  rQ  rk   r   r   r   r   4  s   


zTensor._get_tensorr   c                 C  rs   )zGet the dimension levels.)rM  rk   r   r   r   r   C  rF  zTensor._get_levelsc                 C  rs   )z/Get whether this tensor has device information.)rN  rk   r   r   r   _get_has_deviceG  rF  zTensor._get_has_devicec                 C  s&   | j du r| |  |  | _ | j S )zDGet the batched tensor representation, creating it lazily if needed.N)r8  _add_batch_dimsr   r   rk   r   r   r   rE  K  s
   
zTensor._get_batchtensortlevels_c           
      C  s   t |}	 d}d}td}d}d}t|D ] \}}	|	 s5|	 s1|	 j|k r1|	 j}|}|}|d7 }q|dkr<|S |d u rDtdtj	j
||t|}t ||< q)NTr%   infr   r   zExpected t to be non-None)ra   floatr[   r  r   rX   r6  r   r   rB  rC  rD  r3   r   )
r]   r]  r^  r   min_real_index	min_index	min_valuer2   r-  r   r   r   r   r\  S  s,   

zTensor._add_batch_dimsrQ   c                 G  s    ddl m} || g|R  }|S )z&Reorder the dimensions of this tensor.r   )order)_orderrd  )r]   rQ   rd  rP   r   r   r   rd  q  s   zTensor.orderNr   )rS  r   r   r   )r   r   r   rL  r   r   r   rT  )
rW  r   r   rK   r   rL  r   r   r   r   r4  r3  r   )r]  r   r^  r   r   r   )rQ   r   r   r   )r   r   r   r   r   r   r   r=  r   r   r   r   r[  rE  r\  rd  r   r   r   r   r     s,   
 ;




r   tensorsnew_dimrX   r3   c                 C  sj  | st dt|tstj| |d}|S g }g }| D ]}tj|ddd}|| |jD ]}||vr7|| q,qt	| |_
g }	|D ]}|jdu rMtdt|j|j|}
|	|
 qBt|}d}|durt|trn|dksdd	lm} |||d}z||}W n t y   td
| ddw |}t|	|}||t| t|||r|d j}|S d}|S )a$  
    Stack tensors along a new dimension.

    Args:
        tensors: Sequence of tensors to stack
        new_dim: The new Dim to create for stacking
        dim: The dimension position to insert the new dimension (default: 0)

    Returns:
        Stacked tensor with the new dimension
    z-stack expects a non-empty sequence of tensors)rX   Fr   Nz*Cannot stack tensors with None tensor datar   r   r
  z
Dimension z does not exist in inputsT)rH   rY   r$   r   r   r   r   rJ   r   r=   r"   r   r   r   r   r3   r  r  r   r  r  r   r   r   r   )rf  rg  rX   rP   r   r   r]  r   r   inputsmatched_tensorr   rawdimr  r5   r1  tensor_resultr   r   r   r   y  sT   





r   split_size_or_sectionsrK   c                 C  s  ddl m} t|t}t|tr'|rtdttj	j
t| f| |fd|iS g }d}d}|D ]}|| t|tr>d}q/d}q/|rZ|rItdttj	j
t| f| |fd|iS |s`tdtj| ddd}	|	 }
|sv|
d	krvtd
|dur|||
dnt|
 }d}t|	jD ]\}}||kr|} nq|du r|du rd	}td| g }d	}g }t|D ]\}}|jr||j ||d 7 }q|d	 || q|	jdu rtd|	j|}|r||krtd| d| d|| }|t| d t| }|D ]}t||}||| _|||< ||8 }qn||kr-td| d| d|	j||}g }t|	j}tt||D ]\}\}}t|||< |t	|t||	j qBt|S )z
    Split tensor along a dimension.

    Can handle both regular integer sizes and Dim objects for split sizes.
    When Dim objects are used, they get bound to the resulting tensor dimensions.
    r   r
  zKwhen dim is specified as a Dim object, split sizes must also be dimensions.rX   TFz-split list must be ints or dims but got a mixr   r   z+split expects at least a 1-dimension tensorNz"tensor does not contain dimension r%   z%Cannot get tensor size on None tensorz+sizes of target dimensions add up to more (z) than source dim (r   z#sum of sizes of target dimensions (z) do not match the source dim ()r  r  rY   r$   r3   r  r   r   r   r   r   r   rJ   r   r   r   r   r[   r   rt   r"   r   r   r=   minr   ra   zipr   r   rK   )r   rl  rX   r  dim_is_objectr(   all_dimsall_intsr^   r"  r   dim_lr1  r2   r   ry   
total_sizeunboundsize_dimtensor_sizeremaining_size
chunk_sizeuszresult_tensorsrP   r   result_tensorr   r   r   r     s   









r   c                 C  s    t d}t| ||||g|S r9  )rQ   r   r   )rf  rX   rg  r'   r   r   r   cat?  s   r}  c                   @  s$   e Zd ZdZdddZddd	Zd
S )DotPartzA
    Helper class for organizing dimensions in dot products.
    r   rb   c                 C  s   g | _ d| _d S r9  )rQ   rs  rk   r   r   r   r`   I  s   
zDotPart.__init__	dim_entryr   c                 C  s0   | j | | s|  j| j9  _dS dS )z#Add a dimension entry to this part.N)rQ   rJ   r   rs  rX   r"   )r]   r  r   r   r   rJ   M  s   zDotPart.appendN)r   rb   )r  r   r   rb   )r   r   r   r   r`   rJ   r   r   r   r   r~  D  s    
r~  partslist[DotPart]tensor_infor   c                 C  sr   g }d}| D ]}t |jdkrd}||j q|jdu r!tdt|j|j|}|s-|S dd | D }||S )zJ
    Prepare tensor for dot product by matching levels and reshaping.
    Fr   TNz)Cannot perform dot product on None tensorc                 S  s   g | ]}|j qS r   )rs  )r   partr   r   r   
<listcomp>h  s    zdot_prepare.<locals>.<listcomp>)r=   rQ   r   r   r@   r   r   r  )r  r  r   needs_reshaper  rP   viewr   r   r   dot_prepareT  s   

r  r|  c                 C  sn   g }d}| D ]}t |jdkrd}||j q|r.g }|D ]
}|| j q||}t||d}|S )zE
    Finish dot product by reshaping result and creating Tensor.
    Fr   T)	r=   rQ   r   rJ   rX   r"   r  r   r   )r  r|  r   r  r  new_sizer   rk  r   r   r   
dot_finishl  s   
r  lhsrhssum_dimsrT  c                   s  t j| ddd}t j|ddd}|r|st| |S |jdu s$|jdu r(td|j  |j t t t t d fdd}dgt|j	 }t
|j	D ]"\}}d}	t
|j	D ]\}
}||krs|
}	d||
<  nqc||||	 qXt
|j	D ]\}}|| s||d| qtjtkrD ]}||j	vr||j	vrtd| qtjdkrtg|}tg|}t||}tg|S tg|}tg|}t||}tg|S )z
    Perform dot product between two tensors along specified dimensions.

    Args:
        lhs: Left-hand side tensor
        rhs: Right-hand side tensor
        sum_dims: Dimensions to sum over (contract)

    Returns:
        Result of dot product
    Fr   Nz*Cannot perform dot product on None tensorsr5   r   lhs_idxrhs_idxr   rb   c                   s   | v }|dur | nd}|dur| nd}|r! |  dS |dk|dkkr0 |  dS |dkr; |  dS  |  dS )z?Insert dimension into appropriate part based on stride pattern.Nr   )rJ   )r5   r  r  reduced
lhs_stride
rhs_stridelhs_strideslo_dimslr_dimslro_dimsrhs_stridesro_dimsr  r   r   
insert_dim  s   zdot.<locals>.insert_dimTz$summing over non-existent dimension r   )r5   r   r  r   r  r   r   rb   )r   r   r   matmulr   r   r   r~  r=   r   r[   rQ   rH   r  bmmr  mm)r  r  r  r   r   r  rhs_seenr2   	lhs_levelr  r)  	rhs_levelr5   
lhs_tensor
rhs_tensorrP   r   r  r   dot  sR   

r  )r  )	wrap_typer]   	positionsc                 C  s\   t | trt| ||S tj| ddd}|jdu rtdt|j|j	|j
}t|||S )a  
    Index a regular tensor by binding specified positions to dims.

    This converts a regular tensor to a first-class tensor by binding
    the specified positional dimensions to Dim objects.

    Args:
        positions: Tuple of dimension positions to bind
        dims: Dim objects or tuple of Dim objects to bind to

    Returns:
        First-class tensor with specified dimensions bound
    Fr   NzCannot index None tensor)rY   r   r   r   r   r   r   r   r   r   r   )r]   r  rQ   r   rP   r   r   r   r     s   

r   c                 O  s.   t tj| }tt| t|g|R i | d S r   )getattrr   r   setattrr   r  )r    r   r   rW  r   r   r   _def  s   "r  meanrR  allamaxaminaminmaxanycount_nonzero	logsumexpnanmeannansumprodstdr   )keepdim_offsetvarmax)
single_dimrm  argmaxargminkthvaluemedian	nanmedianmodesortF)reduceargsortunbindchunk)
dim_offsetr  cummax)r  r  cummincumprodcumprod_cumsumcumsum_logcumsumexprenorm)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   rR   )r'   r#   r(   r)   r   r   )r   r   r   r   r   rb   )r   )rf  r   rg  r   rX   r3   r   r   )r   r   rl  r   rX   r   r   rK   )rf  r   rX   r   rg  r   r   r   )r  r  r  r   r   r   )r  r  r|  r   r   r   )r  r   r  r   r  r   r   rT  )r]   r   r  r   rQ   r   r   r   )r    r!   r   r   r   r   r   rb   )B
__future__r   disr>   rD   typingr   r   r   r   collections.abcr   r   r   torch.utils._pytreer	   r
   r   r  r   r   r   _enable_all_layersr   _py_inst_decoderr   _tensor_infor   r   r   r:  r   r   r&   rQ   rR   r   r   	Exceptionr   rc    r   r   r   r   
TensorLiker$   r   r   r}  r~  r  r  r  functorch.dim._wrapr  functorch.dim.wrap_typer  r   r   r   r  nn
functionalr   r   r   r   r   <module>   s    

c Y
   
MQ 0E 



X

