o
    si                     @   s&  d dl 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	 ddl
mZ d	Zd$d
ee defddZed$defddZed$defddZG dd dejZG dd deZG dd deZG dd deZG dd deZG dd deZeZeZeZeZeZdd Zd d! Zd"d# Z dS )%    )partialN)nn)
_BatchNorm)List   )
complex_nn)script_if_tracing:0yE>dimsepsc                 C   s:   | j |dd}tj| |ddd}| | t||  }|S )NTdimkeepdimFr   r   unbiased)meantorchvarsqrt)xr
   r   r   var2value r   I/home/ubuntu/.local/lib/python3.10/site-packages/asteroid/masknn/norms.pyz_norm   s   r   c                 C   "   t dt| j }t| ||S )N   r   arangelenshapetolistr   r   r   r
   r   r   r   
_glob_norm      r#   c                 C   r   )Nr   r   r"   r   r   r   _feat_glob_norm   r$   r%   c                       s(   e Zd ZdZ fddZdd Z  ZS )
_LayerNormzLayer Normalization base class.c                    sD   t t|   || _tjt|dd| _tjt	|dd| _
d S )NT)requires_grad)superr&   __init__channel_sizer   	Parameterr   onesgammazerosbeta)selfr*   	__class__r   r   r)   #   s   z_LayerNorm.__init__c                 C   s    | j |dd | j ddS )z+Assumes input of size `[batch, chanel, *]`.r   )r-   	transposer/   )r0   normed_xr   r   r   apply_gain_and_bias)   s    z_LayerNorm.apply_gain_and_bias)__name__
__module____qualname____doc__r)   r6   __classcell__r   r   r1   r   r&       s    r&   c                   @       e Zd ZdZddefddZdS )GlobLNz$Global Layer Normalization (globLN).r	   EPSc                 C      t ||d}| |S )zApplies forward pass.

        Works for any input size > 2D.

        Args:
            x (:class:`torch.Tensor`): Shape `[batch, chan, *]`

        Returns:
            :class:`torch.Tensor`: gLN_x `[batch, chan, *]`
        r   )r#   r6   r0   r   r>   r   r   r   r   forward1      
zGlobLN.forwardNr	   r7   r8   r9   r:   floatrB   r   r   r   r   r=   .       r=   c                   @   r<   )ChanLNz*Channel-wise Layer Normalization (chanLN).r	   r>   c                 C   s<   t j|ddd}t j|dddd}| || ||   S )zApplies forward pass.

        Works for any input size > 2D.

        Args:
            x (:class:`torch.Tensor`): `[batch, chan, *]`

        Returns:
            :class:`torch.Tensor`: chanLN_x `[batch, chan, *]`
        r   Tr   Fr   )r   r   r   r6   r   )r0   r   r>   r   r   r   r   r   rB   C   s   zChanLN.forwardNrD   rE   r   r   r   r   rH   @   rG   rH   c                   @   r<   )CumLNz-Cumulative Global layer normalization(cumLN).r	   r>   c                 C   s   |  \}}}tj|jddddd}tj|djddddd}tj|||d  ||j|jdddd}|| }	|| |	d }
| 	||	 |
| 
  S )z

        Args:
            x (:class:`torch.Tensor`): Shape `[batch, channels, length]`
        Returns:
             :class:`torch.Tensor`: cumLN_x `[batch, channels, length]`
        r   T)r   r3   )r   r   )startendstepdtypedevice)sizer   cumsumsumpowr   rM   rN   viewr6   r   )r0   r   r>   batchchanspec_lencum_sumcum_pow_sumcntcum_meancum_varr   r   r   rB   V   s   
zCumLN.forwardNrD   rE   r   r   r   r   rI   S   rG   rI   c                   @   r<   )FeatsGlobLNznFeature-wise global Layer Normalization (FeatsGlobLN).
    Applies normalization over frames for each channel.r	   r>   c                 C   r?   )zApplies forward pass.

        Works for any input size > 2D.

        Args:
            x (:class:`torch.Tensor`): `[batch, chan, time]`

        Returns:
            :class:`torch.Tensor`: chanLN_x `[batch, chan, time]`
        r@   )r%   r6   rA   r   r   r   rB   m   rC   zFeatsGlobLN.forwardNrD   rE   r   r   r   r   r\   i   s    r\   c                   @   s   e Zd ZdZdd ZdS )	BatchNormz5Wrapper class for pytorch BatchNorm1D and BatchNorm2Dc                 C   s.   |  dk s|  dkrtd|  d S )Nr      z'expected 4D or 3D input (got {}D input))r   
ValueErrorformat)r0   inputr   r   r   _check_input_dim   s   zBatchNorm._check_input_dimN)r7   r8   r9   r:   rb   r   r   r   r   r]   |   s    r]   c                 C   sL   | j t  v s| j  t  v rtd| j  dt | j | i dS )zqRegister a custom norm, gettable with `norms.get`.

    Args:
        custom_norm: Custom norm to register.

    zNorm z% already exists. Choose another name.N)r7   globalskeyslowerr_   update)custom_normr   r   r   register_norm   s   $rh   c                 C   sZ   | du rdS t | r| S t| tr%t | }|du r#tdt|  |S tdt|  )zReturns a norm class from a string. Returns its input if it
    is callable (already a :class:`._LayerNorm` for example).

    Args:
        identifier (str or Callable or None): the norm identifier.

    Returns:
        :class:`._LayerNorm` or None
    Nz.Could not interpret normalization identifier: )callable
isinstancestrrc   getr_   )
identifierclsr   r   r   rl      s   

rl   c                 C   s    t | }|du r
dS ttj|S )zQLike `.get` but returns a complex norm created with `asteroid.complex_nn.OnReIm`.N)rl   r   r   OnReIm)rm   normr   r   r   get_complex   s   rq   rD   )!	functoolsr   r   r   torch.nn.modules.batchnormr   typingr    r   utils.torch_utilsr   r>   intrF   r   r#   r%   Moduler&   r=   rH   rI   r\   r]   gLNfgLNcLNcgLNbNrh   rl   rq   r   r   r   r   <module>   s6    	