1 /*****************************************************************************
2  *                                                                           *
3  *          UNURAN -- Universal Non-Uniform Random number generator          *
4  *                                                                           *
5  *****************************************************************************
6  *                                                                           *
7  *   FILE:      stringparser.c.                                              *
8  *                                                                           *
9  *                                                                           *
10  *   DESCRIPTION:                                                            *
11  *                                                                           *
12  *   The function unur_str2gen() takes a character string as its argument.   *
13  *   This string is parsed in the following ways and the information         *
14  *   obtained is used to make a generator object. (It returns NULL when      *
15  *   it is not possible to make a generator object either due to a syntax    *
16  *   error in the given string, or due to invalid data.                      *
17  *                                                                           *
18  *   First the given string is copied into a working string. Moreover letter *
19  *   letters are transformed into their lower case counterparts and spaces   *
20  *   are eliminated (i.e. the working string does not contain any white      *
21  *   space characters any more.) Then the working string is splitted into    *
22  *   several blocks, separated by ampersands '&'. Each block consists of     *
23  *   <key>=<value> pairs, separated by semicolons ';'. The first key in      *
24  *   each block is used to indicate the corresponding block.                 *
25  *                                                                           *
26  *   We have three different blocks (yet):                                   *
27  *      distr  ... contains the definition of the distribution               *
28  *      method ... contains the description of the transformation methdod    *
29  *      urng   ... contains the definition of the uniform RNG                *
30  *                 (currently it only supports URNGs from the PRNG library)  *
31  *                                                                           *
32  *   The 'distr' block must be the very first block and is obligatory.       *
33  *   For that reason the keyword "distr" is optional and can be omitted      *
34  *   (together with the '=' character). Moreover it is almost ignored while  *
35  *   parsing the string. To avoid some possible confussion it only has to    *
36  *   start with the letter 'd' (if it is given at all). E.g. "dnormal" can   *
37  *   be used as keyword.                                                     *
38  *   The value of the "distr" key is used to get a distribution object       *
39  *   either via a unur_distr_<value>() call for a standard distribution      *
40  *   or the unur_distr_<value>_new() calls are used to get an object for a   *
41  *   generic distribution. However not all generic distributions are         *
42  *   supported yet (see the list %UNSUPPORTED_DISTR_TYPES in file            *
43  *   make_stringparser.pl).                                                  *
44  *   The parameters for the standard distribution are given as a list of     *
45  *   numbers enclosed in parenthesis. There must not be any character (other *
46  *   than white space) between the name of the standard distribution and     *
47  *   this list.                                                              *
48  *                                                                           *
49  *   All the other blocks are optional and can be arranged in arbitrary      *
50  *   order.                                                                  *
51  *   The value of the "method" key is the name of the transformation method  *
52  *   and is used to execute the unur_<value>_new() call.                     *
53  *                                                                           *
54  *   The value of the "urng" key is passed to the PRNG interface.            *
55  *   However, it only works when using the PRNG library is enabled           *
56  *   --with-urng-prng flag and libprng is linked by the executable.          *
57  *                                                                           *
58  *   In each block consecuting <key>=<value> pairs, separated by semicolons  *
59  *   ';', are used to set parameters. The name of the parameter is given as  *
60  *   key, the argument list is given as value. The arguments of the          *
61  *   corresponding set calls are given as tokens, separated by commata ','.  *
62  *   There are two types of tokens:                                          *
63  *      single tokens, that represent numbers, and                           *
64  *      list, i.e. a list of single tokens, separated by commata ',',        *
65  *            enclosed in parenthesis.                                       *
66  *   The value (including the character '=') can be omitted when no argument *
67  *   are required.                                                           *
68  *   The key is deduced from the UNU.RAN set calls, such that it uses only   *
69  *   the part of the set call beyond "..._set_".                             *
70  *   Not all set commands are supported yet (see the output to STDERR of     *
71  *   the make_stringparser.pl script).                                       *
72  *   As a rule of thumb only those set calls are supported that only have    *
73  *   numbers or arrays of numbers as arguments (besides the pointer to the   *
74  *   distribution or parameter object).                                      *
75  *   (See the code of make_stringparser.pl for details.)                     *
76  *                                                                           *
77  *   There are additional transformations before executing the necessary     *
78  *   set calls (listed by argument types)                                    *
79  *      int:      'true' and 'on' are transformed to 1,                      *
80  *                'false' and 'off' are transformed to 0.                    *
81  *                a missing argument is transformed to 1.                    *
82  *      int, int: Instead of two integers, a list with at least two          *
83  *                numbers can be given.                                      *
84  *                'inf[...]' is transformed to INT_MAX,                      *
85  *                '-inf[...]' is transformed to INT_MIN.                     *
86  *      unsigned: string is interpreted as hexadecimal number.               *
87  *      double:   'inf[...]' is transformed to INFINITY,                     *
88  *                '-inf[...]' is transformed to -INFINITY.                   *
89  *      double, double: Instead of two doubles, a list with at least two     *
90  *                numbers can be given.                                      *
91  *                'inf[...]' is transformed to INFINITY.                     *
92  *      int, double*: If the first argument is missing, it is replaced       *
93  *                by the size of the array.                                  *
94  *                If the second argument is missing, the NULL pointer is     *
95  *                used instead an array as argument.                         *
96  *      double*, int: Only for distributions!                                *
97  *                If the second argument 'int' is missing, it is replaced    *
98  *                by the size of the array.                                  *
99  *   Important: there is no support for 'infinity' in lists!                 *
100  *   (See also the source below for more details.)                           *
101  *                                                                           *
102  *****************************************************************************
103  *                                                                           *
104  *   REMARK:                                                                 *
105  *   The stringparser always uses the default debugging flag.                *
106  *                                                                           *
107  *****************************************************************************
108  *                                                                           *
109  *   Copyright (c) 2000-2006 Wolfgang Hoermann and Josef Leydold             *
110  *   Department of Statistics and Mathematics, WU Wien, Austria              *
111  *                                                                           *
112  *   This program is free software; you can redistribute it and/or modify    *
113  *   it under the terms of the GNU General Public License as published by    *
114  *   the Free Software Foundation; either version 2 of the License, or       *
115  *   (at your option) any later version.                                     *
116  *                                                                           *
117  *   This program is distributed in the hope that it will be useful,         *
118  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
119  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
120  *   GNU General Public License for more details.                            *
121  *                                                                           *
122  *   You should have received a copy of the GNU General Public License       *
123  *   along with this program; if not, write to the                           *
124  *   Free Software Foundation, Inc.,                                         *
125  *   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA                  *
126  *                                                                           *
127  *****************************************************************************/
128 
129 #include <stdarg.h>
130 #include <ctype.h>
131 #include <unur_source.h>
132 #include <methods/unur_methods_source.h>
133 #include <methods/x_gen.h>
134 #include "parser_source.h"
135 #include "parser.h"
136 
137 #include <urng/urng.h>
138 
139 #include <distr/distr_source.h>
140 #include <distr/distr.h>
141 #include <distr/cemp.h>
142 #include <distr/cont.h>
143 #include <distr/corder.h>
144 #include <distr/cvemp.h>
145 #include <distr/discr.h>
146 
147 #include <distributions/unur_distributions.h>
148 
149 #include <methods/arou.h>
150 #include <methods/ars.h>
151 #include <methods/auto.h>
152 #include <methods/cstd.h>
153 #include <methods/dari.h>
154 #include <methods/dau.h>
155 #include <methods/dgt.h>
156 #include <methods/dsrou.h>
157 #include <methods/dss.h>
158 #include <methods/dstd.h>
159 #include <methods/empk.h>
160 #include <methods/empl.h>
161 #include <methods/gibbs.h>
162 #include <methods/hinv.h>
163 #include <methods/hist.h>
164 #include <methods/hitro.h>
165 #include <methods/hrb.h>
166 #include <methods/hrd.h>
167 #include <methods/hri.h>
168 #include <methods/itdr.h>
169 #include <methods/mcorr.h>
170 #include <methods/mvstd.h>
171 #include <methods/mvtdr.h>
172 #include <methods/ninv.h>
173 #include <methods/norta.h>
174 #include <methods/nrou.h>
175 #include <methods/pinv.h>
176 #include <methods/srou.h>
177 #include <methods/ssr.h>
178 #include <methods/tabl.h>
179 #include <methods/tdr.h>
180 #include <methods/unif.h>
181 #include <methods/utdr.h>
182 #include <methods/vempk.h>
183 #include <methods/vnrou.h>
184 
185 #if defined(UNUR_URNG_UNURAN) && defined(UNURAN_HAS_PRNG)
186 #include <uniform/urng_prng.h>
187 #endif
188 
189 /*---------------------------------------------------------------------------*/
190 /* Variants: none                                                            */
191 
192 /*---------------------------------------------------------------------------*/
193 /* Debugging flags                                                           */
194 /*    bit  01    ... pameters and structure of generator (do not use here)   */
195 /*    bits 02-12 ... setup                                                   */
196 /*    bits 13-24 ... adaptive steps                                          */
197 /*    bits 25-32 ... trace sampling                                          */
198 
199 /*---------------------------------------------------------------------------*/
200 /* Flags for logging set calls                                               */
201 
202 /*---------------------------------------------------------------------------*/
203 
204 #define GENTYPE "STRING"       /* (pseudo) type of generator                 */
205 
206 /*---------------------------------------------------------------------------*/
207 
208 static struct unur_distr *_unur_str_distr( char *str_distr );
209 /*---------------------------------------------------------------------------*/
210 /* get distribution object for given distribution.                           */
211 /*---------------------------------------------------------------------------*/
212 
213 static struct unur_distr *_unur_str_distr_new( char *distribution );
214 /*---------------------------------------------------------------------------*/
215 /* get new distribution object.                                              */
216 /*---------------------------------------------------------------------------*/
217 
218 static struct unur_distr *_unur_str_distr_make_os( UNUR_DISTR *distr,
219 						   const char *key,
220 						   char *type_args, char **args );
221 /*---------------------------------------------------------------------------*/
222 /* Make distribution object for order statistics of given distribution.      */
223 /*---------------------------------------------------------------------------*/
224 
225 static int _unur_str_distr_set( UNUR_DISTR **ptr_distr, const char *key, char *value );
226 /*---------------------------------------------------------------------------*/
227 /* set parameters for distribution.                                          */
228 /*---------------------------------------------------------------------------*/
229 
230 /*---------------------------------------------------------------------------*/
231 /* Set parameter in given distribution object.                               */
232 /*---------------------------------------------------------------------------*/
233 typedef int distr_set_i( UNUR_DISTR *distr, int i );
234 typedef int distr_set_ii( UNUR_DISTR *distr, int i1, int i2 );
235 typedef int distr_set_d( UNUR_DISTR *distr, double d );
236 typedef int distr_set_dd( UNUR_DISTR *distr, double d1, double d2 );
237 typedef int distr_set_Di( UNUR_DISTR *distr, const double *array, int size );
238 typedef int distr_set_C( UNUR_DISTR *distr, const char *string );
239 /*---------------------------------------------------------------------------*/
240 /* types of set calls                                                        */
241 /*---------------------------------------------------------------------------*/
242 
243 static int _unur_str_distr_set_i( UNUR_DISTR *distr, const char *key, char *type_args, char **args,
244 				  distr_set_i set );
245 /*---------------------------------------------------------------------------*/
246 /* integer.                                                                  */
247 /*---------------------------------------------------------------------------*/
248 
249 static int _unur_str_distr_set_ii( UNUR_DISTR *distr, const char *key, char *type_args, char **args,
250 				   distr_set_ii set );
251 /*---------------------------------------------------------------------------*/
252 /* 2 integers.                                                               */
253 /*---------------------------------------------------------------------------*/
254 
255 static int _unur_str_distr_set_d( UNUR_DISTR *distr, const char *key, char *type_args, char **args,
256 				  distr_set_d set );
257 /*---------------------------------------------------------------------------*/
258 /* double.                                                                   */
259 /*---------------------------------------------------------------------------*/
260 
261 static int _unur_str_distr_set_dd( UNUR_DISTR *distr, const char *key, char *type_args, char **args,
262 				   distr_set_dd set );
263 /*---------------------------------------------------------------------------*/
264 /* 2 doubles.                                                                */
265 /*---------------------------------------------------------------------------*/
266 
267 static int _unur_str_distr_set_Di( UNUR_DISTR *distr, const char *key, char *type_args, char **args,
268 				   distr_set_Di set );
269 /*---------------------------------------------------------------------------*/
270 /* array of doubles & integer.                                               */
271 /*---------------------------------------------------------------------------*/
272 
273 static int _unur_str_distr_set_C( UNUR_DISTR *distr, const char *key, char *type_args, char **args,
274 				  distr_set_C set );
275 /*---------------------------------------------------------------------------*/
276 /* constant string.                                                          */
277 /*---------------------------------------------------------------------------*/
278 
279 
280 static struct unur_par *_unur_str_par( char *str_method, const UNUR_DISTR *distr,
281 				       struct unur_slist *mlist );
282 /*---------------------------------------------------------------------------*/
283 /* get parameter object for distribution and method.                         */
284 /*---------------------------------------------------------------------------*/
285 
286 static struct unur_par *_unur_str_par_new( const char *method, const UNUR_DISTR *distr );
287 /*---------------------------------------------------------------------------*/
288 /* get new parameter object for method.                                      */
289 /*---------------------------------------------------------------------------*/
290 
291 static int _unur_str_par_set( UNUR_PAR *par, const char *key, char *value,
292 			      struct unur_slist *mlist );
293 /*---------------------------------------------------------------------------*/
294 /* set parameters for method.                                                */
295 /*---------------------------------------------------------------------------*/
296 
297 /*---------------------------------------------------------------------------*/
298 /* Set parameter in given parameter object.                                 */
299 /*---------------------------------------------------------------------------*/
300 typedef int par_set_void( UNUR_PAR *par );
301 typedef int par_set_i( UNUR_PAR *par, int i );
302 typedef int par_set_ii( UNUR_PAR *par, int i1, int i2 );
303 typedef int par_set_u( UNUR_PAR *par, unsigned u );
304 typedef int par_set_d( UNUR_PAR *par, double d );
305 typedef int par_set_dd( UNUR_PAR *par, double d1, double d2 );
306 typedef int par_set_iD( UNUR_PAR *par, int size, const double *array );
307 typedef int par_set_Di( UNUR_PAR *par, const double *array, int size );
308 /*---------------------------------------------------------------------------*/
309 /* types of set calls                                                        */
310 /*---------------------------------------------------------------------------*/
311 
312 static int _unur_str_par_set_void( UNUR_PAR *par, const char *key, char *type_args, char **args,
313 				   par_set_void set );
314 /*---------------------------------------------------------------------------*/
315 /* void (no argument required).                                              */
316 /*---------------------------------------------------------------------------*/
317 
318 static int _unur_str_par_set_i( UNUR_PAR *par, const char *key, char *type_args, char **args,
319 				par_set_i set );
320 /*---------------------------------------------------------------------------*/
321 /* integer.                                                                  */
322 /*---------------------------------------------------------------------------*/
323 
324 static int _unur_str_par_set_ii( UNUR_PAR *par, const char *key, char *type_args, char **args,
325 				   par_set_ii set );
326 /*---------------------------------------------------------------------------*/
327 /* 2 integers.                                                               */
328 /*---------------------------------------------------------------------------*/
329 
330 static int _unur_str_par_set_u( UNUR_PAR *par, const char *key, char *type_args, char **args,
331 				par_set_u set );
332 /*---------------------------------------------------------------------------*/
333 /* unsigned integer.                                                         */
334 /*---------------------------------------------------------------------------*/
335 
336 static int _unur_str_par_set_d( UNUR_PAR *par, const char *key, char *type_args, char **args,
337 				par_set_d set );
338 /*---------------------------------------------------------------------------*/
339 /* double.                                                                   */
340 /*---------------------------------------------------------------------------*/
341 
342 static int _unur_str_par_set_dd( UNUR_PAR *par, const char *key, char *type_args, char **args,
343 				 par_set_dd set );
344 
345 /*---------------------------------------------------------------------------*/
346 /* 2 doubles.                                                                */
347 /*---------------------------------------------------------------------------*/
348 
349 static int _unur_str_par_set_iD( UNUR_PAR *par, const char *key, char *type_args, char **args,
350 				 par_set_iD set, struct unur_slist *mlist );
351 /*---------------------------------------------------------------------------*/
352 /* integer & array of doubles.                                               */
353 /*---------------------------------------------------------------------------*/
354 
355 static int _unur_str_par_set_Di( UNUR_PAR *par, const char *key, char *type_args, char **args,
356 				 par_set_Di set, struct unur_slist *mlist );
357 /*---------------------------------------------------------------------------*/
358 /* array of doubles & integer.                                               */
359 /*---------------------------------------------------------------------------*/
360 
361 
362 static UNUR_URNG *_unur_str2urng( char *str_urng );
363 /*---------------------------------------------------------------------------*/
364 /* get uniform RNG.                                                          */
365 /*---------------------------------------------------------------------------*/
366 
367 
368 static int _unur_str_set_args( char *value, char *type_args, char **args, int max_args );
369 /*---------------------------------------------------------------------------*/
370 /* parse argument string for set call.                                       */
371 /*---------------------------------------------------------------------------*/
372 
373 static int _unur_parse_ilist( char *liststr, int **iarray );
374 /*---------------------------------------------------------------------------*/
375 /* Process a comma separated list of integers.                               */
376 /*---------------------------------------------------------------------------*/
377 
378 static int _unur_parse_dlist( char *liststr, double **darray );
379 /*---------------------------------------------------------------------------*/
380 /* Process a comma separated list of numbers.                                */
381 /*---------------------------------------------------------------------------*/
382 
383 static int _unur_atoi ( const char *str );
384 /*---------------------------------------------------------------------------*/
385 /* Convert string into its integer representation.                           */
386 /*---------------------------------------------------------------------------*/
387 
388 static unsigned _unur_atou ( const char *str );
389 /*---------------------------------------------------------------------------*/
390 /* Convert string into its unsigned representation (using hexadecimal).      */
391 /*---------------------------------------------------------------------------*/
392 
393 static double _unur_atod ( const char *str );
394 /*---------------------------------------------------------------------------*/
395 /* Convert string into its double value.                                     */
396 /*---------------------------------------------------------------------------*/
397 
398 /*---------------------------------------------------------------------------*/
399 #ifdef UNUR_ENABLE_LOGGING
400 /*---------------------------------------------------------------------------*/
401 /* the following functions print debugging information on output stream,     */
402 /* i.e., into the LOG file if not specified otherwise.                       */
403 /*---------------------------------------------------------------------------*/
404 
405 static void _unur_str_debug_string( int level, const char *key, const char *value );
406 /*---------------------------------------------------------------------------*/
407 /* print key & value info into LOG file.                                     */
408 /*---------------------------------------------------------------------------*/
409 
410 static void _unur_str_debug_distr( int level, const char *name, double *params, int n_params );
411 /*---------------------------------------------------------------------------*/
412 /* write info about distribution into LOG file.                              */
413 /*---------------------------------------------------------------------------*/
414 
415 static void _unur_str_debug_set( int level, const char *key, const char *type, ... );
416 
417 /*---------------------------------------------------------------------------*/
418 /* write info about set command into LOG file.                               */
419 /*---------------------------------------------------------------------------*/
420 
421 #endif
422 /*---------------------------------------------------------------------------*/
423 
424 
425 static void _unur_str_error_unknown( const char *file, int line, const char *key, const char *type );
426 /*---------------------------------------------------------------------------*/
427 /* print error message: unknown keyword.                                     */
428 /*---------------------------------------------------------------------------*/
429 
430 static void _unur_str_error_invalid( const char *file, int line, const char *key, const char *type );
431 /*---------------------------------------------------------------------------*/
432 /* print error message: invalid data for keyword.                            */
433 /*---------------------------------------------------------------------------*/
434 
435 static void _unur_str_error_args( const char *file, int line, const char *key );
436 /*---------------------------------------------------------------------------*/
437 /* print error message: invalid argument string for set call.                */
438 /*---------------------------------------------------------------------------*/
439 
440 /*---------------------------------------------------------------------------*/
441 /* abbreviations */
442 
443 #define _unur_error_unknown(key,what) \
444    do { \
445      _unur_str_error_unknown( __FILE__,__LINE__, (key), (what) ); \
446    } while (0)
447 
448 /* invalid data for key */
449 #define _unur_error_invalid(key,what) \
450    do { \
451      _unur_str_error_invalid( __FILE__,__LINE__, (key), (what) ); \
452    } while (0)
453 
454 /* invalid argument string for set calls */
455 #define _unur_error_args(key) \
456    do { \
457      _unur_str_error_args( __FILE__,__LINE__, (key) ); \
458    } while (0)
459 
460 
461 /*---------------------------------------------------------------------------*/
462 /* constants                                                                 */
463 
464 #define MAX_SET_ARGS  (10)
465 /* maximal number of arguments for set calls (must be at least 2) */
466 
467 /*---------------------------------------------------------------------------*/
468 
469 /*****************************************************************************/
470 /**  Load lists of ..._new and ..._set calls                                **/
471 /*****************************************************************************/
472 
473 #include "stringparser_lists.ch"
474 
475 /*****************************************************************************/
476 /**  User Interface                                                         **/
477 /*****************************************************************************/
478 
479 /*---------------------------------------------------------------------------*/
480 
481 struct unur_gen *
unur_str2gen(const char * string)482 unur_str2gen (const char *string)
483      /*----------------------------------------------------------------------*/
484      /* get generator object for distribution and method                     */
485      /*                                                                      */
486      /* parameters:                                                          */
487      /*   string ... string that contains description of generator           */
488      /*                                                                      */
489      /* return:                                                              */
490      /*   generator object                                                   */
491      /*                                                                      */
492      /* error:                                                               */
493      /*   return NULL                                                        */
494      /*----------------------------------------------------------------------*/
495 {
496   UNUR_DISTR *distr = NULL;       /* distribution object */
497   UNUR_PAR   *par   = NULL;       /* parameter object */
498   UNUR_GEN   *gen   = NULL;       /* generator object    */
499   UNUR_URNG  *urng  = NULL;       /* uniform random number generator */
500 
501   char *str_distr   = NULL;       /* string for distribution */
502   char *str_method  = NULL;       /* string for method       */
503   char *str_urng    = NULL;       /* string for uniform RNG  */
504 
505   char *str = NULL;               /* pointer to working string */
506   char *token;
507 
508   struct unur_slist *mlist;       /* list of allocated memory blocks */
509 
510   /* check arguments */
511   _unur_check_NULL( GENTYPE,string,NULL );
512 
513   /* (empty) list of allocated memory blocks */
514   mlist = _unur_slist_new();
515 
516   /* Prepare string for processing:            */
517   /*   Remove all white spaces,                */
518   /*   convert to lower case letters,          */
519   /*   copy into working string                */
520   str = _unur_parser_prepare_string( string );
521 
522 #ifdef UNUR_ENABLE_LOGGING
523   /* write info into LOG file */
524   if (_unur_default_debugflag)
525     _unur_str_debug_string(0,"[input]",str);
526 #endif
527 
528   /* split string into blocks separated by ampersands '&' */
529 
530   /* the first block must contain the distribution */
531   str_distr = strtok(str, "&");
532 
533   /* new get all the other tokens */
534   for ( token  = strtok(NULL, "&");
535         token != NULL;
536         token  = strtok(NULL, "&") ) {
537 
538     /* get type of block */
539     if (!strncmp(token,"method=",(size_t)7)) {
540       str_method = token;
541     }
542     else if (!strncmp(token,"urng=",(size_t)5)) {
543       str_urng = token;
544     }
545     else {
546       _unur_error_unknown(token,"category");
547       _unur_slist_free( mlist );
548       if (str) free(str);
549       return NULL;
550     }
551   }
552 
553   /* make distribution object */
554   distr = _unur_str_distr(str_distr);
555   if ( distr == NULL ) {
556     /* error */
557     _unur_slist_free( mlist );
558     if (str) free(str);
559     return NULL;
560   }
561 
562   /* get parameter object */
563   if ( str_method != NULL )
564     /* method is provided in string */
565     par = _unur_str_par(str_method, distr, mlist);
566   else
567     /* otherwise use default method */
568     par = unur_auto_new(distr);
569 
570   /* make generator object */
571   gen = unur_init(par);
572 
573   /* destroy distribution object */
574   unur_distr_free(distr);
575 
576   /* set uniform random number generator -- if provided */
577   if ( str_urng != NULL )
578     if (gen != NULL) {
579       /* we need a valid generator object */
580       if ((urng = _unur_str2urng(str_urng)) != NULL )
581 	unur_chg_urng(gen, urng);
582     }
583 
584   /* free allocated memory blocks */
585   _unur_slist_free(mlist);
586   if (str) free(str);
587 
588   /* check result: nothing to do */
589   /*  if ( gen == NULL ) { */
590   /*    error */
591   /*    return NULL; */
592   /*  } */
593 
594 #ifdef UNUR_ENABLE_LOGGING
595   /* write info into LOG file */
596   if (_unur_default_debugflag)
597     _unur_str_debug_string(0,"",NULL);
598 #endif
599 
600   /* return pointer to generator object */
601   return gen;
602 
603 } /* end of unur_str2gen() */
604 
605 /*---------------------------------------------------------------------------*/
606 
607 struct unur_par *
_unur_str2par(const struct unur_distr * distr,const char * string,struct unur_slist ** mlist)608 _unur_str2par (const struct unur_distr *distr, const char *string, struct unur_slist **mlist )
609      /*----------------------------------------------------------------------*/
610      /* get parameter object for distribution and method                     */
611      /*                                                                      */
612      /* parameters:                                                          */
613      /*   distr  ... pointer to distribution object                          */
614      /*   string ... string that contains description of method              */
615      /*   mlist  ... pointer to simple list for allocated memory blocks      */
616      /*                                                                      */
617      /* return:                                                              */
618      /*   parameter object                                                   */
619      /*                                                                      */
620      /* error:                                                               */
621      /*   return NULL                                                        */
622      /*----------------------------------------------------------------------*/
623 {
624   UNUR_PAR *par = NULL;           /* parameter object */
625   char *str = NULL;               /* pointer to working string */
626 
627   /* check arguments */
628   _unur_check_NULL( GENTYPE,distr,NULL );
629   _unur_check_NULL( GENTYPE,string,NULL );
630 
631   /* (empty) list of allocated memory blocks */
632   *mlist = _unur_slist_new();
633 
634   /* Prepare string for processing:            */
635   /*   Remove all white spaces,                */
636   /*   convert to lower case letters,          */
637   /*   copy into working string                */
638   str = _unur_parser_prepare_string( string );
639 
640 #ifdef UNUR_ENABLE_LOGGING
641   /* write info into LOG file */
642   if (_unur_default_debugflag)
643     _unur_str_debug_string(0,"[input]",str);
644 #endif
645 
646   /* get parameter object */
647   par = _unur_str_par(str, distr, *mlist);
648 
649   /* free allocated memory blocks */
650   if (str) free(str);
651 
652 #ifdef UNUR_ENABLE_LOGGING
653   /* write info into LOG file */
654   if (_unur_default_debugflag)
655     if ( par != NULL )
656       _unur_str_debug_string(0,"",NULL);
657 #endif
658 
659   /* return pointer to parameter object */
660   return par;
661 
662 } /* end of _unur_str2par() */
663 
664 /*---------------------------------------------------------------------------*/
665 
666 struct unur_distr *
unur_str2distr(const char * string)667 unur_str2distr (const char *string)
668      /*----------------------------------------------------------------------*/
669      /* get distribution object for given distribution                       */
670      /*                                                                      */
671      /* parameters:                                                          */
672      /*   string ... string that contains description of distribution        */
673      /*                                                                      */
674      /* return:                                                              */
675      /*   distribution object                                                */
676      /*                                                                      */
677      /* error:                                                               */
678      /*   return NULL                                                        */
679      /*----------------------------------------------------------------------*/
680 {
681   UNUR_DISTR *distr = NULL;       /* distribution object */
682   char *str = NULL;               /* pointer to working string */
683 
684   /* check arguments */
685   _unur_check_NULL( GENTYPE,string,NULL );
686 
687   /* Prepare string for processing:            */
688   /*   Remove all white spaces,                */
689   /*   convert to lower case letters,          */
690   /*   copy into working string                */
691   str = _unur_parser_prepare_string( string );
692 
693 #ifdef UNUR_ENABLE_LOGGING
694   /* write info into LOG file */
695   if (_unur_default_debugflag)
696     _unur_str_debug_string(0,"[input]",str);
697 #endif
698 
699   /* make distribution object */
700   distr = _unur_str_distr(str);
701 
702   /* free allocated memory blocks */
703   if (str) free(str);
704 
705 #ifdef UNUR_ENABLE_LOGGING
706   /* write info into LOG file */
707   if (_unur_default_debugflag)
708     if ( distr != NULL )
709       _unur_str_debug_string(0,"",NULL);
710 #endif
711 
712   /* return pointer to distribution object */
713   return distr;
714 
715 } /* end of unur_str2distr() */
716 
717 /*---------------------------------------------------------------------------*/
718 
719 struct unur_gen *
unur_makegen_ssu(const char * distrstr,const char * methodstr,UNUR_URNG * urng)720 unur_makegen_ssu( const char *distrstr, const char *methodstr, UNUR_URNG *urng )
721      /*----------------------------------------------------------------------*/
722      /* get generator object for distribution and method                     */
723      /*                                                                      */
724      /* parameters:                                                          */
725      /*   distrstr  ... distribution described by a string                   */
726      /*   methodstr ... chosen method described by a string                  */
727      /*   urng      ... pointer to uniform random number generator           */
728      /*                 (NULL = default generator)                           */
729      /*                                                                      */
730      /* return:                                                              */
731      /*   generator object                                                   */
732      /*                                                                      */
733      /* error:                                                               */
734      /*   return NULL                                                        */
735      /*----------------------------------------------------------------------*/
736 {
737   UNUR_DISTR *distr = NULL;       /* distribution object */
738   UNUR_PAR   *par   = NULL;       /* parameter object */
739   UNUR_GEN   *gen   = NULL;       /* generator object    */
740 
741   char *str_distr   = NULL;       /* string for distribution */
742   char *str_method  = NULL;       /* string for method       */
743 
744   struct unur_slist *mlist;       /* list of allocated memory blocks */
745 
746   /* check arguments */
747   _unur_check_NULL( GENTYPE, distrstr, NULL );
748 
749   /* (empty) list of allocated memory blocks */
750   mlist = _unur_slist_new();
751 
752   /* Prepare string for processing:            */
753   /*   Remove all white spaces,                */
754   /*   convert to lower case letters,          */
755   /*   copy into working string                */
756   str_distr = _unur_parser_prepare_string( distrstr );
757   str_method = (methodstr)
758     ? _unur_parser_prepare_string( methodstr )
759     : NULL;
760 
761 #ifdef UNUR_ENABLE_LOGGING
762   /* write info into LOG file */
763   if (_unur_default_debugflag) {
764     _unur_str_debug_string(0,"[input-distr]",str_distr);
765     _unur_str_debug_string(0,"[input-method]",
766 			   (str_method) ? str_method : "(NULL)" );
767   }
768 #endif
769 
770   do {
771     /* make distribution object */
772     distr = _unur_str_distr(str_distr);
773     if (distr == NULL) break;
774 
775     /* get parameter object */
776     if ( str_method != NULL && strlen(str_method)>0 )
777       /* method is provided in string */
778       par = _unur_str_par(str_method, distr, mlist);
779     else
780       /* otherwise use default method */
781       par = unur_auto_new(distr);
782     if (par == NULL) break;
783 
784     /* make generator object */
785     gen = unur_init(par);
786     if (gen == NULL) break;
787 
788     /* set uniform RNG */
789     if (urng != NULL)
790       unur_chg_urng(gen, urng);
791 
792   } while (0);
793 
794   /* destroy distribution object */
795   unur_distr_free(distr);
796 
797   /* free allocated memory blocks */
798   _unur_slist_free(mlist);
799   if (str_distr) free(str_distr);
800   if (str_method) free(str_method);
801 
802 #ifdef UNUR_ENABLE_LOGGING
803   /* write info into LOG file */
804   if (_unur_default_debugflag)
805     _unur_str_debug_string(0,"",NULL);
806 #endif
807 
808   /* return pointer to generator object */
809   return gen;
810 
811 } /* end of unur_makegen_ssu() */
812 
813 /*---------------------------------------------------------------------------*/
814 
815 struct unur_gen *
unur_makegen_dsu(const struct unur_distr * distr,const char * methodstr,UNUR_URNG * urng)816 unur_makegen_dsu( const struct unur_distr *distr, const char *methodstr, UNUR_URNG *urng )
817      /*----------------------------------------------------------------------*/
818      /* get generator object for distribution and method                     */
819      /*                                                                      */
820      /* parameters:                                                          */
821      /*   distr     ... distribution object                                  */
822      /*   methodstr ... chosen method described by a string                  */
823      /*   urng      ... pointer to uniform random number generator           */
824      /*                 (NULL = default generator)                           */
825      /*                                                                      */
826      /* return:                                                              */
827      /*   generator object                                                   */
828      /*                                                                      */
829      /* error:                                                               */
830      /*   return NULL                                                        */
831      /*----------------------------------------------------------------------*/
832 {
833   UNUR_PAR   *par   = NULL;       /* parameter object */
834   UNUR_GEN   *gen   = NULL;       /* generator object    */
835 
836   char *str_method  = NULL;       /* string for method       */
837 
838   struct unur_slist *mlist;       /* list of allocated memory blocks */
839 
840   /* check arguments */
841   _unur_check_NULL( GENTYPE,distr,NULL );
842 
843   /* (empty) list of allocated memory blocks */
844   mlist = _unur_slist_new();
845 
846   /* Prepare string for processing:            */
847   /*   Remove all white spaces,                */
848   /*   convert to lower case letters,          */
849   /*   copy into working string                */
850   str_method = (methodstr)
851     ? _unur_parser_prepare_string( methodstr )
852     : NULL;
853 
854 #ifdef UNUR_ENABLE_LOGGING
855   /* write info into LOG file */
856   if (_unur_default_debugflag) {
857     _unur_str_debug_string(0,"[input-distr]","(distribution object)");
858     _unur_str_debug_string(0,"[input-method]",
859 			   (str_method) ? str_method : "(NULL)" );
860   }
861 #endif
862 
863   do {
864     /* get parameter object */
865     if ( str_method != NULL && strlen(str_method)>0 )
866       /* method is provided in string */
867       par = _unur_str_par(str_method, distr, mlist);
868     else
869       /* otherwise use default method */
870       par = unur_auto_new(distr);
871     if (par == NULL) break;
872 
873     /* make generator object */
874     gen = unur_init(par);
875     if (gen == NULL) break;
876 
877     /* set uniform RNG */
878     if (urng != NULL)
879       unur_chg_urng(gen, urng);
880 
881   } while (0);
882 
883   /* free allocated memory blocks */
884   _unur_slist_free(mlist);
885   if (str_method) free(str_method);
886 
887 #ifdef UNUR_ENABLE_LOGGING
888   /* write info into LOG file */
889   if (_unur_default_debugflag)
890     _unur_str_debug_string(0,"",NULL);
891 #endif
892 
893   /* return pointer to generator object */
894   return gen;
895 
896 } /* end of unur_makegen_dsu() */
897 
898 /*---------------------------------------------------------------------------*/
899 
900 /*****************************************************************************/
901 /**  Distributions                                                          **/
902 /*****************************************************************************/
903 
904 /*---------------------------------------------------------------------------*/
905 
906 struct unur_distr *
_unur_str_distr(char * str_distr)907 _unur_str_distr( char *str_distr )
908      /*----------------------------------------------------------------------*/
909      /* get distribution object for given distribution                       */
910      /*                                                                      */
911      /* parameters:                                                          */
912      /*   str_distr ... string that contains description of distribution     */
913      /*                                                                      */
914      /* return:                                                              */
915      /*   distribution object                                                */
916      /*                                                                      */
917      /* error:                                                               */
918      /*   return NULL                                                        */
919      /*----------------------------------------------------------------------*/
920 {
921   struct unur_distr *distr = NULL;
922 
923   char *token;             /* pointer to token in string */
924   char *next;              /* pointer to next token in string */
925   char *key, *value;       /* the key and its value */
926 
927 
928   /* tokenize the string using ';' as separator and handle the tokens */
929   for ( token = next = str_distr;
930 	next != NULL && *token != '\0';
931 	token = next ) {
932 
933     /* find end of token (i.e. the pointer to next token) */
934     next = strchr(token,';');
935     if (next != NULL) {
936       /* next separator found */
937       *next = '\0';     /* terminate token string    */
938       next++;           /* set pointer to next token */
939     }
940 
941     /* token points to a key */
942     key = token;
943 
944     /* get the value from the pair key=value and terminate key string */
945     value = strchr(key, '=');
946     if (value != NULL) {
947       *value = '\0';    /* terminate key string        */
948       value++;          /* set pointer to value string */
949     }
950 
951     /* the first key is treated differently: get new distribution object */
952     if (key == str_distr) {
953       /* the keyword "distr" is optional */
954       if (value == NULL) {
955 	/* no "distribution" keyword given, so the key points to the value */
956 	value = key;
957       }
958       else {
959 	if (*key != 'd') {
960 	  _unur_error(GENTYPE,UNUR_ERR_STR_SYNTAX,"key for distribution does not start with 'd'");
961 	  _unur_distr_free(distr);  /* remark: added for ROOT to make coverity integrity manager happy */
962 	  return NULL;
963 	}
964       }
965 
966       /* get new distribution object */
967       if (distr != NULL) {
968 	_unur_error(GENTYPE,UNUR_ERR_SHOULD_NOT_HAPPEN,"");
969 	_unur_distr_free(distr);
970       }
971 
972       distr = _unur_str_distr_new(value);
973       if (distr == NULL) {
974 	/* error */
975 	/* _unur_error(GENTYPE,UNUR_ERR_STR,"setting distribution failed");  */
976 	return NULL;
977       }
978     }
979 
980     /* set parameters for distribution */
981     else {
982       if (_unur_str_distr_set(&distr, key, value)!=UNUR_SUCCESS ) {
983 	/* error */
984 	_unur_distr_free(distr);
985 	/* _unur_error(GENTYPE,UNUR_ERR_STR,"setting distribution failed");  */
986 	return NULL;
987       }
988     }
989   }
990 
991   return distr;
992 
993 } /* end of _unur_str_distr() */
994 
995 /*---------------------------------------------------------------------------*/
996 
997 struct unur_distr *
_unur_str_distr_make_os(UNUR_DISTR * distr,const char * key,char * type_args,char ** args)998 _unur_str_distr_make_os (UNUR_DISTR *distr, const char *key, char *type_args, char **args)
999      /*----------------------------------------------------------------------*/
1000      /* Make distribution object for order statistics of given distribution. */
1001      /* The given distribution `distr' is destroyed.                         */
1002      /* The list of arguments and their types are given as string.           */
1003      /*                                                                      */
1004      /* type: "ii"   (int,int)                                               */
1005      /*                                                                      */
1006      /* input: "tt"  (exactly two single tokens)                             */
1007      /*        "L"   (exactly one list)                                      */
1008      /*                                                                      */
1009      /* action:                                                              */
1010      /*    if "tt": convert both to int.                                     */
1011      /*             execute set call.                                        */
1012      /*    if "L":  convert list entries to int.                             */
1013      /*             execute set call with first two entries.                 */
1014      /*                (error if list has less than two entries)             */
1015      /*    otherwise: error                                                  */
1016      /*                                                                      */
1017      /* parameters:                                                          */
1018      /*   distr     ... pointer to distribution object                       */
1019      /*   key       ... name of parameter to be set                          */
1020      /*   type_args ... contains types of arguments. Possible values:        */
1021      /*                   't'   for single token                             */
1022      /*                   'L'   for a list                                   */
1023      /*   args      ... array of pointers to argument strings                */
1024      /*                                                                      */
1025      /* return:                                                              */
1026      /*   pointer to distribution object for order statistics                */
1027      /*                                                                      */
1028      /* error:                                                               */
1029      /*   return NULL                                                        */
1030      /*----------------------------------------------------------------------*/
1031 {
1032   int *iarray = NULL;                 /* pointer to working array            */
1033   struct unur_distr *os = NULL;       /* pointer to order statistics object  */
1034 
1035   /* either exactly two arguments are given */
1036   if ( !strcmp(type_args, "tt") ) {
1037     iarray = _unur_xmalloc( 2*sizeof(double) );
1038     iarray[0] = _unur_atoi( args[0] );
1039     iarray[1] = _unur_atoi( args[1] );
1040   }
1041 
1042   /* or one list with 2 entries is given */
1043   else if ( !strcmp(type_args, "L") ) {
1044     if ( _unur_parse_ilist( args[0], &iarray ) < 2 ) {
1045       free (iarray);
1046       iarray = NULL;
1047     }
1048   }
1049 
1050   if (iarray == NULL ) {
1051     /* data list empty (incorrect syntax) */
1052     _unur_error_args(key);
1053 #ifdef UNUR_ENABLE_LOGGING
1054     /* write info into LOG file */
1055     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1056       _unur_str_debug_set(2,key,"!");
1057 #endif
1058     return NULL;
1059   }
1060 
1061   /* now make object to order statistics */
1062 
1063 #ifdef UNUR_ENABLE_LOGGING
1064   /* write info into LOG file */
1065   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1066     _unur_str_debug_set(2,key,"ii",iarray[0],iarray[1] );
1067 #endif
1068 
1069   os =  unur_distr_corder_new( distr, iarray[0], iarray[1] );
1070 
1071   /* free memory */
1072   _unur_distr_free(distr);
1073   free (iarray);
1074 
1075   /* return order statistics (or NULL we could not make such a thing) */
1076   return os;
1077 
1078 } /* end of _unur_str_distr_make_os() */
1079 
1080 /*---------------------------------------------------------------------------*/
1081 
1082 int
_unur_str_distr_set_i(UNUR_DISTR * distr,const char * key,char * type_args,char ** args,distr_set_i set)1083 _unur_str_distr_set_i (UNUR_DISTR *distr, const char *key, char *type_args, char **args, distr_set_i set)
1084      /*----------------------------------------------------------------------*/
1085      /* Set parameter in given distribution object.                          */
1086      /* The list of arguments and their types are given as string.           */
1087      /*                                                                      */
1088      /* type: "i"   (int)                                                    */
1089      /*                                                                      */
1090      /* input: "t"  (exactly one single token)                               */
1091      /*        void (no argument given)                                      */
1092      /*                                                                      */
1093      /* action:                                                              */
1094      /*    convert token to int.                                             */
1095      /*      (if no argument is given, use 1.)                               */
1096      /*    execute set call.                                                 */
1097      /*    error if input != "t"                                             */
1098      /*                                                                      */
1099      /* parameters:                                                          */
1100      /*   distr     ... pointer to distribution object                       */
1101      /*   key       ... name of parameter to be set                          */
1102      /*   type_args ... contains types of arguments. Possible values:        */
1103      /*                   't'   for single token                             */
1104      /*                   'L'   for a list                                   */
1105      /*   args      ... array of pointers to argument strings                */
1106      /*   set       ... pointer to UNU.RAN function for set call             */
1107      /*                                                                      */
1108      /* return:                                                              */
1109      /*   return code from set call, i.e.                                    */
1110      /*      UNUR_SUCCESS ... on success                                     */
1111      /*      error code   ... on error                                       */
1112      /*----------------------------------------------------------------------*/
1113 {
1114   int iarg;
1115 
1116   if ( !strcmp(type_args, "t") ) {
1117     iarg = _unur_atoi( args[0] );
1118   }
1119   else if ( strlen(type_args) == 0 ) {
1120     iarg = 1;
1121   }
1122   else {
1123     _unur_error_args(key);
1124 #ifdef UNUR_ENABLE_LOGGING
1125     /* write info into LOG file */
1126     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1127       _unur_str_debug_set(2,key,"!");
1128 #endif
1129     return UNUR_ERR_STR_INVALID;
1130   }
1131 
1132 #ifdef UNUR_ENABLE_LOGGING
1133   /* write info into LOG file */
1134   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1135     _unur_str_debug_set(2,key,"i",iarg);
1136 #endif
1137 
1138   return set(distr,iarg);
1139 
1140 } /* end of _unur_str_distr_set_i() */
1141 
1142 /*---------------------------------------------------------------------------*/
1143 
1144 int
_unur_str_distr_set_ii(UNUR_DISTR * distr,const char * key,char * type_args,char ** args,distr_set_ii set)1145 _unur_str_distr_set_ii (UNUR_DISTR *distr, const char *key, char *type_args, char **args, distr_set_ii set)
1146      /*----------------------------------------------------------------------*/
1147      /* Set parameter in given distribution object.                          */
1148      /* The list of arguments and their types are given as string.           */
1149      /*                                                                      */
1150      /* type: "ii"   (int,int)                                               */
1151      /*                                                                      */
1152      /* input: "tt"  (exactly two single tokens)                             */
1153      /*        "L"   (exactly one list)                                      */
1154      /*                                                                      */
1155      /* action:                                                              */
1156      /*    if "tt": convert both to int.                                     */
1157      /*             execute set call.                                        */
1158      /*    if "L":  convert list entries to int.                             */
1159      /*             execute set call with first two entries.                 */
1160      /*                (error if list has less than two entries)             */
1161      /*    otherwise: error                                                  */
1162      /*                                                                      */
1163      /* parameters:                                                          */
1164      /*   distr     ... pointer to distribution object                       */
1165      /*   key       ... name of parameter to be set                          */
1166      /*   type_args ... contains types of arguments. Possible values:        */
1167      /*                   't'   for single token                             */
1168      /*                   'L'   for a list                                   */
1169      /*   args      ... array of pointers to argument strings                */
1170      /*   set       ... pointer to UNU.RAN function for set call             */
1171      /*                                                                      */
1172      /* return:                                                              */
1173      /*   return code from set call, i.e.                                    */
1174      /*      UNUR_SUCCESS ... on success                                     */
1175      /*      error code   ... on error                                       */
1176      /*----------------------------------------------------------------------*/
1177 {
1178   int *iarray = NULL;
1179   int iarg[2];
1180   int result;
1181 
1182   /* either exactly two arguments are given */
1183   if ( !strcmp(type_args, "tt") ) {
1184     iarg[0] = _unur_atoi( args[0] );
1185     iarg[1] = _unur_atoi( args[1] );
1186 
1187 #ifdef UNUR_ENABLE_LOGGING
1188     /* write info into LOG file */
1189     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1190       _unur_str_debug_set(2,key,"ii",iarg[0],iarg[1]);
1191 #endif
1192 
1193     return set( distr,iarg[0],iarg[1] );
1194   }
1195 
1196   /* or one list with 2 entries is given */
1197   else if ( !strcmp(type_args, "L") ) {
1198     if ( _unur_parse_ilist( args[0], &iarray ) < 2 ) {
1199       _unur_error_args(key);
1200       free (iarray);
1201 #ifdef UNUR_ENABLE_LOGGING
1202       /* write info into LOG file */
1203       if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1204 	_unur_str_debug_set(2,key,"!");
1205 #endif
1206       return UNUR_ERR_STR_INVALID;
1207     }
1208     result = set( distr,iarray[0],iarray[1] );
1209 
1210 #ifdef UNUR_ENABLE_LOGGING
1211     /* write info into LOG file */
1212     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1213       _unur_str_debug_set(2,key,"ii",iarray[0],iarray[1] );
1214 #endif
1215 
1216     free (iarray);
1217     return result;
1218   }
1219 
1220   else {
1221     _unur_error_args(key);
1222 #ifdef UNUR_ENABLE_LOGGING
1223     /* write info into LOG file */
1224     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1225       _unur_str_debug_set(2,key,"!");
1226 #endif
1227     return UNUR_ERR_STR_INVALID;
1228   }
1229 
1230 } /* end of _unur_str_distr_set_ii() */
1231 
1232 /*---------------------------------------------------------------------------*/
1233 
1234 int
_unur_str_distr_set_d(UNUR_DISTR * distr,const char * key,char * type_args,char ** args,distr_set_d set)1235 _unur_str_distr_set_d (UNUR_DISTR *distr, const char *key, char *type_args, char **args, distr_set_d set)
1236      /*----------------------------------------------------------------------*/
1237      /* Set parameter in given distribution object.                          */
1238      /* The list of arguments and their types are given as string.           */
1239      /*                                                                      */
1240      /* type: "d"   (double)                                                 */
1241      /*                                                                      */
1242      /* input: "t"  (exactly one single token)                               */
1243      /*                                                                      */
1244      /* action:                                                              */
1245      /*    convert token to double.                                          */
1246      /*    execute set call.                                                 */
1247      /*    error if input != "t"                                             */
1248      /*                                                                      */
1249      /* parameters:                                                          */
1250      /*   distr     ... pointer to distribution object                       */
1251      /*   key       ... name of parameter to be set                          */
1252      /*   type_args ... contains types of arguments. Possible values:        */
1253      /*                   't'   for single token                             */
1254      /*                   'L'   for a list                                   */
1255      /*   args      ... array of pointers to argument strings                */
1256      /*   set       ... pointer to UNU.RAN function for set call             */
1257      /*                                                                      */
1258      /* return:                                                              */
1259      /*   return code from set call, i.e.                                    */
1260      /*      UNUR_SUCCESS ... on success                                     */
1261      /*      error code   ... on error                                       */
1262      /*----------------------------------------------------------------------*/
1263 {
1264   double darg;
1265 
1266   if ( strcmp(type_args, "t") ) {
1267     _unur_error_args(key);
1268 #ifdef UNUR_ENABLE_LOGGING
1269     /* write info into LOG file */
1270     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1271       _unur_str_debug_set(2,key,"!");
1272 #endif
1273     return UNUR_ERR_STR_INVALID;
1274   }
1275 
1276   darg = _unur_atod( args[0] );
1277 
1278 #ifdef UNUR_ENABLE_LOGGING
1279   /* write info into LOG file */
1280   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1281     _unur_str_debug_set(2,key,"d",darg);
1282 #endif
1283 
1284   return set(distr,darg);
1285 
1286 } /* end of _unur_str_distr_set_d() */
1287 
1288 /*---------------------------------------------------------------------------*/
1289 
1290 int
_unur_str_distr_set_dd(UNUR_DISTR * distr,const char * key,char * type_args,char ** args,distr_set_dd set)1291 _unur_str_distr_set_dd (UNUR_DISTR *distr, const char *key, char *type_args, char **args, distr_set_dd set)
1292      /*----------------------------------------------------------------------*/
1293      /* Set parameter in given distribution object.                          */
1294      /* The list of arguments and their types are given as string.           */
1295      /*                                                                      */
1296      /* type: "dd"   (double,double)                                         */
1297      /*                                                                      */
1298      /* input: "tt"  (exactly two single tokens)                             */
1299      /*        "L"   (exactly one list)                                      */
1300      /*                                                                      */
1301      /* action:                                                              */
1302      /*    if "tt": convert both to double.                                  */
1303      /*             execute set call.                                        */
1304      /*    if "L":  convert list entries to double.                          */
1305      /*             execute set call with first two entries.                 */
1306      /*                (error if list has less than two entries)             */
1307      /*    otherwise: error                                                  */
1308      /*                                                                      */
1309      /* parameters:                                                          */
1310      /*   distr     ... pointer to distribution object                       */
1311      /*   key       ... name of parameter to be set                          */
1312      /*   type_args ... contains types of arguments. Possible values:        */
1313      /*                   't'   for single token                             */
1314      /*                   'L'   for a list                                   */
1315      /*   args      ... array of pointers to argument strings                */
1316      /*   set       ... pointer to UNU.RAN function for set call             */
1317      /*                                                                      */
1318      /* return:                                                              */
1319      /*   return code from set call, i.e.                                    */
1320      /*      UNUR_SUCCESS ... on success                                     */
1321      /*      error code   ... on error                                       */
1322      /*----------------------------------------------------------------------*/
1323 {
1324   double *darray = NULL;
1325   double darg[2];
1326   int result;
1327 
1328   /* either exactly two arguments are given */
1329   if ( !strcmp(type_args, "tt") ) {
1330     darg[0] = _unur_atod( args[0] );
1331     darg[1] = _unur_atod( args[1] );
1332 
1333 #ifdef UNUR_ENABLE_LOGGING
1334     /* write info into LOG file */
1335     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1336       _unur_str_debug_set(2,key,"dd",darg[0],darg[1]);
1337 #endif
1338 
1339     return set( distr,darg[0],darg[1] );
1340   }
1341 
1342   /* or one list with 2 entries is given */
1343   else if ( !strcmp(type_args, "L") ) {
1344     if ( _unur_parse_dlist( args[0], &darray ) < 2 ) {
1345       _unur_error_args(key);
1346       free (darray);
1347 #ifdef UNUR_ENABLE_LOGGING
1348       /* write info into LOG file */
1349       if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1350 	_unur_str_debug_set(2,key,"!");
1351 #endif
1352       return UNUR_ERR_STR_INVALID;
1353     }
1354     result = set( distr,darray[0],darray[1] );
1355 
1356 #ifdef UNUR_ENABLE_LOGGING
1357     /* write info into LOG file */
1358     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1359       _unur_str_debug_set(2,key,"dd",darray[0],darray[1] );
1360 #endif
1361 
1362     free (darray);
1363     return result;
1364   }
1365 
1366   else {
1367     _unur_error_args(key);
1368 #ifdef UNUR_ENABLE_LOGGING
1369     /* write info into LOG file */
1370     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1371       _unur_str_debug_set(2,key,"!");
1372 #endif
1373     return UNUR_ERR_STR_INVALID;
1374   }
1375 
1376 } /* end of _unur_str_distr_set_dd() */
1377 
1378 /*---------------------------------------------------------------------------*/
1379 
1380 int
_unur_str_distr_set_Di(UNUR_DISTR * distr,const char * key,char * type_args,char ** args,distr_set_Di set)1381 _unur_str_distr_set_Di (UNUR_DISTR *distr, const char *key, char *type_args, char **args, distr_set_Di set)
1382      /*----------------------------------------------------------------------*/
1383      /* Set parameter in given distribution object.                          */
1384      /* The list of arguments and their types are given as string.           */
1385      /*                                                                      */
1386      /* type: "Di"   (array of doubles, int)                                 */
1387      /*                                                                      */
1388      /* input: "Lt"  (list & single token)                                   */
1389      /*        "L"   (exactly one list)                                      */
1390      /*                                                                      */
1391      /* action:                                                              */
1392      /*    if "L":  convert list to array of doubles.                        */
1393      /*             execute set with size if array as second argument.       */
1394      /*    if "Lt": convert list to array of doubles.                        */
1395      /*             convert second token to int.                             */
1396      /*             set int to min of int and size of array.                 */
1397      /*             execute set call with int and array.                     */
1398      /*    otherwise: error                                                  */
1399      /*                                                                      */
1400      /* parameters:                                                          */
1401      /*   distr     ... pointer to distribution object                       */
1402      /*   key       ... name of parameter to be set                          */
1403      /*   type_args ... contains types of arguments. Possible values:        */
1404      /*                   't'   for single token                             */
1405      /*                   'L'   for a list                                   */
1406      /*   args      ... array of pointers to argument strings                */
1407      /*   set       ... pointer to UNU.RAN function for set call             */
1408      /*                                                                      */
1409      /* return:                                                              */
1410      /*   return code from set call, i.e.                                    */
1411      /*      UNUR_SUCCESS ... on success                                     */
1412      /*      error code   ... on error                                       */
1413      /*----------------------------------------------------------------------*/
1414 {
1415   int result;
1416   int t_size;
1417   int size = -1;
1418   double *darray = NULL;
1419 
1420   /* either an integer and a list are given */
1421   if ( !strcmp(type_args, "Lt") ) {
1422     t_size = _unur_atoi( args[1] );
1423     size = _unur_parse_dlist( args[0], &darray );
1424     if (size > t_size)
1425       size = t_size;
1426   }
1427 
1428   /* or only a list is given */
1429   else if ( !strcmp(type_args, "L") ) {
1430     size = _unur_parse_dlist( args[0], &darray );
1431   }
1432 
1433   /* or there is a syntax error */
1434   if ( !(size>0) ) {
1435     _unur_error_args(key);
1436 #ifdef UNUR_ENABLE_LOGGING
1437     /* write info into LOG file */
1438     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1439       _unur_str_debug_set(2,key,"!");
1440 #endif
1441     result = UNUR_ERR_STR_INVALID;
1442   }
1443 
1444   else {
1445     /* execute set command */
1446     result = set( distr,darray,size );
1447 #ifdef UNUR_ENABLE_LOGGING
1448     /* write info into LOG file */
1449     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1450       _unur_str_debug_set(2,key,"Di",darray,size,size);
1451 #endif
1452   }
1453 
1454   if (darray) free (darray);
1455 
1456   return result;
1457 
1458 } /* end of _unur_str_distr_set_Di() */
1459 
1460 /*---------------------------------------------------------------------------*/
1461 
1462 int
_unur_str_distr_set_C(UNUR_DISTR * distr,const char * key,char * type_args,char ** args,distr_set_C set)1463 _unur_str_distr_set_C (UNUR_DISTR *distr, const char *key, char *type_args, char **args, distr_set_C set)
1464      /*----------------------------------------------------------------------*/
1465      /* Set parameter in given distribution object.                          */
1466      /* The list of arguments and their types are given as string.           */
1467      /*                                                                      */
1468      /* type: "C"   (string = array of char)                                 */
1469      /*                                                                      */
1470      /* input: "s"  (exactly one string)                                     */
1471      /*                                                                      */
1472      /* action:                                                              */
1473      /*    execute set call.                                                 */
1474      /*    error if input != "s"                                             */
1475      /*                                                                      */
1476      /* parameters:                                                          */
1477      /*   distr     ... pointer to distribution object                       */
1478      /*   key       ... name of parameter to be set                          */
1479      /*   type_args ... contains types of arguments. Possible values:        */
1480      /*                   's'   for single string                            */
1481      /*   args      ... array of pointers to argument strings                */
1482      /*   set       ... pointer to UNU.RAN function for set call             */
1483      /*                                                                      */
1484      /* return:                                                              */
1485      /*   return code from set call, i.e.                                    */
1486      /*      UNUR_SUCCESS ... on success                                     */
1487      /*      error code   ... on error                                       */
1488      /*----------------------------------------------------------------------*/
1489 {
1490   char *string;
1491 
1492   if ( strcmp(type_args, "s") ) {
1493     _unur_error_args(key);
1494 #ifdef UNUR_ENABLE_LOGGING
1495     /* write info into LOG file */
1496     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1497       _unur_str_debug_set(2,key,"!");
1498 #endif
1499     return UNUR_ERR_STR_INVALID;
1500   }
1501 
1502   /* get string */
1503   string = args[0];
1504 
1505 #ifdef UNUR_ENABLE_LOGGING
1506   /* write info into LOG file */
1507   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1508     _unur_str_debug_set(2,key,"C",string);
1509 #endif
1510 
1511   return set(distr,string);
1512 
1513 } /* end of _unur_str_distr_set_C() */
1514 
1515 /*---------------------------------------------------------------------------*/
1516 
1517 /*****************************************************************************/
1518 /**  Methods                                                                **/
1519 /*****************************************************************************/
1520 
1521 /*---------------------------------------------------------------------------*/
1522 
1523 struct unur_par *
_unur_str_par(char * str_method,const UNUR_DISTR * distr,struct unur_slist * mlist)1524 _unur_str_par( char *str_method, const UNUR_DISTR *distr, struct unur_slist *mlist )
1525      /*----------------------------------------------------------------------*/
1526      /* get parameter object for distribution and method                     */
1527      /*                                                                      */
1528      /* parameters:                                                          */
1529      /*   str_method ... string that contains method description             */
1530      /*   distr      ... pointer to distribution object                      */
1531      /*   mlist      ... list of allocated memory blocks                     */
1532      /*                                                                      */
1533      /* return:                                                              */
1534      /*   default parameters (pointer to structure)                          */
1535      /*                                                                      */
1536      /* error:                                                               */
1537      /*   return NULL                                                        */
1538      /*----------------------------------------------------------------------*/
1539 {
1540   struct unur_par *par = NULL;     /* pointer to parameter object */
1541 
1542   char *token;             /* pointer to token in string */
1543   char *next;              /* pointer to next token in string */
1544   char *key, *value;       /* the key and its value */
1545 
1546   /* tokenize the string using ';' as separator and handle the tokens */
1547   for ( token = next = str_method;
1548 	next != NULL && *token != '\0';
1549 	token = next ) {
1550 
1551     /* find end of token (i.e. the pointer to next token) */
1552     next = strchr(token,';');
1553     if (next != NULL) {
1554       /* next separator found */
1555       *next = '\0';     /* terminate token string    */
1556       next++;           /* set pointer to next token */
1557     }
1558 
1559     /* token points to a key */
1560     key = token;
1561 
1562     /* get the value from the pair key=value and terminate key string */
1563     value = strchr(key, '=');
1564     if (value != NULL) {
1565       *value = '\0';    /* terminate key string        */
1566       value++;          /* set pointer to value string */
1567     }
1568 
1569     /* the first key is treated differently: get new parameter object */
1570     if (key == str_method) {
1571       /* the keyword "method" is optional */
1572       if (value == NULL) {
1573 	/* no "method" keyword given, so the key points to the value */
1574 	value = key;
1575       }
1576       else {
1577 	if (*key != 'm') {
1578 	  _unur_error(GENTYPE,UNUR_ERR_STR_SYNTAX,"key for method does not start with 'm'");
1579 	  return NULL;
1580 	}
1581       }
1582 
1583       /* get new parameter object */
1584       par = _unur_str_par_new(value,distr);
1585       if (par == NULL) {
1586 	/* error */
1587 	_unur_error(GENTYPE,UNUR_ERR_STR,"setting method failed");
1588 	return NULL;
1589       }
1590     }
1591 
1592     /* set parameters for method */
1593     else {
1594       if ( !_unur_str_par_set(par, key, value, mlist) ) {
1595 	; /* error: */
1596       }
1597     }
1598   }
1599 
1600   /* end */
1601   return par;
1602 
1603 } /* end of _unur_str_par() */
1604 
1605 /*---------------------------------------------------------------------------*/
1606 
1607 int
_unur_str_par_set_void(UNUR_PAR * par,const char * key,char * type_args,char ** args ATTRIBUTE__UNUSED,par_set_void set)1608 _unur_str_par_set_void (UNUR_PAR *par, const char *key,
1609 			char *type_args, char **args ATTRIBUTE__UNUSED, par_set_void set)
1610      /*----------------------------------------------------------------------*/
1611      /* Set parameter in given parameter object.                             */
1612      /* The list of arguments and their types are given as string.           */
1613      /*                                                                      */
1614      /* type: void   (no arguments required)                                 */
1615      /*                                                                      */
1616      /* input: void  (no arguments should be given)                          */
1617      /*                                                                      */
1618      /* action:                                                              */
1619      /*    execute set call.                                                 */
1620      /*    warning if any argument is given.                                 */
1621      /*                                                                      */
1622      /* parameters:                                                          */
1623      /*   par       ... pointer to parameter object                          */
1624      /*   key       ... name of parameter to be set                          */
1625      /*   type_args ... contains types of arguments. Possible values:        */
1626      /*                   't'   for single token                             */
1627      /*                   'L'   for a list                                   */
1628      /*   args      ... array of pointers to argument strings                */
1629      /*   set       ... pointer to UNU.RAN function for set call             */
1630      /*                                                                      */
1631      /* return:                                                              */
1632      /*   return code from set call, i.e.                                    */
1633      /*      UNUR_SUCCESS ... on success                                     */
1634      /*      error code   ... on error                                       */
1635      /*----------------------------------------------------------------------*/
1636 {
1637 
1638 #ifdef UNUR_ENABLE_LOGGING
1639   /* write info into LOG file */
1640   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1641     _unur_str_debug_set(2,key,"v");
1642 #endif
1643 
1644   if (*type_args != '\0')
1645     _unur_error_args(key);
1646 
1647   return set(par);
1648 
1649 } /* end of _unur_str_par_set_void() */
1650 
1651 /*---------------------------------------------------------------------------*/
1652 
1653 int
_unur_str_par_set_i(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_i set)1654 _unur_str_par_set_i (UNUR_PAR *par, const char *key, char *type_args, char **args, par_set_i set)
1655      /*----------------------------------------------------------------------*/
1656      /* Set parameter in given parameter object.                             */
1657      /* The list of arguments and their types are given as string.           */
1658      /*                                                                      */
1659      /* type: "i"   (int)                                                    */
1660      /*                                                                      */
1661      /* input: "t"   (exactly one single token)                              */
1662      /*         void (no argument given)                                     */
1663      /*                                                                      */
1664      /* action:                                                              */
1665      /*    convert token to int.                                             */
1666      /*      (if no argument is given, use 1.)                               */
1667      /*    execute set call.                                                 */
1668      /*    error if input != "t"                                             */
1669      /*                                                                      */
1670      /* parameters:                                                          */
1671      /*   par       ... pointer to parameter object                          */
1672      /*   key       ... name of parameter to be set                          */
1673      /*   type_args ... contains types of arguments. Possible values:        */
1674      /*                   't'   for single token                             */
1675      /*                   'L'   for a list                                   */
1676      /*   args      ... array of pointers to argument strings                */
1677      /*   set       ... pointer to UNU.RAN function for set call             */
1678      /*                                                                      */
1679      /* return:                                                              */
1680      /*   return code from set call, i.e.                                    */
1681      /*      UNUR_SUCCESS ... on success                                     */
1682      /*      error code   ... on error                                       */
1683      /*----------------------------------------------------------------------*/
1684 {
1685   int iarg;
1686 
1687   if ( !strcmp(type_args, "t") ) {
1688     iarg = _unur_atoi( args[0] );
1689   }
1690   else if ( strlen(type_args) == 0 ) {
1691     iarg = 1;
1692   }
1693   else {
1694     _unur_error_args(key);
1695 #ifdef UNUR_ENABLE_LOGGING
1696     /* write info into LOG file */
1697     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1698       _unur_str_debug_set(2,key,"!");
1699 #endif
1700     return UNUR_ERR_STR_INVALID;
1701   }
1702 
1703 #ifdef UNUR_ENABLE_LOGGING
1704   /* write info into LOG file */
1705   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1706     _unur_str_debug_set(2,key,"i",iarg);
1707 #endif
1708 
1709   return set(par,iarg);
1710 
1711 } /* end of _unur_str_par_set_i() */
1712 
1713 /*---------------------------------------------------------------------------*/
1714 
1715 int
_unur_str_par_set_ii(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_ii set)1716 _unur_str_par_set_ii (UNUR_PAR *par, const char *key, char *type_args, char **args, par_set_ii set)
1717      /*----------------------------------------------------------------------*/
1718      /* Set parameter in given parameter object.                             */
1719      /* The list of arguments and their types are given as string.           */
1720      /*                                                                      */
1721      /* type: "ii"   (int,int)                                               */
1722      /*                                                                      */
1723      /* input: "tt"  (exactly two single tokens)                             */
1724      /*        "L"   (exactly one list)                                      */
1725      /*                                                                      */
1726      /* action:                                                              */
1727      /*    if "tt": convert both to int.                                     */
1728      /*             execute set call.                                        */
1729      /*    if "L":  convert list entries to int.                             */
1730      /*             execute set call with first two entries.                 */
1731      /*                (error if list has less than two entries)             */
1732      /*    otherwise: error                                                  */
1733      /*                                                                      */
1734      /* parameters:                                                          */
1735      /*   par       ... pointer to parameter object                          */
1736      /*   key       ... name of parameter to be set                          */
1737      /*   type_args ... contains types of arguments. Possible values:        */
1738      /*                   't'   for single token                             */
1739      /*                   'L'   for a list                                   */
1740      /*   args      ... array of pointers to argument strings                */
1741      /*   set       ... pointer to UNU.RAN function for set call             */
1742      /*                                                                      */
1743      /* return:                                                              */
1744      /*   return code from set call, i.e.                                    */
1745      /*      UNUR_SUCCESS ... on success                                     */
1746      /*      error code   ... on error                                       */
1747      /*----------------------------------------------------------------------*/
1748 {
1749   int *iarray = NULL;
1750   int iarg[2];
1751   int result;
1752 
1753   /* either exactly two arguments are given */
1754   if ( !strcmp(type_args, "tt") ) {
1755     iarg[0] = _unur_atoi( args[0] );
1756     iarg[1] = _unur_atoi( args[1] );
1757 
1758 #ifdef UNUR_ENABLE_LOGGING
1759     /* write info into LOG file */
1760     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1761       _unur_str_debug_set(2,key,"ii",iarg[0],iarg[1]);
1762 #endif
1763 
1764     return set( par,iarg[0],iarg[1] );
1765   }
1766 
1767   /* or one list with 2 entries is given */
1768   else if ( !strcmp(type_args, "L") ) {
1769     if ( _unur_parse_ilist( args[0], &iarray ) < 2 ) {
1770       _unur_error_args(key);
1771       free (iarray);
1772 #ifdef UNUR_ENABLE_LOGGING
1773       /* write info into LOG file */
1774       if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1775 	_unur_str_debug_set(2,key,"!");
1776 #endif
1777       return UNUR_ERR_STR_INVALID;
1778     }
1779     result = set( par,iarray[0],iarray[1] );
1780 
1781 #ifdef UNUR_ENABLE_LOGGING
1782     /* write info into LOG file */
1783     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1784       _unur_str_debug_set(2,key,"ii",iarray[0],iarray[1] );
1785 #endif
1786 
1787     free (iarray);
1788     return result;
1789   }
1790 
1791   else {
1792     _unur_error_args(key);
1793 #ifdef UNUR_ENABLE_LOGGING
1794     /* write info into LOG file */
1795     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1796       _unur_str_debug_set(2,key,"!");
1797 #endif
1798     return UNUR_ERR_STR_INVALID;
1799   }
1800 
1801 } /* end of _unur_str_par_set_ii() */
1802 
1803 /*---------------------------------------------------------------------------*/
1804 
1805 int
_unur_str_par_set_u(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_u set)1806 _unur_str_par_set_u (UNUR_PAR *par, const char *key, char *type_args, char **args, par_set_u set)
1807      /*----------------------------------------------------------------------*/
1808      /* Set parameter in given parameter object.                             */
1809      /* The list of arguments and their types are given as string.           */
1810      /*                                                                      */
1811      /* type: "u"   (unsigned)                                               */
1812      /*                                                                      */
1813      /* input: "t"  (exactly one single token)                               */
1814      /*                                                                      */
1815      /* action:                                                              */
1816      /*    convert token to unsigned.                                        */
1817      /*    execute set call.                                                 */
1818      /*    error if input != "t"                                             */
1819      /*                                                                      */
1820      /* parameters:                                                          */
1821      /*   par       ... pointer to parameter object                          */
1822      /*   key       ... name of parameter to be set                          */
1823      /*   type_args ... contains types of arguments. Possible values:        */
1824      /*                   't'   for single token                             */
1825      /*                   'L'   for a list                                   */
1826      /*   args      ... array of pointers to argument strings                */
1827      /*   set       ... pointer to UNU.RAN function for set call             */
1828      /*                                                                      */
1829      /* return:                                                              */
1830      /*   return code from set call, i.e.                                    */
1831      /*      UNUR_SUCCESS ... on success                                     */
1832      /*      error code   ... on error                                       */
1833      /*----------------------------------------------------------------------*/
1834 {
1835   unsigned uarg;
1836 
1837   if ( strcmp(type_args, "t") ) {
1838     _unur_error_args(key);
1839 #ifdef UNUR_ENABLE_LOGGING
1840     /* write info into LOG file */
1841     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1842       _unur_str_debug_set(2,key,"!");
1843 #endif
1844     return UNUR_ERR_STR_INVALID;
1845   }
1846 
1847   uarg = _unur_atou( args[0] );
1848 
1849 #ifdef UNUR_ENABLE_LOGGING
1850   /* write info into LOG file */
1851   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1852     _unur_str_debug_set(2,key,"u",uarg);
1853 #endif
1854 
1855   return set(par,uarg);
1856 
1857 } /* end of _unur_str_par_set_u() */
1858 
1859 /*---------------------------------------------------------------------------*/
1860 
1861 int
_unur_str_par_set_d(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_d set)1862 _unur_str_par_set_d (UNUR_PAR *par, const char *key, char *type_args, char **args, par_set_d set)
1863      /*----------------------------------------------------------------------*/
1864      /* Set parameter in given parameter object.                             */
1865      /* The list of arguments and their types are given as string.           */
1866      /*                                                                      */
1867      /* type: "d"   (double)                                                 */
1868      /*                                                                      */
1869      /* input: "t"  (exactly one single token)                               */
1870      /*                                                                      */
1871      /* action:                                                              */
1872      /*    convert token to double.                                          */
1873      /*    execute set call.                                                 */
1874      /*    error if input != "t"                                             */
1875      /*                                                                      */
1876      /* parameters:                                                          */
1877      /*   par       ... pointer to parameter object                          */
1878      /*   key       ... name of parameter to be set                          */
1879      /*   type_args ... contains types of arguments. Possible values:        */
1880      /*                   't'   for single token                             */
1881      /*                   'L'   for a list                                   */
1882      /*   args      ... array of pointers to argument strings                */
1883      /*   set       ... pointer to UNU.RAN function for set call             */
1884      /*                                                                      */
1885      /* return:                                                              */
1886      /*   return code from set call, i.e.                                    */
1887      /*      UNUR_SUCCESS ... on success                                     */
1888      /*      error code   ... on error                                       */
1889      /*----------------------------------------------------------------------*/
1890 {
1891   double darg;
1892 
1893   if ( strcmp(type_args, "t") ) {
1894     _unur_error_args(key);
1895 #ifdef UNUR_ENABLE_LOGGING
1896     /* write info into LOG file */
1897     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1898       _unur_str_debug_set(2,key,"!");
1899 #endif
1900     return UNUR_ERR_STR_INVALID;
1901   }
1902 
1903   darg = _unur_atod( args[0] );
1904 
1905 #ifdef UNUR_ENABLE_LOGGING
1906   /* write info into LOG file */
1907   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1908     _unur_str_debug_set(2,key,"d",darg);
1909 #endif
1910 
1911   return set(par,darg);
1912 
1913 } /* end of _unur_str_par_set_d() */
1914 
1915 /*---------------------------------------------------------------------------*/
1916 
1917 int
_unur_str_par_set_dd(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_dd set)1918 _unur_str_par_set_dd (UNUR_PAR *par, const char *key, char *type_args, char **args, par_set_dd set)
1919      /*----------------------------------------------------------------------*/
1920      /* Set parameter in given parameter object.                             */
1921      /* The list of arguments and their types are given as string.           */
1922      /*                                                                      */
1923      /* type: "dd"   (double,double)                                         */
1924      /*                                                                      */
1925      /* input: "tt"  (exactly two single tokens)                             */
1926      /*        "L"   (exactly one list)                                      */
1927      /*                                                                      */
1928      /* action:                                                              */
1929      /*    if "tt": convert both to double.                                  */
1930      /*             execute set call.                                        */
1931      /*    if "L":  convert list entries to double.                          */
1932      /*             execute set call with first two entries.                 */
1933      /*                (error if list has less than two entries)             */
1934      /*    otherwise: error                                                  */
1935      /*                                                                      */
1936      /* parameters:                                                          */
1937      /*   par       ... pointer to parameter object                          */
1938      /*   key       ... name of parameter to be set                          */
1939      /*   type_args ... contains types of arguments. Possible values:        */
1940      /*                   't'   for single token                             */
1941      /*                   'L'   for a list                                   */
1942      /*   args      ... array of pointers to argument strings                */
1943      /*   set       ... pointer to UNU.RAN function for set call             */
1944      /*                                                                      */
1945      /* return:                                                              */
1946      /*   return code from set call, i.e.                                    */
1947      /*      UNUR_SUCCESS ... on success                                     */
1948      /*      error code   ... on error                                       */
1949      /*----------------------------------------------------------------------*/
1950 {
1951   double *darray = NULL;
1952   double darg[2];
1953   int result;
1954 
1955   /* either exactly two arguments are given */
1956   if ( !strcmp(type_args, "tt") ) {
1957     darg[0] = _unur_atod( args[0] );
1958     darg[1] = _unur_atod( args[1] );
1959 
1960 #ifdef UNUR_ENABLE_LOGGING
1961     /* write info into LOG file */
1962     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1963       _unur_str_debug_set(2,key,"dd",darg[0],darg[1]);
1964 #endif
1965 
1966     return set( par,darg[0],darg[1] );
1967   }
1968 
1969   /* or one list with 2 entries is given */
1970   else if ( !strcmp(type_args, "L") ) {
1971     if ( _unur_parse_dlist( args[0], &darray ) < 2 ) {
1972       _unur_error_args(key);
1973       free (darray);
1974 #ifdef UNUR_ENABLE_LOGGING
1975       /* write info into LOG file */
1976       if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1977 	_unur_str_debug_set(2,key,"!");
1978 #endif
1979       return UNUR_ERR_STR_INVALID;
1980     }
1981     result = set( par,darray[0],darray[1] );
1982 
1983 #ifdef UNUR_ENABLE_LOGGING
1984     /* write info into LOG file */
1985     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1986       _unur_str_debug_set(2,key,"dd",darray[0],darray[1] );
1987 #endif
1988 
1989     free (darray);
1990     return result;
1991   }
1992 
1993   else {
1994     _unur_error_args(key);
1995 #ifdef UNUR_ENABLE_LOGGING
1996     /* write info into LOG file */
1997     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
1998       _unur_str_debug_set(2,key,"!");
1999 #endif
2000     return UNUR_ERR_STR_INVALID;
2001   }
2002 
2003 } /* end of _unur_str_par_set_dd() */
2004 
2005 /*---------------------------------------------------------------------------*/
2006 
2007 int
_unur_str_par_set_iD(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_iD set,struct unur_slist * mlist)2008 _unur_str_par_set_iD (UNUR_PAR *par, const char *key, char *type_args, char **args,
2009 		      par_set_iD set, struct unur_slist *mlist )
2010      /*----------------------------------------------------------------------*/
2011      /* Set parameter in given parameter object.                             */
2012      /* The list of arguments and their types are given as string.           */
2013      /*                                                                      */
2014      /* type: "iD"   (int, array of doubles)                                 */
2015      /*                                                                      */
2016      /* input: "tL"  (single token & list)                                   */
2017      /*        "L"   (exactly one list)                                      */
2018      /*        "t"   (single token)                                          */
2019      /*                                                                      */
2020      /* action:                                                              */
2021      /*    if "L":  convert list to array of doubles.                        */
2022      /*             execute set with size if array as first argument.        */
2023      /*    if "t":  convert token to int.                                    */
2024      /*             execute set call with NULL as its second argument.       */
2025      /*    if "tL": convert list to array of doubles.                        */
2026      /*             convert first token to int.                              */
2027      /*             set int to min of int and size of array.                 */
2028      /*             execute set call with int and array.                     */
2029      /*    otherwise: error                                                  */
2030      /*                                                                      */
2031      /* parameters:                                                          */
2032      /*   par       ... pointer to parameter object                          */
2033      /*   key       ... name of parameter to be set                          */
2034      /*   type_args ... contains types of arguments. Possible values:        */
2035      /*                   't'   for single token                             */
2036      /*                   'L'   for a list                                   */
2037      /*   args      ... array of pointers to argument strings                */
2038      /*   set       ... pointer to UNU.RAN function for set call             */
2039      /*   mlist     ... list of allocated memory blocks                      */
2040      /*                                                                      */
2041      /* return:                                                              */
2042      /*   return code from set call, i.e.                                    */
2043      /*      UNUR_SUCCESS ... on success                                     */
2044      /*      error code   ... on error                                       */
2045      /*----------------------------------------------------------------------*/
2046 {
2047   int result;
2048   int t_size;
2049   int size = -1;
2050   double *darray = NULL;
2051 
2052   /* either an integer and a list are given */
2053   if ( !strcmp(type_args, "tL") ) {
2054     t_size = _unur_atoi( args[0] );
2055     size = _unur_parse_dlist( args[1], &darray );
2056     if (size > 0) {
2057       if (size > t_size)  size = t_size;
2058     }
2059     else {
2060       /* empty list */
2061       size = t_size;
2062       if (darray) free (darray);
2063       darray = NULL;
2064     }
2065   }
2066 
2067   /* or only an integer is given */
2068   else if ( !strcmp(type_args, "t") ) {
2069     size = _unur_atoi( args[0] );
2070     darray = NULL;
2071   }
2072 
2073   /* or only a list is given */
2074   else if ( !strcmp(type_args, "L") ) {
2075     size = _unur_parse_dlist( args[0], &darray );
2076   }
2077 
2078   /* or there is a syntax error */
2079   if ( !(size>0) ) {
2080     _unur_error_args(key);
2081 #ifdef UNUR_ENABLE_LOGGING
2082     /* write info into LOG file */
2083     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
2084       _unur_str_debug_set(2,key,"!");
2085 #endif
2086     result = UNUR_ERR_STR_INVALID;
2087   }
2088 
2089   else {
2090     /* execute set command */
2091     result = set( par,size,darray );
2092 #ifdef UNUR_ENABLE_LOGGING
2093     /* write info into LOG file */
2094     if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
2095       _unur_str_debug_set(2,key,"iD",size,darray,size);
2096 #endif
2097   }
2098 
2099   /* store pointer to allocated array */
2100   if (darray)
2101     _unur_slist_append( mlist, darray );
2102 
2103   return result;
2104 
2105 } /* end of _unur_str_par_set_iD() */
2106 
2107 /*---------------------------------------------------------------------------*/
2108 
2109 int
_unur_str_par_set_Di(UNUR_PAR * par,const char * key,char * type_args,char ** args,par_set_Di set,struct unur_slist * mlist)2110 _unur_str_par_set_Di (UNUR_PAR *par, const char *key, char *type_args, char **args,
2111 		      par_set_Di set, struct unur_slist *mlist )
2112      /*----------------------------------------------------------------------*/
2113      /* Set parameter in given parameter object.                             */
2114      /* The list of arguments and their types are given as string.           */
2115      /*                                                                      */
2116      /* type: "Di"   (array of doubles, int)                                 */
2117      /*                                                                      */
2118      /* input: "Lt"  (list & single token & list)                            */
2119      /*                                                                      */
2120      /* action:                                                              */
2121      /*    convert list to array of doubles.                                 */
2122      /*    convert token to int.                                             */
2123      /*    execute set call with array and int.                              */
2124      /*                                                                      */
2125      /* parameters:                                                          */
2126      /*   par       ... pointer to parameter object                          */
2127      /*   key       ... name of parameter to be set                          */
2128      /*   type_args ... contains types of arguments. Possible values:        */
2129      /*                   't'   for single token                             */
2130      /*                   'L'   for a list                                   */
2131      /*   args      ... array of pointers to argument strings                */
2132      /*   set       ... pointer to UNU.RAN function for set call             */
2133      /*   mlist     ... list of allocated memory blocks                      */
2134      /*                                                                      */
2135      /* return:                                                              */
2136      /*   return code from set call, i.e.                                    */
2137      /*      UNUR_SUCCESS ... on success                                     */
2138      /*      error code   ... on error                                       */
2139      /*----------------------------------------------------------------------*/
2140 {
2141   int result;
2142   int t_size;
2143   int size;
2144   double *darray = NULL;
2145 
2146   if ( !strcmp(type_args, "Lt") ) {
2147     t_size = _unur_atoi( args[1] );
2148     size = _unur_parse_dlist( args[0], &darray );
2149     if (size > 0) {
2150       result = set( par,darray,t_size );
2151 #ifdef UNUR_ENABLE_LOGGING
2152       /* write info into LOG file */
2153       if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
2154 	_unur_str_debug_set(2,key,"Di",darray,size,size);
2155 #endif
2156 
2157       /* store pointer to allocated array */
2158       if (darray)
2159 	_unur_slist_append( mlist, darray );
2160 
2161       return result;
2162     }
2163   }
2164 
2165   /* there is a syntax error */
2166   _unur_error_args(key);
2167 #ifdef UNUR_ENABLE_LOGGING
2168   /* write info into LOG file */
2169   if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
2170     _unur_str_debug_set(2,key,"!");
2171 #endif
2172 
2173   return UNUR_ERR_STR_INVALID;
2174 } /* end of _unur_str_par_set_Di() */
2175 
2176 /*---------------------------------------------------------------------------*/
2177 
2178 /*****************************************************************************/
2179 /**  Uniform RNG                                                            **/
2180 /*****************************************************************************/
2181 
2182 UNUR_URNG *
_unur_str2urng(char * str_urng ATTRIBUTE__UNUSED)2183 _unur_str2urng( char *str_urng ATTRIBUTE__UNUSED)
2184      /*----------------------------------------------------------------------*/
2185      /* get uniform RNG                                                      */
2186      /*                                                                      */
2187      /* parameters:                                                          */
2188      /*   str_urng ... string that contains description of uniform RNG       */
2189      /*                                                                      */
2190      /* return:                                                              */
2191      /*   pointer to uniform RNG                                             */
2192      /*                                                                      */
2193      /* The string must not contain any other keywords than "urng".          */
2194      /* the argument is passed unchanged to the PRNG package.                */
2195      /*                                                                      */
2196      /* error:                                                               */
2197      /*   return NULL                                                        */
2198      /*----------------------------------------------------------------------*/
2199 {
2200 /*---------------------------------------------------------------------------*/
2201 #if defined(UNUR_URNG_UNURAN) && defined(UNURAN_HAS_PRNG)
2202 /*---------------------------------------------------------------------------*/
2203 
2204   UNUR_URNG *urng = NULL;
2205 
2206   char *token;             /* pointer to token in string */
2207   char *next;              /* pointer to next token in string */
2208   char *key, *value;       /* the key and its value */
2209 
2210   /* tokenize the string using ';' as separator and handle the tokens */
2211   for ( token = next = str_urng;
2212 	next != NULL && *token != '\0';
2213 	token = next ) {
2214 
2215     /* find end of token (i.e. the pointer to next token) */
2216     next = strchr(token,';');
2217     if (next != NULL) {
2218       /* next separator found */
2219       *next = '\0';     /* terminate token string    */
2220       next++;           /* set pointer to next token */
2221     }
2222 
2223     /* token points to a key */
2224     key = token;
2225 
2226     /* get the value from the pair key=value and terminate key string */
2227     value = strchr(key, '=');
2228     if (value != NULL) {
2229       *value = '\0';    /* terminate key string        */
2230       value++;          /* set pointer to value string */
2231     }
2232 
2233     /* get (default) parameter object for method */
2234     if ( !strcmp( key, "urng") ) {
2235       if (key == str_urng) {
2236 	/* "urng" must be the first key.                                  */
2237 	/* (on the other hand, the first keyword always must be "urng"    */
2238 	/* since otherwise we had not called this subroutine.             */
2239 	/* hence, we only check, whether the keyword "urng" is unique.)   */
2240 	urng = unur_urng_prng_new(value);
2241 	if (urng == NULL) {
2242 	  /* error */
2243 	  _unur_error(GENTYPE,UNUR_ERR_STR,"setting URNG failed");
2244 	  return NULL;
2245 	}
2246 	else {
2247 #ifdef UNUR_ENABLE_LOGGING
2248 	  /* write info into LOG file */
2249 	  if (_unur_default_debugflag & UNUR_DEBUG_SETUP)
2250 	    _unur_str_debug_string(1,"urng",value);
2251 #endif
2252 	  ;
2253 	}
2254       }
2255       else {
2256 	if (urng) unur_urng_free (urng);
2257 	_unur_error(GENTYPE,UNUR_ERR_STR_SYNTAX,"urng must be first key");
2258 	return NULL;
2259       }
2260     }
2261 
2262     /* there are no other parameters */
2263     else {
2264       /* error: unknown parameter */
2265       if (urng) unur_urng_free (urng);
2266       _unur_error_unknown(key,"parameter for uniform RNG");
2267       return NULL;
2268     }
2269   }
2270 
2271   /*return pointer to uniform RNG */
2272   return urng;
2273 
2274 /*---------------------------------------------------------------------------*/
2275 #else
2276 /*---------------------------------------------------------------------------*/
2277 
2278   _unur_error(GENTYPE,UNUR_ERR_STR,"setting URNG requires PRNG library enabled");
2279   return NULL;
2280 
2281 /*---------------------------------------------------------------------------*/
2282 #endif   /*  end defined(UNUR_URNG_UNURAN) && defined(UNURAN_HAS_PRNG) */
2283 /*---------------------------------------------------------------------------*/
2284 } /* end of _unur_str2urng() */
2285 
2286 /*---------------------------------------------------------------------------*/
2287 
2288 /*****************************************************************************/
2289 /**  Misc                                                                   **/
2290 /*****************************************************************************/
2291 
2292 /*---------------------------------------------------------------------------*/
2293 
2294 int
_unur_str_set_args(char * value,char * type_args,char ** args,int max_args)2295 _unur_str_set_args( char *value, char *type_args, char **args, int max_args )
2296      /*----------------------------------------------------------------------*/
2297      /* parse argument string for set call                                   */
2298      /*                                                                      */
2299      /* parameters:                                                          */
2300      /*   value     ... string that contains list of arguments for set call  */
2301      /*   type_args ... array containing info about arguments                */
2302      /*   args      ... pointers to argument strings                         */
2303      /*   max_args  ... maximal number of argments                           */
2304      /*                                                                      */
2305      /* tokenize string with arguments and store the pointer to each         */
2306      /* argument in 'args'. Evaluate the type of each argument and store it  */
2307      /* in 'type_args'. We have the following types:                         */
2308      /*    't' ... a single token, or                                        */
2309      /*    'L' ... a list, indicated by (...)                                */
2310      /*                                                                      */
2311      /* return:                                                              */
2312      /*   number of parsed arguments                                         */
2313      /*                                                                      */
2314      /* error:                                                               */
2315      /*   return -1                                                           */
2316      /*----------------------------------------------------------------------*/
2317 {
2318   char *token;             /* pointer to token in string */
2319   char *next;              /* pointer to next token in string */
2320   int n_args;              /* number of arguments in set call */
2321 
2322   /* initialize pointers */
2323   n_args = 0;
2324   *type_args = '\0';
2325   *args = NULL;
2326 
2327   /* we have two types of arguments:
2328      't' ... a single token, or
2329      'L' ... a list, indicated by (...)
2330   */
2331 
2332   /* split value string into separate arguments */
2333   if (value && *value != '\0') {
2334     /* there is at least one argument */
2335 
2336     for ( token = next = value;
2337 	  next != NULL && *token != '\0' && n_args < max_args;
2338 	  token = next, n_args++ ) {
2339 
2340       /* get type of argument */
2341 
2342       if ( *token == '(' ) {
2343 	/* argument is a list */
2344 	type_args[n_args] = 'L';
2345 	/* skip to next character */
2346 	token++;
2347 	/* store pointer to argument */
2348 	args[n_args] = token;
2349 	/* find end of list using ')' as terminating character */
2350 	next = strchr(token,')');
2351 	if (next != NULL) {
2352 	  /* end of list found */
2353 	  *next = '\0';      /* terminate token string    */
2354 	  token = ++next;    /* set pointer to first character after ')' */
2355 	  /* first character after ')' must be ',' */
2356 	  if ( !(*token == ',' || *token == '\0') ) {
2357 	    _unur_error(GENTYPE,UNUR_ERR_STR_SYNTAX,") not followed by comma");
2358 	    return -1;
2359 	  }
2360 	}
2361 	else {
2362 	  /* no ')' found */
2363 	  token = NULL;
2364 	}
2365       }
2366 
2367       else if ( *token == '"' ) {
2368 	/* argument is a string */
2369 	type_args[n_args] = 's';
2370 	/* skip to next character */
2371 	token++;
2372 	/* store pointer to argument */
2373 	args[n_args] = token;
2374 
2375 	/* find end of string using '"' as terminating character */
2376 	next = strchr(token,'"');
2377 	if (next != NULL) {
2378 	  /* end of list found */
2379 	  *next = '\0';      /* terminate token string    */
2380 	  token = ++next;    /* set pointer to first character after ')' */
2381 	  /* first character after ')' must be ',' */
2382 	  if ( !(*token == ',' || *token == '\0') ) {
2383 	    _unur_error(GENTYPE,UNUR_ERR_STR_SYNTAX,"closing '\"' not followed by comma");
2384 	    return -1;
2385 	  }
2386 	}
2387 	else {
2388 	  /* no '"' found */
2389 	  token = NULL;
2390 	}
2391       }
2392 
2393       else {
2394 	/* argument is a sigle item */
2395 	type_args[n_args] = 't';
2396 	/* store pointer to argument */
2397 	args[n_args] = token;
2398       }
2399 
2400       /* find end of argument string using ',' as separator */
2401       if (token) {
2402 	next = strchr(token,',');
2403 	if (next != NULL) {
2404 	  /* next separator found */
2405 	  *next = '\0';     /* terminate token string    */
2406 	  next++;           /* set pointer to next token */
2407 	}
2408       }
2409       else {
2410 	next = NULL;
2411       }
2412     }
2413 
2414     /* terminate string */
2415     type_args[n_args] = '\0';
2416 
2417     /* If there are two many arguments, we simply assume a syntax error */
2418     /* (This case should not happen.)                                   */
2419     if (n_args >= max_args) {
2420       _unur_error( GENTYPE, UNUR_ERR_STR_SYNTAX, "too many arguments");
2421       return -1;
2422     }
2423   }
2424 
2425   /* return number of parsed arguments */
2426   return n_args;
2427 
2428 } /* end of _unur_str_set_args() */
2429 
2430 /*---------------------------------------------------------------------------*/
2431 
2432 /*****************************************************************************/
2433 /**  Convert to numbers                                                     **/
2434 /*****************************************************************************/
2435 
2436 /*---------------------------------------------------------------------------*/
2437 
2438 int
_unur_parse_ilist(char * liststr,int ** iarray)2439 _unur_parse_ilist( char *liststr, int **iarray )
2440      /*----------------------------------------------------------------------*/
2441      /* Process a comma separated list of integers, convert it to ints and   */
2442      /* store it an array. The list (string) is terminated by a closing      */
2443      /* parenthesis ')' or '\0'.                                             */
2444      /*                                                                      */
2445      /* parameters:                                                          */
2446      /*   liststr ... string containing list of numbers                      */
2447      /*   iarray  ... pointer to adress of double array for storing result   */
2448      /*                                                                      */
2449      /* return:                                                              */
2450      /*   number of elements extracted                                       */
2451      /*                                                                      */
2452      /* comment:                                                             */
2453      /*   as a side effect an int array of appropriate size is allocated.    */
2454      /*----------------------------------------------------------------------*/
2455 {
2456   int *iarr = NULL;     /* pointer to int array */
2457   int n_iarray = 0;     /* number of elements in processed list */
2458   int n_alloc = 0;      /* number allocated elements */
2459   char *token;
2460 
2461   /* return 0 if no list is given */
2462   if (liststr == NULL) {
2463     *iarray = iarr;
2464     return 0;
2465   }
2466 
2467   /* discard possible leading ',' or '(' characters in front of the numbers */
2468   while ( *liststr == ',' || *liststr == '(' ){
2469     liststr++; /* next char */
2470   }
2471 
2472   /* new get integers */
2473   for ( token  = strtok(liststr, ",)");
2474         token != NULL;
2475         token  = strtok(NULL, ",)") ) {
2476 
2477     /* check if there is enough space in iarr */
2478     if (n_iarray >= n_alloc) {
2479       /* no --> allocate memory */
2480       n_alloc += 100;
2481       iarr = _unur_xrealloc( iarr, n_alloc * sizeof(int) );
2482     }
2483 
2484     /* get int */
2485     iarr[n_iarray++] = _unur_atoi(token);
2486 
2487   } /* end while -- all elements of list read */
2488 
2489   /* store pointer to double array */
2490   *iarray = iarr;
2491 
2492   /* return number of elements in array */
2493   return n_iarray;
2494 
2495 } /* end of _unur_parse_ilist() */
2496 
2497 /*---------------------------------------------------------------------------*/
2498 
2499 int
_unur_parse_dlist(char * liststr,double ** darray)2500 _unur_parse_dlist( char *liststr, double **darray )
2501      /*----------------------------------------------------------------------*/
2502      /* Process a comma separated list of numbers (doubles), convert it to   */
2503      /* doubles and store it an array. The list (string) is terminated by    */
2504      /* a closing parenthesis ')' or '\0'.                                   */
2505      /*                                                                      */
2506      /* parameters:                                                          */
2507      /*   liststr ... string containing list of numbers                      */
2508      /*   darray  ... pointer to adress of double array for storing result   */
2509      /*                                                                      */
2510      /* return:                                                              */
2511      /*   number of elements extracted                                       */
2512      /*                                                                      */
2513      /* comment:                                                             */
2514      /*   as a side effect a double array of appropriate size is allocated.  */
2515      /*----------------------------------------------------------------------*/
2516 {
2517   double *darr = NULL;  /* pointer to double array */
2518   int n_darray = 0;     /* number of elements in processed list */
2519   int n_alloc = 0;      /* number allocated elements */
2520   char *token;          /* pointer to token in string */
2521   char *next;           /* pointer to next token in string */
2522 
2523   /* return 0 if no list is given */
2524   if (liststr == NULL) {
2525     *darray = NULL;
2526     return 0;
2527   }
2528 
2529   /* extract doubles from string and write them to array of doubles.  */
2530   /* end of list is indicated by right bracket ')' or '\0'.           */
2531 
2532   /* pointer to first token in string */
2533   token = liststr;
2534 
2535   /* remove (optional) leading parenthesis '('                        */
2536   while (*token != '\0' && *token == '(')
2537     ++token;
2538 
2539   /* tokenize the string using ',' as separator and handle the tokens */
2540   for ( next = token;
2541 	next != NULL && *token != '\0' &&*token != ')';
2542 	token = next ) {
2543 
2544     /* find end of token (i.e. the pointer to next token) */
2545     next = strchr(token,',');
2546     if (next != NULL) {
2547       /* next separator found */
2548       *next = '\0';     /* terminate token string    */
2549       next++;           /* set pointer to next token */
2550     }
2551 
2552    /* check if there is enough space in darr */
2553     if (n_darray >= n_alloc) {
2554       /* no --> allocate memory */
2555       n_alloc += 100;
2556       darr = _unur_xrealloc( darr, n_alloc * sizeof(double) );
2557     }
2558 
2559     /* extract double and write to array and increase counter */
2560     darr[n_darray] = _unur_atod(token);
2561     n_darray++;
2562 
2563   }
2564 
2565   /* store pointer to double array */
2566   *darray = darr;
2567 
2568   /* return number of elements in array */
2569   return n_darray;
2570 
2571 } /* end of _unur_parse_dlist() */
2572 
2573 /*---------------------------------------------------------------------------*/
2574 
2575 int
_unur_atoi(const char * str)2576 _unur_atoi ( const char *str )
2577      /*----------------------------------------------------------------------*/
2578      /* Converts the string into its integer representation.                 */
2579      /* 'true' and 'on' are converted to 1, 'false' and 'off' to 0.          */
2580      /*                                                                      */
2581      /* parameters:                                                          */
2582      /*   str      ... pointer to string                                     */
2583      /*                                                                      */
2584      /* return:                                                              */
2585      /*   integer                                                            */
2586      /*----------------------------------------------------------------------*/
2587 {
2588   if ( !strcmp(str,"true") || !strcmp(str,"on") )
2589     return 1;
2590 
2591   else if ( !strcmp(str,"false") || !strcmp(str,"off") )
2592     return 0;
2593 
2594   else if ( !strncmp(str,"inf",(size_t)3) )
2595     return INT_MAX;
2596 
2597   else if ( !strncmp(str,"-inf",(size_t)4) )
2598     return INT_MIN;
2599 
2600   else
2601     return atoi(str);
2602 
2603 } /* end of _unur_atoi() */
2604 
2605 /*---------------------------------------------------------------------------*/
2606 
2607 unsigned
_unur_atou(const char * str)2608 _unur_atou ( const char *str )
2609      /*----------------------------------------------------------------------*/
2610      /* Converts the string into its unsigned representation.                */
2611      /* strings are interprated as hexadecimal numbers.                      */
2612      /* 'true' and 'on' are converted to 1u, 'false' and 'off' to 0u.        */
2613      /*                                                                      */
2614      /* parameters:                                                          */
2615      /*   str      ... pointer to string                                     */
2616      /*                                                                      */
2617      /* return:                                                              */
2618      /*   unsigned                                                           */
2619      /*----------------------------------------------------------------------*/
2620 {
2621   char *tail;
2622 
2623   if ( !strcmp(str,"true") || !strcmp(str,"on") )
2624     return 1u;
2625 
2626   else if ( !strcmp(str,"false") || !strcmp(str,"off") )
2627     return 0u;
2628 
2629   else
2630     return ((unsigned) strtoul(str, &tail, 16));
2631 } /* end of _unur_atou() */
2632 
2633 /*---------------------------------------------------------------------------*/
2634 
2635 double
_unur_atod(const char * str)2636 _unur_atod ( const char *str )
2637      /*----------------------------------------------------------------------*/
2638      /* Converts the string into its double value.                           */
2639      /*                                                                      */
2640      /* parameters:                                                          */
2641      /*   str      ... pointer to string                                     */
2642      /*                                                                      */
2643      /* return:                                                              */
2644      /*   double                                                             */
2645      /*----------------------------------------------------------------------*/
2646 {
2647   if ( !strncmp(str,"inf",(size_t)3) )
2648     return INFINITY;
2649 
2650   else if ( !strncmp(str,"-inf",(size_t)4) )
2651     return -INFINITY;
2652 
2653   else
2654     return atof(str);
2655 } /* end of _unur_atod() */
2656 
2657 /*---------------------------------------------------------------------------*/
2658 
2659 /*****************************************************************************/
2660 /**  Debugging utilities                                                    **/
2661 /*****************************************************************************/
2662 
2663 /*---------------------------------------------------------------------------*/
2664 #ifdef UNUR_ENABLE_LOGGING
2665 /*---------------------------------------------------------------------------*/
2666 
2667 void
_unur_str_debug_string(int level,const char * key,const char * value)2668 _unur_str_debug_string( int level, const char *key, const char *value  )
2669      /*----------------------------------------------------------------------*/
2670      /* print key & value info into LOG file                                 */
2671      /*                                                                      */
2672      /* parameters:                                                          */
2673      /*   level ... level of indentation                                     */
2674      /*   key   ... pointer to key string                                    */
2675      /*   value ... pointer to value string                                  */
2676      /*----------------------------------------------------------------------*/
2677 {
2678   FILE *LOG;
2679 
2680   LOG = unur_get_stream();
2681 
2682 /*    fprintf(LOG,"%s: String Interface for UNU.RAN\n",GENTYPE); */
2683   fprintf(LOG,"%s: ",GENTYPE);
2684   for (; level>0; level--)
2685     fprintf(LOG,"\t");
2686   fprintf(LOG,"%s",key);
2687   if (value)
2688     fprintf(LOG,": %s",value);
2689   fprintf(LOG,"\n");
2690 
2691 /*    fprintf(LOG,"%s:\n",GENTYPE); */
2692 
2693 } /* end of _unur_str_debug_string() */
2694 
2695 /*---------------------------------------------------------------------------*/
2696 
2697 void
_unur_str_debug_distr(int level,const char * name,double * params,int n_params)2698 _unur_str_debug_distr( int level, const char *name, double *params, int n_params )
2699      /*----------------------------------------------------------------------*/
2700      /* write info about distribution into LOG file                          */
2701      /*                                                                      */
2702      /* parameters:                                                          */
2703      /*   level    ... level of indentation                                  */
2704      /*   name     ... name of distribution                                  */
2705      /*   params   ... array of parameters                                   */
2706      /*   n_params ... number of parameters                                  */
2707      /*----------------------------------------------------------------------*/
2708 {
2709   FILE *LOG;
2710   int i;
2711 
2712   LOG = unur_get_stream();
2713 
2714   fprintf(LOG,"%s: ",GENTYPE);
2715   for (; level>0; level--)
2716     fprintf(LOG,"\t");
2717 
2718   fprintf(LOG,"distribution = %s (",name);
2719   if (n_params >0) {
2720     fprintf(LOG,"%g",params[0]);
2721     for (i=1; i<n_params; i++)
2722       fprintf(LOG,", %g",params[i]);
2723   }
2724   fprintf(LOG,")\n");
2725 
2726 } /* end of _unur_str_debug_distr() */
2727 
2728 /*---------------------------------------------------------------------------*/
2729 
2730 void
_unur_str_debug_set(int level,const char * key,const char * type,...)2731 _unur_str_debug_set( int level, const char *key, const char *type, ... )
2732      /*----------------------------------------------------------------------*/
2733      /* write info about set command into LOG file                           */
2734      /*                                                                      */
2735      /* parameters:                                                          */
2736      /*   level ... level of indentation                                     */
2737      /*   key   ... pointer to key string                                    */
2738      /*   type  ... list of types of argments                                */
2739      /*   ...   ... variable list of arguments                               */
2740      /*----------------------------------------------------------------------*/
2741 {
2742   va_list ap;
2743   FILE *LOG;
2744 
2745   va_start(ap, type);
2746 
2747   LOG = unur_get_stream();
2748 
2749   /* print key name */
2750   fprintf(LOG,"%s: ",GENTYPE);
2751   for (; level>0; level--)
2752     fprintf(LOG,"\t");
2753   fprintf(LOG,"%s: ",key);
2754 
2755   while (1) {
2756 
2757     switch (*type) {
2758     case 'v':
2759       fprintf(LOG," -none-");
2760       break;
2761     case 'd':
2762       fprintf(LOG," %g",va_arg(ap,double));
2763       break;
2764     case 'i':
2765       fprintf(LOG," %d",va_arg(ap,int));
2766       break;
2767     case 'u':
2768       fprintf(LOG," %x",va_arg(ap,unsigned int));
2769       break;
2770     case 'C':
2771       fprintf(LOG," %s",va_arg(ap,char *));
2772       break;
2773     case 'D': {
2774       int i,size;
2775       double *darray;
2776       darray = va_arg(ap,double *);
2777       size = va_arg(ap,int);
2778       if (size > 0 && darray != NULL) {
2779 	fprintf(LOG," (%g",darray[0]);
2780 	for (i=1; i<size; i++)
2781 	  fprintf(LOG,",%g",darray[i]);
2782 	fprintf(LOG,")");
2783       }
2784       else
2785 	fprintf(LOG," (empty)");
2786       break;
2787     }
2788     case '!':
2789     default:
2790       fprintf(LOG," syntax error");
2791       break;
2792     }
2793 
2794     if ( *(++type) != '\0' )
2795       /* skip. there is a next argument to be processed */
2796       fprintf(LOG,",");
2797     else
2798       /* done */
2799       break;
2800   }
2801 
2802   /* dd, iD, Di */
2803 
2804   fprintf(LOG,"\n");
2805   fflush(LOG);   /* in case of a segmentation fault */
2806 
2807   va_end(ap);
2808 
2809 } /* end of _unur_str_debug_set() */
2810 
2811 /*---------------------------------------------------------------------------*/
2812 #endif   /* end UNUR_ENABLE_LOGGING */
2813 /*---------------------------------------------------------------------------*/
2814 
2815 void
_unur_str_error_unknown(const char * file,int line,const char * key,const char * type)2816 _unur_str_error_unknown( const char *file, int line, const char *key, const char *type )
2817      /*----------------------------------------------------------------------*/
2818      /* print error message: unknown keyword.                                */
2819      /*                                                                      */
2820      /* parameters:                                                          */
2821      /*   file ... file name (inserted by __FILE__)                          */
2822      /*   line ... line number in source file (inserted by __LINE__)         */
2823      /*   key  ... keyword                                                   */
2824      /*   type ... type of keyword                                           */
2825      /*----------------------------------------------------------------------*/
2826 {
2827   struct unur_string *reason = _unur_string_new();
2828   _unur_string_append( reason, "unknown %s: '%s'", type, key );
2829   _unur_error_x( GENTYPE, file, line, "error", UNUR_ERR_STR_UNKNOWN,reason->text);
2830   _unur_string_free( reason );
2831 } /* end of _unur_str_error_unknown() */
2832 
2833 /*---------------------------------------------------------------------------*/
2834 
2835 void
_unur_str_error_invalid(const char * file,int line,const char * key,const char * type)2836 _unur_str_error_invalid( const char *file, int line, const char *key, const char *type )
2837      /*----------------------------------------------------------------------*/
2838      /* print error message: invalid data for keyword.                       */
2839      /*                                                                      */
2840      /* parameters:                                                          */
2841      /*   file ... file name (inserted by __FILE__)                          */
2842      /*   line ... line number in source file (inserted by __LINE__)         */
2843      /*   key  ... keyword                                                   */
2844      /*   type ... type of keyword                                           */
2845      /*----------------------------------------------------------------------*/
2846 {
2847   struct unur_string *reason = _unur_string_new();
2848   _unur_string_append( reason, "invalid data for %s '%s'", type, key );
2849   _unur_error_x( GENTYPE, file, line, "error", UNUR_ERR_STR_INVALID,reason->text);
2850   _unur_string_free( reason );
2851 } /* end of _unur_str_error_invalid() */
2852 
2853 /*---------------------------------------------------------------------------*/
2854 
2855 void
_unur_str_error_args(const char * file,int line,const char * key)2856 _unur_str_error_args( const char *file, int line, const char *key )
2857      /*----------------------------------------------------------------------*/
2858      /* print error message: invalid argument string for set call.           */
2859      /*                                                                      */
2860      /* parameters:                                                          */
2861      /*   file ... file name (inserted by __FILE__)                          */
2862      /*   line ... line number in source file (inserted by __LINE__)         */
2863      /*   key  ... keyword                                                   */
2864      /*----------------------------------------------------------------------*/
2865 {
2866   struct unur_string *reason = _unur_string_new();
2867   _unur_string_append( reason, "invalid argument string for '%s'", key );
2868   _unur_error_x( GENTYPE, file, line, "error", UNUR_ERR_STR_INVALID,reason->text);
2869   _unur_string_free( reason );
2870 } /* end of _unur_str_error_args() */
2871 
2872 /*---------------------------------------------------------------------------*/
2873