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