U
    <c#@                     @   sl  d dl mZ d dlZddlmZmZmZ ddlmZm	Z	m
Z
mZmZ ddlmZmZ ddlmZmZmZmZ ddlmZmZmZ g Zd[d	d
ZG dd dejjZG dd dejjZG dd dejjZG dd dejjZ G dd dejjZ!i Z"e#ee#ee#efeiZ$e$% D ]0\Z&Z'e&D ] Z(e(D ]Z)ee'e)e"e)< q,q$qdd Z*e*ee e dd Z+e*ej,j-ej-gdd Z.e*ej,j/gdd Z0e*ej,j1gdd Z2e*ej,j3gdd  Z4e*ej,j5gd!d" Z6i Z7d#d$ Z8e8ee e d%d& Z9e8ed'd( Z:e8ee d)d* Z;e8ee d+d, Z<e8ej=j>j?gd-d. Z?e8ej=j>j@gd/d0 Z@e8ej=jAjBgd1d2 ZBe8ej=j>jCgd3d4 ZCe8ej=j>jDgd5d6 ZDe8ej=j>jEgd7d8 ZEe8ej=j>j/gd9d: Z/e8ej=j>jFgd;d< ZFe8ej=j>jGgd=d> ZGe8ej=j>jHej=j>jIgd?d@ ZJe8ej=j>jKgdAdB ZKe8ej=j>jLgdCdD ZLe8ej=j>jMgdEdF ZMe8ej=j>jNgdGdH ZNe8ej=j>jOgdIdJ ZOe8ej=j>j-gdKdL Z-e8ej=j>j3gdMdN Z3e8ej=j>j5gdOdP Z5e8ej=j>jPgdQdR ZPe8ej=j>jQgdSdT ZQe8ej=j>jRgdUdV ZRe8ej=j>jSgdWdX ZSe8ej=j>jTgdYdZ ZTdS )\    )partialN   )_apply_native_binaryNATIVE_BINARY_FNSNATIVE_INPLACE_BINARY_FNS)is_masked_tensorMaskedTensor	_get_data_masks_match_maybe_get_mask)_apply_pass_through_fnPASSTHROUGH_FNS)_apply_reductionNATIVE_REDUCE_FNSTORCH_REDUCE_FNSTENSOR_REDUCE_FNS)_apply_native_unaryNATIVE_UNARY_FNSNATIVE_INPLACE_UNARY_FNSc                 C   sd   |d k	r0|t | kr0t| d| dt |  |d k	r`|t |kr`t| d| dt | d S )Nz: len(args) must be z	 but got z: len(kwargs) must be )len
ValueError)argskwargsZerror_prefixlen_args
len_kwargs r   G/tmp/pip-unpacked-wheel-gikjz4vx/torch/masked/maskedtensor/_ops_refs.py_check_args_kwargs_length    s    r   c                   @   s$   e Zd Zedd Zedd ZdS )_MaskedContiguousc                 C   s>   t |std| r|S | }| }t| | S )Nz7MaskedContiguous forward: input must be a MaskedTensor.)r   r   is_contiguousget_dataget_maskr   
contiguousctxinputdatamaskr   r   r   forward(   s    z_MaskedContiguous.forwardc                 C   s   |S Nr   r$   grad_outputr   r   r   backward5   s    z_MaskedContiguous.backwardN__name__
__module____qualname__staticmethodr(   r,   r   r   r   r   r   '   s   
r   c                   @   s$   e Zd Zedd Zedd ZdS )_MaskedToDensec                 C   sJ   t |std|jtjkr |S |j| _| }| }t| | S )Nz4MaskedToDense forward: input must be a MaskedTensor.)	r   r   layouttorchstridedr    r!   r   to_denser#   r   r   r   r(   ;   s    z_MaskedToDense.forwardc                 C   sJ   | j }|tjkr| S |tjkr*| S |tjkr<| S td|d S )Nz$to_dense: Unsupported input layout: )	r3   r4   
sparse_cooto_sparse_coo
sparse_csrto_sparse_csrr5   r6   r   )r$   r+   r3   r   r   r   r,   I   s    


z_MaskedToDense.backwardNr-   r   r   r   r   r2   :   s   
r2   c                   @   s$   e Zd Zedd Zedd ZdS )_MaskedToSparsec                 C   sP   t |std|jtjkr |S | }| }|  }|	|}t
||S )Nz5MaskedToSparse forward: input must be a MaskedTensor.)r   r   r3   r4   r7   r    r!   r8   coalescesparse_maskr   r$   r%   r&   r'   r=   Zsparse_datar   r   r   r(   W   s    
z_MaskedToSparse.forwardc                 C   s   |  S r)   r6   r*   r   r   r   r,   g   s    z_MaskedToSparse.backwardNr-   r   r   r   r   r;   V   s   
r;   c                   @   s$   e Zd Zedd Zedd ZdS )_MaskedToSparseCsrc                 C   sl   t |std|jjdkr0td|j  |jtjkr@|S | }|	 }|
 }||}t||S )Nz8MaskedToSparseCsr forward: input must be a MaskedTensor.   zHOnly 2D tensors can be converted to the SparseCsr layout but got shape: )r   r   Z_masked_datandimsizer3   r4   r9   r    r!   r:   r=   r   r>   r   r   r   r(   m   s    
z_MaskedToSparseCsr.forwardc                 C   s   |  S r)   r?   r*   r   r   r   r,      s    z_MaskedToSparseCsr.backwardNr-   r   r   r   r   r@   l   s   
r@   c                   @   s$   e Zd Zedd Zedd ZdS )_MaskedWherec                 C   s&   |  | | | tjj|||S r)   )Zmark_non_differentiableZsave_for_backwardr4   opsatenwhere)r$   condselfotherr   r   r   r(      s    

z_MaskedWhere.forwardc                 C   s>   | j \}dd }d tjj||||tjj||||fS )Nc                 S   s   t |  t|   S r)   )r   r    r4   Z
zeros_liker!   bool)mtr   r   r   masked_out_like   s    z._MaskedWhere.backward.<locals>.masked_out_like)Zsaved_tensorsr4   rE   rF   rG   )r$   r+   rH   rM   r   r   r   r,      s    z_MaskedWhere.backwardNr-   r   r   r   r   rD      s   
rD   c                    s    fdd}|S )a/  
    Used for registering a new __torch_function__ function to MaskedTensor
    Called via _MASKEDTENSOR_FUNCTION_TABLE[func](*args, **kwargs)

    The code to register a new function looks like:

    @register_function_func(list_of_ops)
    def foo(func, *args, **kwargs):
        <implementation>
    c                    s    D ]}t | |t|< qd S r)   )r   _MASKEDTENSOR_FUNCTION_TABLE)funcoprE   r   r   wrapper   s    z'register_function_func.<locals>.wrapperr   )rE   rR   r   rQ   r   register_function_func   s    rS   c                 O   s   t | f||S r)   r   rO   r   r   r   r   r   _general_function_reductions   s    rV   c                 O   s   t ||dddd tj| S )Nz__torch_function__, torch.where   r   r   r   )r   rD   applyrU   r   r   r   _function_where   s    rZ   c                 O   s   t |d S Nr   )r   rY   rU   r   r   r   _function_contiguous   s    r\   c                 O   s   t |d S r[   )r2   rY   rU   r   r   r   _function_to_dense   s    r]   c                 O   s   t |d S r[   )r;   rY   rU   r   r   r   _function_to_sparse   s    r^   c                 O   s   t |d S r[   )r@   rY   rU   r   r   r   _function_to_sparse_csr   s    r_   c                    s    fdd}|S )a/  
    Used for registering a new __torch_dispatch__ function to MaskedTensor
    Called via _MASKEDTENSOR_DISPATCH_TABLE[func](*args, **kwargs)

    The code to register a new function looks like:

    @register_dispatch_func(list_of_ops)
    def foo(func, *args, **kwargs):
        <implementation>
    c                    s    D ]}t | |t|< qd S r)   )r   _MASKEDTENSOR_DISPATCH_TABLE)rO   Zaten_opaten_opsr   r   rR      s    z'register_dispatch_func.<locals>.wrapperr   )rb   rR   r   ra   r   register_dispatch_func   s    rc   c                 O   s   t | f||S r)   rT   rU   r   r   r   _general_reduction   s    rd   c                 O   s   t | f||S r)   )r   rU   r   r   r   _general_passthrough   s    re   c                 O   s   t | f||S r)   )r   rU   r   r   r   _general_unary   s    rf   c                 O   s   t | f||S r)   )r   rU   r   r   r   _general_binary   s    rg   c                 O   s   d S r)   r   rU   r   r   r   stride   s    rh   c                 O   s   d S r)   r   rU   r   r   r   
sym_stride  s    ri   c                 O   s   t |d jS r[   )r	   r3   rU   r   r   r   r3     s    r3   c                 O   s2   t |d }|jrtd| |f|dd  |S )Nr   z8MaskedTensors with sparse data do not have is_contiguousr   r	   	is_sparser   rO   r   r   r&   r   r   r   r     s    r   c                 O   s2   t |d }|jrtd| |f|dd  |S )Nr   zAMaskedTensors with sparse data do not have is_strides_like_formatr   rj   rl   r   r   r   is_strides_like_format  s    rm   c                 O   s2   t |d }|jrtd| |f|dd  |S )Nr   zGMaskedTensors with sparse data do not have is_non_overlapping_and_denser   rj   rl   r   r   r   is_non_overlapping_and_dense  s    rn   c                 O   s$   t |d jrtdt|d S )Nr   z5MaskedTensors with sparse data do not have contiguous)r	   rk   r   r   rY   rU   r   r   r   r"   )  s
    r"   c                 O   s   t ||d|  dd t|d }t|d }t|d t| krVtd|  dt|d t| kr~td|  dt| ||d |d f||S )	N__torch_dispatch__, rW   r   r   r   z0: args[1] expected to be the same as data.size()rA   z2: args[2] expected to be the same as data.stride())r   r	   r   tuplerC   r   rh   r   )rO   r   r   r&   r'   r   r   r   new_empty_strided2  s    rr   c                 O   s2   t |d std|  dtjjt|d S )Nr   ro   z: expected a mask tensor)r   r   r4   rE   rF   _local_scalar_denser	   rU   r   r   r   rs   >  s    rs   c                 O   s   t | t|d t|d S r[   )r   r	   r   rU   r   r   r   _apply_fn_on_dataE  s    rt   c                 O   s2   | t |d f|dd  |}t|t|d S )Nr   r   )r	   r   r   )rO   r   r   new_datar   r   r   _to_copyJ  s     rv   c                 O   sT   t ||d|  ddd t|d }t|d }tjj|| |d d}t||S )Nro   rW   r   rX   r   rA   )r   r	   r   r4   rE   rF   Z_masked_softmaxr   )rO   r   r   r&   r'   result_datar   r   r   _softmaxP  s
    rx   c                 O   s<   t ||d|  dd | t|d f|}t|t|d S )Nro   r   rp   r   )r   r	   r   r   )rO   r   r   rw   r   r   r   	ones_likeY  s    ry   c           
      O   s   t ||d|  dd |\}}}}t|rt|rt||sDtdt|}tjj|t|t	| ||j
 }t|t	|}	|	S td|  dd S )Nro      rp   zJ__torch_dispatch__, {func}: expected the masks of grad and output to matchz,: grad and output must both be MaskedTensors)r   r   r
   r   r	   r4   rE   rF   Z_masked_softmax_backwardr   rB   r   )
rO   r   r   ZgradoutputZdimZinput_dtypeZ	grad_dataZnew_grad_dataresr   r   r   _softmax_backward_data`  s    
r}   c                 O   sZ   t ||d|  dd tt|d t|d s8td| t|d t|d  |d S )Nro   rA   rp   r   r   z3args[0] mask and args[1] mask must match but do not)r   r
   r   r   r	   rU   r   r   r   copy_t  s
    r~   c                 O   s   t ||d|  ddd t|d s.td|d }|d }t|s\t|tj|tjd}t|szt|tj|tjd}| |d | | }| |d |	 |	 }t||S )	Nro   rW   r   rX   ;__torch_dispatch__, {func}: expected args[0] to be a tensorr   rA   Zdtype)
r   r4   	is_tensorr   r   r   ry   rK   r    r!   )rO   r   r   ZmxZmyru   new_maskr   r   r   rG   }  s    rG   c                 O   s   t ||d|  ddd t|d s.td|d }t|sTt|tj|tjd}| r`|S | t	|d 
 }t|d |}t||S )Nro   r   r   rX   r   r   )r   r4   r   	TypeErrorr   r   ry   rK   Zis_sparse_coor   r<   r	   r=   rO   r   r   rL   r   ru   r   r   r   	to_sparse  s    r   c                 O   s   t ||d|  ddd t|d s.td|d }t|sRt|t| }| r^|S | t	|d }t
|d |}t||S Nro   r   r   rX   r   )r   r4   r   r   r   r   ry   rK   Zis_sparse_csrr   r	   r=   r   r   r   r   r:     s    r:   c                 O   s|   t ||d|  ddd t|d s.td|d }t|sRt|t| }| t|d }| t	|d }t||S r   )
r   r4   r   r   r   r   ry   rK   r	   r   )rO   r   r   rL   ru   r   r   r   r   	_to_dense  s    r   c                 O   s<   t ||d|  ddd t|d  }t|t| S Nro   r   r   rX   )r   r	   indicesr   r4   ry   rK   rl   r   r   r   _indices  s    r   c                 O   s<   t ||d|  ddd t|d  }t|t| S r   )r   r	   valuesr   r4   ry   rK   rl   r   r   r   _values  s    r   c                 O   st   t |}t|d r$|d  |d< t|d r@|d  |d< | ||}t|d |d< | || }t||S )N)listr   r    r4   ry   rK   r   )rO   r   r   new_argsru   r   r   r   r   (_sparse_coo_tensor_with_dims_and_tensors  s    
r   c                 O   s0   t ||d|  dd t|d t|d S )Nro   rA   rp   r   r   )r   r	   is_same_sizerU   r   r   r   r     s    r   )NN)U	functoolsr   r4   binaryr   r   r   corer   r   r	   r
   r   Zpassthroughr   r   Z
reductionsr   r   r   r   Zunaryr   r   r   __all__r   ZautogradZFunctionr   r2   r;   r@   rD   rN   rq   Z_function_fn_apply_mapitemsZfn_map_listZapply_fnZfn_mapfnrS   rV   ZTensorrG   rZ   r"   r\   r6   r]   r   r^   r:   r_   r`   rc   rd   re   rf   rg   rE   rF   rh   ri   Zprimr3   r   rm   rn   rr   rs   detachclonert   rv   rx   ry   r}   r~   r   r   r   r   r   r   r   r   r   <module>   s   
 















	
	
	















