U
    ,d'                     @   s  d dl Z d dlmZmZmZmZmZmZmZm	Z	m
Z
 d dlZejdejfdejfgddZe	eZej ZZe
eeddd	 Ze
eedd
d Ze
eeddd Ze
eeddd Ze
eeddd Ze
eeddd Ze
eeddd Ze
eeddd Zede j Zede j Ze
eeddd Ze
eeddd Ze
eeddd Z d#dd Z!d$d!d"Z"dS )%    N)	configcudafloat32float64uint32int64uint64
from_dtypejits0s1T)Zalign)ZforceobjZloopliftc                 C   sx   t |}t|}|td }||td? A td }||td? A td }||td? A }|| | d< || | d< d	S )
a  Use SplitMix64 to generate an xoroshiro128p state from 64-bit seed.

    This ensures that manually set small seeds don't result in a predictable
    initial sequence from the random number generator.

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: uint64
    :param index: offset in states to update
    :type seed: int64
    :param seed: seed value to use when initializing state
    l   |~fq	    l   e9z    l   b&&&	    r   r   N)r   r   r   )statesindexseedz r   5/tmp/pip-unpacked-wheel-eu7e0c37/numba/cuda/random.pyinit_xoroshiro128p_state-   s    r   c                 C   s(   t | } t|}| |> | td| ? B S )zLeft rotate x by k bits.@   )r   r   )xkr   r   r   rotlG   s    r   c                 C   sx   t |}| | d }| | d }|| }||N }tt|td|A |td> A | | d< tt|td| | d< |S )zReturn the next random uint64 and advance the RNG in states[index].

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: int64
    :param index: offset in states to update
    :rtype: uint64
    r   r   7      $   )r   r   r   r   )r   r   r   r   resultr   r   r   xoroshiro128p_nextO   s    
*r   c                 C   s   t |}tdtdf}td}td}tdD ]T}tdD ]F}|| tdt|> @ rx|| | d N }|| | d N }t| | q<q0|| | d< || | d< d	S )
zAdvance the RNG in ``states[index]`` by 2**64 steps.

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: int64
    :param index: offset in states to update
    l   zKW`u l   "U.XC r      r      r   r   N)r   r   ranger   r   )r   r   Zjumpr   r   ibr   r   r   xoroshiro128p_jumpe   s    	r%   c                 C   s,   t | } | td? tdt dtd>   S )z7Convert uint64 to float64 value in the range [0.0, 1.0)   r!   5   )r   r   r   r   r   r   r   uint64_to_unit_float64   s    r)   c                 C   s   t | } tt| S )z7Convert uint64 to float32 value in the range [0.0, 1.0))r   r   r)   r(   r   r   r   uint64_to_unit_float32   s    r*   c                 C   s   t |}tt| |S )zReturn a float32 in range [0.0, 1.0) and advance ``states[index]``.

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: int64
    :param index: offset in states to update
    :rtype: float32
    )r   r*   r   r   r   r   r   r   xoroshiro128p_uniform_float32   s    
r,   c                 C   s   t |}tt| |S )zReturn a float64 in range [0.0, 1.0) and advance ``states[index]``.

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: int64
    :param index: offset in states to update
    :rtype: float64
    )r   r)   r   r+   r   r   r   xoroshiro128p_uniform_float64   s    
r-   r    c                 C   sH   t |}t| |}t| |}ttd t| tt|  }|S )a  Return a normally distributed float32 and advance ``states[index]``.

    The return value is drawn from a Gaussian of mean=0 and sigma=1 using the
    Box-Muller transform.  This advances the RNG sequence by two steps.

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: int64
    :param index: offset in states to update
    :rtype: float32
           @)r   r,   mathsqrtr   logcosTWO_PI_FLOAT32r   r   u1u2Zz0r   r   r   xoroshiro128p_normal_float32   s
    

(r7   c                 C   sH   t |}t| |}t| |}ttd t| tt|  }|S )a  Return a normally distributed float32 and advance ``states[index]``.

    The return value is drawn from a Gaussian of mean=0 and sigma=1 using the
    Box-Muller transform.  This advances the RNG sequence by two steps.

    :type states: 1D array, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type index: int64
    :param index: offset in states to update
    :rtype: float64
    r.   )r   r,   r/   r0   r   r1   r2   TWO_PI_FLOAT64r4   r   r   r   xoroshiro128p_normal_float64   s
    

(r9   c                 C   st   | j d }t|}t|}|dkrpt| d| t|D ]}t| d q6td|D ]}| |d  | |< t| | qPd S )Nr   r!   )shaper   r   r"   r%   )r   r   subsequence_startn_r#   r   r   r   init_xoroshiro128p_states_cpu   s    
r>   c                 C   s.   t j| jtd}t||| | j||d dS )a  Initialize RNG states on the GPU for parallel generators.

    This initializes the RNG states so that each state in the array corresponds
    subsequences in the separated by 2**64 steps from each other in the main
    sequence.  Therefore, as long no CUDA thread requests more than 2**64
    random numbers, all of the RNG states produced by this function are
    guaranteed to be independent.

    The subsequence_start parameter can be used to advance the first RNG state
    by a multiple of 2**64 steps.

    :type states: 1D DeviceNDArray, dtype=xoroshiro128p_dtype
    :param states: array of RNG states
    :type seed: uint64
    :param seed: starting seed for list of generators
    )r:   dtype)streamN)npemptyr:   xoroshiro128p_dtyper>   Zcopy_to_device)r   r   r;   r@   Z
states_cpur   r   r   init_xoroshiro128p_states   s    rD   c                 C   s"   t j| t|d}t|||| |S )a5  Returns a new device array initialized for n random number generators.

    This initializes the RNG states so that each state in the array corresponds
    subsequences in the separated by 2**64 steps from each other in the main
    sequence.  Therefore, as long no CUDA thread requests more than 2**64
    random numbers, all of the RNG states produced by this function are
    guaranteed to be independent.

    The subsequence_start parameter can be used to advance the first RNG state
    by a multiple of 2**64 steps.

    :type n: int
    :param n: number of RNG states to create
    :type seed: uint64
    :param seed: starting seed for list of generators
    :type subsequence_start: uint64
    :param subsequence_start:
    :type stream: CUDA stream
    :param stream: stream to run initialization kernel on
    )r?   r@   )r   Zdevice_arrayrC   rD   )r<   r   r;   r@   r   r   r   r   create_xoroshiro128p_states  s    rE   )r   r   )r   r   )#r/   Znumbar   r   r   r   r   r   r   r	   r
   ZnumpyrA   r?   rC   Zxoroshiro128p_typeZENABLE_CUDASIMZ	_forceobjZ	_loopliftr   r   r   r%   r)   r*   r,   r-   pir3   r8   r7   r9   r>   rD   rE   r   r   r   r   <module>   sB   ,























