o
    %Ý«i)  ã                   @   sT   d Z ddlZddlmZmZmZmZmZ ddlm	Z	 e	e
ƒZG dd„ dejjƒZdS )z^Library implementing complex-valued linear transformation.

Authors
 * Titouan Parcollet 2020
é    N)Úaffect_initÚcheck_complex_inputÚcomplex_initÚcomplex_linear_opÚunitary_init)Ú
get_loggerc                       s0   e Zd ZdZ			d	‡ fdd„	Zdd„ Z‡  ZS )
ÚCLineara†  This function implements a fully connected complex-valued
    linear layer: y = Wx + b. y, W, x and b are thus complex
    numbers. A complex number is written as: r + xi. A tensor of
    complex numbers x = [batch, 32] can be understood as
    [batch, 0:15] = R and [batch, 16:31] = Xi. Thus the features
    dimension is cut in half (must be divisible by 2).

    Arguments
    ---------
    n_neurons : int
        It is the number of output neurons (i.e, the dimensionality of the
        output). Please note that these are complex-valued neurons. If 256
        neurons are specified, the output dimension will be 512.
    input_shape : tuple
        Expected size of the input.
    bias : bool
        if True, the additive bias b is adopted.
    init_criterion : str , optional
        (glorot, he).
        This parameter controls the initialization criterion of the weights.
        It is combined with weights_init to build the initialization method of
        the complex-valued weights (default "glorot").
    weight_init : str, optional
        (complex, unitary).
        This parameter defines the initialization procedure of the
        complex-valued weights (default "complex"). "complex" will generate random complex-valued
        weights following the init_criterion and the complex polar form.
        "unitary" will normalize the weights to lie on the unit circle.
        More details in: "Deep Complex Networks", Trabelsi C. et al.

    Example
    -------
    >>> inputs = torch.rand(10, 50, 40)
    >>> lin = CLinear(n_neurons=100, input_shape=inputs.shape)
    >>> output = lin(inputs)
    >>> output.shape
    torch.Size([10, 50, 200])
    TÚglorotÚcomplexc                    sê   t ƒ  ¡  || _|| _|| _|| _t|tƒrd|g}t|ƒ |d d | _	| j| _
tj t | j	| j
¡¡| _tj t | j	| j
¡¡| _| jrTtj t d| j
 ¡¡| _nt d| j
 ¡ d¡| _ttdœ| j | _t| j| j| j|ƒ d S )Né   éÿÿÿÿé   F)r
   Úunitary)ÚsuperÚ__init__Ú	n_neuronsÚbiasÚinit_criterionÚweight_initÚ
isinstanceÚintr   Úin_featuresÚout_featuresÚtorchÚnnÚ	ParameterÚTensorÚreal_weightÚimag_weightÚbÚrequires_grad_r   r   Úwinitr   )Úselfr   Úinput_shaper   r   r   ©Ú	__class__© ú^/home/ubuntu/.local/lib/python3.10/site-packages/speechbrain/nnet/complex_networks/c_linear.pyr   =   s2   

ÿÿÿÿzCLinear.__init__c                 C   s   t || j| j| jƒ}|S )züReturns the linear transformation of input tensor.

        Arguments
        ---------
        x : torch.Tensor
            Input to transform linearly.

        Returns
        -------
        The complex linear transformation of the inputs.
        )r   r   r   r   )r"   ÚxÚwxr&   r&   r'   Úforwardn   s   zCLinear.forward)Tr	   r
   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r*   Ú__classcell__r&   r&   r$   r'   r      s    +ú1r   )r.   r   Ú'speechbrain.nnet.complex_networks.c_opsr   r   r   r   r   Úspeechbrain.utils.loggerr   r+   Úloggerr   ÚModuler   r&   r&   r&   r'   Ú<module>   s    