#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) //
    ////////////////////////////////////////////////////////////////////////

    typedef int32_t narray_rands_t;

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

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

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

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

    void test_random1();
    
};
};
};

#endif