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

[main]

[main - data:]

# method (for information only: the program scans the file name)
method: SSR

[main - header:]

/* prototypes */
double pdf_normal( double x, const UNUR_DISTR *distr );
double pdf_invalid( double x, const UNUR_DISTR *distr );

double pdf_sqrtlin( double x, const UNUR_DISTR *distr );
double dpdf_sqrtlin( double x, const UNUR_DISTR *distr );
double cdf_sqrtlin( double x, const UNUR_DISTR *distr );

double pdf_sqrtlinshft(double x, const UNUR_DISTR *distr );
double dpdf_sqrtlinshft( double x, const UNUR_DISTR *distr );
double cdf_sqrtlinshft( double x, const UNUR_DISTR *distr );

int unur_ssr_set_pedantic( struct unur_par *par, int pedantic );

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

/* \#define SEED (1656256) */

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

[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_cont_new(); ]

/* pdf, mode, pdfarea */
~( distr );
	--> expected_NULL --> UNUR_ERR_DISTR_REQUIRED

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

[set]

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

~_cdfatmode(par,0.);
	--> expected_setfailed --> UNUR_ERR_NULL

~_pdfatmode(par,1.);
	--> expected_setfailed --> UNUR_ERR_NULL

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

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

[set - invalid parameter object:
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,2);
   par = unur_arou_new(distr); ]

~_cdfatmode(par,0.);
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_pdfatmode(par,1.);
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

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

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

unur_par_free(par);

[set - invalid parameters:
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,2);
   par = unur_ssr_new(distr); ]

~_cdfatmode(par,-1.);
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_pdfatmode(par,-1.);
	--> expected_setfailed --> UNUR_ERR_PAR_SET

unur_par_free(par);

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

# [get]

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

[chg]

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

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

~_cdfatmode(gen,1.);
	--> expected_setfailed --> UNUR_ERR_GEN_INVALID

~_pdfatmode(gen,1.);
	--> expected_setfailed --> UNUR_ERR_GEN_INVALID


[chg - invalid parameters:
   double fpar[2] = {2.,5.};
   distr = unur_distr_gamma(fpar,2);
   par = unur_ssr_new(distr);
   gen = unur_init( par ); <-- ! NULL ]

~_cdfatmode(gen,-1.);
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_pdfatmode(gen,-1.);
	--> expected_setfailed --> UNUR_ERR_PAR_SET


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

[init]

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

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

[init - invalid data:
   distr = unur_distr_cont_new();
   unur_distr_cont_set_pdf(distr,pdf_invalid);
   unur_distr_cont_set_mode(distr,0.);
   unur_distr_cont_set_pdfarea(distr,1.);
   par = unur_ssr_new(distr); ]

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

[init - data missing in distribution object:
   distr = unur_distr_cont_new();
   par = NULL; ]

/* mode, pdfarea */
unur_distr_cont_set_pdf(distr,pdf_normal);
par = unur_ssr_new( distr );
unur_init(par);
        --> expected_NULL --> UNUR_ERR_DISTR_REQUIRED

/* pdfarea */
unur_distr_cont_set_mode(distr,1.);
par = unur_ssr_new( distr );
unur_init(par);
        --> expected_NULL --> UNUR_ERR_DISTR_REQUIRED

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

[reinit]

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

unur_reinit( gen );
	--> expected_reinit

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

[sample]

[sample - compare:
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,0); 
   par = NULL; ]

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

/* default algorithm - verifying mode */
par = unur_ssr_new(distr);
unur_ssr_set_verify(par,1);
        -->compare_sequence_par

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

[sample - compare:
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,2);
   par = NULL; ]

/* use cdf at mode */
par = unur_ssr_new(distr);
unur_ssr_set_cdfatmode(par,0.5);
        -->compare_sequence_par_start

/* use cdf at mode and squeeze */
par = unur_ssr_new(distr);
unur_ssr_set_cdfatmode(par,0.5);
unur_ssr_set_usesqueeze(par,1);
        -->compare_sequence_par

/* use cdf at mode - verifying mode */
par = unur_ssr_new(distr);
unur_ssr_set_cdfatmode(par,0.5);
unur_ssr_set_verify(par,1);
        --> compare_sequence_par

/* use cdf at mode and squeeze - verifying mode */
par = unur_ssr_new(distr);
unur_ssr_set_cdfatmode(par,0.5);
unur_ssr_set_usesqueeze(par,1);
unur_ssr_set_verify(par,1);
        --> compare_sequence_par

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

[sample - violate condition:
   double fpar[2] = {0.,1.};
   distr = unur_distr_normal(fpar,2);
   par = NULL; ]

/* pdf at mode is too small: hat < pdf near mode */

/* default algorithm */
par = unur_ssr_new(distr);
unur_ssr_set_pdfatmode(par,0.1);
        --> run_verify_generator --> UNUR_ERR_GEN_CONDITION
  
/* use cdf at mode and squeeze */
par = unur_ssr_new(distr);
unur_ssr_set_pdfatmode(par,0.1);
unur_ssr_set_cdfatmode(par,0.5);
unur_ssr_set_usesqueeze(par,1);
        --> run_verify_generator --> UNUR_ERR_GEN_CONDITION

/* pdf at mode is too large: squeeze > pdf near mode */

/* use cdf at mode and squeeze */
unur_distr_cont_set_pdfarea(distr,10.);
par = unur_ssr_new(distr);
unur_ssr_set_cdfatmode(par,0.5);
unur_ssr_set_pdfatmode(par,10.);
unur_ssr_set_usesqueeze(par,1);
        --> run_verify_generator --> UNUR_ERR_GEN_CONDITION

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

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

/* original generator object */
par = unur_ssr_new(distr);
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_ssr_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_beta(fpar,2);
unur_distr_cont_set_pdfarea(distr,2.);
par = unur_ssr_new(distr);
unur_ssr_set_cdfatmode(par,0.5);
unur_ssr_set_pdfatmode(par,1.9);
unur_ssr_set_usesqueeze(par,FALSE);
unur_ssr_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( "beta(3.,3.); pdfarea = 2. & \
  method = ssr; cdfatmode = 0.5; usesqueeze = off; pdfatmode = 1.9; verify" );
	-->compare_sequence_gen


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

[validate]

[validate - generators:]

# default program
par[0] = unur_ssr_new(@distr@);

# use cdf at mode and squeeze
{ double cdfatmode = unur_distr_cont_eval_cdf( unur_distr_cont_get_mode(@distr@), @distr@ );
par[1] = unur_ssr_new(@distr@);
unur_ssr_set_cdfatmode(par,cdfatmode);
unur_ssr_set_usesqueeze(par,1); }

# default variant but reinitialized with changed domain
{ UNUR_DISTR *dg =NULL;
par[2] = unur_ssr_new(@distr@);
dg = unur_get_distr(gen);
unur_distr_cont_set_domain(dg,0.9,0.92);
unur_distr_cont_upd_pdfarea(dg);
unur_distr_cont_upd_mode(dg);
unur_reinit(gen); }

# default variant but reinitialized with changed pdf parameters
{ UNUR_DISTR *dg =NULL;
par[3] = unur_ssr_new(@distr@);
fpm[0] = 1.;
fpm[1] = 4.;
dg = unur_get_distr(gen);
unur_distr_cont_set_pdfparams(dg,fpm,2);
unur_distr_cont_upd_pdfarea(dg);
unur_distr_cont_upd_mode(dg);
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] = 3.;
fpm[1] = 4.;
distr[3] = unur_distr_beta(fpm,2);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

fpm[0] = 0.5;
distr[30] = unur_distr_gamma(fpm,1);

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

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

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

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

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

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

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

# pdf with piecewise linear function as transformed density with T = -1/sqrt
distr[27] = unur_distr_cont_new();
unur_distr_cont_set_pdf(distr[27],pdf_sqrtlin);
unur_distr_cont_set_dpdf(distr[27],dpdf_sqrtlin);
unur_distr_cont_set_cdf(distr[27],cdf_sqrtlin);
unur_distr_set_name(distr[27],"sqrtlin");
unur_distr_cont_set_mode(distr[27],0.);
unur_distr_cont_set_pdfarea(distr[27],2.);

# pdf with piecewise linear function as transformed density with T = -1/sqrt and shifted mode
distr[28] = unur_distr_cont_new();
unur_distr_cont_set_pdf(distr[28],pdf_sqrtlinshft);
unur_distr_cont_set_dpdf(distr[28],dpdf_sqrtlinshft);
unur_distr_cont_set_cdf(distr[28],cdf_sqrtlinshft);
unur_distr_set_name(distr[28],"sqrtlin");
unur_distr_cont_set_mode(distr[28],1000.);
unur_distr_cont_set_pdfarea(distr[28],2.);

# truncated distributions
distr[22] = unur_distr_cauchy(NULL,0);
unur_distr_cont_set_domain(distr[22],0.1,1.);
unur_distr_cont_upd_mode(distr[22]);
unur_distr_cont_upd_pdfarea(distr[22]);

# number of distributions: 31


[validate - test chi2:]

#  + ... pass test
#  0 ... fail to initialize generator
#  - ... fail test
#  . ... do not run test
#  # ... comment
#
# generators:
#  [0] ... default variant
#  [1] ... use cdf at mode and squeeze
#  [2] ... default variant but reinitialized with changed domain
#  [3] ... default variant but reinitialized with changed pdf parameters
#
#gen	0   1   2   3	# distribution
#---------------------------------------------
x <0>	+   +   +   +	# beta (1, 2)
  <1>	+   +   +   +	# beta (1, 5)
x <2>	+   +   .   .	# beta (1, 100)
  <3>	+   +   +   .	# beta (3, 4)
x <4>	+   +   .   .	# beta (5, 100)
x <5>	+   +   .   .	# beta (500, 300)
  <6>	+   +   +   .	# beta (5, 10, -3, 15)
 <23>	+   +   +   +	# exponential ()
 <24>	+   +   +   +	# exponential (30, -5)
  <7>	+   +   +   +	# cauchy ()
  <8>	+   +   +   +	# cauchy (1, 20)
x <9>	+   +   +   +	# gamma (1)
  <0>	+   +   +   +	# gamma (2)
 <11>	+   +   +   .	# gamma (3)
 <12>	+   +   +   .	# gamma (10)
x<13>	+   +   .   .	# gamma (1000)
 <29>	+   +   +   +	# gamma (1, 4)
 <14>	+   +   +   .	# gamma (5, 1000, 0)
x<15>	+   +   .   .	# gamma (5, 1e-05, 0)
x<16>	+   +   -   .	# gamma (5, 10, 100000)
 <30>	0   0   0   0	# gamma (0.5)
 <25>	+   +   +   +	# laplace ()
 <26>	+   +   +   +	# laplace (-10, 100)
 <17>	+   +   +   +	# normal ()
x<18>	+   +   .   +	# normal (1, 1e-05)
 <19>	+   +   .   .	# normal (1, 1e+05)
 <20>	+   +   +   +	# uniform ()
 <21>	+   +   -   +	# uniform (1, 20)

 <22>	+   .   +   +	# cauchy () - truncated

 <27>	+   +   .   .	# pdf with piecewise linear function as transformed density with T = -1/sqrt
 <28>	+   +   .   .	# [27] with shifted mode


[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 variant
#  [1] ... use cdf at mode and squeeze
#  [2] ... default variant but reinitialized with changed domain
#  [3] ... default variant but reinitialized with changed pdf parameters
#
#gen	0   1   2   3	# distribution
#---------------------------------------------
x <0>	+   +   +   +	# beta (1, 2)
  <1>	+   +   +   +	# beta (1, 5)
x <2>	+   +   .   .	# beta (1, 100)
  <3>	+   +   +   .	# beta (3, 4)
x <4>	+   +   .   .	# beta (5, 100)
  <5>	+   +   .   .	# beta (500, 300)
  <6>	+   +   +   .	# beta (5, 10, -3, 15)
 <23>	+   +   +   +	# exponential ()
 <24>	+   +   +   +	# exponential (30, -5)
  <7>	+   +   +   +	# cauchy ()
  <8>	+   +   +   +	# cauchy (1, 20)
x <9>	+   +   +   +	# gamma (1)
  <0>	+   +   +   +	# gamma (2)
 <11>	+   +   +   .	# gamma (3)
 <12>	+   +   +   .	# gamma (10)
x<13>	+   +   .   .	# gamma (1000)
 <14>	+   +   +   .	# gamma (5, 1000, 0)
x<15>	+   +   .   .	# gamma (5, 1e-05, 0)
x<16>	+   +   .   .	# gamma (5, 10, 100000)
 <25>	+   +   +   +	# laplace ()
 <26>	+   +   +   +	# laplace (-10, 100)
 <17>	+   +   +   +	# normal ()
x<18>	+   +   .   +	# normal (1, 1e-05)
 <19>	+   +   .   .	# normal (1, 1e+05)
 <20>	+   +   +   .	# uniform ()
 <21>	+   +   .   +	# uniform (1, 20)

 <22>	+   .   +   +	# cauchy () - truncated

 <27>	+   +   .   .	# pdf with piecewise linear function as transformed density with T = -1/sqrt
 <28>	+   +   .   .	# [27] with shifted mode


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

[verbatim]

/* pdf for normal distribution */
double pdf_normal( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
  return exp(-x*x/2.);
} /* end of pdf_normal */

/* pdf that does not work */
double pdf_invalid( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
  return ((fabs(x)<0.001) ? 0. : exp(-x*x/2.));
} /* end of pdf_invalid */

/* pdf with piecewise linear function as transformed density with T = -1/sqrt */
double pdf_sqrtlin( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
	double y = 1./(fabs(x)+1.);
	return y*y;
}
double dpdf_sqrtlin( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
	double y = 1./(fabs(x)+1.);
	y = 2.*y*y*y;
	return ((x<0.) ? y : - y);
}
double cdf_sqrtlin( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
	if (x<=0.)
		return 0.5/(1.-x);
	else
		return (1.-0.5/(1.+x));
}

/* pdf with piecewise linear function as transformed density with T = -1/sqrt and shifted mode */
double pdf_sqrtlinshft( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
	double y;
	x -= 1000.;
	y = 1./(fabs(x)+1.);
	return y*y;
}
double dpdf_sqrtlinshft( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
	double y;
	x -= 1000.;
	y = 1./(fabs(x)+1.);
	y = 2.*y*y*y;
	return ((x<0.) ? y : - y);
}
double cdf_sqrtlinshft( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{ 
	x -= 1000.;
	if (x<=0.)
		return 0.5/(1.-x);
	else
		return (1.-0.5/(1.+x));
}

/* dummy function */
int unur_ssr_set_pedantic( struct unur_par *par ATTRIBUTE__UNUSED, int pedantic ATTRIBUTE__UNUSED)
{ return 1; }

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