o
    װi                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
m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 d dlmZ d dlZdZd	ZG d
d deZdddZi ae jdd Zdd Zdd Zdd ZdS )    N)LinAlgError)_core)cuda)device)_kernels)_utill    l    c                   @   s@  e Zd ZdZdddZdd Zdd Zdefd	d
Zde	fddZ
defddZdefddZddefddZdefddZddefddZde	fddZde	fddZeddddZd ddefd!d"Zd ddefd#d$Zd ddefd%d&Zde	fd'd(Zdd)d*d+efd,d-Zde	fd.d/Zd ddefd0d1Zdefd2d3Zdefd4d5Zdefd6d7Zdde	fd8d9Zdefd:d;Z d<d= Z!d>d? Z"ed@dAdBdCZ#dDdE Z$defdFdGZ%ddefdHdIZ&edJdKdLdMZ'edJdNdOdPZ(dQdR Z)dSdT Z*dUdV Z+edWdXdYdZZ,dd[d\Z-defd]d^Z.defd_d`Z/defdadbZ0defdcddZ1defdedfZ2ddgdhZ3edidAdjdkZ4defdldmZ5edndAdodpZ6d ddefdqdrZ7defdsdtZ8edudvdwdxZ9defdydzZ:defd{d|Z;de	fd}d~Z<dddZ=dd Z>dd Z?dd Z@eddddZAd ddefddZBdde	fddZCdS )RandomStateaV  Portable container of a pseudo-random number generator.

    An instance of this class holds the state of a random number generator. The
    state is available only on the device which has been current at the
    initialization of the instance.

    Functions of :mod:`cupy.random` use global instances of this class.
    Different instances are used for different devices. The global state for
    the current device can be obtained by the
    :func:`cupy.random.get_random_state` function.

    Args:
        seed (None or int): Seed of the random number generator. See the
            :meth:`~cupy.random.RandomState.seed` method for detail.
        method (int): Method of the random number generator. Following values
            are available::

               cupy.cuda.curand.CURAND_RNG_PSEUDO_DEFAULT
               cupy.cuda.curand.CURAND_RNG_PSEUDO_XORWOW
               cupy.cuda.curand.CURAND_RNG_PSEUDO_MRG32K3A
               cupy.cuda.curand.CURAND_RNG_PSEUDO_MTGP32
               cupy.cuda.curand.CURAND_RNG_PSEUDO_MT19937
               cupy.cuda.curand.CURAND_RNG_PSEUDO_PHILOX4_32_10

    Nc                 C   sN   ddl m} |d u r|j}||| _t| |j| j| _|| _	| 
| d S )Nr   curand)cupy_backends.cuda.libsr
   CURAND_RNG_PSEUDO_DEFAULTcreateGenerator
_generatorweakreffinalizedestroyGenerator
_finalizermethodseed)selfr   r   r
    r   J/home/ubuntu/.local/lib/python3.10/site-packages/cupy/random/_generator.py__init__8   s   
zRandomState.__init__c                 C   s   | j | t | _ d S N)_rk_seed_UINT64_MAX)r   sizer   r   r   _update_seedC   s   zRandomState._update_seedc                 G   s   t |}t j|}|d dkr(tj||d}|| j|jj|j	g|R   |S tj|d f|d}|| j|jj|j	g|R   |d | 
|S )N   r   dtype   )r   get_sizeinternalprodcupyemptyr   dataptrr   reshape)r   funcr   r    argselement_sizeoutr   r   r   _generate_normalF   s   
zRandomState._generate_normalc                 C   \   t |t |}}|du rt ||j}t j||d}t||| j| | |j	 |S )zReturns an array of samples drawn from the beta distribution.

        .. seealso::
            - :func:`cupy.random.beta` for full documentation
            - :meth:`numpy.random.RandomState.beta`
        Nshaper    )
r%   asarray	broadcastr1   r&   r   beta_kernelr   r   r   )r   abr   r    yr   r   r   betaY      zRandomState.betac                 C   r/   )zReturns an array of samples drawn from the binomial distribution.

        .. seealso::
            - :func:`cupy.random.binomial` for full documentation
            - :meth:`numpy.random.RandomState.binomial`
        Nr0   )
r%   r2   r3   r1   r&   r   binomial_kernelr   r   r   r   npr   r    r7   r   r   r   binomialh   r9   zRandomState.binomialc                 C   F   t |}|du r|j}t j||d}t|| j| | |j |S )zReturns an array of samples drawn from the chi-square distribution.

        .. seealso::
            - :func:`cupy.random.chisquare` for full documentation
            - :meth:`numpy.random.RandomState.chisquare`
        Nr0   )	r%   r2   r1   r&   r   chisquare_kernelr   r   r   r   dfr   r    r7   r   r   r   	chisquarew      
zRandomState.chisquarec                 C   s   t |}|du r|j}nt|tt jfr|f|j }n||j7 }t j||d}t|| j	| ||j
ddd }| |j |S )zReturns an array of samples drawn from the dirichlet distribution.

        .. seealso::
            - :func:`cupy.random.dirichlet` for full documentation
            - :meth:`numpy.random.RandomState.dirichlet`
        Nr0   T)axiskeepdims)r%   r2   r1   
isinstanceintintegerr&   r   standard_gamma_kernelr   sumr   r   )r   alphar   r    r7   r   r   r   	dirichlet   s   

zRandomState.dirichlet      ?c                 C   sF   t ||}|dk  rtd|du r|j}| ||}||9 }|S )a.  Returns an array of samples drawn from a exponential distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.exponential` for full documentation
            - :meth:`numpy.random.RandomState.exponential`
        r   	scale < 0N)r%   r2   any
ValueErrorr1   standard_exponentialr   scaler   r    xr   r   r   exponential   s   zRandomState.exponentialc                 C   r/   )zReturns an array of samples drawn from the f distribution.

        .. seealso::
            - :func:`cupy.random.f` for full documentation
            - :meth:`numpy.random.RandomState.f`
        Nr0   )
r%   r2   r3   r1   r&   r   f_kernelr   r   r   )r   dfnumdfdenr   r    r7   r   r   r   f   r9   zRandomState.fc                 C   sb   t |t |}}|du rt ||j}t j||d}t|| j| ||9 }| |j	 |S )zReturns an array of samples drawn from a gamma distribution.

        .. seealso::
            - :func:`cupy.random.gamma` for full documentation
            - :meth:`numpy.random.RandomState.gamma`
        Nr0   )
r%   r2   r3   r1   r&   r   rK   r   r   r   )r   r1   rU   r   r    r7   r   r   r   gamma   s   zRandomState.gammac                 C   r?   )zReturns an array of samples drawn from the geometric distribution.

        .. seealso::
            - :func:`cupy.random.geometric` for full documentation
            - :meth:`numpy.random.RandomState.geometric`
        Nr0   )	r%   r2   r1   r&   r   geometric_kernelr   r   r   r   r=   r   r    r7   r   r   r   	geometric   rD   zRandomState.geometricc                 C   sl   t |t |t |}}}|du rt |||j}t j||d}t|||| j| | |j	 |S )zReturns an array of samples drawn from the hypergeometric distribution.

        .. seealso::
            - :func:`cupy.random.hypergeometric` for full documentation
            - :meth:`numpy.random.RandomState.hypergeometric`
        Nr0   )
r%   r2   r3   r1   r&   r   hypergeometric_kernelr   r   r   )r   ngoodnbadnsampler   r    r7   r   r   r   hypergeometric   s   zRandomState.hypergeometriczT x, T loc, T scalezT yz>y = loc + scale * ((x <= 0.5) ? log(x + x): -log(x + x - 1.0))cupy_laplace_kernel        c                 C   sN   t ||}t ||}|du rt ||j}| ||}t|||| |S )zReturns an array of samples drawn from the laplace distribution.

        .. seealso::
            - :func:`cupy.random.laplace` for full documentation
            - :meth:`numpy.random.RandomState.laplace`
        N)r%   r2   r3   r1   _random_sample_rawr   _laplace_kernelr   locrU   r   r    rV   r   r   r   laplace   s   zRandomState.laplacec                 C   s   t |t |}}|du rt ||j}t j||d}t| j| | |j	 d| | }t j
||d t j|||d t j|||d |S )zReturns an array of samples drawn from the logistic distribution.

        .. seealso::
            - :func:`cupy.random.logistic` for full documentation
            - :meth:`numpy.random.RandomState.logistic`
        Nr0   rO   r-   )r%   r2   r3   r1   r&   r   open_uniform_kernelr   r   r   logmultiplyaddri   r   r   r   logistic   s   zRandomState.logisticc                 C   s   ddl m} tdd ||fD r"| ||||}tj||d |S |du r(d}t|}|jdkr5|j}n|j	}| 
|||||S )	zReturns an array of samples drawn from a log normal distribution.

        .. seealso::
            - :func:`cupy.random.lognormal` for full documentation
            - :meth:`numpy.random.RandomState.lognormal`

        r   r	   c                 s   s    | ]	}t |tjV  qd S r   )rH   r%   ndarray).0argr   r   r   	<genexpr>  s    z(RandomState.lognormal.<locals>.<genexpr>rl   Nr   r[   )r   r
   rQ   normalr%   exp_check_and_get_dtypechargenerateLogNormalgenerateLogNormalDoubler.   )r   meansigmar   r    r
   rV   r*   r   r   r   	lognormal  s   
zRandomState.lognormalc                 C   sr   t |}t |dkrtdt |dkrtd|du r"|j}t j||d}t|| j| | 	|j
 |S )a*  Returns an array of samples drawn from a log series distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.logseries` for full documentation
            - :meth:`numpy.random.RandomState.logseries`

        r   zp <= 0.0r!   zp >= 1.0Nr0   )r%   r2   rQ   rR   r1   r&   r   logseries_kernelr   r   r   r^   r   r   r   	logseries*  s   
zRandomState.logseriesignoreg:0yE>choleskyc                 C   s>  t d tj||d}tj||d}|du rg }nt|ttjfr&|g}n|}t|jdkr3t	dt|jdksD|jd |jd krHt	d|jd |jd krVt	d	t
|dd }	|	|jd  |d
vrnt	d|dkr~|dkr~|dkr~t	d|dkrtjdd ztj|}
W nv ty   tjdd] |dkr|dkrtj|\}}t|| k  }|dkrtj|\}}}tjt|j| ||||d}|tt| }
|stdt ntdt tj|}
W d   n	1 sw   Y  Y nw W d   n	1 sw   Y  nbtj|dS z>|dkr.tj|}
n0|dkrFtj|\}}|tt| }
n|dkr^tj|\}}}|tt| }
W n tyk   tdw W d   n	1 sww   Y  | j|	|dd|jd }t|
|j}|j}||7 }t|	|_|S )ae  Returns an array of samples drawn from the multivariate normal
        distribution.

        .. warning::
            This function calls one or more cuSOLVER routine(s) which may yield
            invalid results if input conditions are not met.
            To detect these invalid results, you can set the `linalg`
            configuration to a value that is not `ignore` in
            :func:`cupyx.errstate` or :func:`cupyx.seterr`.

        .. seealso::
            - :func:`cupy.random.multivariate_normal` for full documentation
            - :meth:`numpy.random.RandomState.multivariate_normal`
        z+cupy.random.RandomState.multivariate_normalr   Nr!   zmean must be 1 dimensionalr   r   z$cov must be 2 dimensional and squarez"mean and cov must have same length>   svdeighr   z1method must be one of {'eigh', 'svd', 'cholesky'}r   warnraisez3check_valid must equal 'warn', 'raise', or 'ignore')linalgr   r   r   )rtolatolz?covariance is not positive-semidefinite, output may be invalid.z=covariance is not positive-semidefinite, output *is* invalid.z_Matrix is not positive definite; if matrix is positive-semidefinite, set'check_valid' to 'warn'rE   )r   experimentalr%   r2   rH   rI   rJ   lenr1   rR   listappendcupyxerrstater   r   r   r   rQ   r   allclosedotTsqrtabswarningsr   RuntimeWarningstandard_normalr)   tuple)r   r|   covr   check_validtolr   r    r1   final_shapedecompsupsdvhrV   r   r   r   multivariate_normalB  s   
"




zRandomState.multivariate_normalc                 C   sz   t |}t |}t |dkrtdt |dk r tdt |dkr+td| |d| | |}| j||dS )aB  Returns an array of samples drawn from the negative binomial distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.negative_binomial` for full documentation
            - :meth:`numpy.random.RandomState.negative_binomial`
        r   zn <= 0zp < 0r!   zp > 1r   )r%   r2   rQ   rR   r\   poissonr;   r   r   r   negative_binomial  s   

zRandomState.negative_binomialc                 C   s   ddl m} t|}|du rt||j}|jdkr|j}n|j}t	|tj
rB| |||dd}tj|||d tj|||d |S t	|tj
r[| |||d|}tj|||d |S | |||||}|S )zReturns an array of normally distributed samples.

        .. seealso::
            - :func:`cupy.random.normal` for full documentation
            - :meth:`numpy.random.RandomState.normal`

        r   r	   Nr[   rf   rO   rl   )r   r
   rx   r%   r3   r1   ry   generateNormalgenerateNormalDoublerH   rr   r.   ro   rp   )r   rj   rU   r   r    r
   r*   rV   r   r   r   rv     s$   
zRandomState.normalc                 C   sN   t |}|du r|j}| ||}t j||d t j| | |d |d S )zReturns an array of samples drawn from the pareto II distribution.

        .. seealso::
            - :func:`cupy.random.pareto` for full documentation
            - :meth:`numpy.random.RandomState.pareto`
        Nrl   r!   )r%   r2   r1   rg   rn   rw   r   r5   r   r    rV   r   r   r   pareto  s   
zRandomState.paretoc                 C   s   t |t |}}t |dkrtdt |dk r!td|du r,t ||j}t j||d}t||| j	| | 
|j |S )aT  Returns an array of samples drawn from the noncentral chi-square
        distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.noncentral_chisquare` for full documentation
            - :meth:`numpy.random.RandomState.noncentral_chisquare`
        r   zdf <= 0nonc < 0Nr0   )r%   r2   rQ   rR   r3   r1   r&   r   noncentral_chisquare_kernelr   r   r   )r   rB   noncr   r    r7   r   r   r   noncentral_chisquare  s   z RandomState.noncentral_chisquarec                 C   s   t |t |t |}}}t |dkrtdt |dkr'tdt |dk r2td|du r>t |||j}t j||d}t|||| j	| | 
|j |S )a3  Returns an array of samples drawn from the noncentral F distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.noncentral_f` for full documentation
            - :meth:`numpy.random.RandomState.noncentral_f`
        r   z
dfnum <= 0z
dfden <= 0r   Nr0   )r%   r2   rQ   rR   r3   r1   r&   r   noncentral_f_kernelr   r   r   )r   rY   rZ   r   r   r    r7   r   r   r   noncentral_f  s   zRandomState.noncentral_fc                 C   r?   )zReturns an array of samples drawn from the poisson distribution.

        .. seealso::
            - :func:`cupy.random.poisson` for full documentation
            - :meth:`numpy.random.RandomState.poisson`
        Nr0   )	r%   r2   r1   r&   r   poisson_kernelr   r   r   )r   lamr   r    r7   r   r   r   r     rD   zRandomState.poissonc                 C   sv   t |}t |dk rtd|du r|j}| j||d}t j| |d t jd| |d t j|d| |d |S )a  Returns an array of samples drawn from the power distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.power` for full documentation
            - :meth:`numpy.random.RandomState.power`
        r   a < 0Nr   r    rl   r!   rO   )	r%   r2   rQ   rR   r1   rS   rw   rp   powerr   r   r   r   r   $  s   
zRandomState.powerc                 O   4   | dt}|rtdd|  | j||dS )zReturns uniform random values over the interval ``[0, 1)``.

        .. seealso::
            - :func:`cupy.random.rand` for full documentation
            - :meth:`numpy.random.RandomState.rand`

        r    z*rand() got unexpected keyword arguments %s, r   )popfloat	TypeErrorjoinkeysrandom_sampler   r   kwargr    r   r   r   rand:     zRandomState.randc                 O   r   )zReturns an array of standard normal random values.

        .. seealso::
            - :func:`cupy.random.randn` for full documentation
            - :meth:`numpy.random.RandomState.randn`

        r    z+randn() got unexpected keyword arguments %sr   r   )r   r   r   r   r   rv   r   r   r   r   randnH  r   zRandomState.randn zT xzx = (x == (T)1) ? 0 : xcupy_random_x_mod_1c                 C   sR   ddl m} t|}tj||d}|jdkr|j}n|j}|| j|j	j
|j |S )Nr   r	   r   r[   )r   r
   rx   r%   r&   ry   generateUniformgenerateUniformDoubler   r'   r(   r   )r   r   r    r
   r-   r*   r   r   r   rg   Y  s   
zRandomState._random_sample_rawc                 C   s&   |du rd}|  ||}t| |S )zReturns an array of random values over the interval ``[0, 1)``.

        .. seealso::
            - :func:`cupy.random.random_sample` for full documentation
            - :meth:`numpy.random.RandomState.random_sample`

        Nr   )rg   r   _mod1_kernel)r   r   r    r-   r   r   r   r   e  s
   
zRandomState.random_samplec                 C   sz   t |}|du r|j}t |dk rtd| ||}t j||d}t j|d|d}t j||d}t j|||d}|S )a%  Returns an array of samples drawn from a rayleigh distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.rayleigh` for full documentation
            - :meth:`numpy.random.RandomState.rayleigh`
        Nr   rP   rl   g       )	r%   r2   r1   rQ   rR   rg   rn   ro   r   rT   r   r   r   rayleighs  s   
zRandomState.rayleighzT max, T mxzT outz3out = max - (mx != max ? (max - mx) % (mx + 1) : 0) cupy_random_interval_upper_limitzT samplez$if (mx != max) { sample %= mx + 1; }"cupy_random_interval_sample_moduloc                 C   s  |du rd}nt |tr|f}t|}|rX|dkr"tj|tjdS |dk r-td||t	kr?tj}|t	d|d   }nY|t
krQtj}|t
d|d   }nGtd	||j}|tjkse|tjkrvtj}|j|d
d}| t	|}n"|tjks|tjkrtj}|j|d
d}| t
|}ntd|ttj|d}|dkrtj||dS | ||}|r|d }|d| d > krd| > d }	||	M }||S | ||d
}
|
j}|dkrt|s||
 }|dkr=|rt|d dn|j}| ||}| ||d}|j}||kr||d|  ||
< d}n|| ||
d| < |
|d }
|s5||d }||8 }|dks|rE||; }n|tjkrS| t	||}n| t
||}||S )a`  Generate multiple integers independently sampled uniformly from ``[0, mx]``.

        Args:
            mx (int): Upper bound of the interval
            size (None or int or tuple): Shape of the array or the scalar
                returned.
        Returns:
            int or cupy.ndarray: If ``None``, an :class:`cupy.ndarray` with
            shape ``()`` is returned.
            If ``int``, 1-D array of length size is returned.
            If ``tuple``, multi-dimensional array with shape
            ``size`` is returned.
            Currently, only 32 bit or 64 bit integers can be sampled.
        Nr   r   r   z$mx must be non-negative (actual: {})        r!               z+mx must be within uint64 range (actual: {})Fcopyzdtype must be integer, got: {}r   i   T)rH   rI   numpyisscalarr%   zerosuint32rR   format_UINT32_MAXr   uint64r    int32astype_interval_upper_limitint64	functoolsreduceoperatormulr&   _curand_generate
bit_lengthr)   _get_indicesr   max_interval_sample_modulo)r   mxr   is_mx_scalarr    upper_limitn_samplesamplemx1mask
ng_indicesn_ngn_supplement
supplement
ok_indicesn_okr   r   r   	_interval  s   






zRandomState._intervalc                 C   sD   ddl m} tj|f|d}|jtjdj}|| j	|j
j| |S )Nr   r	   r   )r   r
   r%   r&   viewr   r   r   generater   r'   r(   )r   numr    r
   r   size32r   r   r   r     s
   zRandomState._curand_generatec                 C   sh   |j dk rtjntj}|r||kn||k}tj||d}~tjt|d f|d}| j|||j d |S )Nr   r   rE   r   )	r   r   r   r   r%   cumsumr&   rI   _kernel_get_indices)r   r   r   condr    flagscsumindicesr   r   r   r      s   zRandomState._get_indicesz
raw U csumzraw U indiceszo
        int j = 0;
        if (i > 0) { j = csum[i-1]; }
        if (csum[i] > j) { indices[j] = i; }
        cupy_get_indicesc                 C   s   ddl m} |du r+zttd}t|d}W nG ty*   t d t	 }Y n7w t
|tjrBttj|dd dd d}nt|}|jjd	vrQtd
t|}|dk s]|dkratd|| j| | j|j|jfvrx|| jd || _dS )zResets the state of the random number generator with a seed.

        .. seealso::
            - :func:`cupy.random.seed` for full documentation
            - :meth:`numpy.random.RandomState.seed`

        r   r	   N      i@B F)usedforsecuritybiuzSeed must be an integer.r   z/Seed must be an integer between 0 and 2**64 - 1)r   r
   binasciihexlifyosurandomrI   NotImplementedErrortimer   rH   r   rr   hashlibmd5	hexdigestr2   r    kindr   rR   setPseudoRandomGeneratorSeedr   r   CURAND_RNG_PSEUDO_MT19937CURAND_RNG_PSEUDO_MTGP32setGeneratorOffsetr   )r   r   r
   seed_strseed_arrr   r   r   r     s<   


zRandomState.seedc                 C   s"   | j ||d}ttj|d  S )zReturns an array of samples drawn from the standard cauchy distribution.

        .. seealso::
            - :func:`cupy.random.standard_cauchy` for full documentation
            - :meth:`numpy.random.RandomState.standard_cauchy`
        r   g      ?)uniformr%   tanpir   r   r    rV   r   r   r   standard_cauchy7  s   zRandomState.standard_cauchyc                 C   s(   |du rd}|  ||}tj||d S )zReturns an array of samples drawn from the standard exp distribution.

         .. seealso::
            - :func:`cupy.random.standard_exponential` for full documentation
            - :meth:`numpy.random.RandomState.standard_exponential`
        Nr   rl   )rg   r%   rn   r  r   r   r   rS   A  s   z RandomState.standard_exponentialc                 C   r?   )zReturns an array of samples drawn from a standard gamma distribution.

        .. seealso::
            - :func:`cupy.random.standard_gamma` for full documentation
            - :meth:`numpy.random.RandomState.standard_gamma`
        Nr0   )	r%   r2   r1   r&   r   rK   r   r   r   )r   r1   r   r    r7   r   r   r   standard_gammaM  rD   zRandomState.standard_gammac                 C   s   | j ||dS )zReturns samples drawn from the standard normal distribution.

        .. seealso::
            - :func:`cupy.random.standard_normal` for full documentation
            - :meth:`numpy.random.RandomState.standard_normal`

        r   )rv   )r   r   r    r   r   r   r   \  s   zRandomState.standard_normalc                 C   r?   )zReturns an array of samples drawn from the standard t distribution.

        .. seealso::
            - :func:`cupy.random.standard_t` for full documentation
            - :meth:`numpy.random.RandomState.standard_t`
        Nr0   )	r%   r2   r1   r&   r   standard_t_kernelr   r   r   rA   r   r   r   
standard_tf  rD   zRandomState.standard_tc                 C   sd   ddl m} |du rd}tj|tjd}|jjd }|| j|j	j
|j|  |ttjjM }|S )a  Draws integers between 0 and max integer inclusive.

        Return a sample of uniformly distributed random integers in the
        interval [0, ``np.iinfo(np.int_).max``]. The `np.int_` type translates
        to the C long integer type and its precision is platform dependent.

        Args:
            size (int or tuple of ints): Output shape.

        Returns:
            cupy.ndarray: Drawn samples.

        .. seealso::
            :meth:`numpy.random.RandomState.tomaxint`

        r   r	   Nr   r      )r   r
   r%   r&   int_r    itemsizer   r   r'   r(   r   iinfor   )r   r   r
   r   size_in_intr   r   r   tomaxintu  s   zRandomState.tomaxintzL left, M mode, R righta  
        T base, leftbase, ratio, leftprod, rightprod;

        base = right - left;
        leftbase = mode - left;
        ratio = leftbase / base;
        leftprod = leftbase*base;
        rightprod = (right - mode)*base;

        if (x <= ratio)
        {
            x = left + sqrt(x*leftprod);
        } else
        {
            x = right - sqrt((1.0 - x) * rightprod);
        }
        cupy_triangular_kernelc                 C   s   t |t |t |}}}t ||krtdt ||kr'tdt ||kr2td|du r>t |||j}| j||d}t||||S )a-  Returns an array of samples drawn from the triangular distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.triangular` for full documentation
            - :meth:`numpy.random.RandomState.triangular`
        zleft > modezmode > rightzleft == rightNr   )	r%   r2   rQ   rR   r3   r1   r   r   _triangular_kernel)r   leftmoderightr   r    rV   r   r   r   
triangular  s   zRandomState.triangularzT low, T highzx = T(low) + x * T(high - low)
cupy_scalec                 C   sh   t |st||}t |st||}|du r!t||j}t |}| j||d}t	|||S )zReturns an array of uniformly-distributed samples over an interval.

        .. seealso::
            - :func:`cupy.random.uniform` for full documentation
            - :meth:`numpy.random.RandomState.uniform`

        Nr   )
r   r   r%   r2   r3   r1   r    r   r   _scale_kernel)r   lowhighr   r    r   r   r   r   r    s   


zRandomState.uniformc                 C   r/   )zReturns an array of samples drawn from the von Mises distribution.

        .. seealso::
            - :func:`cupy.random.vonmises` for full documentation
            - :meth:`numpy.random.RandomState.vonmises`
        Nr0   )
r%   r2   r3   r1   r&   r   vonmises_kernelr   r   r   )r   mukappar   r    r7   r   r   r   vonmises  r9   zRandomState.vonmiseszT mean, T scale, T UzT Xa	  
            T mu_2l;
            T Y;
            mu_2l = mean / (2*scale);
            Y = mean*X*X;
            X = mean + mu_2l*(Y - sqrt(4*scale*Y + Y*Y));
            if (U > mean/(mean+X))
            {
                X = mean*mean/X;
            }
        cupy_wald_scalec                 C   s`   t j||dt j||d}}|du rt ||j}| j||d}| j||d}t||||S )zReturns an array of samples drawn from the Wald distribution.

         .. seealso::
            - :func:`cupy.random.wald` for full documentation
            - :meth:`numpy.random.RandomState.wald`
        r   Nr   )r%   r2   r3   r1   rv   r   r   _wald_kernel)r   r|   rU   r   r    rV   r   r   r   r   wald  s   zRandomState.waldc                 C   sR   t |}t |dk rtd|du r|j}| ||}t j|d| |d |S )a$  Returns an array of samples drawn from the weibull distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.weibull` for full documentation
            - :meth:`numpy.random.RandomState.weibull`
        r   r   NrO   rl   )r%   r2   rQ   rR   r1   rS   r   r   r   r   r   weibull  s   
zRandomState.weibullc                 C   s\   t |}t |dkrtd|du r|j}t j||d}t|| j| | 	|j
 |S )a  Returns an array of samples drawn from the Zipf distribution.

        .. warning::

            This function may synchronize the device.

        .. seealso::
            - :func:`cupy.random.zipf` for full documentation
            - :meth:`numpy.random.RandomState.zipf`
        rO   z'a' must be a valid float > 1.0Nr0   )r%   r2   rQ   rR   r1   r&   r   zipf_kernelr   r   r   )r   r5   r   r    r7   r   r   r   zipf  s   
zRandomState.zipfTc           
      C   s0  |du rt dt|tjr|jdkrtt|tr%|}|dk r$t dntj|dd}|jdkr5t dt|}|durpt|}|jdkrKt dt||krUt d	|dk	 s_t d
t
| }t|dspt d|du rxtd|}t|}|dkr|dkrt d|s|du r||k rt dt|trtj|dd}n| }| | |d| |S |st|durt|||f}tjt|| j||fd dd}	t|tst|	|}	n|dkrd}| jd||d}	|	jtjdd}	t|tr|	S |	jdkrtj||	 |jdS ||	 S )zReturns an array of random values from a given 1-D array.

        .. seealso::
            - :func:`cupy.random.choice` for full documentation
            - :meth:`numpy.random.choice`

        Nz%a must be 1-dimensional or an integerr   z$a must be greater than or equal to 0Fr   r!   zp must be 1-dimensionalza and p must have same sizez"probabilities are not non-negativezprobabilities do not sum to 1z5choice() without specifying size is not supported yetz-a cannot be empty unless no samples are takenz@Cannot take a larger sample than population when 'replace=False'lr   r   )rF   )rR   rH   r%   rr   ndimr  rI   arrayr   allrL   getr   r   r$   aranger   shuffler)   broadcast_toargmaxrn   gumbelrandintr   r   r    )
r   r5   r   replacer=   a_sizep_sumr1   r   indexr   r   r   choice3  s~   







zRandomState.choicec                 C   sD   t |tjs
td|jdkrtd|| t| |dd< dS )zReturns a shuffled array.

        .. seealso::
            - :func:`cupy.random.shuffle` for full documentation
            - :meth:`numpy.random.shuffle`

        zThe array must be cupy.ndarrayr   z)An array whose ndim is 0 is not supportedN)rH   r%   rr   r   r2  _permutationr   r   r5   r   r   r   r7    s
   
zRandomState.shufflec                 C   s&   t |tr
| |S || t| S )z6Returns a permuted range or a permutation of an array.)rH   rI   rA  r   rB  r   r   r   permutation  s   

zRandomState.permutationc                 C   s@   ddl m} tj|ftjd}|| j|jj	| t
|}|S )zReturns a permuted range.r   r	   r   )r   r
   r%   r&   r   r   r   r   r'   r(   argsort)r   r   r
   r   r3  r   r   r   rA    s
   
zRandomState._permutationz$y = T(loc) - log(-log(x)) * T(scale)cupy_gumbel_kernelc                 C   sd   t |st||}t |st||}|du r!t||j}| j||d}t|||| |S )zReturns an array of samples drawn from a Gumbel distribution.

        .. seealso::
            - :func:`cupy.random.gumbel` for full documentation
            - :meth:`numpy.random.RandomState.gumbel`
        Nr   )	r   r   r%   r2   r3   r1   rg   r   _gumbel_kernelri   r   r   r   r:    s   

zRandomState.gumbelc                 C   st  t |s\t|}|du rt|}|d }n	|}t|d }|du r,t||j}|| }tt	j
|d}| | |}	|	|}	t|	|}	|j|dd}tj|	||	d |	S |du rid}t|d }
n
t|}t|d }
||
kr{td|t|jk rtdt|j|
t|jkrtd	t|j|
| }| ||j|dd}tj|||d |S )
zReturns a scalar or an array of integer values over ``[low, high)``.

        .. seealso::
            - :func:`cupy.random.randint` for full documentation
            - :meth:`numpy.random.RandomState.randint`
        Nr!   Fr   rl   r   zlow >= highzlow is out of bounds for {}zhigh is out of bounds for {})r   r   r%   r2   
zeros_liker3   r1   r   r   r   r   r   flattenr   r)   rp   rI   rR   r  minr   r    namer   )r   r%  r&  r   r    lohidifftotal_elemsr-   hi1rV   r   r   r   r;    sP   






zRandomState.randint)NNr   )NTN)D__name__
__module____qualname____doc__r   r   r.   r   r8   rI   r>   rC   rN   rW   r[   r\   r_   rd   r   ElementwiseKernelrh   rk   rq   r~   r   r   r   rv   r   r   r   r   r   r   r   r   rg   r   r   r   r   r   r   r   r   r   r  rS   r  r   r  r  r  r"  r$  r  r*  r,  r-  r.  r0  r@  r7  rC  rA  rF  r:  r;  r   r   r   r   r      s    

`c		
	%



P	r   c                 C   s   t  |  dS )a  Resets the state of the random number generator with a seed.

    This function resets the state of the global random number generator for
    the current device. Be careful that generators for other devices are not
    affected.

    Args:
        seed (None or int): Seed for the random number generator. If ``None``,
            it uses :func:`os.urandom` if available or :func:`time.time`
            otherwise. Note that this function does not support seeding by
            an integer array.

    N)get_random_stater   )r   r   r   r   r     s   r   c                   C   s   i a d S r   )_random_statesr   r   r   r   reset_states  s   rW  c                  C   sX   t  } t| jd}|du r*td}|durtt	|}t
|}t| j|}|S )aX  Gets the state of the random number generator for the current device.

    If the state for the current device is not created yet, this function
    creates a new one, initializes it, and stores it as the state for the
    current device.

    Returns:
        RandomState: The state of the random number generator for the
        device.

    N	CUPY_SEED)r   DevicerV  r5  idr  getenvr   r   rI   r   
setdefault)devrsr   r   r   r   rU  	  s   
rU  c                 C   s,   t | tstdt| | tt < dS )zSets the state of the random number generator for the current device.

    Args:
        state(RandomState): Random state to set for the current device.
    z;Random state must be an instance of RandomState. Actual: {}N)rH   r   r   r   typerV  r   get_device_id)r^  r   r   r   set_random_state   s   

ra  c                 C   s    t | } | jdvrtd| S )N)r[   dz-cupy.random only supports float32 and float64)r   r    ry   r   r   r   r   r   rx   -  s   

rx   r   ) atexitr   r   r  r   r  r  r   r   r   numpy.linalgr   r%   r   r   	cupy.cudar   cupy.randomr   r   r   r   r   objectr   r   rV  registerrW  rU  ra  rx   r   r   r   r   <module>   sJ             
Z
