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

[main]

[main - data:]

# method
method: HINV

[main - header:]

\#include <methods/x_gen_source.h>

/* constants */

## \#define UERROR_SAMPLESIZE (100000)
\#define UERROR_SAMPLESIZE (10000)

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

/* \#define SEED   (298346) */

\#ifndef M_PI
\#define M_PI       3.14159265358979323846264338328      /* pi */
\#endif

\#define set_debug_flag(par) \
   do { \
      if (fullcheck) unur_set_debug((par),~0u); \
      else           unur_set_debug((par),1u); \
   } while (0);

/* prototypes */

double sin_cdf( double x, const UNUR_DISTR *distr );
double sin_pdf( double x, const UNUR_DISTR *distr );
double sin_dpdf( double x, const UNUR_DISTR *distr );

double sin0_cdf( double x, const UNUR_DISTR *distr );
double sin0_pdf( double x, const UNUR_DISTR *distr );
double sin0_dpdf( double x, const UNUR_DISTR *distr );


int hinv_error_experiment( UNUR_PAR *par, int samplesize );

int chg_domain_experiment( UNUR_PAR *par, int samplesize );

int hinv_error_gen_experiment( UNUR_GEN *gen, 
    			       double u_resolution, int order, int samplesize ); 

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

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

/* cdf */
~( distr );
	--> expected_NULL --> UNUR_ERR_DISTR_REQUIRED

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

[set]

[set - invalid NULL ptr: 
   double stp[] = {1.,2.,3.};
   par = NULL; ]

~_order( par, 3 );
	--> expected_setfailed --> UNUR_ERR_NULL

~_u_resolution( par, 1.e-8 );
	--> expected_setfailed --> UNUR_ERR_NULL

~_cpoints(par,stp,3);
	--> expected_setfailed --> UNUR_ERR_NULL

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

~_guidefactor( par, 2. );
	--> expected_setfailed --> UNUR_ERR_NULL

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

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

~_order( par, 3 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_u_resolution( par, 1.e-8 );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

~_cpoints(par,stp,3);
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

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

~_guidefactor( par, 2. );
	--> expected_setfailed --> UNUR_ERR_PAR_INVALID

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

unur_par_free(par);

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

~_order( par, 30 );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

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

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

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

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

~_guidefactor( par, -2. );
	--> expected_setfailed --> UNUR_ERR_PAR_SET

~_max_intervals(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 ]

~_n_intervals(gen);
        --> expected_zero --> UNUR_ERR_GEN_INVALID


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

[chg]

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

~_truncated( gen, 1., 0. );
	--> expected_setfailed --> UNUR_ERR_DISTR_SET

~_truncated( gen, -2., 0. );
	--> none --> UNUR_ERR_DISTR_SET

~_truncated( gen, 0., 10. );
	--> none --> UNUR_ERR_DISTR_SET


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

# [init]

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

[reinit]

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

unur_reinit( gen );
	--> expected_reinit

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

[sample]

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

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

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

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

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


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

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

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

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

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

/* original generator object */
par = unur_hinv_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_hinv_new(distr);
gen = unur_init(par);
        -->compare_sequence_gen_start

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

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

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


distr = unur_distr_gamma(fpar,2);
unur_distr_cont_set_domain(distr,2.,UNUR_INFINITY);
par = unur_hinv_new(distr);
set_debug_flag(par);
gen = unur_init(par);
	-->compare_sequence_gen_start
	
unur_free(gen); gen = NULL;
unur_distr_free(distr); distr = NULL;
gen = unur_str2gen( "gamma(3.,4.); domain = 2,infinity & \
  method = hinv; debug = 0x1" );
	-->compare_sequence_gen


unur_free(gen); gen = NULL;
distr = unur_distr_normal(NULL,0);
unur_distr_cont_set_domain(distr,2.,UNUR_INFINITY);
par = unur_hinv_new(distr);
unur_hinv_set_order(par,1);
unur_hinv_set_max_intervals(par,1000);
unur_hinv_set_u_resolution(par,0.001);
unur_hinv_set_boundary(par,2.,5.);
set_debug_flag(par);
gen = unur_init(par);
	-->compare_sequence_gen_start
	
unur_free(gen); gen = NULL;
unur_distr_free(distr); distr = NULL;
gen = unur_str2gen( "normal; domain = (2,inf) & \
         method = hinv; order = 1; max_intervals = 1000; u_resolution = 0.001; \
         boundary = (2,5); debug = 0x1" );
	-->compare_sequence_gen


## not tested:
## int unur_hinv_set_cpoints( UNUR_PAR *parameters, const double *stp, int n_stp );
## int unur_hinv_set_guidefactor( UNUR_PAR *parameters, double factor );


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

[validate]

[validate - generators:]

# linear with default precision
par[0] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,1);
unur_hinv_set_u_resolution(par,1.e-8);
set_debug_flag(par);

# cubic with precision 1.e-10
par[1] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,3);
unur_hinv_set_u_resolution(par,1.e-10);
set_debug_flag(par);

# quintic with precision 1.e-10
par[2] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,5);
unur_hinv_set_u_resolution(par,1.e-10);
set_debug_flag(par);

# cubic with truncated distribution
par[3] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,3);
unur_hinv_set_u_resolution(par,1.e-10);
set_debug_flag(par);
unur_hinv_chg_truncated(gen,0.5,0.9);

# quintic with precision 1.e-12
par[4] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,5);
unur_hinv_set_u_resolution(par,1.e-12);
set_debug_flag(par);

# cubic with starting construction points for distribution 33
par[5] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,3);
unur_hinv_set_u_resolution(par,1.e-10);
set_debug_flag(par);
fpm[0]= -0.75;
fpm[1]= -0.25;
fpm[2]=  0.25;
fpm[3]=  0.75;
unur_hinv_set_cpoints(par,fpm,4);

# cubic with starting construction points for distribution 34
par[6] = unur_hinv_new(@distr@);
unur_hinv_set_order(par,3);
unur_hinv_set_u_resolution(par,1.e-10);
set_debug_flag(par);
fpm[0]= -0.75;
fpm[1]= -0.5;
fpm[2]=  0.;
fpm[3]=  0.25;
unur_hinv_set_cpoints(par,fpm,4);

# default variant but reinitialized with changed domain
{ UNUR_DISTR *dg =NULL;
par[7] = unur_hinv_new(@distr@);
dg = unur_get_distr(gen);
unur_distr_cont_set_domain(dg,0.1,0.99);
unur_distr_cont_upd_pdfarea(dg);
unur_reinit(gen); }

# default variant but reinitialized with changed pdf parameters
{ UNUR_DISTR *dg =NULL;
par[8] = unur_hinv_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_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);

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

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

fpm[0] = 0.5;
fpm[1] = 0.4;
distr[30] = unur_distr_beta(fpm,2);

# 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[24] = unur_distr_exponential(NULL,0);

fpm[0] = 30.;
fpm[1] = -5.;
distr[25] = 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] = 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[31] = unur_distr_gamma(fpm,1);

fpm[0] = 0.2;
distr[32] = unur_distr_gamma(fpm,1);

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

fpm[0] = -10.;
fpm[1] = 100.;
distr[27] = 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);

# F distributions
fpm[0] = 1.;
fpm[1] = 10.;
distr[35] = unur_distr_F(fpm,2);

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

fpm[0] = 4.;
fpm[1] = 10.;
distr[37] = unur_distr_F(fpm,2);

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

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

fpm[0] = 0.1;
fpm[1] = 10.;
distr[43] = unur_distr_F(fpm,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]);

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

# distribution with vanishing density
distr[33] = unur_distr_cont_new();
unur_distr_cont_set_cdf( distr[33], sin_cdf );
unur_distr_cont_set_pdf( distr[33], sin_pdf );
unur_distr_cont_set_dpdf( distr[33], sin_dpdf );
unur_distr_cont_set_domain( distr[33], -1., 1. );

# distribution with vanishing density
distr[34] = unur_distr_cont_new();
unur_distr_cont_set_cdf( distr[34], sin0_cdf );
unur_distr_cont_set_pdf( distr[34], sin0_pdf );
unur_distr_cont_set_dpdf( distr[34], sin0_dpdf );
unur_distr_cont_set_domain( distr[34], -1., 1. );

# triangular distribution, defined by CDF via string API
distr[39] = unur_distr_cont_new();
unur_distr_cont_set_cdfstr(distr[39], "(x<=2)*(0.5-x+0.5*x*x)+(x>2)*(-3.5+3*x-0.5*x*x)");
unur_distr_cont_set_domain(distr[39],1.,3.);
unur_distr_set_name(distr[39],"triangular-string");

# triangular distribution with invalid CDF via string API
distr[41] = unur_distr_cont_new();
unur_distr_cont_set_cdfstr(distr[41], "(x<=2)*(0.5-x+0.5*x*x)+(x>2)*(-3.5+3*x-0.5*x*x)");
unur_distr_cont_set_domain(distr[41],1.,5.);
unur_distr_set_name(distr[41],"triangular-invalid-string");

# triangular distribution with invalid CDF via string API
distr[42] = unur_distr_cont_new();
unur_distr_cont_set_cdfstr(distr[42], "(x<=2)*(0.5-x+0.5*x*x)+(x>2)*(-3.5+3*x-0.5*x*x)");
unur_distr_cont_set_domain(distr[42],-1.,3.);
unur_distr_set_name(distr[42],"triangular-invalid-string");


# number of distributions: 44


[validate - test chi2:]

#  + ... pass test
#  0 ... fail to initialize generator
#  - ... fail test
#  . ... do not run test
#  # ... comment
#
# generators:
#  [0]  ... linear with default precision
#  [1]  ... cubic with precision 1.e-10
#  [2]  ... quintic with precision 1.e-10
#  [3]  ... cubic with truncated distribution on [0.5,0.9]
#  [4]  ... quintic with precision 1.e-12
#  [5]  ... cubic with starting construction points for distribution 34
#  [6]  ... cubic with starting construction points for distribution 34
#  [7]  ... default variant but reinitialized with changed domain
#  [8]  ... default variant but reinitialized with changed pdf parameters
#
#	0  1  2  3  4  5  6  7  8	# distribution
#-------------------------------------
x <0>	+  +  +  +  +  +  +  +  +	# beta (1, 2)
  <1>	+  +  +  +  +  +  +  +  +	# beta (1, 5)
x <2>	+  +  +  .  +  +  +  +  +	# beta (1, 100)
  <3>	+  +  +  +  +  +  +  +  +	# beta (3, 4)
  <4>	+  +  +  .  +  +  +  +  +	# beta (5, 100)
  <5>	+  +  +  +  +  +  +  +  +	# beta (500, 300)
  <6>	+  +  +  +  +  +  +  +  +	# beta (5, 10, -3, 15)
 <28>	+  +  +  +  +  +  +  +  +	# beta (0.5, 3)
 <29>	+  +  +  +  +  +  +  +  +	# beta (5, 0.3)
 <30>	+  +  +  +  +  +  +  +  +	# beta (0.5, 0.4)
  <7>	+  +  +  +  +  +  +  +  +	# cauchy ()
  <8> 	+  +  +  +  +  +  +  +  +	# cauchy (1, 20)
 <24>	+  +  +  +  +  +  +  +  +	# exponential ()
 <25>	+  +  +  +  +  +  +  +  +	# exponential (30, -5)
x <9>	+  +  +  +  +  +  +  +  +	# gamma (1)
 <10>	+  +  +  +  +  +  +  +  +	# 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)
 <31>	+  +  +  +  +  +  +  +  +	# gamma (0.5)
 <32>	+  +  +  +  +  +  +  .  +	# gamma (0.2)
 <26>	+  +  +  +  +  +  +  +  +	# laplace ()
 <27>	+  +  +  +  +  +  +  .  +	# laplace (-10, 100)
 <17>	+  +  +  +  +  +  +  +  +	# normal ()
x<18>	+  +  +  .  +  +  +  .  +	# normal (1, 1e-05)
 <19>	+  +  +  +  +  +  +  +  +	# normal (1, 1e+05)
 <20>	+  +  +  +  +  +  +  +  +	# uniform ()
 <21>	+  +  +  .  +  +  +  -  +	# uniform (1, 20)
 <35>	+  +  +  +  +  +  +  +  +	# F (1, 10)
 <36>	+  +  +  +  +  +  +  +  +	# F (2, 10)
 <37>	+  +  +  +  +  +  +  +  +	# F (4, 10)
 <38>	+  +  +  +  +  +  +  +  +	# F (10, 10)
 <40>	+  +  +  +  +  +  +  +  +	# F (10, 1)
 <43>	+  +  +  +  +  +  +  +  +	# F (0.1, 10)

 <22>	+  +  +  +  +  +  +  .  .	# cauchy () - truncated
 <23>	+  +  +  +  +  +  +  +  .	# beta () - domain superset of support

 <33>	+  +  +  +  +  +  .  +  .	# distribution with vanishing PDF
 <34>	+  +  +  +  +  .  +  +  .	# distribution with vanishing PDF
 <39>	+  +  +  .  .  .  .  .  .       # triangular distribution
 <41>	0  0  0  .  .  .  .  .  .       # invalid triangular distribution
 <42>	0  0  0  .  .  .  .  .  .       # invalid triangular distribution

# Remark:
#  No tests with truncated distribution where the call
#  unur_hinv_chg_truncated() fails since the CDF values at the
#  boundaries are too close.
#  generator 6 has the cpoints for the special distribution 33
#  generator 6 has the cpoints for the special distribution 34

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

[special]

[special - decl:]

  int samplesize = UERROR_SAMPLESIZE;
  int errorsum = 0;
  double fpar[4];
  double cpoints[10];     

  UNUR_DISTR *distr;
  UNUR_PAR   *par;

[special - start:]

  /* test for maximal u-error */
  printf("\ntest maximal u-error: "); 
  fprintf(TESTLOG,"\nTest maximal u-error:\n"); 

  distr = unur_distr_normal(NULL,0);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  distr = unur_distr_cauchy(NULL,0);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  distr = unur_distr_exponential(NULL,0);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  fpar[0]= 5.; 
  distr = unur_distr_gamma(fpar,1);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  fpar[0]= 0.5; 
  distr = unur_distr_gamma(fpar,1);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  fpar[0]=2.; fpar[1]=2.;fpar[2]= 0.; fpar[3]=1.;
  distr = unur_distr_beta(fpar,4);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  fpar[0]=0.3; fpar[1]=3.;fpar[2]= 0.; fpar[3]=1.;
  distr = unur_distr_beta(fpar,4);
  par = unur_hinv_new(distr);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);

  distr = unur_distr_cont_new();
  unur_distr_set_name(distr,"sin-example");
  unur_distr_cont_set_cdf( distr, sin_cdf );
  unur_distr_cont_set_pdf( distr, sin_pdf );
  unur_distr_cont_set_dpdf( distr, sin_dpdf );
  unur_distr_cont_set_domain( distr, -1., 1. );
  cpoints[0]= -0.75;
  cpoints[1]= -0.25;
  cpoints[2]=  0.25;
  cpoints[3]=  0.75;
  par = unur_hinv_new(distr);
  unur_hinv_set_cpoints(par, cpoints, 4);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);
	
  distr = unur_distr_cont_new();
  unur_distr_set_name(distr,"sin-0-example");
  unur_distr_cont_set_cdf( distr, sin0_cdf );
  unur_distr_cont_set_pdf( distr, sin0_pdf );
  unur_distr_cont_set_dpdf( distr, sin0_dpdf );
  unur_distr_cont_set_domain( distr, -1., 0.5 );
  cpoints[0]= -0.75;
  cpoints[1]= -0.5;
  cpoints[2]=  0.;
  cpoints[3]=  0.25;
  par = unur_hinv_new(distr);
  unur_hinv_set_cpoints(par, cpoints, 4);
  errorsum += hinv_error_experiment(par,samplesize);
  unur_distr_free(distr);

 
  /* extra test for changeing the domain of the generator object */

  printf("\ntest unur_chg_truncated(): "); 
  fprintf(TESTLOG,"\nTests unur_chg_truncated():\n\n"); 

  printf(" normal");
  
  distr = unur_distr_normal(NULL,0);
  par = unur_hinv_new(distr);
  
  errorsum += chg_domain_experiment(par,samplesize);

  unur_distr_free(distr);
  fprintf(TESTLOG,"\n");

  /****/

  printf(" sinus1");
  distr = unur_distr_cont_new();
  unur_distr_set_name(distr,"sin-example");
  unur_distr_cont_set_cdf( distr, sin_cdf );
  unur_distr_cont_set_pdf( distr, sin_pdf );
  unur_distr_cont_set_dpdf( distr, sin_dpdf );
  unur_distr_cont_set_domain( distr, -1., 1. );
  cpoints[0]= -0.75;
  cpoints[1]= -0.25;
  cpoints[2]=  0.25;
  cpoints[3]=  0.75;
  par = unur_hinv_new(distr);
  unur_hinv_set_cpoints(par, cpoints, 4);

  errorsum += chg_domain_experiment(par,samplesize);

  unur_distr_free(distr);
  fprintf(TESTLOG,"\n");

  /****/

  printf(" sinus2");
  distr = unur_distr_cont_new();
  unur_distr_set_name(distr,"sin-0-example");
  unur_distr_cont_set_cdf( distr, sin0_cdf );
  unur_distr_cont_set_pdf( distr, sin0_pdf );
  unur_distr_cont_set_dpdf( distr, sin0_dpdf );
  unur_distr_cont_set_domain( distr, -1., 0.5 );
  cpoints[0]= -0.75;
  cpoints[1]= -0.5;
  cpoints[2]=  0.;
  cpoints[3]=  0.25;
  par = unur_hinv_new(distr);
  unur_hinv_set_cpoints(par, cpoints, 4);

  errorsum += chg_domain_experiment(par,samplesize);

  unur_distr_free(distr);
  fprintf(TESTLOG,"\n");


  /* test finished */
  FAILED = (errorsum < 2) ? 0 : 1;


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

[verbatim]

/*---------------------------------------------------------------------------*/
/* Example of  a distribution with f(x)=0 at x=-0.25 and x=0.75              */
/*                                                                           */
/*          /  (1 +sin(2 Pi x))/2  if |x| <= 1                               */
/*  f(x) = <                                                                 */
/*          \  0        otherwise                                            */
/*                                                                           */
double sin_pdf( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
  if (fabs(x) > 1.)
    return 0.;
  else
    return (0.5*(1.+sin((2.*M_PI)*x)));
} /* end of sin_pdf() */

/* The derivative of the PDF of our distribution:                */
double sin_dpdf( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
  if (fabs(x) > 1.)
    return 0.;
  else
    return (M_PI*cos((2.*M_PI)*x));
} /* end of sin_dpdf() */

/* The CDF of our distribution:                                  */
double sin_cdf( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
  if (x < -1.)
    return 0.;
  else if(x<=1.)
    return (1.+2.*M_PI*(1+x)-cos((2.*M_PI)*x))/(4.*M_PI);
  else return 1.;
} /* end of sin_cdf() */

/*---------------------------------------------------------------------------*/

/* Example of  a distribution with f(x)=0 in (-0.5,0)                        */
/*                                                                           */
/*          /  Max(sin(2 Pi x)),0)Pi/2  if -1 < x <0.5                       */
/*  f(x) = <                                                                 */
/*          \  0        otherwise                                            */
/*                                                                           */
double sin0_pdf( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
  if (x < -1.) return 0.;
  if (x <= -0.5) return sin((2.*M_PI)*x)*0.5*M_PI;
  if (x < 0.) return 0.;
  if (x <= 0.5) return sin((2.*M_PI)*x)*0.5*M_PI;
  return 0.;
} /* end of sin0_pdf() */

/* The derivative of the PDF of our distribution:                */
double sin0_dpdf( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
  if (x < -1.) return 0.;
  if (x <= -0.5) return cos((2.*M_PI)*x)*M_PI*M_PI;
  if (x < 0.) return 0.;
  if (x <= 0.5) return cos((2.*M_PI)*x)*M_PI*M_PI;
  return 0.;
} /* end of sin0_dpdf() */

/* The CDF of our distribution:                                  */
double sin0_cdf( double x, const UNUR_DISTR *distr ATTRIBUTE__UNUSED)
{
  if (x < -1.) return 0.;
  if(x<= -0.5) return 0.25*(1-cos((2.*M_PI)*x));
  if (x < 0.) return 0.5;
  if (x <= 0.5) return 0.75-0.25*cos((2.*M_PI)*x);
  return 1.;
} /* end of sin0_cdf() */

#############################################################################
#
# routines for special tests
#
#############################################################################


/*****************************************************************************/
/* run unur_test_u_error for a particular generator object and print result  */

int
hinv_error_gen_experiment( UNUR_GEN *gen,       /* generator object */
			   double u_resolution, /* maximal tolerated u-error */
			   int order,           /* order of polynomial */
			   int samplesize )     /* sample size for error experiment */
     /* returns 0 if maxerror < u_resolution, errorcode otherwise */
{   
  int i, nfpar;
  const double *fpar;     
  const UNUR_DISTR *distr = unur_get_distr(gen);
  const char *genid = unur_get_genid(gen);
  double score;

  /* print data about distribution */
  fprintf(TESTLOG,"%s: %s distribution",genid,unur_distr_get_name(distr));
  nfpar = unur_distr_cont_get_pdfparams(distr,&fpar);
  if (nfpar) { 
     fprintf(TESTLOG," with parameters ");
     for(i=0;i<nfpar;i++) fprintf(TESTLOG," | %g",fpar[i]);
     fprintf(TESTLOG," |");
  }
  fprintf(TESTLOG,":\n");

  /* print chosen parameter for method HINV and for experiment */
  fprintf(TESTLOG,"%s:   setting: order = %d, u-error <= %g, samplesize = %d\n",
                  genid,order,u_resolution,samplesize);
  fprintf(TESTLOG,"%s:   \#intervals = %d\n",genid,unur_hinv_get_n_intervals(gen));

  /* run test */
  score = run_validate_u_error( TESTLOG, gen, distr, u_resolution, samplesize );

  /* return score */
  return score;

} /* end of hinv_error_gen_experiment() */

/*****************************************************************************/
/* run experiment for a particular distribution object                       */

int
hinv_error_experiment( UNUR_PAR *par,     /* parameter object */
		       int samplesize )   /* samplesize for error experiment */
     /* returns 0 if maxerror < u_resolution, errorcode otherwise */
{ 
  UNUR_PAR *par_clone;  /* working copy of parameter object */
  UNUR_GEN *gen;        /* generator object */

  int order = 3;
  double u_resolution = 1.e-8;  /* (maximal) tolerated u-error */
  int errorsum = 0;

  /* check for invalid NULL pointer */
  if (par==NULL) {
     printf(" NULL! ");
     return 1000;
  }

  for ( u_resolution = 1.e-6; u_resolution > 1.e-13; u_resolution *= 0.01 ) {
     for ( order=(u_resolution<1.e-9 ? 3:1); order<=5; order+=2) {

       /* make a working copy */
       par_clone = _unur_par_clone(par);

       /* create generator object */
       unur_hinv_set_order(par_clone,order);
       unur_hinv_set_u_resolution(par_clone,u_resolution);
       set_debug_flag(par_clone);
       gen = unur_init(par_clone);

       /* run test */
       errorsum += hinv_error_gen_experiment(gen, u_resolution, order, samplesize);
       fprintf(TESTLOG,"\n");

       /* clear memory */
       unur_free(gen);
     }
  }

  unur_par_free(par);

  return errorsum;
} /* end of hinv_error_experiment() */

/*****************************************************************************/
/* run test with truncated distributions                                     */

int
chg_domain_experiment( UNUR_PAR *par,   /* generator object */
		       int samplesize ) /* sample size for experiment */
     /* returns 0 if maxerror < u_resolution, errorcode otherwise */
{ 
  int k;
  int result = 0;
  UNUR_GEN *gen;           /* generator object */
  double left, right;      /* border of userdefined original domain */
  double newleft, newright;

  double u_resolution = 1.e-10;  /* maximal tolerated u-error */
  int order = 3;           /* order of polynomial */

  unur_hinv_set_order(par,order);
  unur_hinv_set_u_resolution(par,u_resolution);
  gen = unur_init(par);

  unur_distr_cont_get_domain(unur_get_distr(gen), &left, &right );
  if (left <= UNUR_INFINITY) 
     left = unur_hinv_eval_approxinvcdf(gen, 1.e-10);
  if (right >= UNUR_INFINITY) 
     right = unur_hinv_eval_approxinvcdf(gen, 1-1.e-10);

  for(k=1; k<=10;k++){
    newleft = left + k*0.05*(right-left);
    newright = right - k*0.04*(right-left);
    unur_hinv_chg_truncated(gen, newleft, newright);
    result += hinv_error_gen_experiment(gen, u_resolution, order, samplesize/10);
  }

  unur_hinv_chg_truncated(gen, left, right);
  result += hinv_error_gen_experiment(gen, u_resolution, order, samplesize/10);

  unur_free(gen);
  
  return result;
} /* end of chg_domain_experiment() */

/*****************************************************************************/
