/* Dominik Szelenbaum                                            16.IV.2008 */
/* Krótkie wprowadzenie do biblioteki boost::random                         */

/*Na kolekcję bibliotek BOOST składa się wiele bibliotek o różnej funkcjonalności.      				*/
/*W ponizszym pliku postaram się przybliżyć biblioteką  "The Boost Random Number Library"				*/
/*Służącą do generacji liczb pseudolosowych, według wybranych rozkładów, za pomocą wybranych generatorów.		*/

/*By móc korzystać z pełni funkcjonalności biblioteki BOOST::Random należy załączyć plik nagłówkowy jak poniżej:	*/

#include <boost/random.hpp>


/*BOOST::Random oferuje niespełna 10  różnych generatorów liczb pseudolosowych różniących się między sobą parametrami:	*/
/*															*/
/* *Długość cyklu <- będąca "miernikiem" jakości generatora; czym większa długośc cyklu, tym rzadziej generowane są 	*/
/*  te same liczby.													*/
/*															*/
/* *Przybliżone zapotrzebowanie na pamięć <- jak sama nazwa wskazuje, im większy ten parametr tym więcej pamięci	*/
/*   do działania wymaga dany generator											*/
/*															*/
/* *Względna szybkość <- czym większy ten parametr tym szybciej działa dany generator					*/

/* Tabela parametrów poszczególnych generatorów:									*/
/* [za : http://www.boost.org/doc/libs/1_35_0/libs/random/random-generators.html]					*/

/*######################################################################################################################*/
/*##         NAZWA         #######   DŁUGOŚĆ CYKLU   ####### ZAPOTRZEBOWANIE NA PAMIĘĆ ####### WZGLĘDNA SZYBKOŚĆ #######*/
/*######################################################################################################################*/
/*##     minstd_rand       #######     2^31 - 2      #######      sizeof(int32_t)      #######         40        #######*/
/*##       rand48          #######     2^48 - 1      #######    sizeof(uint64_t)       #######         80        #######*/
/*##     ecuyer1988        #######     ok. 2^61      #######    2*sizeof(int32_t)      #######         20        #######*/
/*##    kreutzer1986       #######        ???        #######  1368*sizeof(uint32_t)    #######         60        #######*/
/*##   hellekalek1995      #######     2^31 - 1      #######      sizeof(int32_t)      #######          3        #######*/
/*######################################################################################################################*/
/*##      mt11213b         #######   2^11213 - 1     #######   352*sizeof(uint32_t)    #######        100        #######*/
/*##      mt19937          #######   2^19937 - 1     #######   625*sizeof(uint32_t)    #######        100        #######*/
/*######################################################################################################################*/
/*## lagged_fibonacci607   #######  ok. 2^  32000    #######     607*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci1279  #######  ok. 2^  67000    #######    1279*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci2281  #######  ok. 2^ 120000    #######    2281*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci3217  #######  ok. 2^ 170000    #######    3217*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci4423  #######  ok. 2^ 230000    #######    4423*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci9689  #######  ok. 2^ 510000    #######    9689*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci19937 #######  ok. 2^1050000    #######   19937*sizeof(double)    #######        150        #######*/
/*## lagged_fibonacci23209 #######  ok. 2^1200000    #######   23209*sizeof(double)    #######        140        #######*/
/*## lagged_fibonacci44497 #######  ok. 2^2300000    #######   44497*sizeof(double)    #######         60        #######*/
/*######################################################################################################################*/

/* Przy tworzeniu nowego generatora należy go zainicjować tzw. ziarnem (z angielskiego: "seed") od którego generator    */
/* rozpocznie swe działanie (tzn. wyliczanie kolejnych liczb pseudolosowych, bazując na ziarnie). Chcąc zachować 	*/
/* losowość pomiędzy kolejnymi wywołaniami programu (uniknąć sytuacji w której w każdym wykonaniu programu generowane 	*/
/* byłyby te same liczby pseudolosowe), należy zapewnić zmmienność / unikalność wartości ziarna dla kolejnych wywołań 	*/
/* programu; ciekawym pomysłem jest wykorzystanie do tego celu zegara systemowego zliczającego sekundy od 1970 roku. 	*/
/* Wymaga to załączenia pliku nagłówkowego:						*/

#include <ctime>

/* A funkcją zwracającą liczbe sekund wywołujemy: 									*/
/*		std::time(0);												*/
/* Przykładowe utworzenie generatora wraz z inicjalizacją miałoby postać:						*/

/* Ziarno można podać podczas wywołania konstruktora danego generatora, lub poprzez fukncję seed() wywołaną z 		*/
/* odpowiednim parametrem.												*/
/* Szczegółowych informacji nalezy szukać na stronie:									*/
/* http://www.boost.org/doc/libs/1_35_0/libs/random/random-generators.html#minstd_rand					*/

/* Przykładowe utworzenie generatora:											*/
/* lagged_fibonacci2281 ->												*/

boost::lagged_fibonacci2281 przykladowy_generator( static_cast <unsigned>  ( std::time(0) ) );

/* Tak utworzony generator jest już gotowy do użycia									*/

 long double y = przykladowy_generator();

/*  BOOST::random oferuje dodatkowo możliwość przekształcenia rozkładu generowanego przez wybrmny przez nas generator	*/
/* w inny rozkład rozkład.												*/
/* Biblioteka oddaje nam do dyspozycji rozkłady takie jak: geometryczny, nornalny, Bernoulliego				*/
/* Poniżej przykładowe inicjalizacje wybranych rozkładów:								*/

/* Rozkład wykładniczy:													*/

boost::exponential_distribution<double> rozklad_wykladniczy(1.5);

/* Gdzie 1.5 jest parametrem lambda rozkładu wykładniczego, a double typew zwracanym					*/

/* Rozkład trójkątny													*/

boost::triangle_distribution<double> rozklad_trojkatny( 1.0, 2.0, 3.0);

/* Gdzie dla http://pl.wikipedia.org/wiki/Grafika:Triangular_distribution_PMF.png     a = 1.0 ; b = 3.0 ; c = 2.0	*/
/* Double jest typew zwracanym.												*/


boost::geometric_distribution<int, double> rozklad_geometryczny(0.5);


/**/
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <math.h>


int main()
 {


	// Tu następuje powiązanie generatora lagged_fibonacci2281 z rozkładem geometryczny,
	boost::variate_generator<boost::lagged_fibonacci2281, boost::geometric_distribution<int, double> >  przemapowana_generacja(przykladowy_generator, rozklad_geometryczny);

	std::cout << std::endl;
	//Proste wywołania generatora nie powiązanego z rozkładem
	std::cout << "Przykładowe wywołania generatora lagged_fibonacci2281"<<std::endl;
	long double y = przykladowy_generator();
	std::cout << y << std::endl;
	y = przykladowy_generator();
	std::cout << y << std::endl;
	y = przykladowy_generator();
 	std::cout << y << std::endl;

	std::cout << "Teraz możesz spróbować zgadnąć, po ilu rzutach monetą wypadnie pierwszy orzeł"<<std::endl;
	std::cout << "Gotowy?" << std::endl;
	std::cin  >> y;

	std::cout << "No to ruszamy!" << std::endl;

	//Wywołania generatora z powiązanym rozkładem, jak widać zostaje zwrócony numer pierwszej próby zakończonej sukcesem, przy prawdopodobieństwu powodzenia 0.5 ["Rzucając kolejno monetą -> za którym rzutem po raz pierwszy wypadnie orzeł ]
	double z = przemapowana_generacja();
	std::cout << z << std::endl;

	std::cout << "\nI jak, zgadłeś?" << std::endl;

	std::cout << "Poniżej wyniki kolejnych dwóch prób: " <<std::endl;
	z = przemapowana_generacja();
	std::cout << z << std::endl;
	z = przemapowana_generacja();
	std::cout << z << std::endl;


return 0;
}
