#ifndef __AMSMATHUTIL25_RANDOM_HPP__
#define __AMSMATHUTIL25_RANDOM_HPP__

namespace ams
{
namespace rand
{

typedef ::int32_t amsmu_randt1;
typedef ::int64_t amsmu_randt2;

static const amsmu_randt1 dpr32_mod = ( ((amsmu_randt1)1) << ((amsmu_randt1)30) ) - (amsmu_randt1)1;
static const amsmu_randt1 dpr32_mult1 = ( (amsmu_randt1) 1201633 );
static const amsmu_randt1 dpr32_add1 = ( (amsmu_randt1) 293487 );

static const amsmu_randt2 dpr64_mod = ( ((amsmu_randt2)1) << ((amsmu_randt2)62) ) - (amsmu_randt2)1;
static const amsmu_randt2 dpr64_mult1 = ( (amsmu_randt2) 1201633L );
static const amsmu_randt2 dpr64_add1 = ( (amsmu_randt2) 293487L );

extern amsmu_randt1 dpr32_rseed;
extern amsmu_randt2 dpr64_rseed;

amsmu_randt1 seed32_next(amsmu_randt1 seed);
amsmu_randt2 seed64_next(amsmu_randt2 seed);

double rand(amsmu_randt1 *seed = &dpr32_rseed);
float randf(amsmu_randt1 *seed = &dpr32_rseed);
double randgaussian(amsmu_randt1 *seed = &dpr32_rseed);
float randgaussianf(amsmu_randt1 *seed = &dpr32_rseed);
int randint(int low, int highexcl, amsmu_randt1 *seed = &dpr32_rseed);
int64_t randintl(int64_t low, int64_t highexcl, amsmu_randt2 *seed = &dpr64_rseed);

void seed32_set(amsmu_randt1 _seed);
void seed64_set(amsmu_randt2 _seed);
void seed_init_timer();

//Threaded generation of random amsarrays

amsarray<double> amsarray_rand(amsarray_size_t N, amsmu_randt1 *seed = &dpr32_rseed);
amsarray<float> amsarray_randf(amsarray_size_t N, amsmu_randt1 *seed = &dpr32_rseed);

amsarray<int> amsarray_randint(amsarray_size_t N, int low, int highexcl, amsmu_randt1 *seed = &dpr32_rseed);
amsarray<int64_t> amsarray_randintl(amsarray_size_t N, int64_t low, int64_t highexcl, amsmu_randt2 *seed = &dpr64_rseed);



}; //end namespace rand
}; //end namespace ams

#endif

