B
     \$                 @   s:  d dl mZmZ d dlZd dl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dd	 Zed
d Zedd Ze
de
dfZedd Zedd Zedd Zedd Zedd Zedej Zedej Zedd Zedd Zedd  Z d%d!d"Z!d&d#d$Z"dS )'    )print_functionabsolute_importN)cudafloat32float64uint32int64uint64
from_dtypejits0s1T)Zalignc             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   0lib/python3.7/site-packages/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   rotl?   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_nextG   s    
*r    l   zKW`u l   "U.XC c             C   s   t |}td}td}xdtdD ]X}xRtdD ]F}t| tdt|> @ rl|| | d N }|| | d N }t| | q0W q"W || | 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
    r      r      r   r   N)r   r	   rangeXOROSHIRO128P_JUMPr   r    )r   r   r   r   ibr   r   r   xoroshiro128p_jump`   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_float64y   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   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
    g       @)r   r,   mathsqrtr   logcosTWO_PI_FLOAT32)r   r   u1u2z0r   r   r   xoroshiro128p_normal_float32   s
    

(r6   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
    g       @)r   r,   r.   r/   r   r0   r1   TWO_PI_FLOAT64)r   r   r3   r4   r5   r   r   r   xoroshiro128p_normal_float64   s
    

(r8   c             C   s|   | j d }t|}t|}|dkrxt| d| xt|D ]}t| d q8W x,td|D ]}| |d  | |< t| | qVW d 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 intializes 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
    )r9   dtype)streamN)npemptyr9   xoroshiro128p_dtyper=   Zcopy_to_device)r   r   r:   r?   Z
states_cpur   r   r   init_xoroshiro128p_states   s    rC   c             C   s"   t j| t|d}t|||| |S )a4  Returns a new device array initialized for n random number generators.

    This intializes 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_arrayrB   rC   )r;   r   r:   r?   r   r   r   r   create_xoroshiro128p_states  s    rD   )r   r   )r   r   )#Z
__future__r   r   r.   Znumbar   r   r   r   r   r	   r
   r   Znumpyr@   r>   rB   Zxoroshiro128p_typer   r   r    r$   r'   r*   r+   r,   r-   Zpir2   r7   r6   r8   r=   rC   rD   r   r   r   r   <module>   s*   (
