U
    <ºcD  ã                   @   sl   d dl Z d dlm  mZ ddlmZ ddlmZm	Z	m
Z
 d dlmZmZ eejƒG dd„ de jjƒƒZdS )é    Né   )Úimplements_per_sample_grads)Úforward_helperÚset_grad_sample_if_existsÚ unpack_expanded_weight_or_tensor)ÚListÚOptionalc                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )ÚLinearPerSampleGradc                 G   sp   t |d jƒdkr*tdt |d jƒ› ƒ‚dt |ƒdkr@|d nd i}|d d… }ttj||ƒ}|| _|| _|S )Nr   r   zgInput does not have a batch dimension. Expanded Weights expected input of at least rank 2, got of rank Úbiasé   é   )ÚlenÚshapeÚRuntimeErrorr   ÚFÚlinearÚargsÚkwargs)ÚctxÚ_Ú__Zexpanded_args_and_kwargsZexpanded_kwargsZexpanded_argsÚoutput© r   ú\/tmp/pip-unpacked-wheel-gikjz4vx/torch/nn/utils/_expanded_weights/linear_expanded_weights.pyÚforward
   s    zLinearPerSampleGrad.forwardc                    s   | j \‰}| jd }g }| d ¡ | d ¡ ˆjrH| ˆ  t|ƒ¡¡ n
| d ¡ | d gd ¡ t|‡ ‡fdd„ƒ t|‡ fdd„ƒ t|ƒS )Nr
   r   c                    s   t  dˆ ˆ¡S )Nzn...i,n...j->nij©ÚtorchZeinsum©r   ©Úgrad_outputÚinputr   r   Ú<lambda>%   ó    z.LinearPerSampleGrad.backward.<locals>.<lambda>c                    s   t  dˆ ¡S )Nz	n...k->nkr   r   )r   r   r   r!   &   r"   )	r   r   ÚappendZrequires_gradÚmatmulr   Úextendr   Útuple)r   r   Zweightr
   Úresultsr   r   r   Úbackward   s    




zLinearPerSampleGrad.backwardN)Ú__name__Ú
__module__Ú__qualname__Ústaticmethodr   r(   r   r   r   r   r	      s   
r	   )r   Ztorch.nn.functionalÚnnZ
functionalr   Zexpanded_weights_implr   Zexpanded_weights_utilsr   r   r   Útypingr   r   r   ZautogradZFunctionr	   r   r   r   r   Ú<module>   s   