1 /*****************************************************************************
2  *                                                                           *
3  *          UNURAN -- Universal Non-Uniform Random number generator          *
4  *                                                                           *
5  *****************************************************************************
6  *                                                                           *
7  *   FILE: x_gen.c                                                           *
8  *                                                                           *
9  *   miscelleanous routines for manipulation generator objects               *
10  *                                                                           *
11  *****************************************************************************
12  *                                                                           *
13  *   Copyright (c) 2000-2006 Wolfgang Hoermann and Josef Leydold             *
14  *   Department of Statistics and Mathematics, WU Wien, Austria              *
15  *                                                                           *
16  *   This program is free software; you can redistribute it and/or modify    *
17  *   it under the terms of the GNU General Public License as published by    *
18  *   the Free Software Foundation; either version 2 of the License, or       *
19  *   (at your option) any later version.                                     *
20  *                                                                           *
21  *   This program is distributed in the hope that it will be useful,         *
22  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
23  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
24  *   GNU General Public License for more details.                            *
25  *                                                                           *
26  *   You should have received a copy of the GNU General Public License       *
27  *   along with this program; if not, write to the                           *
28  *   Free Software Foundation, Inc.,                                         *
29  *   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA                  *
30  *                                                                           *
31  *****************************************************************************/
32 
33 /*---------------------------------------------------------------------------*/
34 
35 #include <unur_source.h>
36 #include <distr/distr_source.h>
37 #include <distr/matr.h>
38 #include <methods/cstd.h>
39 #include <methods/cstd_struct.h>
40 #include <methods/dgt.h>
41 #include <methods/dstd.h>
42 #include <methods/dstd_struct.h>
43 #include <methods/hinv.h>
44 #include <methods/mixt.h>
45 #include <methods/mixt_struct.h>
46 #include <methods/ninv.h>
47 #include <methods/pinv.h>
48 #include "unur_methods_source.h"
49 #include "x_gen.h"
50 #include "x_gen_source.h"
51 
52 /*---------------------------------------------------------------------------*/
53 
54 /*****************************************************************************/
55 /**                                                                         **/
56 /**  Call Init, Sampling, and Free functions                                **/
57 /**                                                                         **/
58 /*****************************************************************************/
59 
60 /*---------------------------------------------------------------------------*/
61 
unur_init(struct unur_par * par)62 struct unur_gen *unur_init( struct unur_par *par )
63 {
64   _unur_check_NULL(NULL,par,NULL);
65   return (par->init(par));
66 } /* end of unur_init() */
67 
68 /*---------------------------------------------------------------------------*/
69 
unur_reinit(struct unur_gen * gen)70 int unur_reinit( struct unur_gen *gen )
71 {
72   int status = UNUR_SUCCESS;
73   _unur_check_NULL(NULL,gen,UNUR_ERR_NULL);
74 
75   if (gen->reinit) {
76     status = gen->reinit(gen);
77     if (status == UNUR_SUCCESS) return status;
78   }
79   else {
80     _unur_error(gen->genid,UNUR_ERR_NO_REINIT,"");
81     status = UNUR_ERR_NO_REINIT;
82   }
83 
84   /* error: change sampling routine */
85   switch (gen->method & UNUR_MASK_TYPE) {
86   case UNUR_METH_DISCR:
87     gen->sample.discr = _unur_sample_discr_error;
88     break;
89   case UNUR_METH_CONT:
90   case UNUR_METH_CEMP:
91     gen->sample.cont = _unur_sample_cont_error;
92     break;
93   case UNUR_METH_VEC:
94   case UNUR_METH_CVEMP:
95     gen->sample.cvec = _unur_sample_cvec_error;
96     break;
97   case UNUR_METH_MAT:
98     gen->sample.matr = _unur_sample_matr_error;
99     break;
100   default:
101     _unur_error("reinit",UNUR_ERR_SHOULD_NOT_HAPPEN,"");
102   }
103 
104   return status;
105 } /* end of unur_reinit() */
106 
107 /*---------------------------------------------------------------------------*/
108 
109 int
unur_sample_discr(struct unur_gen * gen)110 unur_sample_discr( struct unur_gen *gen )
111 {
112   CHECK_NULL(gen,0);
113   return (gen->sample.discr(gen));
114 } /* end of unur_sample_discr() */
115 
116 double
unur_sample_cont(struct unur_gen * gen)117 unur_sample_cont( struct unur_gen *gen )
118 {
119   CHECK_NULL(gen,INFINITY);
120   return (gen->sample.cont(gen));
121 } /* end of unur_sample_cont() */
122 
123 int
unur_sample_vec(struct unur_gen * gen,double * vector)124 unur_sample_vec( struct unur_gen *gen, double *vector )
125 {
126   CHECK_NULL(gen,UNUR_ERR_NULL);
127   return (gen->sample.cvec(gen,vector));
128 } /* end of unur_sample_vec() */
129 
130 int
unur_sample_matr(struct unur_gen * gen,double * matrix)131 unur_sample_matr( struct unur_gen *gen, double *matrix )
132 {
133   CHECK_NULL(gen,UNUR_ERR_NULL);
134   return (gen->sample.matr(gen,matrix));
135 } /* end of unur_sample_matr() */
136 
137 /*---------------------------------------------------------------------------*/
138 /* Estimate quantiles                                                        */
139 
140 double
unur_quantile(struct unur_gen * gen,double U)141 unur_quantile ( struct unur_gen *gen, double U )
142 {
143   /* check arguments */
144   CHECK_NULL(gen,FALSE);
145 
146   /* Remark:
147    * We DO NOT check the argument U here
148    * (i.e. whether 0<=U<=1 holds)
149    */
150   switch (gen->method) {
151   case UNUR_METH_HINV:
152     return unur_hinv_eval_approxinvcdf(gen,U);
153 
154   case UNUR_METH_NINV:
155     return unur_ninv_eval_approxinvcdf(gen,U);
156 
157   case UNUR_METH_PINV:
158     return unur_pinv_eval_approxinvcdf(gen,U);
159 
160   case UNUR_METH_CSTD:
161     if (((struct unur_cstd_gen*)gen->datap)->is_inversion)
162       return unur_cstd_eval_invcdf(gen,U);
163     break;
164 
165   case UNUR_METH_MIXT:
166     if (((struct unur_mixt_gen*)gen->datap)->is_inversion)
167       return unur_mixt_eval_invcdf(gen,U);
168     break;
169 
170   case UNUR_METH_DGT:
171     return ((double) unur_dgt_eval_invcdf(gen,U));
172 
173   case UNUR_METH_DSTD:
174     if (((struct unur_dstd_gen*)gen->datap)->is_inversion)
175       return unur_dstd_eval_invcdf(gen,U);
176     break;
177   }
178 
179   /* default: */
180   _unur_error(gen->genid,UNUR_ERR_NO_QUANTILE,"");
181   return UNUR_INFINITY;
182 
183 } /* end of unur_quantile() */
184 
185 /*---------------------------------------------------------------------------*/
186 
187 int
_unur_gen_is_inversion(struct unur_gen * gen)188 _unur_gen_is_inversion ( struct unur_gen *gen )
189      /*----------------------------------------------------------------------*/
190      /* check for type of generator object                                   */
191      /*----------------------------------------------------------------------*/
192 {
193   /* check arguments */
194   CHECK_NULL(gen,FALSE);
195 
196   switch (gen->method) {
197   case UNUR_METH_HINV:
198   case UNUR_METH_NINV:
199   case UNUR_METH_PINV:
200   case UNUR_METH_DGT:
201     return TRUE;
202 
203   case UNUR_METH_CSTD:
204     return (((struct unur_cstd_gen*)gen->datap)->is_inversion);
205 
206   case UNUR_METH_MIXT:
207     return (((struct unur_mixt_gen*)gen->datap)->is_inversion);
208 
209   default:
210     return FALSE;
211   }
212 } /* end of _unur_gen_is_inversion() */
213 
214 /*---------------------------------------------------------------------------*/
215 /* aux routines when no sampling routine is available                         */
216 
217 int
_unur_sample_discr_error(struct unur_gen * gen ATTRIBUTE__UNUSED)218 _unur_sample_discr_error( struct unur_gen *gen ATTRIBUTE__UNUSED )
219 {
220   unur_errno = UNUR_ERR_GEN_CONDITION;
221   return 0;
222 } /* end of _unur_sample_discr_error() */
223 
224 double
_unur_sample_cont_error(struct unur_gen * gen ATTRIBUTE__UNUSED)225 _unur_sample_cont_error( struct unur_gen *gen ATTRIBUTE__UNUSED )
226 {
227   unur_errno = UNUR_ERR_GEN_CONDITION;
228   return INFINITY;
229 } /* end of _unur_sample_cont_error() */
230 
231 int
_unur_sample_cvec_error(struct unur_gen * gen,double * vec)232 _unur_sample_cvec_error( struct unur_gen *gen, double *vec )
233 {
234   int d;
235   unur_errno = UNUR_ERR_GEN_CONDITION;
236   for (d=0; d<(gen->distr->dim); d++) vec[d] = INFINITY;
237   return UNUR_FAILURE;
238 } /* end of _unur_sample_cvec_error() */
239 
240 int
_unur_sample_matr_error(struct unur_gen * gen,double * mat)241 _unur_sample_matr_error( struct unur_gen *gen, double *mat )
242 {
243   int n_rows, n_cols, dim, j;
244 
245   unur_errno = UNUR_ERR_GEN_CONDITION;
246   unur_distr_matr_get_dim(gen->distr, &n_rows, &n_cols );
247   dim = n_rows * n_cols;
248   for (j=0; j<dim; j++)
249     mat[j] = INFINITY;
250   return UNUR_FAILURE;
251 } /* end of _unur_sample_matr_error() */
252 
253 /*---------------------------------------------------------------------------*/
254 
255 void
unur_free(struct unur_gen * gen)256 unur_free( struct unur_gen *gen )
257 {
258   if (gen) gen->destroy(gen);
259 } /* end of unur_free() */
260 
261 /*---------------------------------------------------------------------------*/
262 
263 /*****************************************************************************/
264 /**                                                                         **/
265 /**  Get data about generator object                                        **/
266 /**                                                                         **/
267 /*****************************************************************************/
268 
269 /*---------------------------------------------------------------------------*/
270 const char *
unur_gen_info(struct unur_gen * gen,int help)271 unur_gen_info( struct unur_gen *gen, int help )
272      /*----------------------------------------------------------------------*/
273      /* return pointer to character string that contains information about   */
274      /* the given generator object.                                          */
275      /*                                                                      */
276      /* parameters:                                                          */
277      /*   gen ... pointer to generator object                                */
278      /*   help ... whether to print additional comments                      */
279      /*                                                                      */
280      /* return:                                                              */
281      /*   pointer to character string                                        */
282      /*                                                                      */
283      /* error:                                                               */
284      /*   return NULL                                                        */
285      /*----------------------------------------------------------------------*/
286 {
287 #ifdef UNUR_ENABLE_INFO
288 
289   /* check arguments */
290   _unur_check_NULL("",gen,NULL);
291 
292   if (gen->info) {
293     /* prepare generator object for creating info string */
294     if (gen->infostr == NULL)
295       /* either allocate memory block */
296       gen->infostr = _unur_string_new();
297     else
298       /* or clear string object (i.e. reset pointer) */
299       _unur_string_clear(gen->infostr);
300 
301     /* create info string */
302     gen->info((struct unur_gen*) gen, help);
303 
304     /* return info string */
305     return gen->infostr->text;
306   }
307   else {
308     return NULL;
309   }
310 #else
311 
312   return "INFO string not enable";
313 
314 #endif
315 } /* end of unur_gen_info() */
316 /*---------------------------------------------------------------------------*/
317 
318 int
unur_get_dimension(const struct unur_gen * gen)319 unur_get_dimension( const struct unur_gen *gen )
320      /*----------------------------------------------------------------------*/
321      /* get dimension of generator for multivariate distribution             */
322      /*                                                                      */
323      /* parameters:                                                          */
324      /*   gen ... pointer to generator object                                */
325      /*                                                                      */
326      /* return:                                                              */
327      /*   dimension of distribution                                          */
328      /*                                                                      */
329      /* error:                                                               */
330      /*   return 0                                                           */
331      /*----------------------------------------------------------------------*/
332 {
333   /* check arguments */
334   CHECK_NULL(gen,0);
335 
336   return (gen->distr->dim);
337 } /* end of unur_get_dimension() */
338 
339 /*---------------------------------------------------------------------------*/
340 
341 const char *
unur_get_genid(const struct unur_gen * gen)342 unur_get_genid( const struct unur_gen *gen )
343      /*----------------------------------------------------------------------*/
344      /* get generator id                                                     */
345      /*                                                                      */
346      /* parameters:                                                          */
347      /*   gen ... pointer to generator object                                */
348      /*                                                                      */
349      /* return:                                                              */
350      /*   pointer to generator id                                            */
351      /*                                                                      */
352      /* error:                                                               */
353      /*   return NULL                                                        */
354      /*----------------------------------------------------------------------*/
355 {
356   /* check arguments */
357   CHECK_NULL(gen,NULL);
358 
359   return gen->genid;
360 } /* end of unur_get_genid() */
361 
362 /*---------------------------------------------------------------------------*/
363 
364 struct unur_distr *
unur_get_distr(const struct unur_gen * gen)365 unur_get_distr( const struct unur_gen *gen )
366      /*----------------------------------------------------------------------*/
367      /* get pointer to distribution object from generator object             */
368      /*                                                                      */
369      /* parameters:                                                          */
370      /*   gen ... pointer to generator object                                */
371      /*                                                                      */
372      /* return:                                                              */
373      /*   pointer to distribution object                                     */
374      /*                                                                      */
375      /* error:                                                               */
376      /*   return NULL                                                        */
377      /*----------------------------------------------------------------------*/
378 {
379   /* check arguments */
380   CHECK_NULL(gen,NULL);
381 
382   return gen->distr;
383 } /* end of unur_get_distr() */
384 
385 /*---------------------------------------------------------------------------*/
386 
387 int
unur_set_use_distr_privatecopy(struct unur_par * par,int use_privatecopy)388 unur_set_use_distr_privatecopy( struct unur_par *par, int use_privatecopy )
389      /*----------------------------------------------------------------------*/
390      /* Set flag whether the generator object should make a private copy or  */
391      /* just stores the pointer to the distribution object                   */
392      /*                                                                      */
393      /* parameters:                                                          */
394      /*   par             ... pointer to parameter object                    */
395      /*   use_privatecopy ... TRUE = use private copy                        */
396      /*                       FALSE = store pointer to given distr. object   */
397      /*                                                                      */
398      /* return:                                                              */
399      /*   pointer to distribution object                                     */
400      /*                                                                      */
401      /* error:                                                               */
402      /*   return NULL                                                        */
403      /*                                                                      */
404      /* WARNING!                                                             */
405      /* Using a pointer to the external distribution object instead of a     */
406      /* private copy must be applied with EXTREME CARE!                      */
407      /* When the distrubtion object is changed or freed then the generator   */
408      /* object does not work any more, might case a segmentation fault, or   */
409      /* (even worse) produces garbage.                                       */
410      /* On the other hand, when the generator object is initialized or used  */
411      /* to draw a random sampling the distribution object may be changed.    */
412      /*----------------------------------------------------------------------*/
413 {
414   /* check arguments */
415   _unur_check_NULL("",par,UNUR_ERR_NULL);
416 
417   par->distr_is_privatecopy = use_privatecopy;
418   return UNUR_SUCCESS;
419 } /* end of unur_set_use_distr_privatecopy() */
420 
421 
422 /*****************************************************************************/
423 /**                                                                         **/
424 /**  Copy (clone) generator object                                          **/
425 /**                                                                         **/
426 /*****************************************************************************/
427 
428 struct unur_gen *
unur_gen_clone(const struct unur_gen * gen)429 unur_gen_clone( const struct unur_gen *gen )
430      /*----------------------------------------------------------------------*/
431      /* copy (clone) generator object                                        */
432      /*                                                                      */
433      /* parameters:                                                          */
434      /*   gen ... pointer to generator object                                */
435      /*                                                                      */
436      /* return:                                                              */
437      /*   pointer to clone of generator object                               */
438      /*                                                                      */
439      /* error:                                                               */
440      /*   return NULL                                                        */
441      /*----------------------------------------------------------------------*/
442 {
443   /* check arguments */
444   _unur_check_NULL( "Clone", gen, NULL );
445   _unur_check_NULL( "Clone", gen->clone, NULL );
446 
447   return (gen->clone(gen));
448 } /* end of unur_gen_clone() */
449 
450 
451 /*****************************************************************************/
452 /**                                                                         **/
453 /**  Create and free parameter objects                                      **/
454 /**                                                                         **/
455 /*****************************************************************************/
456 
457 struct unur_par *
_unur_par_new(size_t s)458 _unur_par_new( size_t s)
459      /*----------------------------------------------------------------------*/
460      /* create new parameter object                                          */
461      /*                                                                      */
462      /* parameters:                                                          */
463      /*   s ... size of data structure                                       */
464      /*                                                                      */
465      /* error:                                                               */
466      /*   return NULL                                                        */
467      /*----------------------------------------------------------------------*/
468 {
469   struct unur_par *par = _unur_xmalloc( sizeof(struct unur_par) );
470   par->datap = _unur_xmalloc(s);
471   par->s_datap = s;
472 
473   /* set defaults for distribution object */
474   par->distr_is_privatecopy = TRUE;   /* use private copy of distribution object */
475 
476   return par;
477 } /* end of _unur_par_new() */
478 
479 /*---------------------------------------------------------------------------*/
480 
481 struct unur_par *
_unur_par_clone(const struct unur_par * par)482 _unur_par_clone( const struct unur_par *par )
483      /*----------------------------------------------------------------------*/
484      /* copy parameter object                                                */
485      /*                                                                      */
486      /* parameters:                                                          */
487      /*   par ... pointer to parameter object                                */
488      /*                                                                      */
489      /* error:                                                               */
490      /*   return NULL                                                        */
491      /*----------------------------------------------------------------------*/
492 {
493   struct unur_par *clone;
494 
495   _unur_check_NULL("clone", par, NULL);
496 
497   clone = _unur_xmalloc( sizeof(struct unur_par) );
498   memcpy (clone, par, sizeof(struct unur_par));
499 
500   clone->datap = _unur_xmalloc(par->s_datap);
501   memcpy (clone->datap, par->datap, par->s_datap);
502 
503   return clone;
504 } /* end of unur_par_free() */
505 
506 /*---------------------------------------------------------------------------*/
507 
508 void
unur_par_free(struct unur_par * par)509 unur_par_free( struct unur_par *par)
510      /*----------------------------------------------------------------------*/
511      /* free parameter object                                                */
512      /*                                                                      */
513      /* parameters:                                                          */
514      /*   par ... pointer to parameter object                                */
515      /*----------------------------------------------------------------------*/
516 {
517   _unur_check_NULL("free", par, RETURN_VOID );
518   _unur_par_free(par);
519 } /* end of unur_par_free() */
520 
521 /*****************************************************************************/
522 /**                                                                         **/
523 /**  Create, copy (clone) and free generator objects                        **/
524 /**                                                                         **/
525 /*****************************************************************************/
526 
527 struct unur_gen *
_unur_generic_create(struct unur_par * par,size_t s)528 _unur_generic_create( struct unur_par *par, size_t s )
529      /*----------------------------------------------------------------------*/
530      /* create new generic generator object                                  */
531      /*                                                                      */
532      /* parameters:                                                          */
533      /*   par ... pointer to parameter for building generator object         */
534      /*   s   ... size of data structure                                     */
535      /*                                                                      */
536      /* error:                                                               */
537      /*   return NULL                                                        */
538      /*----------------------------------------------------------------------*/
539 {
540   struct unur_gen *gen;
541 
542   /* allocate memory for generator object */
543   gen = _unur_xmalloc( sizeof(struct unur_gen) );
544   gen->datap = _unur_xmalloc(s);
545   gen->s_datap = s;
546 
547   /* copy distribution object into generator object */
548   gen->distr_is_privatecopy = par->distr_is_privatecopy;
549   if (gen->distr_is_privatecopy)
550     gen->distr = (par->distr) ? _unur_distr_clone(par->distr) : NULL;
551   else
552     gen->distr = (struct unur_distr *) par->distr;
553 
554   /* initialize function pointers */
555   gen->destroy = NULL;              /* destructor      */
556   gen->clone = NULL;                /* clone generator */
557   gen->reinit = NULL;               /* reinit routine  */
558 
559   /* copy some parameters into generator object */
560   gen->method = par->method;        /* indicates method and variant          */
561   gen->variant = par->variant;      /* indicates variant                     */
562   gen->set = par->set;              /* indicates parameter settings          */
563   gen->debug = par->debug;          /* debuging flags                        */
564   gen->urng = par->urng;            /* pointer to urng                       */
565   gen->urng_aux = par->urng_aux;    /* pointer to auxilliary URNG            */
566 
567   gen->gen_aux = NULL;              /* no auxilliary generator objects       */
568   gen->gen_aux_list = NULL;         /* no auxilliary generator objects       */
569   gen->n_gen_aux_list = 0;
570 
571   /* status of generator object */
572   gen->status = UNUR_FAILURE;       /* not successfully created yet          */
573 
574 #ifdef UNUR_ENABLE_INFO
575   gen->infostr = NULL;              /* pointer to info string                */
576   gen->info = NULL;                 /* routine that return info string       */
577 #endif
578 
579   /* return pointer to (almost empty) generator object */
580   return gen;
581 
582 } /* end of _unur_generic_create() */
583 
584 /*---------------------------------------------------------------------------*/
585 
586 struct unur_gen *
_unur_generic_clone(const struct unur_gen * gen,const char * type)587 _unur_generic_clone( const struct unur_gen *gen, const char *type )
588      /*----------------------------------------------------------------------*/
589      /* copy (clone) generic generator object                                */
590      /*                                                                      */
591      /* parameters:                                                          */
592      /*   gen  ... pointer to generator object                               */
593      /*   type ... type of generator (string)                                */
594      /*                                                                      */
595      /* return:                                                              */
596      /*   pointer to clone of generator object                               */
597      /*                                                                      */
598      /* error:                                                               */
599      /*   return NULL                                                        */
600      /*----------------------------------------------------------------------*/
601 {
602   struct unur_gen *clone;
603 
604   /* allocate memory for generator object and copy main part */
605   clone = _unur_xmalloc( sizeof(struct unur_gen) );
606   memcpy( clone, gen, sizeof(struct unur_gen) );
607   clone->datap = _unur_xmalloc(gen->s_datap);
608   memcpy (clone->datap, gen->datap, gen->s_datap);
609 
610   /* set generator identifier */
611   clone->genid = _unur_set_genid(type);
612 
613 #ifdef UNUR_ENABLE_INFO
614   /* do not copy pointer to info string */
615   clone->infostr = NULL;
616 #endif
617 
618   /* copy distribution object into generator object */
619   clone->distr_is_privatecopy = gen->distr_is_privatecopy;
620   if (clone->distr_is_privatecopy)
621     clone->distr = (gen->distr) ? _unur_distr_clone(gen->distr) : NULL;
622   else
623     clone->distr = gen->distr;
624 
625   /* auxiliary generators */
626   if (gen->gen_aux)
627     clone->gen_aux = _unur_gen_clone( gen->gen_aux );
628   if (gen->gen_aux_list && gen->n_gen_aux_list) {
629     clone->gen_aux_list = _unur_gen_list_clone( gen->gen_aux_list, gen->n_gen_aux_list );
630     clone->n_gen_aux_list = gen->n_gen_aux_list;
631   }
632 
633   /* finished clone */
634   return clone;
635 } /* _unur_generic_clone() */
636 
637 /*---------------------------------------------------------------------------*/
638 
639 void
_unur_generic_free(struct unur_gen * gen)640 _unur_generic_free( struct unur_gen *gen )
641      /*----------------------------------------------------------------------*/
642      /* deallocate generator object                                          */
643      /*                                                                      */
644      /* parameters:                                                          */
645      /*   gen  ... pointer to generator object                               */
646      /*----------------------------------------------------------------------*/
647 {
648   if (gen->gen_aux)
649     _unur_free(gen->gen_aux);
650 
651   if (gen->gen_aux_list && gen->n_gen_aux_list)
652     _unur_gen_list_free( gen->gen_aux_list, gen->n_gen_aux_list );
653 
654   if (gen->distr_is_privatecopy && gen->distr)
655     _unur_distr_free( gen->distr );
656 
657   _unur_free_genid(gen);
658   COOKIE_CLEAR(gen);
659   free(gen->datap);
660 
661 #ifdef UNUR_ENABLE_INFO
662   /* free pointer to info string */
663   if (gen->infostr) _unur_string_free(gen->infostr);
664 #endif
665 
666   free(gen);
667 } /* end of _unur_generic_free() */
668 
669 /*---------------------------------------------------------------------------*/
670 
671 /*****************************************************************************/
672 /**                                                                         **/
673 /**  Set and copy (clone) arrays of auxiliary generators                    **/
674 /**                                                                         **/
675 /*****************************************************************************/
676 
677 struct unur_gen **
_unur_gen_list_set(struct unur_gen * gen,int n_gen_list)678 _unur_gen_list_set( struct unur_gen *gen, int n_gen_list )
679      /*----------------------------------------------------------------------*/
680      /* set all entries in list to same generator object 'gen'               */
681      /*                                                                      */
682      /* IMPORTANT: Be careful when using this call. When the resulting array */
683      /*   is stored in some multivariate generator object then 'gen'         */
684      /*   _must not_  be used any more after this call!                      */
685      /*                                                                      */
686      /* parameters:                                                          */
687      /*   gen        ... pointer to generator object                         */
688      /*   n_gen_list ... length of array of generator objects                */
689      /*                                                                      */
690      /* return:                                                              */
691      /*   pointer to list of generator objects                               */
692      /*                                                                      */
693      /* error:                                                               */
694      /*   return NULL                                                        */
695      /*----------------------------------------------------------------------*/
696 {
697   struct unur_gen **gen_list;
698   int i;
699 
700   /* check arguments */
701   _unur_check_NULL( "gen_list_set", gen, NULL );
702 
703   if (n_gen_list < 1) {
704     _unur_error("gen_list_set",UNUR_ERR_PAR_SET,"dimension < 1");
705     return NULL;
706   }
707 
708   /* allocate memory for array */
709   gen_list = _unur_xmalloc (n_gen_list * sizeof(struct unur_gen *));
710 
711   /* copy pointer */
712   for (i=0; i<n_gen_list; i++)
713     gen_list[i] = gen;
714 
715   return gen_list;
716 
717 } /* end of _unur_gen_list_set() */
718 
719 /*---------------------------------------------------------------------------*/
720 
721 struct unur_gen **
_unur_gen_list_clone(struct unur_gen ** gen_list,int n_gen_list)722 _unur_gen_list_clone( struct unur_gen **gen_list, int n_gen_list )
723      /*----------------------------------------------------------------------*/
724      /* clone list of generator objects                                      */
725      /*                                                                      */
726      /* parameters:                                                          */
727      /*   gen_list   ... pointer to array of generator objects               */
728      /*   n_gen_list ... length of array of generator objects                */
729      /*                                                                      */
730      /* return:                                                              */
731      /*   pointer to clone of list of generator objects                      */
732      /*                                                                      */
733      /* error:                                                               */
734      /*   return NULL                                                        */
735      /*----------------------------------------------------------------------*/
736 {
737   struct unur_gen **clone_list;
738   int i;
739 
740   /* check arguments */
741   _unur_check_NULL( "gen_list_clone", gen_list, NULL );
742 
743   if (n_gen_list < 1) {
744     _unur_error("gen_list_clone",UNUR_ERR_PAR_SET,"dimension < 1");
745     return NULL;
746   }
747 
748   for (i=0; i<n_gen_list; i++)
749     _unur_check_NULL( "gen_list_clone", *(gen_list+i), NULL );
750 
751   /* allocate memory for array */
752   clone_list = _unur_xmalloc (n_gen_list * sizeof(struct unur_gen *));
753 
754   /* make copy of generator objects */
755   /* There are (should be) only two possibilities:
756      either all entries in the array point to the same generator object;
757        (set by _unur_gen_list_set() call)
758      or each entry has its own copy of some generation object.
759        (set by _unur_gen_list_clone() call)
760   */
761 
762   if (n_gen_list > 1 && gen_list[0] == gen_list[1]) {
763       clone_list[0] = _unur_gen_clone( gen_list[0] );
764       for (i=0; i<n_gen_list; i++)
765 	clone_list[i] = clone_list[0];
766   }
767 
768   else {
769     for (i=0; i<n_gen_list; i++)
770       clone_list[i] = _unur_gen_clone( gen_list[i] );
771   }
772 
773   return clone_list;
774 
775 } /* end of _unur_gen_list_clone() */
776 
777 /*---------------------------------------------------------------------------*/
778 
779 void
_unur_gen_list_free(struct unur_gen ** gen_list,int n_gen_list)780 _unur_gen_list_free( struct unur_gen **gen_list, int n_gen_list )
781      /*----------------------------------------------------------------------*/
782      /* free list of generator objects                                       */
783      /*                                                                      */
784      /* parameters:                                                          */
785      /*   gen_list   ... pointer to array of generator objects               */
786      /*   n_gen_list ... length of array of generator objects                */
787      /*----------------------------------------------------------------------*/
788 {
789   int i, i2, imax;
790 
791   /* check arguments */
792   if (gen_list==NULL)
793     /* nothing to do */
794     return;
795 
796   if (n_gen_list < 1) {
797     _unur_error("gen_list_free",UNUR_ERR_PAR_SET,"dimension < 1");
798     return;
799   }
800 
801   /* free memory */
802   /* There are (should be) only two possibilities:
803      either all entries in the array point to the same generator object;
804        (set by _unur_gen_list_set() call)
805      or each entry has its own copy of some generation object.
806        (set by _unur_gen_list_clone() call)
807   */
808   i2 = (n_gen_list>1) ? 1 : 0;
809   imax = (gen_list[0] == gen_list[i2]) ? 1 : n_gen_list;
810   for (i=0; i<imax; i++)
811     if (gen_list[i]) _unur_free(gen_list[i]);
812   free (gen_list);
813 
814 } /* end of _unur_gen_list_clone() */
815 
816 /*---------------------------------------------------------------------------*/
817