/*////////////////////////////////////////////////////////////////////////////
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <s.engelmann@uni-wuppertal.de> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return Sven Engelmann
* 
* Random number generator for random numbers following a Gaussian distribution and 
* approximation of the exponential function are added by lena.tarrach@uni-wuppertal.de
* ----------------------------------------------------------------------------
*/////////////////////////////////////////////////////////////////////////////
#ifndef HELPER_HPP
#define HELPER_HPP
////////////////////////////////////////////////////////////////////////
// includes
#include <iostream>
#include <iomanip>														// output manipulation
#include <random>														// stl library for random number creation
#include <ctime>
#include <valarray>
////////////////////////////////////////////////////////////////////////
// random number generator
std::mt19937 &global_urng()
{
	std::random_device device;
	static std::mt19937 u{device()};
	return u;
}
// uniform distribution
double randomnumber(const double dmin,const double dmax)
{
	static std::uniform_real_distribution<>  d{};
	using parm_t  = decltype(d)::param_type;
	return d(global_urng(), parm_t{dmin, dmax});
}
// Gaussian distribution 
double rnd_gaussian(const double _mean, const double _std) {
	static std::normal_distribution<double> d(_mean, _std);
	return d(global_urng());
}
// random integer from uniform distribution
inline int randomint(int xmin, int xmax)
{
	std::random_device rd;  //Will be used to obtain a seed for the random number engine
	std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
	std::uniform_int_distribution<int> dis(xmin, xmax);
	return dis(gen);
}

////////////////////////////////////////////////////////////////////////
// exponential function
double exponential(const size_t n, const double x) {
	double sum = 1.0;
	for (size_t i = n - 1; i > 0; --i) {
		const double i_inv = 1.0 / static_cast<double>(i);
		sum = 1.0 + x * sum * i_inv;
	}
	return sum;
}
////////////////////////////////////////////////////////////////////////
// print loadbar 
static inline void loadbar(int i, int elements)
{
    if( (i!=elements) && (i%(elements/100+1)) != 0 )
		return;

	double ratio = static_cast<double>(i)/static_cast<double>(elements);
	int    fill  = static_cast<int>(ratio*50);
    
	std::cout << std::setw(3) << static_cast<int>(ratio*100) << "% [";
	for(int j = 0; j<fill; j++)
		std::cout << "=";
	for(int j = fill; j<50; j++)
		std::cout << " ";
	std::cout << "] \r" << std::flush;
	if(i==elements)
		std::cout<<std::endl;
}
////////////////////////////////////////////////////////////////////////
// swap element i and j
//~ template<class Type> inline void swap(Type &i, Type &j)
//~ {
	//~ Type temp = i;
	//~ i = j;
	//~ j = temp;
//~ }
////////////////////////////////////////////////////////////////////////
// do nothing for n seconds
inline void sleep(double nseconds)
{
    clock_t goal{static_cast<clock_t>(nseconds*static_cast<double>(CLOCKS_PER_SEC)) + clock()};
    while (goal > clock());
}
////////////////////////////////////////////////////////////////////////
// tic() tac() functions for runtime measurements
namespace tmeasure
{
	double measure_time(const bool bstart,const bool boutput=false)
	{
		static clock_t tstart{0};
		if(bstart)
		{
			const clock_t cnow{clock()};
			const double t{static_cast<double>(cnow)/static_cast<double>(CLOCKS_PER_SEC)};
			if(boutput)
				std::cout<<"# Timer started at t="<<t<<"s from boot."<<std::endl;
			tstart = cnow;
			return t;	
		}
		else
		{
			const double t{static_cast<double>(clock() - tstart)/static_cast<double>(CLOCKS_PER_SEC)};
			if(boutput)
				std::cout<<"# Elapsed time is t="<<t<<"s."<<std::endl;
			return t;
		}
	}
};
double tic(void)
{
	return tmeasure::measure_time(true);
}
double tac(void)
{
	return tmeasure::measure_time(false,true);
}
////////////////////////////////////////////////////////////////////////
#endif
