o
    %ݫi(                     @   s   d Z ddlZddlZddlm  mZ dd ZdddZ	dd	d
Z
dddZdd Zdd Z	dddZ	dddZdd Zdd ZdddZdS ) zThis library implements different operations needed by complex-
 valued architectures.
 This work is inspired by: "Deep Complex Networks" from Trabelsi C.
 et al.

Authors
 * Titouan Parcollet 2020
    Nc                 C   sH   t | dvrtdtt  | d }|d dkr"tdt| dS )zCheck the complex-valued shape for a linear layer.

    Arguments
    ---------
    input_shape : tuple
        Expected shape of the input.
    >         zCComplex linear accepts only input of dimension 2 or 3. input.dim =    r   zWComplex torch.Tensors must have an even number of hidden dimensions. input.size()[1] = N)len	Exceptionstrinputdim)input_shape	nb_hidden r   [/home/ubuntu/.local/lib/python3.10/site-packages/speechbrain/nnet/complex_networks/c_ops.pycheck_complex_input   s   
r   linearr   c                 C   sp   |dkr*|   d }|  dkr| dd|d S |  dkr(| dd|d S dS |  |}| |d|d S )aF  Returns the real components of the complex-valued input.

    Arguments
    ---------
    input : torch.Tensor
        Input tensor.
    input_type : str,
        (convolution, linear) (default "linear")
    channels_axis : int.
        Default 1.

    Returns
    -------
    The real component of complex-valued inputs.
    r   r   r   r   r   r   Nsizer
   narrowr	   
input_typechannels_axisr   nb_featmapsr   r   r   get_real&   s   


r   c                 C   s|   |dkr.|   d }|  dkr| d|d |d S |  dkr,| d|d |d S dS |  |}| ||d |d S )aO  Returns the imaginary components of the complex-valued input.

    Arguments
    ---------
    input : torch.Tensor
        Input tensor.
    input_type : str
        (convolution, linear) (default "linear")
    channels_axis : int
        Default 1.

    Returns
    -------
    The imaginary components of complex-valued inputs.
    r   r   r   r   r   Nr   r   r   r   r   get_imagF   s   
r   c                 C   sT   t | ||}t| ||}|dkrtj|| gddS |dkr(tj|| g|dS dS )aL  Returns the conjugate (z = r - xi) of the input complex numbers.

    Arguments
    ---------
    input : torch.Tensor
        Input tensor
    input_type : str,
        (convolution, linear) (default "linear")
    channels_axis : int.
        Default 1.

    Returns
    -------
    The conjugate of the input complex numbers.
    r   r   r
   convolutionN)r   r   torchcat)r	   r   r   
input_imag
input_realr   r   r   get_conjugatef   s   r    c                 C   s   t j|| gdd}t j||gdd}t j||gdd}|  dkr2|jr,t || |S t | |S t | |}|jr?|| S |S )a  
    Applies a complex linear transformation to the incoming data.

    Arguments
    ---------
    input : torch.Tensor
        Complex input tensor to be transformed.
    real_weight : torch.Parameter
        Real part of the quaternion weight matrix of this layer.
    imag_weight : torch.Parameter
        First imaginary part of the quaternion weight matrix of this layer.
    bias : torch.Parameter

    Returns
    -------
    Output after complex linear transformation is applied.
    r   r   r   r   )r   r   r
   requires_gradaddmmmmmatmul)r	   real_weightimag_weightbiascat_realcat_imagcat_complexoutputr   r   r   complex_linear_op~   s   r,   c                 C   s\   t j|| gdd}t j||gdd}	t j||	gdd}
|r"tj}ntj}|| |
||||S )a>  Applies a complex convolution to the incoming data.

    Arguments
    ---------
    input : torch.Tensor
        Complex input tensor to be transformed.
    real_weight : torch.Parameter
        Real part of the quaternion weight matrix of this layer.
    imag_weight : torch.Parameter
        First imaginary part of the quaternion weight matrix of this layer.
    bias : torch.Parameter
    stride : int
        Stride factor of the convolutional filters.
    padding : int
        Amount of padding. See torch.nn documentation for more information.
    dilation : int
        Dilation factor of the convolutional filters.
    conv1d : bool
        If true, a 1D convolution operation will be applied. Otherwise, a 2D
        convolution is called.

    Returns
    -------
    Output after complex convolution is applied.
    r   r   r   )r   r   Fconv1dconv2d)r	   r%   r&   r'   stridepaddingdilationr.   r(   r)   r*   convfuncr   r   r   complex_conv_op   s   r4   glorotc           
      C   s   |du r	| |f}nt |tu r|| ft|f }n	|| fg |R  }t|}tjdd|}tjdd|}td|D ]#}t|| d || d  d }	||  |	  < ||  |	  < q<|	|}|	|}||fS )a  Returns a matrix of unitary complex numbers.

    Arguments
    ---------
    in_features : int
        Number of real values of the input layer (quaternion // 4).
    out_features : int
        Number of real values of the output layer (quaternion // 4).
    kernel_size : int
        Kernel_size for convolutional layers (ex: (3,3)).
    criterion : str
        (glorot, he) (default "glorot").

    Returns
    -------
    Matrix of unitary complex numbers.
    Ng            ?r   r   g-C6?)
typeinttuplenpprodrandomuniformrangesqrtreshape)
in_featuresout_featureskernel_size	criterionkernel_shapenumber_of_weightsv_rv_iinormr   r   r   unitary_init   s   

"

rK   c                 C   s   |durt |}|| }| | }n|}| }|dkr!d||  }nd| }|du r.| |f}nt|tu r>|| ft|f }n	|| fg |R  }t jj||d}	t jt j t j|}
|	t 	|
 }|	t 
|
 }||fS )a  Returns a matrix of complex numbers initialized as described in:
    "Deep Complex Networks", Trabelsi C. et al.

    Arguments
    ---------
    in_features : int
        Number of real values of the input layer (quaternion // 4).
    out_features : int
        Number of real values of the output layer (quaternion // 4).
    kernel_size : int
        Kernel_size for convolutional layers (ex: (3,3)).
    criterion: str
        (glorot, he) (default "glorot")

    Returns
    -------
    Matrix of initialized complex numbers.
    Nr5   r6   )scaler   )r:   r;   r7   r8   r9   r<   rayleighr=   picossin)rA   rB   rC   rD   receptive_fieldfan_outfan_insr   modulusphaseweight_realweight_imagr   r   r   complex_init   s&   


rY   c                 C   sT   ||  d|  dd|\}}t|t|}}|| j| _||j|_dS )a  Applies the weight initialization function given to the parameters.

    Arguments
    ---------
    real_weight: torch.Parameters
    imag_weight: torch.Parameters
    init_func: function
        (unitary_init, complex_init)
    criterion: str
        (glorot, he)
    r   r   Nr   r   
from_numpytype_asdata)r%   r&   	init_funcrD   abr   r   r   affect_init*  s   ra   c           	      C   s^   |  d}|  d}|||||d\}}t|t|}}|| j| _||j|_dS )a^  Applies the weight initialization function given to the parameters.
    This is specifically written for convolutional layers.

    Arguments
    ---------
    real_weight: torch.Parameters
    imag_weight: torch.Parameters
    kernel_size: int
    init_func: function
        (unitary_init, complex_init)
    criterion: str
        (glorot, he)
    r   r   )rC   rD   NrZ   )	r%   r&   rC   r^   rD   in_channelsout_channelsr_   r`   r   r   r   affect_conv_init<  s   


rd   Fc                 C   s*   t |}| }t|D ]}|||}q
|S )zD
    Performs `torch.mean` over multiple dimensions of `input`.
    )sortedreversedmean)r	   axeskeepdimmaxisr   r   r   
multi_mean[  s
   rl   )r   r   )Nr5   )F)__doc__numpyr:   r   torch.nn.functionalnn
functionalr-   r   r   r   r    r,   r4   rK   rY   ra   rd   rl   r   r   r   r   <module>   s"    	

 
 %)
.
2