#ifndef __AMSCPPNARRAY_RANDOM_HPP__
#define __AMSCPPNARRAY_RANDOM_HPP__

namespace ams
{
namespace narray
{
namespace rand
{

    //Random functions for numeric array class

    ////////////////////////////////////////////////////////////////////////
    //Simple Deterministic Psuedorandom Number Generator (32 bit version) //
    ////////////////////////////////////////////////////////////////////////

    static const int32_t dpr32_mod = ( ((int32_t)1) << ((int32_t)30) ) - (int32_t)1;
    static const int32_t dpr32_mult1 = ( (int32_t) 1201633 );
    static int32_t dpr32_rseed = 0; // global random number seed for numeric array class
    
    int32_t dpr32_nextseed(int32_t seed);
    double dpr32_randd(int32_t *seed);
    float dpr32_randf(int32_t *seed);
    double dpr32_gaussian(int32_t *seed);
    float dpr32_gaussianf(int32_t *seed);
    int dpr32_randint(int32_t *seed, int low, int high);
    
    ams::vect2 dpr32_randuvect2(int32_t *seed);
    ams::vect3 dpr32_randuvect3(int32_t *seed);
    ams::vect4 dpr32_randuvect4(int32_t *seed);
    
    ams::vect2f dpr32_randuvect2f(int32_t *seed);
    ams::vect3f dpr32_randuvect3f(int32_t *seed);
    ams::vect4f dpr32_randuvect4f(int32_t *seed);

    ////////////////////////////////////////////
    //Numeric array threaded random generators//
    ////////////////////////////////////////////

    int32_t get_rseed();
    void set_rseed(int32_t seed);
    void set_rseed_withtimer();

    narray<double> narray_rand(narray_size_t N, 
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<float> narray_randf(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<double> narray_randgauss(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<float> narray_randgaussf(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    
    narray<int> narray_randint(narray_size_t N, int low, int highexcl,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<vect2> narray_randuvect2(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<vect3> narray_randuvect3(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<vect4> narray_randuvect4(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<vect2f> narray_randuvect2f(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<vect3f> narray_randuvect3f(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    narray<vect4f> narray_randuvect4f(narray_size_t N,
        int32_t *rseed = &(ams::narray::rand::dpr32_rseed));
    

    void test_random1();
    
};
};
};

#endif