
    `iJ                     `    d Z ddlZd Zd Zd Zd Zdd	ZddZd ZddZ	ddZ
ddZddZdS )z8
Routines for manipulating partial fraction expansions.
    Nc                     ddl }t          j        |                                           } t          j        |                    |                     S )zEnp.roots replacement. XXX: calls into NumPy, then converts back.
    r   N)numpycupyasarraygetroots)arrnps     q/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/cupyx/scipy/signal/_polyutils.pyr   r      sE     
,s




!
!C<&&&    c                    | j         }t          |          dk    r|d         |d         k    r|d         dk    st          d          ddl}|j                            |                                           }|j        }|                    d|          }|D ](}|	                    ||j
        d| f         d	          })t          |j        j        t          j                  r|                    |t                     }|                    |                    |          |                    |                                          k              r|j                                        }t          j        |          S )
z7np.poly replacement for 2D A. Otherwise, use cupy.poly.   r      z*input must be a non-empty square 2d array.N)r   dtypefull)mode)shapelen
ValueErrorr   linalgeigvalsr   r   onesconvolver_
issubclasstyper   complexfloatingr   complexallsort	conjugaterealcopy)Ashr
   seq_of_zerosdtazeror   s           r   polyr+      sA   	
BGGqLLRUbe^^1

EFFF9$$QUUWW--L		B
BA 9 9KK25TE?K88!', 455 

<w
7766"''%..BGGEOO,=,=$>$>>?? 	A<??r   c                 ~    t          j        t          j        |                     }t          j        | |d          |fS )z#Sort roots based on magnitude.
    r   )r   argsortabstake)pindxs     r   _cmplx_sortr2   )   s4     <$$D9Qa  $&&r   c                    t          j        |           dz   } t          j        |          dz   }| d         |d         z   }t          |           dz
  }t          |          dz
  }d|d         z  }t          j        t	          ||z
  dz   d          f|j                  }|                     |j                  }t          d||z
  dz             D ]-}|||         z  }	|	||<   ||||z   dz   xx         |	|z  z  cc<   .t          j        |d         dd          rI|j	        d         dk    r8|dd          }t          j        |d         dd          r|j	        d         dk    8||fS )Ng        r   r   g      ?g+=)rtol)
r   
atleast_1dr   zerosmaxr   astyperangeallcloser   )
uvwmnscaleqrkds
             r   _polydivrF   1   sl   S AS A	!qtAA
AA
A1IE
CA	1%%'11A	A1ac!e__    AaDL!	!AEAI+!a%
-!ae
,
,
, !'"+//abbE -!ae
,
,
, !'"+//a4Kr   MbP?minc                 \   |dv rt           j        }n1|dv rt           j        }n |dv rt           j        }nt	          d          t          j        | j        d         df          }t          j        |           |dddf<   t          j        |           |dddf<   t           j	        
                    |dddddf         |dddddf         z
  d	
          }g }g }t          j        | j        d         t                    }t          |          D ]t\  }	}
||	         r|
|k     | z  }|
|         }|j        dk    rD|                     || |                              |                    |j        d                    d||<   ut          j        |          t          j        |          fS )a  Determine unique roots and their multiplicities from a list of roots.

    Parameters
    ----------
    p : array_like
        The list of roots.
    tol : float, optional
        The tolerance for two roots to be considered equal in terms of
        the distance between them. Default is 1e-3. Refer to Notes about
        the details on roots grouping.
    rtype : {'max', 'maximum', 'min', 'minimum', 'avg', 'mean'}, optional
        How to determine the returned root if multiple roots are within
        `tol` of each other.

          - 'max', 'maximum': pick the maximum of those roots
          - 'min', 'minimum': pick the minimum of those roots
          - 'avg', 'mean': take the average of those roots

        When finding minimum or maximum among complex roots they are compared
        first by the real part and then by the imaginary part.

    Returns
    -------
    unique : ndarray
        The list of unique roots.
    multiplicity : ndarray
        The multiplicity of each root.

    See Also
    --------
    scipy.signal.unique_roots

    Notes
    -----
    If we have 3 roots ``a``, ``b`` and ``c``, such that ``a`` is close to
    ``b`` and ``b`` is close to ``c`` (distance is less than `tol`), then it
    doesn't necessarily mean that ``a`` is close to ``c``. It means that roots
    grouping is not unique. In this function we use "greedy" grouping going
    through the roots in the order they are given in the input `p`.

    This utility function is not specific to roots but can be used for any
    sequence of values for which uniqueness and multiplicity has to be
    determined. For a more general routine, see `numpy.unique`.

    )r8   maximum)rH   minimum)avgmeanzJ`rtype` must be one of {'max', 'maximum', 'min', 'minimum', 'avg', 'mean'}r   r   Nr   r5   )axisr   T)r   r8   rH   rM   r   emptyr   r#   imagr   normr7   bool	enumeratesizeappendr   )r0   tolrtypereducepointsdistp_uniquep_multiplicityusedidsmaskgroups                r   unique_rootsrb   D   s   \ """	$	$	$	/	!	! O P P 	P ZQ((F9Q<<F111a4L9Q<<F111a4L ;F111dAAA:.aaa
1CC"MMDHN:agaj---D4 
 
27 	STE!4:>>OOFF1T7OO,,,!!%+a.111T

<!!4<#?#???r   Fc                    t          j        dg          }|g}t          | ddd         |ddd                   D ]c\  }}t           j        d| f         }t	          t          |                    D ]}t          j        ||          }|                    |           d|ddd         }g }	t          j        dg          }t          | ||          D ]\  }}}
t           j        d| f         }g }t	          t          |                    D ]G}|dk    s|r(|                    t          j        ||
                     t          j        ||          }H|	                    t          |                     |	|fS )z>Compute the total polynomial divided by factors for each root.r   r5   r   N)
r   arrayzipr   r:   intpolymulrU   extendreversed)r   multiplicityinclude_powerscurrentsuffixespolemultmonomial_factorssuffixblockr^   s                r   _compute_factorsru      s~   j!ooGyH%1R.,r!Bw*?@@ ! !
d71te8$s4yy!! 	6 	6Al7H55GG    "~HGj!ooG!%x@@ ( (dF71te8$s4yy!! 	6 	6AAvvvT\'6::;;;l7H55GGx''''Gr   c                    t          | |          \  }}|                    | j                  }g }t          | ||          D ]\  }}}|dk    r?|                    t          j        ||          t          j        ||          z             L|                                }	t
          j        d| f         }
t          ||
          \  }}g }t          t          |                    D ]S}t          |	|
          \  }	}|d         |d         z  }t          j        |	||z            }	|                    |           T|                    t          |                     t          j        |          S )Nr   r   )ru   r9   r   re   rU   r   polyvalr$   r   rF   r:   rf   polysubrh   ri   r   )polesrj   	numeratordenominator_factorsrq   residuesrn   ro   factornumerrp   rE   rt   r@   rC   s                  r   _compute_residuesr      sk   -e\BB  --IH!%"57 7 - -dF199OODLD99 L667 8 8 8 8 NN$$Ewq4%x(H 22IFAE3t99%%    #E844qaD1Q4KUAJ77QOOHUOO,,,,<!!!r   rL   c                    t          j        |           } t          j        |          }t          j        t          j        |          d          }t          |||          \  }}t	          ||d          \  }}t          |          dk    rd}	nt          j        ||          }	t          | |          D ]\  }
}t          j        |	|
|z            }	|	|fS )a  Compute b(s) and a(s) from partial fraction expansion.

    If `M` is the degree of numerator `b` and `N` the degree of denominator
    `a`::

              b(s)     b[0] s**(M) + b[1] s**(M-1) + ... + b[M]
      H(s) = ------ = ------------------------------------------
              a(s)     a[0] s**(N) + a[1] s**(N-1) + ... + a[N]

    then the partial-fraction expansion H(s) is defined as::

               r[0]       r[1]             r[-1]
           = -------- + -------- + ... + --------- + k(s)
             (s-p[0])   (s-p[1])         (s-p[-1])

    If there are any repeated roots (closer together than `tol`), then H(s)
    has terms like::

          r[i]      r[i+1]              r[i+n-1]
        -------- + ----------- + ... + -----------
        (s-p[i])  (s-p[i])**2          (s-p[i])**n

    This function is used for polynomials in positive powers of s or z,
    such as analog filters or digital filters in controls engineering.  For
    negative powers of z (typical for digital filters in DSP), use `invresz`.

    Parameters
    ----------
    r : array_like
        Residues corresponding to the poles. For repeated poles, the residues
        must be ordered to correspond to ascending by power fractions.
    p : array_like
        Poles. Equal poles must be adjacent.
    k : array_like
        Coefficients of the direct polynomial term.
    tol : float, optional
        The tolerance for two roots to be considered equal in terms of
        the distance between them. Default is 1e-3. See `unique_roots`
        for further details.
    rtype : {'avg', 'min', 'max'}, optional
        Method for computing a root to represent a group of identical roots.
        Default is 'avg'. See `unique_roots` for further details.

    Returns
    -------
    b : ndarray
        Numerator polynomial coefficients.
    a : ndarray
        Denominator polynomial coefficients.

    See Also
    --------
    scipy.signal.invres
    residue, invresz, unique_roots

    fTrk   r   	r   r6   
trim_zerosrb   ru   r   rg   re   polyaddrC   r0   rD   rV   rW   unique_polesrj   rr   denominatorrz   residuer}   s               r   invresr      s    r 	AA**C00A!-ae!<!<L,+L,;?A A AG[ 1vv{{		LK00	q'?? > >LGf,<==		k!!r   c           	         t          j        |           } t          j        |          }t          j        t          j        |          d          }t          |||          \  }}t	          ||d          \  }}t          |          dk    rd}	n't          j        |ddd         |ddd                   }	t          | |          D ]&\  }
}t          j        |	|
|ddd         z            }	'|	ddd         |fS )a  Compute b(z) and a(z) from partial fraction expansion.

    If `M` is the degree of numerator `b` and `N` the degree of denominator
    `a`::

                b(z)     b[0] + b[1] z**(-1) + ... + b[M] z**(-M)
        H(z) = ------ = ------------------------------------------
                a(z)     a[0] + a[1] z**(-1) + ... + a[N] z**(-N)

    then the partial-fraction expansion H(z) is defined as::

                 r[0]                   r[-1]
         = --------------- + ... + ---------------- + k[0] + k[1]z**(-1) ...
           (1-p[0]z**(-1))         (1-p[-1]z**(-1))

    If there are any repeated roots (closer than `tol`), then the partial
    fraction expansion has terms like::

             r[i]              r[i+1]                    r[i+n-1]
        -------------- + ------------------ + ... + ------------------
        (1-p[i]z**(-1))  (1-p[i]z**(-1))**2         (1-p[i]z**(-1))**n

    This function is used for polynomials in negative powers of z,
    such as digital filters in DSP.  For positive powers, use `invres`.

    Parameters
    ----------
    r : array_like
        Residues corresponding to the poles. For repeated poles, the residues
        must be ordered to correspond to ascending by power fractions.
    p : array_like
        Poles. Equal poles must be adjacent.
    k : array_like
        Coefficients of the direct polynomial term.
    tol : float, optional
        The tolerance for two roots to be considered equal in terms of
        the distance between them. Default is 1e-3. See `unique_roots`
        for further details.
    rtype : {'avg', 'min', 'max'}, optional
        Method for computing a root to represent a group of identical roots.
        Default is 'avg'. See `unique_roots` for further details.

    Returns
    -------
    b : ndarray
        Numerator polynomial coefficients.
    a : ndarray
        Denominator polynomial coefficients.

    See Also
    --------
    scipy.signal.invresz
    residuez, unique_roots, invres

    bTr   r   Nr5   r   r   s               r   invreszr     s	   p 	AA**C00A!-ae!<!<L,+L,;?A A AG[ 1vv{{		L44R4+ddd*;<<	q'?? D DLGfTTrTl,BCC		TTrT?K''r   c                 d   t          j        | j        t           j                  s$t          j        |j        t           j                  r5|                     t
                    } |                    t
                    }n4|                     t                    } |                    t                    }t          j        t          j        |           d          } t          j        t          j        |          d          }|j	        dk    rt          d          t          |          }| j	        dk    rAt          j        |j                  t          |          d         t          j        g           fS t!          |           t!          |          k     rt          j        d          }nt%          | |          \  }} t'          |||          \  }}t          |          \  }}||         }t)          |||           }	d}
t+          ||          D ]\  }}|||
|
|z   <   |
|z  }
|	|d         z  ||fS )a  Compute partial-fraction expansion of b(s) / a(s).

    If `M` is the degree of numerator `b` and `N` the degree of denominator
    `a`::

              b(s)     b[0] s**(M) + b[1] s**(M-1) + ... + b[M]
      H(s) = ------ = ------------------------------------------
              a(s)     a[0] s**(N) + a[1] s**(N-1) + ... + a[N]

    then the partial-fraction expansion H(s) is defined as::

               r[0]       r[1]             r[-1]
           = -------- + -------- + ... + --------- + k(s)
             (s-p[0])   (s-p[1])         (s-p[-1])

    If there are any repeated roots (closer together than `tol`), then H(s)
    has terms like::

          r[i]      r[i+1]              r[i+n-1]
        -------- + ----------- + ... + -----------
        (s-p[i])  (s-p[i])**2          (s-p[i])**n

    This function is used for polynomials in positive powers of s or z,
    such as analog filters or digital filters in controls engineering.  For
    negative powers of z (typical for digital filters in DSP), use `residuez`.

    See Notes for details about the algorithm.

    Parameters
    ----------
    b : array_like
        Numerator polynomial coefficients.
    a : array_like
        Denominator polynomial coefficients.
    tol : float, optional
        The tolerance for two roots to be considered equal in terms of
        the distance between them. Default is 1e-3. See `unique_roots`
        for further details.
    rtype : {'avg', 'min', 'max'}, optional
        Method for computing a root to represent a group of identical roots.
        Default is 'avg'. See `unique_roots` for further details.

    Returns
    -------
    r : ndarray
        Residues corresponding to the poles. For repeated poles, the residues
        are ordered to correspond to ascending by power fractions.
    p : ndarray
        Poles ordered by magnitude in ascending order.
    k : ndarray
        Coefficients of the direct polynomial term.

    Warning
    -------
    This function may synchronize the device.

    See Also
    --------
    scipy.signal.residue
    invres, residuez, numpy.poly, unique_roots

    Notes
    -----
    The "deflation through subtraction" algorithm is used for
    computations --- method 6 in [1]_.

    The form of partial fraction expansion depends on poles multiplicity in
    the exact mathematical sense. However there is no way to exactly
    determine multiplicity of roots of a polynomial in numerical computing.
    Thus you should think of the result of `residue` with given `tol` as
    partial fraction expansion computed for the denominator composed of the
    computed poles with empirically determined multiplicity. The choice of
    `tol` can drastically change the result if there are close poles.

    References
    ----------
    .. [1] J. F. Mahoney, B. D. Sivazlian, "Partial fractions expansion: a
           review of computational methodology and efficiency", Journal of
           Computational and Applied Mathematics, Vol. 9, 1983.
    r   r   Denominator `a` is zero.rV   rW   )r   
issubdtyper   r   r9   r   floatr   r6   rT   r   r   r7   r   r2   rd   r   rO   rF   rb   r   re   )r   r)   rV   rW   ry   rD   r   rj   orderr|   indexrn   ro   s                r   r   r   a  s   b 	!566 qw(<==HHWHHWHHUOOHHUOO**C00A**C00Av{{3444!HHEv{{z%+&&E(:(:1(=tz"~~MM
1vvAJqMM1~~1!-eE!J!J!JL,%l33L%&L |Q??HE,55  
d$(eEDL !ad?E1$$r   c                    t          j        | j        t           j                  s$t          j        |j        t           j                  r5|                     t
                    } |                    t
                    }n4|                     t                    } |                    t                    }t          j        t          j        |           d          } t          j        t          j        |          d          }|j	        dk    rt          d          |d         dk    rt          d          t          |          }| j	        dk    rAt          j        |j                  t          |          d         t          j        g           fS | ddd         }|ddd         }t!          |          t!          |          k     rt          j        d          }nt%          ||          \  }}t'          |||          \  }}	t          |          \  }}
|	|
         }	t)          d|z  |	|          }d}t          j        t!          |          t*          	          }t-          ||	          D ]@\  }}|||||z   <   dt          j        t+          |                    z   ||||z   <   ||z  }A|| |z  |d         z  z  }|||ddd         fS )
aS  Compute partial-fraction expansion of b(z) / a(z).

    If `M` is the degree of numerator `b` and `N` the degree of denominator
    `a`::

                b(z)     b[0] + b[1] z**(-1) + ... + b[M] z**(-M)
        H(z) = ------ = ------------------------------------------
                a(z)     a[0] + a[1] z**(-1) + ... + a[N] z**(-N)

    then the partial-fraction expansion H(z) is defined as::

                 r[0]                   r[-1]
         = --------------- + ... + ---------------- + k[0] + k[1]z**(-1) ...
           (1-p[0]z**(-1))         (1-p[-1]z**(-1))

    If there are any repeated roots (closer than `tol`), then the partial
    fraction expansion has terms like::

             r[i]              r[i+1]                    r[i+n-1]
        -------------- + ------------------ + ... + ------------------
        (1-p[i]z**(-1))  (1-p[i]z**(-1))**2         (1-p[i]z**(-1))**n

    This function is used for polynomials in negative powers of z,
    such as digital filters in DSP.  For positive powers, use `residue`.

    See Notes of `residue` for details about the algorithm.

    Parameters
    ----------
    b : array_like
        Numerator polynomial coefficients.
    a : array_like
        Denominator polynomial coefficients.
    tol : float, optional
        The tolerance for two roots to be considered equal in terms of
        the distance between them. Default is 1e-3. See `unique_roots`
        for further details.
    rtype : {'avg', 'min', 'max'}, optional
        Method for computing a root to represent a group of identical roots.
        Default is 'avg'. See `unique_roots` for further details.

    Returns
    -------
    r : ndarray
        Residues corresponding to the poles. For repeated poles, the residues
        are ordered to correspond to ascending by power fractions.
    p : ndarray
        Poles ordered by magnitude in ascending order.
    k : ndarray
        Coefficients of the direct polynomial term.

    Warning
    -------
    This function may synchronize the device.

    See Also
    --------
    scipy.signal.residuez
    invresz, residue, unique_roots
    r   r   r   z6First coefficient of determinant `a` must be non-zero.Nr5   r   r   r   )r   r   r   r   r9   r   r   r   r6   rT   r   r   r7   r   r2   rd   r   rO   rF   rb   r   rf   re   arange)r   r)   rV   rW   ry   b_reva_revk_revr   rj   r   r|   r   powersrn   ro   s                   r   residuezr     s   | 	!566 qw(<==HHWHHWHHUOOHHUOO**C00A**C00Av{{3444	
1 % & & 	& !HHEv{{z%+&&E(:(:1(=tz"~~MMdddGEdddGE
5zzCJJ
1u--u!-eE!J!J!JL,%l33L%&L \!1<GGHEZHS111F,55  
d$(eEDL !%&SYY)?)?%?uUT\!"%F"U1X--HUE$$B$K''r   )rG   rH   )F)rG   rL   )__doc__r   r   r+   r2   rF   rb   ru   r   r   r   r   r    r   r   <module>r      s    ' ' '  0' ' '  &O@ O@ O@ O@d   2" " "6I" I" I" I"XH( H( H( H(Vs% s% s% s%lj( j( j( j( j( j(r   