U
    KvfY                     @   s  d dl 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 edej ZedZeejZdZdd	 Zd&d
dZd'ddZG dd dZG dd dZG dd dZdZdZdZdZeeedZeeedZG dd deZe ZG dd deZ dZ!dZ"dZ#e!e"ed Z$de#ed Z%G d!d" d"eZ&G d#d$ d$eZ'e& Z(d%D ]:Z)e&j*e) Z+e'j*e) Z,e-e+j.e%e,_.e-e+j.e$e+_.qLdS )(    N)doccer)gammaln)check_random_state)mvn   a  random_state : {None, int, np.random.RandomState, np.random.Generator}, optional
    Used for drawing random variates.
    If `seed` is `None` the `~np.random.RandomState` singleton is used.
    If `seed` is an int, a new ``RandomState`` instance is used, seeded
    with seed.
    If `seed` is already a ``RandomState`` or ``Generator`` instance,
    then that object is used.
    Default is None.
c                 C   s   |   } | jdkr| d } | S )z`
    Remove single-dimensional entries from array and convert to scalar,
    if necessary.

    r    )Zsqueezendim)outr   r   L/tmp/pip-unpacked-wheel-2v6byqio/statsmodels/compat/_scipy_multivariate_t.py_squeeze_output    s    
r   c                 C   sT   |dk	r|}|dkr>| j j }ddd}|| t|j }|tt|  }|S )a  
    Determine which eigenvalues are "small" given the spectrum.

    This is for compatibility across various linear algebra functions
    that should agree about whether or not a Hermitian matrix is numerically
    singular and what is its numerical matrix rank.
    This is designed to be compatible with scipy.linalg.pinvh.

    Parameters
    ----------
    spectrum : 1d ndarray
        Array of eigenvalues of a Hermitian matrix.
    cond, rcond : float, optional
        Cutoff for small eigenvalues.
        Singular values smaller than rcond * largest_eigenvalue are
        considered zero.
        If None or -1, suitable machine precision is used.

    Returns
    -------
    eps : float
        Magnitude cutoff for numerical negligibility.

    N)Ng     @@g    .A)fd)dtypecharlowernpZfinfoepsmaxabs)ZspectrumcondrcondtZfactorr   r   r   r
   _eigvalsh_to_eps,   s    
r   h㈵>c                    s   t j fdd| D tdS )a  
    A helper function for computing the pseudoinverse.

    Parameters
    ----------
    v : iterable of numbers
        This may be thought of as a vector of eigenvalues or singular values.
    eps : float
        Values with magnitude no greater than eps are considered negligible.

    Returns
    -------
    v_pinv : 1d float ndarray
        A vector of pseudo-inverted numbers.

    c                    s$   g | ]}t | krd nd| qS )r      )r   ).0xr   r   r
   
<listcomp>`   s     z_pinv_1d.<locals>.<listcomp>r   )r   arrayfloat)vr   r   r   r
   _pinv_1dO   s    r$   c                   @   s&   e Zd ZdZdddZedd ZdS )	_PSDaN  
    Compute coordinated functions of a symmetric positive semidefinite matrix.

    This class addresses two issues.  Firstly it allows the pseudoinverse,
    the logarithm of the pseudo-determinant, and the rank of the matrix
    to be computed using one call to eigh instead of three.
    Secondly it allows these functions to be computed in a way
    that gives mutually compatible results.
    All of the functions are computed with a common understanding as to
    which of the eigenvalues are to be considered negligibly small.
    The functions are designed to coordinate with scipy.linalg.pinvh()
    but not necessarily with np.linalg.det() or with np.linalg.matrix_rank().

    Parameters
    ----------
    M : array_like
        Symmetric positive semidefinite matrix (2-D).
    cond, rcond : float, optional
        Cutoff for small eigenvalues.
        Singular values smaller than rcond * largest_eigenvalue are
        considered zero.
        If None or -1, suitable machine precision is used.
    lower : bool, optional
        Whether the pertinent array data is taken from the lower
        or upper triangle of M. (Default: lower)
    check_finite : bool, optional
        Whether to check that the input matrices contain only finite
        numbers. Disabling may give a performance gain, but may result
        in problems (crashes, non-termination) if the inputs do contain
        infinities or NaNs.
    allow_singular : bool, optional
        Whether to allow a singular matrix.  (Default: True)

    Notes
    -----
    The arguments are similar to those of scipy.linalg.pinvh().

    NTc                 C   s   t jj|||d\}}t|||}	t||	 k r:td|||	k }
t|
t|k rf|sftjdt	||	}t
|t|}t|
| _|| _tt|
| _d | _d S )N)r   check_finitez.the input matrix must be positive semidefinitezsingular matrix)scipylinalgZeighr   r   min
ValueErrorlenZLinAlgErrorr$   multiplysqrtrankUsumloglog_pdet_pinv)selfMr   r   r   r&   allow_singularsur   r   Zs_pinvr/   r   r   r
   __init__   s    

z_PSD.__init__c                 C   s$   | j d krt| j| jj| _ | j S N)r3   r   dotr/   Tr4   r   r   r
   pinv   s    
z	_PSD.pinv)NNTTT)__name__
__module____qualname____doc__r9   propertyr>   r   r   r   r
   r%   c   s   '    
r%   c                       sD   e Zd ZdZd
 fdd	Zedd Zejdd Zdd	 Z  Z	S )multi_rv_genericzd
    Class which encapsulates common functionality between all multivariate
    distributions.

    Nc                    s   t t|   t|| _d S r:   )superrD   r9   r   _random_stater4   seed	__class__r   r
   r9      s    zmulti_rv_generic.__init__c                 C   s   | j S )a   Get or set the RandomState object for generating random variates.

        This can be either None, int, a RandomState instance, or a
        np.random.Generator instance.

        If None (or np.random), use the RandomState singleton used by
        np.random.
        If already a RandomState or Generator instance, use it.
        If an int, use a new RandomState instance seeded with seed.

        )rF   r=   r   r   r
   random_state   s    zmulti_rv_generic.random_statec                 C   s   t || _d S r:   r   rF   rG   r   r   r
   rK      s    c                 C   s   |d k	rt |S | jS d S r:   rL   )r4   rK   r   r   r
   _get_random_state   s    z"multi_rv_generic._get_random_state)N)
r?   r@   rA   rB   r9   rC   rK   setterrM   __classcell__r   r   rI   r
   rD      s   

rD   c                   @   s*   e Zd ZdZedd Zejdd ZdS )multi_rv_frozenzj
    Class which encapsulates common functionality between all frozen
    multivariate distributions.
    c                 C   s   | j jS r:   )_distrF   r=   r   r   r
   rK      s    zmulti_rv_frozen.random_statec                 C   s   t || j_d S r:   )r   rQ   rF   rG   r   r   r
   rK      s    N)r?   r@   rA   rB   rC   rK   rN   r   r   r   r
   rP      s
   
rP   a   mean : array_like, optional
    Mean of the distribution (default zero)
cov : array_like, optional
    Covariance matrix of the distribution (default one)
allow_singular : bool, optional
    Whether to allow a singular covariance matrix.  (Default: False)
a2  Setting the parameter `mean` to `None` is equivalent to having `mean`
    be the zero-vector. The parameter `cov` can be a scalar, in which case
    the covariance matrix is the identity times that value, a vector of
    diagonal entries for the covariance matrix, or a two-dimensional
    array_like.
     z>See class definition for a detailed description of parameters.)_mvn_doc_default_callparams_mvn_doc_callparams_note_doc_random_statec                       s   e Zd ZdZd fdd	ZdddZd	d
 Zdd Zdd Zd ddZ	d!ddZ
dd Zd"ddZd#ddZd$ddZd%ddZ  ZS )&multivariate_normal_gena  
    A multivariate normal random variable.

    The `mean` keyword specifies the mean. The `cov` keyword specifies the
    covariance matrix.

    Methods
    -------
    ``pdf(x, mean=None, cov=1, allow_singular=False)``
        Probability density function.
    ``logpdf(x, mean=None, cov=1, allow_singular=False)``
        Log of the probability density function.
    ``cdf(x, mean=None, cov=1, allow_singular=False, maxpts=1000000*dim, abseps=1e-5, releps=1e-5)``
        Cumulative distribution function.
    ``logcdf(x, mean=None, cov=1, allow_singular=False, maxpts=1000000*dim, abseps=1e-5, releps=1e-5)``
        Log of the cumulative distribution function.
    ``rvs(mean=None, cov=1, size=1, random_state=None)``
        Draw random samples from a multivariate normal distribution.
    ``entropy()``
        Compute the differential entropy of the multivariate normal.

    Parameters
    ----------
    x : array_like
        Quantiles, with the last axis of `x` denoting the components.
    %(_mvn_doc_default_callparams)s
    %(_doc_random_state)s

    Alternatively, the object may be called (as a function) to fix the mean
    and covariance parameters, returning a "frozen" multivariate normal
    random variable:

    rv = multivariate_normal(mean=None, cov=1, allow_singular=False)
        - Frozen object with the same methods but holding the given
          mean and covariance fixed.

    Notes
    -----
    %(_mvn_doc_callparams_note)s

    The covariance matrix `cov` must be a (symmetric) positive
    semi-definite matrix. The determinant and inverse of `cov` are computed
    as the pseudo-determinant and pseudo-inverse, respectively, so
    that `cov` does not need to have full rank.

    The probability density function for `multivariate_normal` is

    .. math::

        f(x) = \frac{1}{\sqrt{(2 \pi)^k \det \Sigma}}
               \exp\left( -\frac{1}{2} (x - \mu)^T \Sigma^{-1} (x - \mu) \right),

    where :math:`\mu` is the mean, :math:`\Sigma` the covariance matrix,
    and :math:`k` is the dimension of the space where :math:`x` takes values.

    .. versionadded:: 0.14.0

    Examples
    --------
    >>> import matplotlib.pyplot as plt
    >>> from scipy.stats import multivariate_normal

    >>> x = np.linspace(0, 5, 10, endpoint=False)
    >>> y = multivariate_normal.pdf(x, mean=2.5, cov=0.5); y
    array([ 0.00108914,  0.01033349,  0.05946514,  0.20755375,  0.43939129,
            0.56418958,  0.43939129,  0.20755375,  0.05946514,  0.01033349])
    >>> fig1 = plt.figure()
    >>> ax = fig1.add_subplot(111)
    >>> ax.plot(x, y)

    The input quantiles can be any shape of array, as long as the last
    axis labels the components.  This allows us for instance to
    display the frozen pdf for a non-isotropic random variable in 2D as
    follows:

    >>> x, y = np.mgrid[-1:1:.01, -1:1:.01]
    >>> pos = np.dstack((x, y))
    >>> rv = multivariate_normal([0.5, -0.2], [[2.0, 0.3], [0.3, 0.5]])
    >>> fig2 = plt.figure()
    >>> ax2 = fig2.add_subplot(111)
    >>> ax2.contourf(x, y, rv.pdf(pos))

    Nc                    s$   t t| | t| jt| _d S r:   )rE   rV   r9   r   	docformatrB   mvn_docdict_paramsrG   rI   r   r
   r9   T  s    z multivariate_normal_gen.__init__r   Fc                 C   s   t ||||dS )z
        Create a frozen multivariate normal distribution.

        See `multivariate_normal_frozen` for more information.

        )r6   rH   )multivariate_normal_frozen)r4   meancovr6   rH   r   r   r
   __call__X  s    z multivariate_normal_gen.__call__c                 C   s  |dkr^|dkrH|dkrd}q\t j|td}|jdk r<d}q\|jd }qpt j|td}|j}nt |sptd|dkrt |}t j|td}|dkrd}t j|td}|dkrd|_d	|_|jdks|jd |krtd
| |jdkr|t 	| }n|jdkrt 
|}n~|jdkrx|j||fkrx|j\}}||krTdt|j }nd}|t|jt|f }t|n|jdkrtd|j |||fS )z
        Infer dimensionality from mean or covariance matrix, ensure that
        mean and covariance are full vector resp. matrix.

        Nr   r    r   r   z.Dimension of random variable must be a scalar.      ?r   r   r   z+Array 'mean' must be a vector of length %d.HArray 'cov' must be square if it is two dimensional, but cov.shape = %s.zTDimension mismatch: array 'cov' is of shape %s, but 'mean' is a vector of length %d.>Array 'cov' must be at most two-dimensional, but cov.ndim = %d)r   asarrayr"   r   shapesizeZisscalarr*   zeroseyediagstrr+   )r4   dimrZ   r[   rowscolsmsgr   r   r
   _process_parametersc  sV    






z+multivariate_normal_gen._process_parametersc                 C   s`   t j|td}|jdkr$|t j }n8|jdkr\|dkrJ|ddt jf }n|t jddf }|S zm
        Adjust quantiles array so that last axis labels the components of
        each data point.

        r    r   r   Nr   rb   r"   r   Znewaxisr4   r   ri   r   r   r
   _process_quantiles  s    

z*multivariate_normal_gen._process_quantilesc                 C   s8   || }t jt t ||dd}d|t | |  S )a  
        Parameters
        ----------
        x : ndarray
            Points at which to evaluate the log of the probability
            density function
        mean : ndarray
            Mean of the distribution
        prec_U : ndarray
            A decomposition such that np.dot(prec_U, prec_U.T)
            is the precision matrix, i.e. inverse of the covariance matrix.
        log_det_cov : float
            Logarithm of the determinant of the covariance matrix
        rank : int
            Rank of the covariance matrix.

        Notes
        -----
        As this function does no argument checking, it should not be
        called directly; use 'logpdf' instead.

        r   Zaxisg      )r   r0   squarer;   _LOG_2PI)r4   r   rZ   prec_UZlog_det_covr.   devmahar   r   r
   _logpdf  s    zmultivariate_normal_gen._logpdfc                 C   sL   |  d||\}}}| ||}t||d}| |||j|j|j}t|S )a  
        Log of the multivariate normal probability density function.

        Parameters
        ----------
        x : array_like
            Quantiles, with the last axis of `x` denoting the components.
        %(_mvn_doc_default_callparams)s

        Returns
        -------
        pdf : ndarray or scalar
            Log of the probability density function evaluated at `x`

        Notes
        -----
        %(_mvn_doc_callparams_note)s

        Nr6   )rm   rq   r%   rx   r/   r2   r.   r   r4   r   rZ   r[   r6   ri   Zpsdr	   r   r   r
   logpdf  s
    zmultivariate_normal_gen.logpdfc              	   C   sR   |  d||\}}}| ||}t||d}t| |||j|j|j}t	|S )a  
        Multivariate normal probability density function.

        Parameters
        ----------
        x : array_like
            Quantiles, with the last axis of `x` denoting the components.
        %(_mvn_doc_default_callparams)s

        Returns
        -------
        pdf : ndarray or scalar
            Probability density function evaluated at `x`

        Notes
        -----
        %(_mvn_doc_callparams_note)s

        Nry   )
rm   rq   r%   r   exprx   r/   r2   r.   r   rz   r   r   r
   pdf  s
    zmultivariate_normal_gen.pdfc           	         s>   t jt j  fdd}t |d|}t|S )a  
        Parameters
        ----------
        x : ndarray
            Points at which to evaluate the cumulative distribution function.
        mean : ndarray
            Mean of the distribution
        cov : array_like
            Covariance matrix of the distribution
        maxpts: integer
            The maximum number of points to use for integration
        abseps: float
            Absolute error tolerance
        releps: float
            Relative error tolerance

        Notes
        -----
        As this function does no argument checking, it should not be
        called directly; use 'cdf' instead.

        .. versionadded:: 1.0.0

        c              	      s   t |  d S )Nr   )r   Zmvnun)Zx_sliceabsepsr[   r   maxptsrZ   relepsr   r
   <lambda>  s     z.multivariate_normal_gen._cdf.<locals>.<lambda>r   )r   fullrc   infZapply_along_axisr   )	r4   r   rZ   r[   r   r   r   Zfunc1dr	   r   r~   r
   _cdf  s    zmultivariate_normal_gen._cdfr   c           
   
   C   sV   |  d||\}}}| ||}t||d |s8d| }t| ||||||}	|	S )a  
        Log of the multivariate normal cumulative distribution function.

        Parameters
        ----------
        x : array_like
            Quantiles, with the last axis of `x` denoting the components.
        %(_mvn_doc_default_callparams)s
        maxpts: integer, optional
            The maximum number of points to use for integration
            (default `1000000*dim`)
        abseps: float, optional
            Absolute error tolerance (default 1e-5)
        releps: float, optional
            Relative error tolerance (default 1e-5)

        Returns
        -------
        cdf : ndarray or scalar
            Log of the cumulative distribution function evaluated at `x`

        Notes
        -----
        %(_mvn_doc_callparams_note)s

        .. versionadded:: 1.0.0

        Nry   @B )rm   rq   r%   r   r1   r   
r4   r   rZ   r[   r6   r   r   r   ri   r	   r   r   r
   logcdf#  s    zmultivariate_normal_gen.logcdfc           
      C   sP   |  d||\}}}| ||}t||d |s8d| }| ||||||}	|	S )a  
        Multivariate normal cumulative distribution function.

        Parameters
        ----------
        x : array_like
            Quantiles, with the last axis of `x` denoting the components.
        %(_mvn_doc_default_callparams)s
        maxpts: integer, optional
            The maximum number of points to use for integration
            (default `1000000*dim`)
        abseps: float, optional
            Absolute error tolerance (default 1e-5)
        releps: float, optional
            Relative error tolerance (default 1e-5)

        Returns
        -------
        cdf : ndarray or scalar
            Cumulative distribution function evaluated at `x`

        Notes
        -----
        %(_mvn_doc_callparams_note)s

        .. versionadded:: 1.0.0

        Nry   r   )rm   rq   r%   r   r   r   r   r
   cdfJ  s    zmultivariate_normal_gen.cdfc                 C   s4   |  d||\}}}| |}||||}t|S )a  
        Draw random samples from a multivariate normal distribution.

        Parameters
        ----------
        %(_mvn_doc_default_callparams)s
        size : integer, optional
            Number of samples to draw (default 1).
        %(_doc_random_state)s

        Returns
        -------
        rvs : ndarray or scalar
            Random variates of size (`size`, `N`), where `N` is the
            dimension of the random variable.

        Notes
        -----
        %(_mvn_doc_callparams_note)s

        N)rm   rM   multivariate_normalr   )r4   rZ   r[   rd   rK   ri   r	   r   r   r
   rvsq  s    
zmultivariate_normal_gen.rvsc                 C   s<   |  d||\}}}tjdtj tj | \}}d| S )aP  
        Compute the differential entropy of the multivariate normal.

        Parameters
        ----------
        %(_mvn_doc_default_callparams)s

        Returns
        -------
        h : scalar
            Entropy of the multivariate normal distribution

        Notes
        -----
        %(_mvn_doc_callparams_note)s

        Nr         ?)rm   r   r(   Zslogdetpie)r4   rZ   r[   ri   _Zlogdetr   r   r
   entropy  s     zmultivariate_normal_gen.entropy)N)Nr   FN)Nr   F)Nr   F)Nr   FNr   r   )Nr   FNr   r   )Nr   r   N)Nr   )r?   r@   rA   rB   r9   r\   rm   rq   rx   r{   r}   r   r   r   r   r   rO   r   r   rI   r
   rV      s&   T
?

     
'    
'
rV   c                   @   sH   e Zd ZdddZdd Zd	d
 Zdd Zdd ZdddZdd Z	dS )rY   Nr   Fr   c                 C   sZ   t || _| jd||\| _| _| _t| j|d| _|sDd| j }|| _|| _	|| _
dS )a  
        Create a frozen multivariate normal distribution.

        Parameters
        ----------
        mean : array_like, optional
            Mean of the distribution (default zero)
        cov : array_like, optional
            Covariance matrix of the distribution (default one)
        allow_singular : bool, optional
            If this flag is True then tolerate a singular
            covariance matrix (default False).
        seed : {None, int, `~np.random.RandomState`, `~np.random.Generator`}, optional
            This parameter defines the object to use for drawing random
            variates.
            If `seed` is `None` the `~np.random.RandomState` singleton is used.
            If `seed` is an int, a new ``RandomState`` instance is used, seeded
            with seed.
            If `seed` is already a ``RandomState`` or ``Generator`` instance,
            then that object is used.
            Default is None.
        maxpts: integer, optional
            The maximum number of points to use for integration of the
            cumulative distribution function (default `1000000*dim`)
        abseps: float, optional
            Absolute error tolerance for the cumulative distribution function
            (default 1e-5)
        releps: float, optional
            Relative error tolerance for the cumulative distribution function
            (default 1e-5)

        Examples
        --------
        When called with the default parameters, this will create a 1D random
        variable with mean 0 and covariance 1:

        >>> from scipy.stats import multivariate_normal
        >>> r = multivariate_normal()
        >>> r.mean
        array([ 0.])
        >>> r.cov
        array([[1.]])

        Nry   r   )rV   rQ   rm   ri   rZ   r[   r%   cov_infor   r   r   )r4   rZ   r[   r6   rH   r   r   r   r   r   r
   r9     s    .
  
z#multivariate_normal_frozen.__init__c                 C   s:   | j || j}| j || j| jj| jj| jj}t	|S r:   )
rQ   rq   ri   rx   rZ   r   r/   r2   r.   r   r4   r   r	   r   r   r
   r{     s     z!multivariate_normal_frozen.logpdfc                 C   s   t | |S r:   r   r|   r{   r4   r   r   r   r
   r}     s    zmultivariate_normal_frozen.pdfc                 C   s   t | |S r:   )r   r1   r   r   r   r   r
   r     s    z!multivariate_normal_frozen.logcdfc                 C   s8   | j || j}| j || j| j| j| j| j}t	|S r:   )
rQ   rq   ri   r   rZ   r[   r   r   r   r   r   r   r   r
   r     s
    zmultivariate_normal_frozen.cdfc                 C   s   | j | j| j||S r:   )rQ   r   rZ   r[   r4   rd   rK   r   r   r
   r     s    zmultivariate_normal_frozen.rvsc                 C   s$   | j j}| j j}d|td  |  S )z
        Computes the differential entropy of the multivariate normal.

        Returns
        -------
        h : scalar
            Entropy of the multivariate normal distribution

        r   r   )r   r2   r.   rt   )r4   r2   r.   r   r   r
   r     s    
z"multivariate_normal_frozen.entropy)Nr   FNNr   r   )r   N)
r?   r@   rA   r9   r{   r}   r   r   r   r   r   r   r   r
   rY     s         
8
rY   a  
loc : array_like, optional
    Location of the distribution. (default ``0``)
shape : array_like, optional
    Positive semidefinite matrix of the distribution. (default ``1``)
df : float, optional
    Degrees of freedom of the distribution; must be greater than zero.
    If ``np.inf`` then results are multivariate normal. The default is ``1``.
allow_singular : bool, optional
    Whether to allow a singular matrix. (default ``False``)
a  Setting the parameter `loc` to ``None`` is equivalent to having `loc`
be the zero-vector. The parameter `shape` can be a scalar, in which case
the shape matrix is the identity times that value, a vector of
diagonal entries for the shape matrix, or a two-dimensional array_like.
)_mvt_doc_default_callparams_mvt_doc_callparams_noterU   c                       sb   e Zd ZdZd fdd	ZdddZdd	d
ZdddZdd ZdddZ	dd Z
dd Z  ZS )multivariate_t_gena	  
    A multivariate t-distributed random variable.

    The `loc` parameter specifies the location. The `shape` parameter specifies
    the positive semidefinite shape matrix. The `df` parameter specifies the
    degrees of freedom.

    In addition to calling the methods below, the object itself may be called
    as a function to fix the location, shape matrix, and degrees of freedom
    parameters, returning a "frozen" multivariate t-distribution random.

    Methods
    -------
    ``pdf(x, loc=None, shape=1, df=1, allow_singular=False)``
        Probability density function.
    ``logpdf(x, loc=None, shape=1, df=1, allow_singular=False)``
        Log of the probability density function.
    ``rvs(loc=None, shape=1, df=1, size=1, random_state=None)``
        Draw random samples from a multivariate t-distribution.

    Parameters
    ----------
    x : array_like
        Quantiles, with the last axis of `x` denoting the components.
    %(_mvt_doc_default_callparams)s
    %(_doc_random_state)s

    Notes
    -----
    %(_mvt_doc_callparams_note)s
    The matrix `shape` must be a (symmetric) positive semidefinite matrix. The
    determinant and inverse of `shape` are computed as the pseudo-determinant
    and pseudo-inverse, respectively, so that `shape` does not need to have
    full rank.

    The probability density function for `multivariate_t` is

    .. math::

        f(x) = \frac{\Gamma(\nu + p)/2}{\Gamma(\nu/2)\nu^{p/2}\pi^{p/2}|\Sigma|^{1/2}}
               \exp\left[1 + \frac{1}{\nu} (\mathbf{x} - \boldsymbol{\mu})^{\top}
               \boldsymbol{\Sigma}^{-1}
               (\mathbf{x} - \boldsymbol{\mu}) \right]^{-(\nu + p)/2},

    where :math:`p` is the dimension of :math:`\mathbf{x}`,
    :math:`\boldsymbol{\mu}` is the :math:`p`-dimensional location,
    :math:`\boldsymbol{\Sigma}` the :math:`p \times p`-dimensional shape
    matrix, and :math:`\nu` is the degrees of freedom.

    .. versionadded:: 1.6.0

    Examples
    --------
    >>> import matplotlib.pyplot as plt
    >>> from scipy.stats import multivariate_t
    >>> x, y = np.mgrid[-1:3:.01, -2:1.5:.01]
    >>> pos = np.dstack((x, y))
    >>> rv = multivariate_t([1.0, -0.5], [[2.1, 0.3], [0.3, 1.5]], df=2)
    >>> fig, ax = plt.subplots(1, 1)
    >>> ax.set_aspect('equal')
    >>> plt.contourf(x, y, rv.pdf(pos))

    Nc                    s.   t t| | t| jt| _t|| _dS )z
        Initialize a multivariate t-distributed random variable.

        Parameters
        ----------
        seed : Random state.

        N)	rE   r   r9   r   rW   rB   mvt_docdict_paramsr   rF   rG   rI   r   r
   r9   i  s    	zmultivariate_t_gen.__init__r   Fc                 C   s,   |t jkrt||||dS t|||||dS )zs
        Create a frozen multivariate t-distribution. See
        `multivariate_t_frozen` for parameters.

        )rZ   r[   r6   rH   )locrc   dfr6   rH   )r   r   rY   multivariate_t_frozen)r4   r   rc   r   r6   rH   r   r   r
   r\   v  s    
 zmultivariate_t_gen.__call__c           	   	   C   sT   |  |||\}}}}| ||}t||d}| |||j|j|||j}t|S )al  
        Multivariate t-distribution probability density function.

        Parameters
        ----------
        x : array_like
            Points at which to evaluate the probability density function.
        %(_mvt_doc_default_callparams)s

        Returns
        -------
        pdf : Probability density function evaluated at `x`.

        Examples
        --------
        >>> from scipy.stats import multivariate_t
        >>> x = [0.4, 5]
        >>> loc = [0, 1]
        >>> shape = [[1, 0.1], [0.1, 1]]
        >>> df = 7
        >>> multivariate_t.pdf(x, loc, shape, df)
        array([0.00075713])

        ry   )	rm   rq   r%   rx   r/   r2   r.   r   r|   )	r4   r   r   rc   r   r6   ri   
shape_infor{   r   r   r
   r}     s     zmultivariate_t_gen.pdfc              	   C   sF   |  |||\}}}}| ||}t|}| |||j|j|||jS )a  
        Log of the multivariate t-distribution probability density function.

        Parameters
        ----------
        x : array_like
            Points at which to evaluate the log of the probability density
            function.
        %(_mvt_doc_default_callparams)s

        Returns
        -------
        logpdf : Log of the probability density function evaluated at `x`.

        Examples
        --------
        >>> from scipy.stats import multivariate_t
        >>> x = [0.4, 5]
        >>> loc = [0, 1]
        >>> shape = [[1, 0.1], [0.1, 1]]
        >>> df = 7
        >>> multivariate_t.logpdf(x, loc, shape, df)
        array([-7.1859802])

        See Also
        --------
        pdf : Probability density function.

        )rm   rq   r%   rx   r/   r2   r.   )r4   r   r   rc   r   ri   r   r   r   r
   r{     s    zmultivariate_t_gen.logpdfc                 C   s   |t jkrt|||||S || }t t ||jdd}	d||  }
t|
}td| }|d t |t j	  }d| }|
 t dd| |	   }t
|| | | | S )aB  Utility method `pdf`, `logpdf` for parameters.

        Parameters
        ----------
        x : ndarray
            Points at which to evaluate the log of the probability density
            function.
        loc : ndarray
            Location of the distribution.
        prec_U : ndarray
            A decomposition such that `np.dot(prec_U, prec_U.T)` is the inverse
            of the shape matrix.
        log_pdet : float
            Logarithm of the determinant of the shape matrix.
        df : float
            Degrees of freedom of the distribution.
        dim : int
            Dimension of the quantiles x.
        rank : int
            Rank of the shape matrix.

        Notes
        -----
        As this function does no argument checking, it should not be called
        directly; use 'logpdf' instead.

        r   rr   r   g       @r   r]   )r   r   r   rx   rs   r;   r0   r   r1   r   r   )r4   r   r   ru   r2   r   ri   r.   rv   rw   r   ABCDEr   r   r
   rx     s    
zmultivariate_t_gen._logpdfc                 C   s   |  |||\}}}}|dk	r(t|}n| j}t|rDt|}n|j||d| }|jt|||d}	||	t	|dddf   }
t
|
S )a  
        Draw random samples from a multivariate t-distribution.

        Parameters
        ----------
        %(_mvt_doc_default_callparams)s
        size : integer, optional
            Number of samples to draw (default 1).
        %(_doc_random_state)s

        Returns
        -------
        rvs : ndarray or scalar
            Random variates of size (`size`, `P`), where `P` is the
            dimension of the random variable.

        Examples
        --------
        >>> from scipy.stats import multivariate_t
        >>> x = [0.4, 5]
        >>> loc = [0, 1]
        >>> shape = [[1, 0.1], [0.1, 1]]
        >>> df = 7
        >>> multivariate_t.rvs(loc, shape, df)
        array([[0.93477495, 3.00408716]])

        N)rd   )rm   r   rF   r   isinfZonesZ	chisquarer   re   r-   r   )r4   r   rc   r   rd   rK   ri   rngr   zZsamplesr   r   r
   r     s    !

zmultivariate_t_gen.rvsc                 C   s`   t j|td}|jdkr$|t j }n8|jdkr\|dkrJ|ddt jf }n|t jddf }|S rn   ro   rp   r   r   r
   rq   #  s    

z%multivariate_t_gen._process_quantilesc                 C   s  |dkr2|dkr2t jdtd}t jdtd}d}n|dkrnt j|td}|jdk rXd}n
|jd }t |}nJ|dkrt j|td}|j}t |}n"t j|td}t j|td}|j}|dkrd|_d|_|jdks|jd |krtd| |jdkr|t | }n|jdkr$t 	|}n~|jdkr|j||fkr|j\}}||krdd	t
|j }nd
}|t
|jt|f }t|n|jdkrtd|j |dkrd}n(|dkrtdnt |rtd||||fS )z
        Infer dimensionality from location array and shape matrix, handle
        defaults, and ensure compatible dimensions.

        Nr   r    r   r   r^   r_   z*Array 'loc' must be a vector of length %d.r`   zSDimension mismatch: array 'cov' is of shape %s, but 'loc' is a vector of length %d.ra   z'df' must be greater than zero.z8'df' is 'nan' but must be greater than zero or 'np.inf'.)r   rb   r"   r   rc   re   rd   rf   r*   rg   rh   r+   isnan)r4   r   rc   r   ri   rj   rk   rl   r   r   r
   rm   3  s`    







z&multivariate_t_gen._process_parameters)N)Nr   r   FN)Nr   r   F)Nr   r   )Nr   r   r   N)r?   r@   rA   rB   r9   r\   r}   r{   rx   r   rq   rm   rO   r   r   rI   r
   r   (  s   @  

 
$+
0r   c                   @   s0   e Zd ZdddZdd Zdd	 Zdd
dZdS )r   Nr   Fc                 C   sP   t || _| j|||\}}}}||||f\| _| _| _| _t||d| _dS )a  
        Create a frozen multivariate t distribution.

        Parameters
        ----------
        %(_mvt_doc_default_callparams)s

        Examples
        --------
        >>> loc = np.zeros(3)
        >>> shape = np.eye(3)
        >>> df = 10
        >>> dist = multivariate_t(loc, shape, df)
        >>> dist.rvs()
        array([[ 0.81412036, -1.53612361,  0.42199647]])
        >>> dist.pdf([1, 1, 1])
        array([0.01237803])

        ry   N)	r   rQ   rm   ri   r   rc   r   r%   r   )r4   r   rc   r   r6   rH   ri   r   r   r
   r9   s  s    
zmultivariate_t_frozen.__init__c              	   C   sB   | j || j}| jj}| jj}| j || j||| j| j| jj	S r:   )
rQ   rq   ri   r   r/   r2   rx   r   r   r.   )r4   r   r/   r2   r   r   r
   r{     s    zmultivariate_t_frozen.logpdfc                 C   s   t | |S r:   r   r   r   r   r
   r}     s    zmultivariate_t_frozen.pdfc                 C   s   | j j| j| j| j||dS )N)r   rc   r   rd   rK   )rQ   r   r   rc   r   r   r   r   r
   r     s    
zmultivariate_t_frozen.rvs)Nr   r   FN)r   N)r?   r@   rA   r9   r{   r}   r   r   r   r   r
   r   q  s     
r   )r{   r}   r   )NN)r   )/Znumpyr   Zscipy.linalgr'   Z
scipy._libr   Zscipy.specialr   Zscipy._lib._utilr   Zscipy.statsr   r1   r   rt   Z_LOG_2Z_LOG_PIrU   r   r   r$   r%   rD   rP   rS   rT   Z_mvn_doc_frozen_callparamsZ_mvn_doc_frozen_callparams_noterX   Zmvn_docdict_noparamsrV   r   rY   r   r   Z_mvt_doc_frozen_callparams_noter   Zmvt_docdict_noparamsr   r   Zmultivariate_tname__dict__methodZmethod_frozenrW   rB   r   r   r   r
   <module>   sz   

#
G$
   (^  K.

