o
    i.                     @   s  d dl Z d dlmZmZmZ d dlZddlmZ dej	dej	fddZ
	d+d	ej	d
ee dee dej	fddZG dd dZG dd dZG dd dZG dd dZG dd dZdej	dej	dej	fddZ					d,deej	eef dej	deej	 dee d eeej	eef  d!ee d"eej	 dej	fd#d$Z			d-d%ej	d&ej	deej	 dee d"eej	 dej	fd'd(Z			d-d%ej	d&ej	deej	 dee d"eej	 dej	fd)d*ZdS ).    N)OptionalTupleUnion   )clampcol_toeplitzreturnc                 C   sp   | j d }td|| }| dddf |ddddf  }tj| dddf ||ddddf  fdd}|S )z
    compute the first column of the circulant matrix closest to
    the Toeplitz matrix with provided first column in terms of the
    Froebenius norm
    r   .Naxis)shapenparangeconcatenate)r   nbwcol_circ r   K/home/ubuntu/.local/lib/python3.10/site-packages/fast_bss_eval/numpy/cgd.py*optimal_symmetric_circulant_precond_column   s
   
"0r   rr   r   c                 C   s   |durt | |d} |du r| jd d d }t d|| }| d|d ddf }| dd| df }|| d| |  }t j| dddf |fdd}|durYt |d|}|S )	a  
    compute the first column of the circulant matrix closest to
    the non-symmetric Toeplitz matrix with provided first column in terms of the
    Froebenius norm

    The input is assumed to be of shape (..., 2 * n_col) in order
    r = [s_0, s_1, ..., s_{n-1}, (s_{-n}) , s_{-n+1}, ..., s_{-1}]

    where the first row of the Toeplitz matrix is
    [s_0, ..., s_{n-1}]
    and the first column is
    [s_0, s_{-1}, ..., s_{-n+1}]
    Nr	   r      .r   g      ?r
   )r   moveaxisr   r   r   )r   r   r   r   s1s2r   cr   r   r   -optimal_nonsymmetric_circulant_precond_column+   s   r   c                   @   N   e Zd ZdZdejfddZedd Zedd Z	d	ejd
ejfddZ
dS )CirculantPreconditionerOperatorT
    Optimal circulant pre-conditioner operator for a symmetric topelitz matrix
    toeplitz_colc                 C   sj   t |}tjj|dd}| t|jd |jd  dd | _|j	d | _
|j	d d | j
| j
f | _d S )Nr	   r
   r   ư>min)r   r   fftrfftconjr   realimagCr   r   _shapeselfr!   col_precondr*   r   r   r   __init__U   s
   & z(CirculantPreconditionerOperator.__init__c                 C      | j S Nr+   r-   r   r   r   r   ^      z%CirculantPreconditionerOperator.shapec                 C   
   t | jS r1   lenr+   r3   r   r   r   ndimb      
z$CirculantPreconditionerOperator.ndimlhsr   c                 C   sj   |j | j kr)|jd | jd ksJ tjj| jd tjj|| jdd | jddS td| j d|j )Nr	   .Nr   r   1Dimension mismatch between operators with shapes  and )	r8   r   r   r%   irfftr*   r&   r   
ValueErrorr-   r:   r   r   r   
__matmul__f   s   z*CirculantPreconditionerOperator.__matmul__N__name__
__module____qualname____doc__r   ndarrayr/   propertyr   r8   rC   r   r   r   r   r   P   s    	

r   c                   @   sJ   e Zd ZdejfddZedd Zedd Zdejd	ejfd
dZ	dS )SymmetricToeplitzOperatorcolc                 C   s   |j d }d| }|d|  d }|j dd |f }tj|tj||d|ddddf fdd}tjj|dd| _|j |j d f | _|| _|| _	dS )	zF
        col: numpy.ndarray, (..., n_chan_ref, filter_length)
        r	   r   r   Nr   .r   r
   )
r   r   r   
zeros_liker%   r&   Cforwardr+   n_coln_fftr-   rL   rP   rQ   pad_len	pad_shapecirc_colr   r   r   r/   x   s   
"
z"SymmetricToeplitzOperator.__init__c                 C   r0   r1   r2   r3   r   r   r   r      r4   zSymmetricToeplitzOperator.shapec                 C   r5   r1   r6   r3   r   r   r   r8      r9   zSymmetricToeplitzOperator.ndimr:   r   c                 C   s   |j | j kr7|jd | jd ksJ tjj|| jdd}tjj|| jd  | jdd}|dd | jd d f S t	d| j d|j )Nr;   r	   r=   r<   .r>   r?   )
r8   r   r   r%   r&   rQ   r@   rO   rP   rA   )r-   r:   Yyr   r   r   rC      s   z$SymmetricToeplitzOperator.__matmul__N)
rE   rF   rG   r   rI   r/   rJ   r   r8   rC   r   r   r   r   rK   w   s    

rK   c                   @   r   )$BlockCirculantPreconditionerOperatorr    r!   c                 C   sn   t |dd}tjj|dd}tj|| _|jd | _|jdd | j| jjd  | j| jjd  f | _	dS )z_
        toeplitz_col: numpy.ndarray, (..., 2 * filter_length, n_channels, n_channels)
        r
   Nr	   r;   )
r   r   r%   r&   linalginvr*   r   r   r+   r,   r   r   r   r/      s   z-BlockCirculantPreconditionerOperator.__init__c                 C   r0   r1   r2   r3   r   r   r   r      r4   z*BlockCirculantPreconditionerOperator.shapec                 C   r5   r1   r6   r3   r   r   r   r8      r9   z)BlockCirculantPreconditionerOperator.ndimr:   r   c                 C   s   |j d | j d ksJ d| j  d|j  ||j d d d| jj d f |j dd   }tjj|| jdd}td| j|}tjj|| jdd}||j d d d |j dd   }|S )	Nr;   r	   r>   r?   rY   r=   ...rc,...cm->...rmr	   )	r   reshaper*   r   r%   r&   r   einsumr@   )r-   r:   prodrW   r   r   r   rC      s   2&z/BlockCirculantPreconditionerOperator.__matmul__NrD   r   r   r   r   rX      s    

rX   c                   @   r   )BlockToeplitzOperatorz
    Operator implementing fast matrix multiplication by a block Toeplitz matrix.
    Each block of the matrix is a symmetric Toeplitz matrix.
    rL   c              
   C   s4  |j d d }dttd|  }|d|  d }|j dd |f |j dd  }tj|dddddddf |dd| dddddf tj||d|d|d d	dddddf fdd
}tjj|dd
| _	|j d | _
|j d | _|| _|j d | _|j dd | j
| | j| f | _|| _dS )aj  
        Parameters
        ----------
        col: numpy.ndarray, (..., 2 * n_toeplitz, n_block_rows, n_block_cols)
            The reduced representation  of the block Toeplitz matrix.
            The last dimension contains the concatenated first column and first row
            of the Toeplitz matrix.
            We can thus directly apply the FFT
        rY   r   r   Nr;   .r	   rM   r   r
   )r   mathceillog2r   r   rN   r%   r&   rO   _n_block_rows_n_block_cols_n_toeplitzrQ   r+   rR   r   r   r   r/      s,   
" 	
zBlockToeplitzOperator.__init__c                 C   r0   r1   r2   r3   r   r   r   r      r4   zBlockToeplitzOperator.shapec                 C   r5   r1   r6   r3   r   r   r   r8     r9   zBlockToeplitzOperator.ndimr:   r   c                 C   s   |j d | j d ksJ d| j  d|j  ||j d d d| jf |j dd   }tjj|| jdd}td| j|}tjj	|| jdd}|dd | j
d d d d f }||j d d d	 |j dd   }|S )
Nr;   r	   r>   r?   rY   r=   r\   .r]   )r   r^   rf   r   r%   r&   rQ   r_   rO   r@   rg   )r-   r:   rV   r`   rW   r   r   r   rC     s   ,&z BlockToeplitzOperator.__matmul__NrD   r   r   r   r   ra      s    (

ra   c                   @   s"   e Zd ZdejdejfddZdS )IdentityOperatorr:   r   c                 C   s   |S r1   r   rB   r   r   r   rC     s   zIdentityOperator.__matmul__N)rE   rF   rG   r   rI   rC   r   r   r   r   rh     s    rh   ar   c                 C   s   t d|  |S )Nz...cd,...cd->...d)r   r_   r'   )ri   r   r   r   r   
inner_prod  s   rj   FAxn_iterprecondverbosex_truec              	   C   s  | j d |j k}|r|d }t| jt|jkr"| jd |jd ks$J |d u r-t|}|d u r6|jd }|d u r=t }|| |  }|| }	|	}
t||	}|d urf|rX|d }ttjj	|| ddg}t
|D ]v}| |
 }t|
|}|t|dd }||dd d d f |
  }|d d	kr|| |  }n||dd d d f |  }|| }	t||	}|rt|  |t|dd }|	|dd d d f |
  }
|}|d ur|ttjj	|| dd qj|r|d
 }|d ur||fS |S )Nr   r<   r	   r;   r
   r"   r#   .r   ).r   )r8   r7   r   r   rN   rh   rj   meanrZ   normranger   printappend)rk   r   rl   rm   rn   ro   rp   add_axisr   zprsolderrorsepochAppApalpharsnewbetar   r   r   conjugate_gradient#  sR   ,




 r   acfxcorrc                 C   $   t | }t| }t||||||dS N)rm   rn   rl   rp   )r   rK   r   r   r   rl   rm   rp   rn   forwardr   r   r   toeplitz_conjugate_gradientn  s
   	r   c                 C   r   r   )rX   ra   r   r   r   r   r   !block_toeplitz_conjugate_gradient  s
   	r   )NN)NNNFN)NNN)rb   typingr   r   r   numpyr   helpersr   rI   r   intr   r   rK   rX   ra   rh   rj   boolr   r   r   r   r   r   r   <module>   s   

%')0J
N
