o
    i^                      @  s   d Z ddlmZ ddlZddlmZmZmZ ddlZddl	m
Z
 ddlmZ ddlmZ dd	lmZ er:dd
lmZ d7ddZG dd dZd8d9ddZd8d:ddZd;d"d#Z					d<d=d.d/Z	0	d>d?d5d6ZdS )@zM
Python implementation of function wrapping functionality for functorch.dim.
    )annotationsN)AnyOptionalTYPE_CHECKING)tree_map   )DimEntry)EnableAllLayers)
TensorInfo)Callabletensortorch.Tensorreturnc                 C  s   | S )z8Handle tensor conversion for torch function integration. )r   r   r   U/sda-disk/www/egybert/egybert_env/lib/python3.10/site-packages/functorch/dim/_wrap.pyhandle_from_tensor   s   r   c                   @  s(   e Zd ZdZ	dddd	ZdddZdS )WrappedOperatorzP
    This class wraps PyTorch operations to support first-class dimensions.
    dimorigr   wrapper_implementationdim_namestrc                 C  sz   || _ || _t|dd| _t|dd | _|| _d| _d| _d| _d| _	d| _
| jr9| jr;| j d| j d	| _d S d S d S )
N__name__ __doc__Fr   r   Tz
Argument 'z5' can be either an integer or a torchdim.Dim object.
)r   r   getattrnamedocr   is_pointwise
dim_offsetkeepdim_offset
single_dimreduce)selfr   r   r   r   r   r   __init__    s   zWrappedOperator.__init__r   c                   s.   d fdd}t j| jddd	  j|_|S )z@Create a wrapped function that calls our wrapper implementation.argsr   kwargsr   c                    s    j  g| R i |S )N)r   )r%   r&   r#   r   r   wrapped_func6   s   z.WrappedOperator.function.<locals>.wrapped_func)r   r   )assignedupdatedN)r%   r   r&   r   r   r   )	functoolsupdate_wrapperr   r   r   )r#   r(   r   r'   r   function3   s   
zWrappedOperator.functionN)r   )r   r   r   r   r   r   )r   r   )r   
__module____qualname__r   r$   r-   r   r   r   r   r      s
    r   Fr   r   ndimintkeepdimboolr   c                 C  s^   ddl m} t| |r|rtdt| S t| tr,| }|dkr(||8 }|dks t|S t S )z:Convert single dimension specification to DimEntry object.r   )Dimz8cannot preserve first-class dimensions with keepdim=Truer   )r   r4   
isinstance
ValueErrorr   r1   )r   r0   r2   r4   ir   r   r   	_wrap_dimB   s   

r8   list[DimEntry]c                 C  sF   t | ||}g }| s|| |S | D ]}|t ||| q|S )z<Convert dimension specification to list of DimEntry objects.)r8   is_noneappend)r   r0   r2   deresultdr   r   r   
_wrap_dimsS   s   
r?   wrapperr%   r&   c                   sN  |st d|| j}|du r&| jt|k r&| jd }|t|k r&|| }|du r|tj|d ddd  s>| j|i |S t j	1} j
dusKJ | j
 j	 t|}t j
|d< | j|i |}|| jW  d   S 1 sww   Y  t|d   s| j|i |S d}| jr|d}	|	du r| jt|k r| jd }
|
t|k r||
 }	|	durt|	}  }t|||}g }dgt j	 }|D ]U}d}t j	D ]\}}||kr|} nq|du rt j	D ]\}}t|d	r||r|} nq|du rd
d  j	D }t d| d| d||< || qg | jrD|sDt j	D ]\}}|| sA| q3n j	dd t|dkrW|d }nt|}t|}| } jduskJ t j|d< | j|v r~||| j< n| jd }|t|k rt|}|||< | j|i |}d fdd}t||S )zJ
    This is the core method that handles dimension-aware operations.
    z%Expected at least one argument (self)Nr   r   TF)ensure_batchedensure_presentr2   matchesc                 S  s   g | ]}t |qS r   )r   ).0levelr   r   r   
<listcomp>   s    z&patched_dim_method.<locals>.<listcomp>zTensor with dimensions z does not contain objr   r   c                   s,   t | tjrddlm} ||  jS | S )Nr   )Tensor)r5   torchrH   r   from_positional
has_device)rG   rH   info
new_levelsr   r   wrap_result   s   z'patched_dim_method.<locals>.wrap_result)rG   r   r   r   )r6   getr   r   lenr
   creater   r	   levelsbatchedtensorinplace_update_layerslistr   from_batchedrK   r"   r    r3   r0   r?   	enumeratehasattrrC   r;   tuplecopyr   r   )r@   r%   r&   dim_argdim_idxguardnew_argsr=   r2   keepdim_argkeepdim_idxr0   dimsdim_indicesseenr>   midxr7   rE   
level_strs
py_indices
new_kwargsrO   r   rL   r   patched_dim_method_   s   
 	








ri   r   r   r   Optional[int]r    r   Optional[str]r!   Optional[bool]r"   c                 C  sT   |pd}t | t|}|dur||_|dur||_|dur||_|dur&||_| S )a  
    Wrap a PyTorch function to support first-class dimensions.

    Args:
        orig: Original function to wrap
        dim_offset: Offset for dimension argument (default: 0)
        keepdim_offset: Offset for keepdim argument (default: 1)
        dim_name: Name of dimension parameter (default: "dim")
        single_dim: Whether function takes single dimension (default: False)
        reduce: Whether function reduces dimensions (default: True)
    r   N)r   ri   r   r    r!   r"   r-   )r   r   r    r   r!   r"   r@   r   r   r   _wrap   s   rm   r   functypesrZ   Optional[dict]c                 C  s(   |du ri }ddl m} |||||S )z@
    Handle __torch_function__ calls for wrapped operators.
    Nr   )_Tensor)r   rq   __torch_function__)r@   rn   ro   r%   r&   rq   r   r   r   call_torch_function   s   
rs   )r   r   r   r   )F)r   r   r0   r1   r2   r3   r   r   )r   r   r0   r1   r2   r3   r   r9   )r@   r   r%   r   r&   r   r   r   )NNNNN)r   r   r   rj   r    rj   r   rk   r!   rl   r"   rl   r   r   )r   N)r@   r   rn   r   ro   rZ   r%   rZ   r&   rp   r   r   )r   
__future__r   r+   typingr   r   r   rI   torch.utils._pytreer   
_dim_entryr   _enable_all_layersr	   _tensor_infor
   collections.abcr   r   r   r8   r?   ri   rm   rs   r   r   r   r   <module>   s2    
'
z'