#############################################################################

[main]

[main - data:]

# method
method: ARS

[main - header:]

/* prototypes */
double logpdf_normal_1( double x, const UNUR_DISTR *distr );
double dlogpdf_normal_1( double x, const UNUR_DISTR *distr );
double cdf_normal_1( double x, const UNUR_DISTR *distr );
double logpdf_normal_2( double x, const UNUR_DISTR *distr );
double dlogpdf_normal_2( double x, const UNUR_DISTR *distr );
double cdf_normal_2( double x, const UNUR_DISTR *distr );

\#define COMPARE_SAMPLE_SIZE   (10000)
\#define VIOLATE_SAMPLE_SIZE   (20)

/* \#define SEED   (298346) */

#############################################################################

[new]

[new - invalid NULL ptr: 
   distr = NULL; ]

~( distr );
	--> expected_NULL --> UNUR_ERR_NULL

[new - invalid distribution type:
   distr = unur_distr_discr_new(); ]

~( distr );
	 --> expected_NULL --> UNUR_ERR_DISTR_INVALID

[new - data missing in distribution object:
   distr = unur_distr_normal_wo_logpdf(NULL,0); ]

~( distr );
	--> expected_NULL --> UNUR_ERR_DISTR_REQUIRED


[new - data missing in distribution object:
   distr = unur_distr_cont_new(); ]

/* logpdf, dlogpdf */
~( distr );
	--> expected_NULL --> UNUR_ERR_DISTR_REQUIRED

/* dlogpdf */
unur_distr_cont_set_logpdf(distr,logpdf_normal_1);
~( distr );
	--> expected_NULL --> UNUR_ERR_DISTR_REQUIRED

#############################################################################

[set]

[set - invalid NULL ptr: 
   par = NULL; ]

~_cpoints( par, 0, NULL );
	--> expected_setfailed --> UNUR_ERR_NULL

~_reinit_percentiles( par, 0, NULL );
	--> expected_setfailed --> UNUR_ERR_NULL

~_reinit_ncpoints( par, 20 );
	--> expected_setfailed --> UNUR_ERR_NULL

~_max_intervals( par, 100 );
	--> expected_setfailed --> UNUR_ERR_NULL

~_max_iter( par, 100 );
	--> expected_setfailed --> UNUR_ERR_NULL

~_verify( par, 1 );
	--> expected_setfailed --> UNUR_ERR_NULL

~_pedantic( par, 1 );
	--> expected_setfailed --> UNUR_ERR_NULL


[set - invalid parameter object:
   distr = unur_distr_normal(NULL,0);
   par = unur_tdr_new(distr); ]

~_cpoints( par, 0, NULL );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_reinit_percentiles( par, 0, NULL );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_reinit_ncpoints( par, 30 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_max_intervals( par, 100 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_max_iter( par, 100 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_verify( par, 1 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_pedantic( par, 1 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

unur_par_free(par);

[set - invalid parameters:
   double stp[] = {1.,0.,1.};
   double perc[] = {0.1,0.4,0.2};
   int n_stp = 3;
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,2);
   par = unur_ars_new(distr); ]

~_cpoints( par, -1, NULL );
	--> none --> UNUR_ERR_PAR_SET

~_cpoints( par, n_stp, stp );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_reinit_percentiles( par, -1, NULL );
	--> none --> UNUR_ERR_PAR_SET

~_reinit_percentiles( par, n_stp, stp );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_reinit_percentiles( par, n_stp, perc );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_reinit_ncpoints( par, 9 );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_max_intervals( par, 0 );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_max_iter( par, 0 );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

unur_par_free(par);

#############################################################################

[get]

[get - invalid generator object:
   distr = unur_distr_normal(NULL,0);
   par = unur_tdr_new(distr);
   gen = unur_init(par); <-- ! NULL ]

~_loghatarea(gen);
        --> expected_INFINITY --> UNUR_ERR_GEN_INVALID

#############################################################################

[chg]

[chg - invalid generator object:
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,2);
   par = unur_tdr_new(distr);
   unur_set_debug(par,0);
   gen = unur_init( par ); <-- ! NULL ]

~_verify(gen,1);
	--> expected_setfailed --> UNUR_ERR_GEN_INVALID

~_reinit_percentiles(gen, -1, NULL);
	--> expected_setfailed --> UNUR_ERR_GEN_INVALID

~_reinit_ncpoints(gen, 30);
	--> expected_setfailed --> UNUR_ERR_GEN_INVALID


[chg - invalid parameters:
   double percmon[] = {0.1,0.4,0.2};
   double percdom[] = {0.1,0.4,2.};
   int n_perc = 3;
   distr = unur_distr_normal(NULL,0);
   par = unur_ars_new(distr); 
   unur_set_debug(par,0);
   gen = unur_init( par ); <-- ! NULL ]

~_reinit_percentiles( gen, -1, NULL );
	--> none --> UNUR_ERR_PAR_SET

~_reinit_percentiles( gen, n_perc, percmon );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_reinit_percentiles( gen, n_perc, percdom );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_reinit_ncpoints( gen, 0 );
	--> expected_setfailed --> UNUR_ERR_PAR_SET


#############################################################################

[init]

[init - invalid NULL ptr: 
   par = NULL; ]

unur_init( par );
	--> expected_NULL --> UNUR_ERR_NULL

[init - stp out of domain:
   double stp[] = {-2.5,-1.,0.,1.,2.5};
   int n_stp = 5;
   gen = NULL;
   distr = unur_distr_normal(NULL,0);
   unur_distr_cont_set_domain(distr,-2.,2.);
   par = unur_ars_new(distr);
   unur_ars_set_cpoints( par, n_stp, stp ); ]

gen = unur_init( par );
	--> none --> UNUR_ERR_GEN_DATA


#############################################################################

[reinit]

[reinit - exist:
   distr = unur_distr_normal(NULL,0);
   par = unur_ars_new(distr);
   gen = unur_init( par ); <-- ! NULL ]

unur_reinit( gen );
	--> expected_reinit

#############################################################################

[sample]

[sample - invalid NULL ptr: 
   gen = NULL; ]

unur_ars_eval_invcdfhat(gen,0.5);
	--> expected_INFINITY --> UNUR_ERR_NULL

#.....................................................................

[sample - invalid generator object:
   distr = unur_distr_normal(NULL,0);
   par = unur_arou_new(distr);
   gen = unur_init(par); <-- ! NULL ]

unur_ars_eval_invcdfhat(gen,0.5);
	--> expected_INFINITY --> UNUR_ERR_GEN_INVALID

#.....................................................................

[sample - invalid domain:
   distr = unur_distr_normal(NULL,0);
   par = unur_ars_new(distr);
   gen = unur_init( par ); <-- ! NULL ]

unur_ars_eval_invcdfhat(gen,1.5);
	--> expected_INFINITY --> UNUR_ERR_DOMAIN

unur_ars_eval_invcdfhat(gen,-0.5);
	--> expected_negINFINITY --> UNUR_ERR_DOMAIN

#.....................................................................

[sample - compare:
   distr = unur_distr_normal(NULL,0); 
   par = NULL; ]

/* default */
par = unur_ars_new(distr);
        -->compare_sequence_par_start

/* verifying mode */
par = unur_ars_new(distr);
unur_ars_set_verify(par,1);
	-->compare_sequence_par

/* don't use private copy for distr object */
par = unur_ars_new(distr);
unur_set_use_distr_privatecopy(par,FALSE);
	-->compare_sequence_par

/* verifying mode, don't use private copy for distr object */
par = unur_ars_new(distr);
unur_set_use_distr_privatecopy(par,FALSE);
unur_ars_set_verify(par,1);
        -->compare_sequence_par

#.....................................................................

[sample - compare clone:
   UNUR_GEN *clone;
   double fpar[] = {1.23456,2.3456}; 
   distr = unur_distr_normal(fpar,2);
   par = NULL;
   gen = NULL; ]

/* original generator object */
par = unur_ars_new(distr);
unur_ars_set_max_intervals(par,2);
gen = unur_init(par);
        -->compare_sequence_gen_start

/* clone */
clone = unur_gen_clone(gen);
unur_free(gen);
gen = clone;
        -->compare_sequence_gen

/* dont use private copy for distr object */
/* original generator object */
unur_free(clone);
par = unur_ars_new(distr);
unur_set_use_distr_privatecopy(par,FALSE);
unur_ars_set_max_intervals(par,2);
gen = unur_init(par);
	-->compare_sequence_gen_start

/* clone */
clone = unur_gen_clone(gen);
unur_free(gen);
gen = clone;
	-->compare_sequence_gen

#.....................................................................

[sample - compare reinit:
   distr = unur_distr_normal(NULL,0); 
   par = NULL;
   gen = NULL; ]

/* original generator object */
par = unur_ars_new(distr);
gen = unur_init(par);
        -->compare_sequence_gen_start

/* reinit */
unur_reinit(gen);
        -->compare_sequence_gen

#.....................................................................

[sample - compare stringparser:
   double fpar[2] = {3.,3.};
   distr = NULL;
   par = NULL;
   gen = NULL; ]

distr = unur_distr_gamma(fpar,2);
par = unur_ars_new(distr);
gen = unur_init(par);
	-->compare_sequence_gen_start
	
unur_free(gen); gen = NULL;
unur_distr_free(distr); distr = NULL;
gen = unur_str2gen( "gamma(3.,3.) & method = ars ");
	-->compare_sequence_gen


unur_free(gen); gen = NULL;
distr = unur_distr_gamma(fpar,2);
par = unur_ars_new(distr);
unur_ars_set_cpoints(par,20,NULL);
unur_ars_set_max_intervals(par,32);
unur_ars_set_verify(par,TRUE);
gen = unur_init(par);
	-->compare_sequence_gen_start
	
unur_free(gen); gen = NULL;
unur_distr_free(distr); distr = NULL;
gen = unur_str2gen( "gamma(3.,3.) & \
  method = ars; cpoints = 20; \
  max_intervals = 32; verify" );
	-->compare_sequence_gen


#############################################################################

[validate]

[validate - generators:]

# default (few starting points)
par[0] = unur_ars_new(@distr@);

# many starting points
par[1] = unur_ars_new(@distr@);
unur_ars_set_cpoints(par,30,NULL);

# few starting points, ARS switchted off
par[2] = unur_ars_new(@distr@);
unur_ars_set_cpoints(par,3,NULL);
unur_ars_set_max_intervals(par,10);

# no private copy of distr object, many starting points
par[3] = unur_ars_new(@distr@);
unur_set_use_distr_privatecopy(par,FALSE);
unur_ars_set_cpoints(par,30,NULL);

# reinitialized with changed parameters
par[4] = unur_ars_new(@distr@);
unur_set_use_distr_privatecopy(par,FALSE);
unur_ars_set_cpoints(par,10,NULL);
fpm[0] = 1.;
fpm[1] = 4.;
unur_distr_cont_set_pdfparams(@distr@,fpm,2);
unur_reinit(gen);	

# reinitialized with changed parameters, use percentiles
par[5] = unur_ars_new(@distr@);
unur_set_use_distr_privatecopy(par,FALSE);
unur_ars_set_cpoints(par,10,NULL);
fpm[0] = 1.;
fpm[1] = 4.;
unur_distr_cont_set_pdfparams(@distr@,fpm,2);
unur_ars_chg_reinit_percentiles(gen, 2, NULL );
unur_reinit(gen);	

# reinitialized with changed parameters, use percentiles
double perc[] = {0.1,0.3,0.5,0.7,0.9};
par[6] = unur_ars_new(@distr@);
unur_set_use_distr_privatecopy(par,FALSE);
unur_ars_set_cpoints(par,10,NULL);
fpm[0] = 1.;
fpm[1] = 4.;
unur_distr_cont_set_pdfparams(@distr@,fpm,2);
unur_ars_chg_reinit_percentiles(gen, 5, perc );
unur_reinit(gen);	


[validate - distributions:]

# Beta distributions
fpm[0] = 1.;
fpm[1] = 2.;
distr[0] = unur_distr_beta(fpm,2);

fpm[0] = 1.;
fpm[1] = 5.;
distr[1] = unur_distr_beta(fpm,2);

fpm[0] = 1.;
fpm[1] = 100.;
distr[2] = unur_distr_beta(fpm,2);

fpm[0] = 2.;
fpm[1] = 5.;
distr[3] = unur_distr_beta(fpm,2);

fpm[0] = 5.;
fpm[1] = 2.;
distr[4] = unur_distr_beta(fpm,2);

fpm[0] = 3.;
fpm[1] = 4.;
distr[5] = unur_distr_beta(fpm,2);

fpm[0] = 5.;
fpm[1] = 100.;
distr[6] = unur_distr_beta(fpm,2);

fpm[0] = 500.;
fpm[1] = 300.;
distr[7] = unur_distr_beta(fpm,2);

fpm[0] = 5.;
fpm[1] = 10.;
fpm[2] = -3.;
fpm[3] = 15.;
distr[8] = unur_distr_beta(fpm,4);

# Cauchy distributions
distr[9] = unur_distr_cauchy(NULL,0);

fpm[0] = 1.;
fpm[1] = 20.;
distr[10] = unur_distr_cauchy(fpm,2);

# Exponential distributions
distr[11] = unur_distr_exponential(NULL,0);

fpm[0] = 30.;
fpm[1] = -5.;
distr[12] = unur_distr_exponential(fpm,2);

# Gamma distributions
fpm[0] = 1.;
distr[13] = unur_distr_gamma(fpm,1);

fpm[0] = 2.;
distr[14] = unur_distr_gamma(fpm,1);

fpm[0] = 3.;
distr[15] = unur_distr_gamma(fpm,1);

fpm[0] = 10.;
distr[16] = unur_distr_gamma(fpm,1);

fpm[0] = 1000.;
distr[17] = unur_distr_gamma(fpm,1);

fpm[0] = 5.;
fpm[1] = 1000.;
distr[18] = unur_distr_gamma(fpm,2);

fpm[0] = 5.;
fpm[1] = 1.e-5;
distr[19] = unur_distr_gamma(fpm,2);

fpm[0] = 5.;
fpm[1] = 10.;
fpm[2] = 1000;
distr[20] = unur_distr_gamma(fpm,3);

# Laplace distributions
distr[21] = unur_distr_laplace(NULL,0);

fpm[0] = -10.;
fpm[1] = 100.;
distr[22] = unur_distr_laplace(fpm,2);

# Normal distributions
distr[23] = unur_distr_normal(NULL,0);

fpm[0] = 1.;
fpm[1] = 1.e-5;
distr[24] = unur_distr_normal(fpm,2);

fpm[0] = 0.;
fpm[1] = 1.e+5;
distr[25] = unur_distr_normal(fpm,2);

# Uniform distributions
distr[26] = unur_distr_uniform(NULL,0);

fpm[0] = 1.;
fpm[1] = 20.;
distr[27] = unur_distr_uniform(fpm,2);

# domain exceeds support of pdf
fpm[0] = 3.;
fpm[1] = 4.;
distr[28] = unur_distr_beta(fpm,2);
unur_distr_cont_set_domain(distr[23],-2.,5.);

# normal distributions with very bad normalization constant
distr[29] = unur_distr_cont_new();
unur_distr_cont_set_logpdf(distr[29],logpdf_normal_1);
unur_distr_cont_set_dlogpdf(distr[29],dlogpdf_normal_1);
unur_distr_cont_set_cdf(distr[29],cdf_normal_1);
unur_distr_set_name(distr[29],"normal_1"); 

distr[30] = unur_distr_cont_new();
unur_distr_cont_set_logpdf(distr[30],logpdf_normal_2);
unur_distr_cont_set_dlogpdf(distr[30],dlogpdf_normal_2);
unur_distr_cont_set_cdf(distr[30],cdf_normal_2);
unur_distr_set_name(distr[30],"normal_2"); 


# number of distributions: 31


[validate - test chi2:]

#  + ... pass test
#  0 ... fail to initialize generator
#  - ... fail test
#  . ... do not run test
#  # ... comment
#
# generators:
#   [0] default (few starting points)
#   [1] many starting points
#   [2] few starting points, ARS switchted off
#   [3] no private copy of distr object, many starting points
#   [4] reinitialized with changed parameters
#   [5] reinitialized with changed parameters, use percentiles
#   [6] reinitialized with changed parameters, use percentiles
#
#	0  1  2  3  4  5  6	# distribution
#----------------------------------------
x <0>	+  +  +  +  +  +  +	# beta (1, 2)
  <1>	+  +  +	 +  +  +  +	# beta (1, 5)
x <2>	+  +  +	 +  +  +  +	# beta (1, 100)
x <3>	+  +  +	 +  +  +  +	# beta (2, 5)
  <4>	+  +  +	 +  +  +  +	# beta (5, 2)
  <5>	+  +  +	 +  +  +  +	# beta (3, 4)
x <6>	+  +  +	 +  +  +  +	# beta (5, 100)
x <7>	+  +  +	 +  +  +  +	# beta (500, 300)
  <8>	+  +  +	 +  +  +  +	# beta (5, 10, -3, 15)
  <9>	-  -  -	 -  .  .  .	# cauchy ()
x<10>	-  -  -	 -  .  .  .	# cauchy (1, 20)
 <11>	+  +  +	 +  +  +  +	# exponential ()
 <12>	+  +  +  +  +  +  +	# exponential (30, -5)
x<13>	+  +  +  +  .  .  .	# gamma (1)
 <14>	+  +  +  +  .  .  .	# gamma (2)
 <15>	+  +  +  +  .  .  .	# gamma (3)
 <16>	+  +  +  +  .  .  .	# gamma (10)
x<17>	+  +  .  +  .  .  .	# gamma (1000)
 <18>	+  +  .  +  .  .  .	# gamma (5, 1000, 0)
x<19>	+  +  .  +  .  .  .	# gamma (5, 1e-05, 0)
x<20>	+  +  .  +  .  .  .	# gamma (5, 10, 100000)
 <21>	+  +  +  +  +  +  +	# laplace ()
 <22>	+  +  +  +  +  +  +	# laplace (-10, 100)
 <23>	+  +  +  +  +  +  +	# normal ()
 <24>	+  +  .  +  +  +  +	# normal (1, 1e-05)
 <25>	+  +  .  +  +  +  +	# normal (1, 1e+05)
 <26>	+  +  +  +  +  +  +	# uniform ()
x<27>	+  +  +  +  +  +  +	# uniform (1, 20)

 <28>	+  +  +  +  +  +  +	# beta (3,4) - domain superset of support
 <29>	+  +  +	 +  .  .  .	# normal(0,1) with bad normalization constant
x<30>	+  +  .	 +  .  .  .	# normal(100,1) with bad normalization constant


[validate - verify hat:]

#  + ... pass test
#  ~ ... fail in at most 1% of samples
#  0 ... fail to initialize generator
#  - ... fail test
#  . ... do not run test
#  # ... comment
#
# generators:
#   [0] default (few starting points)
#   [1] many starting points
#   [2] few starting points, ARS switchted off
#   [3] no private copy of distr object, many starting points
#   [4] reinitialized with changed parameters
#   [5] reinitialized with changed parameters, use percentiles
#   [6] reinitialized with changed parameters, use percentiles
#
#	0  1  2  3  4  5  6	# distribution
#----------------------------------------
x <0>	+  +  +  +  +  +  +	# beta (1, 2)
  <1>	+  +  +	 +  +  +  +	# beta (1, 5)
x <2>	+  +  +	 +  +  +  +	# beta (1, 100)
x <3>	+  +  +	 +  +  +  +	# beta (2, 5)
  <4>	+  +  +	 +  +  +  +	# beta (5, 2)
  <5>	+  +  +	 +  +  +  +	# beta (3, 4)
x <6>	+  +  +	 +  +  +  +	# beta (5, 100)
x <7>	+  +  +	 +  +  +  +	# beta (500, 300)
  <8>	+  +  +	 +  +  +  +	# beta (5, 10, -3, 15)
  <9>	-  -  -	 -  .  .  .	# cauchy ()
x<10>	-  -  .	 -  .  .  .	# cauchy (1, 20)
 <11>	+  +  +	 +  +  +  +	# exponential ()
 <12>	+  +  +  +  .  .  .	# exponential (30, -5)
x<13>	+  +  +  +  .  .  .	# gamma (1)
 <14>	+  +  +  +  .  .  .	# gamma (2)
 <15>	+  +  +  +  .  .  .	# gamma (3)
 <16>	+  +  +  +  .  .  .	# gamma (10)
x<17>	+  +  .  +  .  .  .	# gamma (1000)
 <18>	+  +  .  +  .  .  .	# gamma (5, 1000, 0)
x<19>	+  +  .  +  .  .  .	# gamma (5, 1e-05, 0)
x<20>	+  +  .  +  .  .  .	# gamma (5, 10, 100000)
 <21>	+  +  +  +  +  +  +	# laplace ()
 <22>	+  +  +  +  +  +  +	# laplace (-10, 100)
 <23>	+  +  +  +  +  +  +	# normal ()
 <24>	+  +  .  +  +  +  +	# normal (1, 1e-05)
 <25>	+  +  .  +  +  +  +	# normal (1, 1e+05)
 <26>	+  +  +  +  +  +  +	# uniform ()
x<27>	+  +  +  +  +  +  +	# uniform (1, 20) 

 <28>	+  +  +  +  +  +  +	# beta (3,4) - domain superset of support
 <29>	+  +  +	 +  .  .  .	# normal(0,1) with bad normalization constant
x<30>	+  +  .	 +  .  .  .	# normal(100,1) with bad normalization constant


#############################################################################
#############################################################################

[verbatim]

/* logPDF of normal density */
double logpdf_normal_1( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
	return (-x*x/2. - 10000.);
}
double dlogpdf_normal_1( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
	return (-x);
}

static UNUR_DISTR *normal_1 = NULL;
void remove_normal_1(void) { unur_distr_free(normal_1); }

double cdf_normal_1( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED) 
{ 
	static double fpm[2] = {0., 1.};
	if (normal_1 == NULL) {
	   normal_1 = unur_distr_normal(fpm,2);
           atexit(remove_normal_1);
	}	   
	return unur_distr_cont_eval_cdf( x, normal_1 );
}

/* ......................................................................... */

\#define mu_2 (100.)

double logpdf_normal_2( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
	return (-(x-mu_2)*(x-mu_2)/2. - 10000.);
}
double dlogpdf_normal_2( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
	return (-(x-mu_2));
}

double cdf_normal_2( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED) 
{ 
	static UNUR_DISTR *normal_2 = NULL;
	static double fpm[2] = {mu_2, 1.};
	if (normal_2 == NULL) normal_2 = unur_distr_normal(fpm,2);
	return unur_distr_cont_eval_cdf( x, normal_2 );
}

##############################################################################
