1 /*****************************************************************************
2 * *
3 * UNURAN -- Universal Non-Uniform Random number generator *
4 * *
5 *****************************************************************************
6 * *
7 * FILE: testroutines.c *
8 * *
9 * Common test routines *
10 * *
11 *****************************************************************************
12 * *
13 * Copyright (c) 2000-2006 Wolfgang Hoermann and Josef Leydold *
14 * Department of Statistics and Mathematics, WU Wien, Austria *
15 * *
16 * This program is free software; you can redistribute it and/or modify *
17 * it under the terms of the GNU General Public License as published by *
18 * the Free Software Foundation; either version 2 of the License, or *
19 * (at your option) any later version. *
20 * *
21 * This program is distributed in the hope that it will be useful, *
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
24 * GNU General Public License for more details. *
25 * *
26 * You should have received a copy of the GNU General Public License *
27 * along with this program; if not, write to the *
28 * Free Software Foundation, Inc., *
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *
30 * *
31 *****************************************************************************/
32
33 /*---------------------------------------------------------------------------*/
34
35 #include "testunuran.h"
36 #include <signal.h>
37
38 #ifdef HAVE_UNISTD_H
39 # include <unistd.h>
40 #endif
41
42 /*---------------------------------------------------------------------------*/
43 /* Compiler switches */
44
45 /* whether to test U-errors for inversion method in tails more accurately */
46 #define TEST_INVERROR_TAILS (FALSE)
47
48 /*---------------------------------------------------------------------------*/
49 /* global switches */
50
51 static int stopwatch = FALSE; /* whether to use a stop watch for checks */
52 static TIMER vw; /* timer for particular tests */
53
54 /*---------------------------------------------------------------------------*/
55
56 #if defined(HAVE_ALARM) && defined(HAVE_SIGNAL)
57
58 /* time limit before SIGALRM is sent to process */
59 int time_limit = 0u;
60
61 /* handle SIGALRM signals */
62 static void catch_alarm (int sig);
63
64 /* test log file */
65 static FILE *TESTLOG = NULL;
66
67 #endif
68
69 /*---------------------------------------------------------------------------*/
70
71 /* compare two doubles */
72 static int compare_doubles ( double x1, double x2 );
73
74 /* compare double sequences generated by generator */
75 static int compare_double_sequence_gen_start ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
76 static int compare_double_sequence_gen ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
77
78 /* compare int sequences generated by generator */
79 static int compare_int_sequence_gen_start ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
80 static int compare_int_sequence_gen ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
81
82 /* compare sequences of double vectors generated by generator */
83 static int compare_cvec_sequence_gen_start ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
84 static int compare_cvec_sequence_gen ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
85
86 /* compare sequences of double matrices generated by generator */
87 static int compare_matr_sequence_gen_start ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
88 static int compare_matr_sequence_gen ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size );
89
90 /*---------------------------------------------------------------------------*/
91 /* check whether unur_urng_reset() works */
92
93 static int
cannot_compare_sequence(FILE * LOG)94 cannot_compare_sequence ( FILE *LOG )
95 {
96 fprintf (LOG,"\nURNG cannot be reset. Cannot compare sequences. (Skip)\n");
97 printf ("URNG cannot be reset. Cannot compare sequences. (Skip)\n");
98
99 return UNUR_SUCCESS; /* indicate as "not failed" for practical reasons */
100 } /* end of cannot_compare_sequence() */
101
102 /*---------------------------------------------------------------------------*/
103 /* stop watch */
104
stopwatch_start(TIMER * t)105 void stopwatch_start(TIMER *t)
106 /* start stop watch */
107 {
108 t->stop = stopwatch_get_time(t->tv);
109 t->interim = t->stop;
110 t->start = t->stop;
111 }
112
stopwatch_lap(TIMER * t)113 double stopwatch_lap(TIMER *t)
114 /* return elapsed time (in ms) since last call to stopwatch_start(),
115 stopwatch_stop(), or stopwatch_lap() */
116 {
117 double etime;
118
119 t->stop = stopwatch_get_time(t->tv);
120 etime = t->stop - t->interim;
121
122 t->interim = t->stop;
123
124 return etime;
125 }
126
stopwatch_stop(TIMER * t)127 double stopwatch_stop(TIMER *t)
128 /* return elapsed time (in ms) since last call to stopwatch_start()
129 or stopwatch_stop() */
130 {
131 double etime;
132
133 t->stop = stopwatch_get_time(t->tv);
134 etime = t->stop - t->start;
135
136 t->interim = t->stop;
137 t->start = t->stop;
138
139 return etime;
140 }
141
stopwatch_init(void)142 void stopwatch_init(void)
143 /* initialize watch */
144 {
145 /* detect whether stopwatch should be used */
146 stopwatch = (getenv("UNURANSTOPWATCH")==NULL) ? FALSE : TRUE;
147 stopwatch_start(&vw);
148 }
149
stopwatch_print(FILE * LOG,const char * format,double etime)150 void stopwatch_print( FILE *LOG, const char *format, double etime )
151 /* print time depending whether watch is enabled or not */
152 {
153 if (stopwatch)
154 fprintf(LOG,format,etime);
155 }
156
157 /*---------------------------------------------------------------------------*/
158 /* exit with FAIL when run time exceeds limit */
159
160 #if defined(HAVE_ALARM) && defined(HAVE_SIGNAL)
161
catch_alarm(int sig ATTRIBUTE__UNUSED)162 void catch_alarm (int sig ATTRIBUTE__UNUSED)
163 {
164 fprintf(stdout," aborted! time limit of %d seconds exceeded ...\n",time_limit);
165 fprintf(TESTLOG,"\n\n=== ABORTED! ===\ntime limit of %d seconds exceeded ...\n\n",time_limit);
166 exit (EXIT_FAILURE);
167 }
168
set_alarm(FILE * LOG)169 void set_alarm(FILE *LOG)
170 {
171 char *read_timer;
172
173 /* file handle for test log file */
174 TESTLOG = LOG;
175
176 /* read time limit from environment */
177 read_timer = getenv("UNURANTIMER");
178 time_limit = (read_timer!=NULL) ? atoi(read_timer) : 0;
179
180 /* alarm is only set when environment variable is defined */
181 if (time_limit<=0) return;
182
183 /* Establish a handler for SIGALRM signals. */
184 signal(SIGALRM, catch_alarm);
185
186 /* set in alarm in 'time' seconds */
187 alarm((unsigned)time_limit);
188
189 /* print message into test log file */
190 fprintf(TESTLOG,"Send alarm in %d seconds\n",time_limit);
191 fprintf(TESTLOG,"\n====================================================\n\n");
192
193 }
194
195 #else
196
set_alarm(FILE * LOG ATTRIBUTE__UNUSED)197 void set_alarm(FILE *LOG ATTRIBUTE__UNUSED) {;}
198
199 #endif
200
201 /*---------------------------------------------------------------------------*/
202 /* print header for test log file */
203
print_test_log_header(FILE * LOG,unsigned long seed,int fullcheck)204 void print_test_log_header( FILE *LOG, unsigned long seed, int fullcheck )
205 {
206 time_t started;
207
208 /* Title */
209 fprintf(LOG,"\nUNU.RAN - Universal Non-Uniform RANdom number generator\n\n");
210 if (time( &started ) != -1)
211 fprintf(LOG,"%s",ctime(&started));
212 fprintf(LOG,"\n=======================================================\n\n");
213
214 /* version */
215 fprintf(LOG,"UNU.RAN version: %s\n", PACKAGE_STRING);
216
217 /* deprecated code */
218 fprintf(LOG,"Use deprecated code: %s\n",
219 #ifdef USE_DEPRECATED_CODE
220 "yes"
221 #else
222 "no"
223 #endif
224 );
225
226 /* runtime checks */
227 fprintf(LOG,"Enable runtime checks: %s\n",
228 #if defined(UNUR_ENABLE_CHECKNULL) || defined(UNUR_COOKIES)
229 "yes"
230 #else
231 "no"
232 #endif
233 );
234
235 /* printing debugging info into log file */
236 fprintf(LOG,"Enable logging of data: %s\n",
237 #ifdef UNUR_ENABLE_LOGGING
238 "yes"
239 #else
240 "no"
241 #endif
242 );
243
244 /* creating info string */
245 fprintf(LOG,"Enable info routine: %s\n",
246 #ifdef UNUR_ENABLE_INFO
247 "yes"
248 #else
249 "no"
250 #endif
251 );
252
253 fprintf(LOG,"\n");
254
255 /* Uniform random number generator */
256 fprintf(LOG,"Uniform random number generator: %s\n",
257 #ifdef UNUR_URNG_DEFAULT_RNGSTREAM
258 "RngStreams"
259 #else
260 "[default] (built-in or user supplied)"
261 #endif
262 );
263
264 /* seed */
265 if (seed != ~0u)
266 fprintf(LOG,"SEED = %lu\n",seed);
267 else
268 fprintf(LOG,"SEED = (not set)\n");
269
270 fprintf(LOG,"\n");
271
272 /* whether all checks are performed */
273 fprintf(LOG,"check mode: %s\n",
274 fullcheck ? "fullcheck" : "installation");
275
276 /* end */
277 fprintf(LOG,"\n=======================================================\n\n");
278
279 } /* end of print_test_log_header() */
280
281 /*---------------------------------------------------------------------------*/
282 /* check for invalid NULL pointer, that should not happen in this program */
283
abort_if_NULL(FILE * LOG,int line,const void * ptr)284 void abort_if_NULL( FILE *LOG, int line, const void *ptr )
285 {
286 if (ptr) return; /* o.k. */
287
288 /*
289 There must not be a NULL pointer.
290 Since we do not expect a NULL pointer something serious has
291 happend. So it is better to abort the tests.
292 */
293 fprintf(LOG,"line %4d: Unexpected NULL pointer. Panik --> Abort tests!!\n\n",line);
294 printf(" Panik --> Tests aborted\n"); fflush(stdout);
295
296 /* test finished */
297 printf("\n"); fflush(stdout);
298
299 /* close log files and exit */
300 fclose(LOG);
301 exit(EXIT_FAILURE);
302
303 } /* abort_if_NULL() */
304
305 /*---------------------------------------------------------------------------*/
306 /* compare error code */
307
check_errorcode(FILE * LOG,int line,int errno_exp)308 int check_errorcode( FILE *LOG, int line, int errno_exp )
309 {
310 int errno_obs = unur_get_errno();
311
312 fprintf(LOG,"line %4d: Error code ...\t\t",line);
313
314 if (errno_obs != errno_exp) {
315 fprintf(LOG," Failed");
316 fprintf(LOG," (observed = %#x, expected = %#x)\n",errno_obs,errno_exp);
317 fflush(LOG);
318 return UNUR_FAILURE;
319 }
320
321 else {
322 fprintf(LOG," ok\n");
323 fflush(LOG);
324 return UNUR_SUCCESS;
325 }
326 } /* end of check_errorcode() */
327
328 /*---------------------------------------------------------------------------*/
329 /* check for expected NULL pointer */
330
do_check_expected_NULL(FILE * LOG,int line,int is_NULL)331 int do_check_expected_NULL( FILE *LOG, int line, int is_NULL )
332 {
333 fprintf(LOG,"line %4d: NULL pointer expected ...\t",line);
334
335 if (is_NULL) {
336 fprintf(LOG," ok\n");
337 fflush(LOG);
338 return UNUR_SUCCESS;
339 }
340
341 else {
342 fprintf(LOG," Failed\n");
343 fflush(LOG);
344 return UNUR_FAILURE;
345 }
346
347 } /* end of check_expected_NULL() */
348
349 /*---------------------------------------------------------------------------*/
350 /* check for "set failed" */
351
check_expected_setfailed(FILE * LOG,int line,int rcode)352 int check_expected_setfailed( FILE *LOG, int line, int rcode )
353 {
354 fprintf(LOG,"line %4d: `failed' expected ...\t",line);
355 if (rcode==UNUR_SUCCESS) {
356 fprintf(LOG," Failed\n");
357 fflush(LOG);
358 return UNUR_FAILURE;
359 }
360
361 else {
362 fprintf(LOG," ok\n");
363 fflush(LOG);
364 return UNUR_SUCCESS;
365 }
366 } /* end of check_expected_setfailed() */
367
368 /*---------------------------------------------------------------------------*/
369 /* check for O (zero) */
370
check_expected_zero(FILE * LOG,int line,int k)371 int check_expected_zero( FILE *LOG, int line, int k )
372 {
373 fprintf(LOG,"line %4d: 0 (zero) expected ...\t",line);
374
375 if (k != 0) {
376 fprintf(LOG," Failed\n");
377 fflush(LOG);
378 return UNUR_FAILURE;
379 }
380
381 else {
382 fprintf(LOG," ok\n");
383 fflush(LOG);
384 return UNUR_SUCCESS;
385 }
386 } /* end of check_expected_zero() */
387
388 /*---------------------------------------------------------------------------*/
389 /* check for INFINITY */
390
check_expected_INFINITY(FILE * LOG,int line,double x)391 int check_expected_INFINITY( FILE *LOG, int line, double x )
392 {
393 fprintf(LOG,"line %4d: INFINITY expected ...\t",line);
394
395 if (x < UNUR_INFINITY) {
396 fprintf(LOG," Failed\n");
397 fflush(LOG);
398 return UNUR_FAILURE;
399 }
400
401 else {
402 fprintf(LOG," ok\n");
403 fflush(LOG);
404 return UNUR_SUCCESS;
405 }
406 } /* end of check_expected_INFINITY() */
407
check_expected_negINFINITY(FILE * LOG,int line,double x)408 int check_expected_negINFINITY( FILE *LOG, int line, double x )
409 {
410 fprintf(LOG,"line %4d: -INFINITY expected ...\t",line);
411
412 if (x > -UNUR_INFINITY) {
413 fprintf(LOG," Failed\n");
414 fflush(LOG);
415 return UNUR_FAILURE;
416 }
417
418 else {
419 fprintf(LOG," ok\n");
420 fflush(LOG);
421 return UNUR_SUCCESS;
422 }
423 } /* end of check_expected_negINFINITY() */
424
check_expected_INTMAX(FILE * LOG,int line,int k)425 int check_expected_INTMAX( FILE *LOG, int line, int k )
426 {
427 fprintf(LOG,"line %4d: INT_MAX expected ...\t",line);
428
429 if (k < INT_MAX) {
430 fprintf(LOG," Failed\n");
431 fflush(LOG);
432 return UNUR_FAILURE;
433 }
434
435 else {
436 fprintf(LOG," ok\n");
437 fflush(LOG);
438 return UNUR_SUCCESS;
439 }
440 } /* end of check_expected_INTMAX() */
441
442 /*---------------------------------------------------------------------------*/
443 /* check for reinit */
444
check_expected_reinit(FILE * LOG,int line,int rcode)445 int check_expected_reinit( FILE *LOG, int line, int rcode )
446 {
447 fprintf(LOG,"line %4d: reinit ...\t\t\t",line);
448
449 if (rcode!=UNUR_SUCCESS) {
450 fprintf(LOG," Failed\n");
451 fflush(LOG);
452 return UNUR_FAILURE;
453 }
454
455 else {
456 fprintf(LOG," ok\n");
457 fflush(LOG);
458 return UNUR_SUCCESS;
459 }
460 } /* end of check_expected_reinit() */
461
462 /*---------------------------------------------------------------------------*/
463 /* check for non existing reinit */
464
check_expected_no_reinit(FILE * LOG,int line,int rcode)465 int check_expected_no_reinit( FILE *LOG, int line, int rcode )
466 {
467 fprintf(LOG,"line %4d: no reinit ...\t\t",line);
468
469 if (rcode==UNUR_SUCCESS) {
470 fprintf(LOG," Failed\n");
471 fflush(LOG);
472 return UNUR_FAILURE;
473 }
474
475 else {
476 fprintf(LOG," ok\n");
477 fflush(LOG);
478 return UNUR_SUCCESS;
479 }
480 } /* end of check_expected_no_reinit() */
481
482 /*---------------------------------------------------------------------------*/
483 /* compare two doubles */
484
485 int
compare_doubles(double x1,double x2)486 compare_doubles ( double x1, double x2 )
487 {
488 if (_unur_FP_approx(x1,x2))
489 return TRUE;
490 else if (fabs(x1-x2) < UNUR_EPSILON)
491 return TRUE;
492 else
493 return FALSE;
494 } /* end of compare_doubles() */
495
496 /*---------------------------------------------------------------------------*/
497 /* compare sequences generated by generator */
498
499 int
compare_sequence_gen_start(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)500 compare_sequence_gen_start( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
501 {
502
503 if (gen == NULL) return UNUR_FAILURE;
504
505 /* reset uniform RNG */
506 if (unur_urng_reset(unur_get_urng(gen)) != UNUR_SUCCESS)
507 return UNUR_SUCCESS;
508
509 switch( unur_distr_get_type(unur_get_distr(gen)) ) {
510
511 case UNUR_DISTR_CONT:
512 case UNUR_DISTR_CEMP:
513 case 0: /* method UNIF */
514 return compare_double_sequence_gen_start(LOG,line,gen,sample_size );
515
516 case UNUR_DISTR_CVEC:
517 case UNUR_DISTR_CVEMP:
518 return compare_cvec_sequence_gen_start(LOG,line,gen,sample_size );
519
520 case UNUR_DISTR_DISCR:
521 return compare_int_sequence_gen_start(LOG,line,gen,sample_size );
522
523 case UNUR_DISTR_MATR:
524 return compare_matr_sequence_gen_start(LOG,line,gen,sample_size );
525
526 default:
527 fprintf(stderr,"\ncannot handle distribution type! ... aborted\n");
528 exit (EXIT_FAILURE);
529 }
530
531 } /* end of compare_sequence_gen_start() */
532
533 int
compare_sequence_gen(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)534 compare_sequence_gen ( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
535 {
536 if (gen == NULL) return UNUR_FAILURE;
537
538 /* reset uniform RNG */
539 if (unur_urng_reset(unur_get_urng(gen)) != UNUR_SUCCESS)
540 return cannot_compare_sequence(LOG);
541
542 switch( unur_distr_get_type(unur_get_distr(gen)) ) {
543
544 case UNUR_DISTR_CONT:
545 case UNUR_DISTR_CEMP:
546 case 0: /* method UNIF */
547 return compare_double_sequence_gen(LOG,line,gen,sample_size );
548
549 case UNUR_DISTR_CVEC:
550 case UNUR_DISTR_CVEMP:
551 return compare_cvec_sequence_gen(LOG,line,gen,sample_size );
552
553 case UNUR_DISTR_DISCR:
554 return compare_int_sequence_gen(LOG,line,gen,sample_size );
555
556 case UNUR_DISTR_MATR:
557 return compare_matr_sequence_gen(LOG,line,gen,sample_size );
558
559 default:
560 fprintf(stderr,"\ncannot handle distribution type! ... aborted\n");
561 exit (EXIT_FAILURE);
562 }
563 } /* end of compare_sequence_gen() */
564
565 /*---------------------------------------------------------------------------*/
566
567 int
compare_sequence_par_start(FILE * LOG,int line,UNUR_PAR * par,int sample_size)568 compare_sequence_par_start( FILE *LOG, int line, UNUR_PAR *par, int sample_size )
569 {
570 UNUR_GEN *gen;
571 int result;
572
573 /* reset uniform RNG */
574 if (unur_urng_reset(unur_get_default_urng()) != UNUR_SUCCESS) {
575 if (par) free(par); return UNUR_SUCCESS;
576 }
577
578 /* init generator */
579 gen = unur_init( par ); abort_if_NULL(LOG,line,gen);
580
581 /* run test */
582 result = compare_sequence_gen_start(LOG,line,gen,sample_size);
583
584 unur_free(gen);
585 return result;
586
587 } /* end of compare_sequence_par_start() */
588
589 int
compare_sequence_par(FILE * LOG,int line,UNUR_PAR * par,int sample_size)590 compare_sequence_par ( FILE *LOG, int line, UNUR_PAR *par, int sample_size )
591 {
592 UNUR_GEN *gen;
593 int result;
594
595 /* reset uniform RNG */
596 if (unur_urng_reset(unur_get_default_urng()) != UNUR_SUCCESS) {
597 if (par) free(par); return cannot_compare_sequence(LOG);
598 }
599
600 /* init generator */
601 gen = unur_init( par ); abort_if_NULL(LOG, line,gen);
602
603 /* run test */
604 result = compare_sequence_gen(LOG,line,gen,sample_size);
605
606 unur_free(gen);
607
608 return result;
609
610 } /* end of compare_sequence_par() */
611
612 /*---------------------------------------------------------------------------*/
613 /* compare double sequences generated by generator */
614 /* only when when we can reset the uniform RNG */
615
616 static double *double_sequence_A = NULL;
617
compare_sequence_urng_start(FILE * LOG,int line,int sample_size)618 int compare_sequence_urng_start( FILE *LOG, int line, int sample_size )
619 {
620 int i;
621 UNUR_URNG *urng = unur_get_default_urng();
622
623 /* allocate memory for storing sequence */
624 if (double_sequence_A == NULL) {
625 double_sequence_A = malloc( sample_size * sizeof(double) );
626 abort_if_NULL(LOG, line, double_sequence_A);
627 }
628
629 /* reset uniform RNG */
630 if (unur_urng_reset(urng) != UNUR_SUCCESS)
631 return UNUR_SUCCESS;
632
633 /* generate sequence */
634 for (i=0; i<sample_size; i++)
635 double_sequence_A[i] = unur_urng_sample(urng);
636
637 /* there cannot be a failure */
638 return UNUR_SUCCESS;
639
640 } /* end of compare_sequence_urng_start() */
641
642 /*...........................................................................*/
643
compare_double_sequence_gen_start(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)644 int compare_double_sequence_gen_start( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
645 {
646 int i;
647
648 /* check generator object */
649 if (gen==NULL) {
650 /* error */
651 if (double_sequence_A) free (double_sequence_A);
652 double_sequence_A = NULL;
653 return UNUR_FAILURE;
654 }
655
656 /* allocate memory for storing sequence */
657 if (double_sequence_A == NULL) {
658 double_sequence_A = malloc( sample_size * sizeof(double) );
659 abort_if_NULL(LOG,line, double_sequence_A);
660 }
661
662 /* generate sequence */
663 for (i=0; i<sample_size; i++)
664 double_sequence_A[i] = unur_sample_cont(gen);
665
666 /* there cannot be a failure */
667 return UNUR_SUCCESS;
668
669 } /* end of compare_double_sequence_gen_start() */
670
671 /*...........................................................................*/
672
compare_double_sequence_gen(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)673 int compare_double_sequence_gen( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
674 {
675 int i;
676 int ok = TRUE;
677 double x = 0.;
678 int failed = 0;
679
680 /* check generator object and stored sequence */
681 if (gen==NULL || double_sequence_A==NULL) {
682 /* error */
683 return UNUR_FAILURE;
684 }
685
686 /* compare sequence */
687 for (i=0; i<sample_size; i++) {
688 x = unur_sample_cont(gen);
689 if (!compare_doubles(double_sequence_A[i], x)) {
690 /* if ( !_unur_FP_approx(double_sequence_A[i], x)) { */
691 ok = FALSE;
692 break;
693 }
694 }
695
696 /* print result */
697 fprintf(LOG,"line %4d: random seqences ...\t\t",line);
698 if (!ok) {
699 failed = 1;
700 fprintf(LOG," Failed\n");
701 fprintf(LOG,"\tx[1] = %g, x[2] = %g, diff = %g\n",double_sequence_A[i],x,double_sequence_A[i]-x);
702 }
703 else
704 fprintf(LOG," ok\n");
705
706 fflush(LOG);
707 return (failed ? UNUR_FAILURE : UNUR_SUCCESS);
708
709 } /* end of compare_double_sequence_gen() */
710
711 /*---------------------------------------------------------------------------*/
712 /* compare int sequences generated by generator */
713 /* only when when we can reset the uniform RNG */
714
715 static int *int_sequence_A = NULL;
716
compare_int_sequence_gen_start(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)717 int compare_int_sequence_gen_start( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
718 {
719 int i;
720
721 /* check generator object */
722 if (gen==NULL) {
723 /* error */
724 if (int_sequence_A) free (int_sequence_A);
725 int_sequence_A = NULL;
726 return UNUR_FAILURE;
727 }
728
729 /* allocate memory for storing sequence */
730 if (int_sequence_A == NULL) {
731 int_sequence_A = malloc( sample_size * sizeof(int) );
732 abort_if_NULL(LOG, line, int_sequence_A);
733 }
734
735 /* generate sequence */
736 for (i=0; i<sample_size; i++)
737 int_sequence_A[i] = unur_sample_discr(gen);
738
739 /* there cannot be a failure */
740 return UNUR_SUCCESS;
741
742 } /* end of compare_int_sequence_gen_start() */
743
744 /*...........................................................................*/
745
compare_int_sequence_gen(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)746 int compare_int_sequence_gen( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
747 {
748 int i;
749 int ok = TRUE;
750 int failed = 0;
751
752 /* check generator object and stored sequence */
753 if (gen==NULL || int_sequence_A==NULL) {
754 /* error */
755 return UNUR_FAILURE;
756 }
757
758 /* compare sequence */
759 for (i=0; i<sample_size; i++)
760 if (int_sequence_A[i] != unur_sample_discr(gen)) {
761 ok = FALSE;
762 break;
763 }
764
765 /* print result */
766 fprintf(LOG,"line %4d: random seqences ...\t\t",line);
767 if (!ok) {
768 failed = 1;
769 fprintf(LOG," Failed\n");
770 }
771 else
772 fprintf(LOG," ok\n");
773
774 fflush(LOG);
775 return (failed ? UNUR_FAILURE : UNUR_SUCCESS);
776
777 } /* end of compare_int_sequence_gen() */
778
779 /*---------------------------------------------------------------------------*/
780 /* compare sequences of double vectors generated by generator */
781 /* only when when we can reset the uniform RNG */
782
783 static double *cvec_sequence_A = NULL;
784
compare_cvec_sequence_gen_start(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)785 int compare_cvec_sequence_gen_start( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
786 {
787 int i;
788 int dim;
789
790 /* free sequence */
791 if (cvec_sequence_A) {
792 free (cvec_sequence_A);
793 cvec_sequence_A = NULL;
794 }
795
796 /* check generator object */
797 if (gen==NULL) {
798 /* error */
799 return UNUR_FAILURE;
800 }
801
802 /* get dimension */
803 dim = unur_get_dimension (gen);
804
805 /* allocate memory for storing sequence */
806 if (cvec_sequence_A == NULL) {
807 cvec_sequence_A = malloc( dim * sample_size * sizeof(double) );
808 abort_if_NULL(LOG,line, cvec_sequence_A);
809 }
810
811 /* generate sequence */
812 for (i=0; i<sample_size; i++)
813 unur_sample_vec( gen, cvec_sequence_A+(i*dim) );
814
815 /* there cannot be a failure */
816 return UNUR_SUCCESS;
817
818 } /* end of compare_cvec_sequence_gen_start() */
819
820 /*...........................................................................*/
821
compare_cvec_sequence_gen(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)822 int compare_cvec_sequence_gen( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
823 {
824 int i,k;
825 int ok = TRUE;
826 double *x;
827 int failed = 0;
828 int dim;
829
830 /* check generator object and stored sequence */
831 if (gen==NULL || cvec_sequence_A==NULL) {
832 /* error */
833 return UNUR_FAILURE;
834 }
835
836 /* get dimension */
837 dim = unur_get_dimension (gen);
838
839 /* need space for sampling result */
840 x = malloc( dim * sizeof(double) );
841 abort_if_NULL(LOG,line, x);
842
843 /* compare sequence */
844 for (i=0; i<sample_size; i++) {
845 unur_sample_vec( gen, x );
846 for (k=0; k<dim; k++) {
847 if ( _unur_FP_cmp(cvec_sequence_A[i*dim+k], x[k], 100.*UNUR_SQRT_DBL_EPSILON) !=0 ) {
848 /* multivariate random variates are more sensitive against rounding effects */
849 ok = FALSE;
850 break;
851 }
852 }
853 if (!ok) break;
854 }
855
856 /* print result */
857 fprintf(LOG,"line %4d: random seqences ...\t\t",line);
858 if (!ok) {
859 failed = 1;
860 fprintf(LOG," Failed\n");
861 fprintf(LOG,"\tx[1] = (");
862 for (k=0; k<dim; k++)
863 fprintf(LOG," %g",cvec_sequence_A[i*dim+k]);
864 fprintf(LOG,"),\tx[2] = (");
865 for (k=0; k<dim; k++)
866 fprintf(LOG," %g",x[k]);
867 fprintf(LOG,"),\tdiff = (");
868 for (k=0; k<dim; k++)
869 fprintf(LOG," %g",cvec_sequence_A[i*dim+k]-x[k]);
870 fprintf(LOG,")\n");
871 }
872 else
873 fprintf(LOG," ok\n");
874
875 fflush(LOG);
876 free (x);
877 return (failed ? UNUR_FAILURE : UNUR_SUCCESS);
878
879 } /* end of compare_cvec_sequence_gen() */
880
881 /*---------------------------------------------------------------------------*/
882 /* compare sequences of double matrices generated by generator */
883 /* only when when we can reset the uniform RNG */
884
885 static double *matr_sequence_A = NULL;
886
compare_matr_sequence_gen_start(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)887 int compare_matr_sequence_gen_start( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
888 {
889 int i;
890 int dim;
891
892 /* free sequence */
893 if (matr_sequence_A) {
894 free (matr_sequence_A);
895 matr_sequence_A = NULL;
896 }
897
898 /* check generator object */
899 if (gen==NULL) {
900 /* error */
901 return UNUR_FAILURE;
902 }
903
904 /* get dimension */
905 dim = unur_get_dimension (gen);
906
907 /* allocate memory for storing sequence */
908 if (matr_sequence_A == NULL) {
909 matr_sequence_A = malloc( dim * sample_size * sizeof(double) );
910 abort_if_NULL(LOG,line, matr_sequence_A);
911 }
912
913 /* generate sequence */
914 for (i=0; i<sample_size; i++)
915 unur_sample_matr( gen, matr_sequence_A+(i*dim) );
916
917 /* there cannot be a failure */
918 return UNUR_SUCCESS;
919
920 } /* end of compare_matr_sequence_gen_start() */
921
922 /*...........................................................................*/
923
compare_matr_sequence_gen(FILE * LOG,int line,UNUR_GEN * gen,int sample_size)924 int compare_matr_sequence_gen( FILE *LOG, int line, UNUR_GEN *gen, int sample_size )
925 {
926 int i,k;
927 int ok = TRUE;
928 double *x;
929 int failed = 0;
930 int dim;
931
932 /* check generator object and stored sequence */
933 if (gen==NULL || matr_sequence_A==NULL) {
934 /* error */
935 return UNUR_FAILURE;
936 }
937
938 /* get dimension */
939 dim = unur_get_dimension (gen);
940
941 /* need space for sampling result */
942 x = malloc( dim * sizeof(double) );
943 abort_if_NULL(LOG,line, x);
944
945 /* compare sequence */
946 for (i=0; i<sample_size; i++) {
947 unur_sample_matr( gen, x );
948 for (k=0; k<dim; k++) {
949 if ( !compare_doubles(matr_sequence_A[i*dim+k], x[k])) {
950 /* if ( !_unur_FP_approx(matr_sequence_A[i*dim+k], x[k])) { */
951 ok = FALSE;
952 break;
953 }
954 }
955 if (!ok) break;
956 }
957
958 /* print result */
959 fprintf(LOG,"line %4d: random seqences ...\t\t",line);
960 if (!ok) {
961 failed = 1;
962 fprintf(LOG," Failed\n");
963 fprintf(LOG,"\tx[1] = (");
964 for (k=0; k<dim; k++)
965 fprintf(LOG," %g",matr_sequence_A[i*dim+k]);
966 fprintf(LOG,"),\tx[2] = (");
967 for (k=0; k<dim; k++)
968 fprintf(LOG," %g",x[k]);
969 fprintf(LOG,"),\tdiff = (");
970 for (k=0; k<dim; k++)
971 fprintf(LOG," %g",matr_sequence_A[i*dim+k]-x[k]);
972 fprintf(LOG,")\n");
973 }
974 else
975 fprintf(LOG," ok\n");
976
977 fflush(LOG);
978 free (x);
979 return (failed ? UNUR_FAILURE : UNUR_SUCCESS);
980
981 } /* end of compare_matr_sequence_gen() */
982
983 /*---------------------------------------------------------------------------*/
984 /* free memory used for comparing sequences */
985
compare_free_memory(void)986 void compare_free_memory( void )
987 {
988 if (double_sequence_A) free (double_sequence_A);
989 if (int_sequence_A) free (int_sequence_A);
990 if (cvec_sequence_A) free (cvec_sequence_A);
991 if (matr_sequence_A) free (matr_sequence_A);
992 } /* end of compare_free_memory */
993
994 /*---------------------------------------------------------------------------*/
995 /* print name of distribution */
996
print_distr_name(FILE * LOG,const UNUR_DISTR * distr,const char * genid)997 void print_distr_name( FILE *LOG, const UNUR_DISTR *distr, const char *genid )
998 {
999 int i,n_fpar;
1000 const double *fpar;
1001
1002 /* print name of distribution */
1003 if (genid)
1004 fprintf(LOG,"%s: ",genid);
1005 fprintf(LOG,"%s ",unur_distr_get_name(distr));
1006
1007 /* get parameters */
1008 n_fpar = 0;
1009 if ( unur_distr_is_cont(distr) )
1010 /* continuous distribution */
1011 n_fpar = unur_distr_cont_get_pdfparams( distr, &fpar );
1012 else if ( unur_distr_is_discr(distr) )
1013 /* discrete distribution */
1014 n_fpar = unur_distr_discr_get_pmfparams( distr, &fpar );
1015
1016 /* print parameter list */
1017 fprintf(LOG,"(");
1018 if (n_fpar) {
1019 fprintf(LOG,"%g",fpar[0]);
1020 for (i=1; i<n_fpar; i++)
1021 fprintf(LOG,", %g",fpar[i]);
1022 }
1023 fprintf(LOG,")");
1024
1025 } /* end of print_distr_name() */
1026
1027 /*---------------------------------------------------------------------------*/
1028 /* check p-value of statistical test and print result */
1029
print_pval(FILE * LOG,UNUR_GEN * gen,const UNUR_DISTR * distr,double pval,int trial,int todo)1030 int print_pval( FILE *LOG, UNUR_GEN *gen, const UNUR_DISTR *distr,
1031 double pval, int trial, int todo )
1032 {
1033 int failed = 0;
1034 double pval_corrected;
1035 int dim;
1036 int l;
1037
1038 /* Correct p-value. */
1039 /* For multivariate distributions unur_test_chi2() runs chi^2 tests on the */
1040 /* multivariate distribution itself as well as on all marginal distibutions. */
1041 /* It returns the minimum of all p-palues. Thus we have to adjust this */
1042 /* value and multiply it with (dim+1) before deciding about the significance */
1043 /* of the result. */
1044 dim = unur_distr_get_dim(distr);
1045 pval_corrected = (dim>1) ? pval : pval*(dim+1);
1046
1047
1048 if (pval < -1.5) {
1049 /* was not able to run test (CDF missing) */
1050
1051 fprintf(LOG," not performed (missing data)\t");
1052 /* print distribution name */
1053 print_distr_name( LOG, distr, gen ? unur_get_genid(gen):"???\t" );
1054 fprintf(LOG,"\n");
1055
1056 printf("X");
1057
1058 fflush(stdout);
1059 fflush(LOG);
1060
1061 /* test failed */
1062 return UNUR_FAILURE;
1063 }
1064
1065 if (pval < 0.) {
1066 fprintf(LOG," setup failed\t\t");
1067 }
1068 else {
1069 fprintf(LOG," pval = %8.6f ",pval);
1070 l = _unur_isnan(pval_corrected)
1071 ? 10000
1072 : -(int) ((pval_corrected > 1e-6) ? (log(pval_corrected) / M_LN10) : 6.);
1073 switch (l) {
1074 case 0:
1075 fprintf(LOG," "); break;
1076 case 1:
1077 fprintf(LOG,". "); break;
1078 case 2:
1079 fprintf(LOG,"** "); break;
1080 case 3:
1081 fprintf(LOG,"XXX "); break;
1082 case 4:
1083 fprintf(LOG,"XXXX "); break;
1084 case 5:
1085 fprintf(LOG,"XXXXX "); break;
1086 default:
1087 fprintf(LOG,"######"); break;
1088 }
1089 }
1090
1091 switch (todo) {
1092 case '+':
1093 if (pval_corrected >= PVAL_LIMIT) {
1094 fprintf(LOG,"\t ok");
1095 printf("+");
1096 }
1097 else {
1098 failed = 1;
1099 if (trial > 2) {
1100 fprintf(LOG,"\t Failed");
1101 printf("(!+)");
1102 }
1103 else {
1104 fprintf(LOG,"\t Try again");
1105 printf("?");
1106 }
1107 }
1108 break;
1109 case '0':
1110 case '/':
1111 fprintf(LOG,"\t ok (expected to fail)");
1112 printf("0");
1113 break;
1114 case '-':
1115 if (pval_corrected < PVAL_LIMIT) {
1116 /* in this case it is expected to fail */
1117 failed = 0;
1118 fprintf(LOG,"\t ok (expected to fail)");
1119 printf("-");
1120 }
1121 else {
1122 /* the test has failed which was not what we have expected */
1123 failed = 1;
1124 fprintf(LOG,"\t Not ok (expected to fail)");
1125 printf("(!-)");
1126 }
1127 break;
1128 default:
1129 fprintf(stderr, "%s:%d: invalid test symbol\n", __FILE__, __LINE__);
1130 exit (-1);
1131 }
1132
1133 /* timing */
1134 stopwatch_print(LOG,"\ttime=%.1f ms ", stopwatch_lap(&vw));
1135
1136 /* print distribution name */
1137 fprintf(LOG,"\t");
1138 print_distr_name( LOG, distr, gen ? unur_get_genid(gen):"???\t" );
1139 fprintf(LOG,"\n");
1140
1141 fflush(stdout);
1142 fflush(LOG);
1143 return (failed ? UNUR_FAILURE : UNUR_SUCCESS);
1144
1145 } /* end of print_pval() */
1146
1147 /*---------------------------------------------------------------------------*/
1148 /* run chi2 test */
1149
run_validate_chi2(FILE * LOG,int line ATTRIBUTE__UNUSED,UNUR_GEN * gen,const UNUR_DISTR * distr,int todo)1150 int run_validate_chi2( FILE *LOG, int line ATTRIBUTE__UNUSED,
1151 UNUR_GEN *gen, const UNUR_DISTR *distr, int todo )
1152 /* UNUR_SUCCESS ... on success */
1153 /* UNUR_ERR_SILENT ... test failed only once */
1154 /* UNUR_FAILURE ... serious failure */
1155 {
1156 #define BUFSIZE 128
1157 const char *distr_name;
1158 static char last_distr_name[BUFSIZE] = "";
1159 unsigned int type;
1160 int i;
1161 double pval;
1162 int failed = 0;
1163
1164 /* check input */
1165 if (distr == NULL) {
1166 printf(" [!!no distribution!!] "); fflush(stdout);
1167 return UNUR_FAILURE;
1168 }
1169
1170 /* timer */
1171 stopwatch_lap(&vw);
1172
1173 /* get name of distribution */
1174 distr_name = unur_distr_get_name( distr );
1175
1176 /* get type of distribution */
1177 type = unur_distr_get_type( distr );
1178
1179 if ( strcmp(distr_name,last_distr_name) ) {
1180 /* different distributions */
1181 strncpy(last_distr_name,distr_name,(size_t)BUFSIZE);
1182 last_distr_name[BUFSIZE-1] = '\0';
1183 printf(" %s",distr_name); fflush(stdout);
1184 }
1185
1186 if (todo == '.') {
1187 /* nothing to do */
1188 printf("."); fflush(stdout);
1189 return UNUR_SUCCESS;
1190 }
1191
1192 if (todo == '0') {
1193 /* initialization of generator is expected to fail */
1194 if (gen == NULL) {
1195 printf("0"); fflush(stdout);
1196 return UNUR_SUCCESS;
1197 }
1198 else {
1199 /* error */
1200 printf("(!0)"); fflush(stdout);
1201 return UNUR_FAILURE;
1202 }
1203 }
1204
1205 if (gen == NULL) {
1206 if (todo == '-') {
1207 print_pval(LOG,gen,distr,-0.5,10,todo);
1208 return UNUR_SUCCESS;
1209 }
1210 else if (todo == '/') {
1211 printf("/"); fflush(stdout);
1212 return UNUR_SUCCESS;
1213 }
1214 else {
1215 /* initialization failed --> cannot run test */
1216 print_pval(LOG,gen,distr,-0.5,10,todo);
1217 return UNUR_FAILURE;
1218 }
1219 }
1220
1221 /* init successful */
1222 if ( todo == '/' ) todo = '+';
1223
1224 /* run chi^2 test */
1225 for (i=1; i<=3; i++) {
1226 /* we run the test up to three times when it fails */
1227
1228 switch (type) {
1229 case UNUR_DISTR_DISCR:
1230 pval = unur_test_chi2( gen, CHI_TEST_INTERVALS, 100000, 20, CHI_TEST_VERBOSITY, LOG);
1231 break;
1232 case UNUR_DISTR_CONT:
1233 case UNUR_DISTR_CEMP:
1234 pval = unur_test_chi2( gen, CHI_TEST_INTERVALS, 0, 20, CHI_TEST_VERBOSITY, LOG);
1235 break;
1236 case UNUR_DISTR_CVEC:
1237 case UNUR_DISTR_CVEMP:
1238 pval = unur_test_chi2( gen, CHI_TEST_INTERVALS, 0, 20, CHI_TEST_VERBOSITY, LOG);
1239 break;
1240 default:
1241 fprintf(stderr, "\n%s:%d: run_validate_chi2: this should not happen\n", __FILE__, __LINE__);
1242 exit (EXIT_FAILURE);
1243 }
1244
1245 if ( print_pval(LOG,gen,distr,pval,i,todo) != UNUR_SUCCESS )
1246 /* test failed */
1247 failed++;
1248 else
1249 /* test ok */
1250 break;
1251 }
1252
1253 return (failed==0 ? UNUR_SUCCESS : (failed<=2 ? UNUR_ERR_SILENT : UNUR_FAILURE));
1254
1255 #undef BUFSIZE
1256 } /* end of run_validate_chi2() */
1257
1258 /*---------------------------------------------------------------------------*/
1259 /* run verify hat test */
1260
1261 #define VERIFYHAT_SAMPLESIZE 10000
1262
run_validate_verifyhat(FILE * LOG,int line,UNUR_GEN * gen,const UNUR_DISTR * distr,int todo)1263 int run_validate_verifyhat( FILE *LOG, int line, UNUR_GEN *gen,
1264 const UNUR_DISTR *distr, int todo )
1265 {
1266 #define BUFSIZE 128
1267 const char *distr_name;
1268 static char last_distr_name[BUFSIZE] = "";
1269 unsigned int type;
1270 int i;
1271 int failed = 0;
1272 int dim;
1273 double *x = NULL;
1274 int errno_obs;
1275
1276 /* check input */
1277 if (distr == NULL) {
1278 printf(" [!!no distribution!!]" ); fflush(stdout);
1279 return UNUR_FAILURE;
1280 }
1281
1282 /* timer */
1283 stopwatch_lap(&vw);
1284
1285 /* get name of distribution */
1286 distr_name = unur_distr_get_name( distr );
1287
1288 /* get type of distribution */
1289 type = unur_distr_get_type( distr );
1290
1291 if (strcmp(distr_name,last_distr_name) ) {
1292 /* different distributions */
1293 strncpy(last_distr_name,distr_name,(size_t)BUFSIZE);
1294 last_distr_name[BUFSIZE-1] = '\0';
1295 printf(" %s",distr_name); fflush(stdout);
1296 }
1297
1298 if (todo == '.') {
1299 /* nothing to do */
1300 printf("."); fflush(stdout);
1301 return UNUR_SUCCESS;
1302 }
1303
1304 if (todo == '0') {
1305 /* initialization of generator is expected to fail */
1306 if (gen == NULL) {
1307 printf("0"); fflush(stdout);
1308 print_verifyhat_result(LOG,gen,distr,-1,todo);
1309 return UNUR_SUCCESS;
1310 }
1311 else {
1312 /* error */
1313 printf("(!0)"); fflush(stdout);
1314 return UNUR_FAILURE;
1315 }
1316 }
1317
1318 if (gen == NULL) {
1319 if (todo == '-') {
1320 printf("-"); fflush(stdout);
1321 print_verifyhat_result(LOG,gen,distr,-1,todo);
1322 return UNUR_SUCCESS;
1323 }
1324 else {
1325 /* initialization failed --> cannot run test */
1326 printf("(!+)"); fflush(stdout);
1327 print_verifyhat_result(LOG,gen,distr,-1,todo);
1328 return UNUR_FAILURE;
1329 }
1330 }
1331
1332 /* get dimension of distribution */
1333 dim = unur_get_dimension (gen);
1334
1335 /* allocate working space */
1336 if (dim > 0) {
1337 x = malloc( dim * sizeof(double) );
1338 abort_if_NULL(LOG, line, x);
1339 }
1340
1341 /* run verify hat test */
1342 for (i=0; i<VERIFYHAT_SAMPLESIZE; i++) {
1343
1344 unur_reset_errno();
1345 switch (type) {
1346 case UNUR_DISTR_DISCR:
1347 unur_sample_discr(gen);
1348 break;
1349 case UNUR_DISTR_CONT:
1350 case UNUR_DISTR_CEMP:
1351 unur_sample_cont(gen);
1352 break;
1353 case UNUR_DISTR_CVEC:
1354 unur_sample_vec(gen,x);
1355 break;
1356 default:
1357 fprintf(stderr, "\n%s:%d: run_validate_verifyhat: this should not happen\n", __FILE__, __LINE__);
1358 exit (EXIT_FAILURE);
1359 }
1360
1361 if ((errno_obs = unur_get_errno())) {
1362 /* error */
1363 if (errno_obs == UNUR_ERR_GEN_CONDITION)
1364 failed++;
1365 unur_reset_errno();
1366 }
1367
1368 }
1369
1370 /* free working space */
1371 if (x!=NULL) free(x);
1372
1373 return print_verifyhat_result(LOG,gen,distr,failed,todo);
1374
1375 } /* end of run_validate_verifyhat() */
1376
1377 /*---------------------------------------------------------------------------*/
1378 /* print result of verify hat test */
1379
print_verifyhat_result(FILE * LOG,UNUR_GEN * gen,const UNUR_DISTR * distr,int failed,int todo)1380 int print_verifyhat_result( FILE *LOG, UNUR_GEN *gen, const UNUR_DISTR *distr,
1381 int failed, int todo )
1382 {
1383 int failed_test = 0;
1384 double failed_ratio = ((double)failed) / VERIFYHAT_SAMPLESIZE;
1385
1386 if (failed >= 0) {
1387 fprintf(LOG," failures = %d (%g%%) ",failed, 100. * failed_ratio);
1388 switch (todo) {
1389 case '+':
1390 if (failed > 0) {
1391 fprintf(LOG,"\t Failed");
1392 printf("(!+)");
1393 failed_test = 1;
1394 }
1395 else {
1396 fprintf(LOG,"\t ok");
1397 printf("+");
1398 }
1399 break;
1400 case '~':
1401 if (failed == 0) {
1402 fprintf(LOG,"\t ok");
1403 printf("+");
1404 }
1405 else if (failed_ratio <= 0.01) {
1406 fprintf(LOG,"\t tolerated");
1407 printf("(~+)");
1408 }
1409 else {
1410 fprintf(LOG,"\t Failed");
1411 printf("(!~+)");
1412 failed_test = 1;
1413 }
1414 break;
1415 case '-':
1416 if (failed_ratio > 0.01) {
1417 /* in this case it is expected to fail */
1418 fprintf(LOG,"\t ok (expected to fail)");
1419 printf("-");
1420 }
1421 else {
1422 /* the test has failed which was not what we have expected */
1423 fprintf(LOG,"\t Not ok (expected to fail)");
1424 printf("(!-)");
1425 failed_test = 1;
1426 }
1427 break;
1428 default:
1429 fprintf(stderr,"%s:%d: invalid test symbol\n", __FILE__, __LINE__);
1430 exit (EXIT_FAILURE);
1431 }
1432 }
1433
1434 else {
1435 fprintf(LOG," setup failed\t");
1436 switch (todo) {
1437 case '0':
1438 case '-':
1439 fprintf(LOG,"\t ok (expected to fail)");
1440 break;
1441 default:
1442 fprintf(LOG,"\t Failed");
1443 }
1444 }
1445
1446 /* timing */
1447 stopwatch_print(LOG,"\ttime=%.1f ms ", stopwatch_lap(&vw));
1448
1449 /* print distribution name */
1450 fprintf(LOG,"\t");
1451 print_distr_name( LOG, distr, gen ? unur_get_genid(gen):"???\t" );
1452 fprintf(LOG,"\n");
1453
1454 fflush(stdout);
1455 fflush(LOG);
1456
1457 return (failed_test ? UNUR_ERR_SILENT : UNUR_SUCCESS);
1458
1459 } /* end of print_verifyhat_result() */
1460 #undef VERIFYHAT_SAMPLESIZE
1461
1462 /*---------------------------------------------------------------------------*/
1463 /* print result of timings */
1464
print_timing_results(FILE * LOG,int line ATTRIBUTE__UNUSED,const UNUR_DISTR * distr,double * timing_setup,double * timing_marginal,int n_results)1465 void print_timing_results( FILE *LOG, int line ATTRIBUTE__UNUSED, const UNUR_DISTR *distr,
1466 double *timing_setup, double *timing_marginal, int n_results )
1467 {
1468 const char *distr_name;
1469 static const char *last_distr_name = "";
1470 int i;
1471
1472 /* get name of distribution */
1473 distr_name = unur_distr_get_name( distr );
1474
1475 if (strcmp(distr_name,last_distr_name) ) {
1476 /* different distributions */
1477 last_distr_name = distr_name;
1478 printf(" %s=",distr_name); fflush(stdout);
1479 }
1480 else {
1481 printf("="); fflush(stdout);
1482 }
1483
1484 /* print timings into log file */
1485 for (i=0; i<n_results; i++)
1486 if (timing_marginal[i] < 0.)
1487 /* no test */
1488 fprintf(LOG, " / ");
1489 else
1490 fprintf(LOG, "%5.0f /%7.2f ", timing_setup[i], timing_marginal[i]);
1491
1492 /* print name of distribution into log file */
1493 fprintf(LOG,"\t");
1494 print_distr_name( LOG, distr, NULL );
1495 fprintf(LOG,"\n");
1496
1497 } /* end of print_timing_results() */
1498
1499 /*---------------------------------------------------------------------------*/
1500 /* run test for u-error of inversion method and print results */
1501
run_validate_u_error(FILE * LOG,UNUR_GEN * gen,const UNUR_DISTR * distr,double u_resolution,int samplesize)1502 int run_validate_u_error( FILE *LOG, UNUR_GEN *gen, const UNUR_DISTR *distr,
1503 double u_resolution, int samplesize )
1504 {
1505 double maxerror, MAE; /* maximum observed and mean absolute u-error */
1506 double score; /* penalty score of inversion error test */
1507 const char *genid;
1508
1509 /* check objectst */
1510 if (gen == NULL || distr == NULL) {
1511 fprintf(LOG,"test_inverror: ERROR: generator not initialized\n");
1512 printf("(!!+)"); fflush(stdout);
1513 return 1000;
1514 }
1515
1516 /* get generator id */
1517 genid = unur_get_genid(gen);
1518
1519 /* run test */
1520 score = unur_test_u_error(gen, &maxerror, &MAE, u_resolution, samplesize,
1521 FALSE, TEST_INVERROR_TAILS, TRUE, LOG);
1522
1523 /* check score */
1524 if (score < 0.) {
1525 /* an error has occured */
1526 fprintf(LOG,"%s: ERROR: could not run test\n",genid);
1527 printf("(!!+)"); fflush(stdout);
1528 return 3;
1529 }
1530
1531 /* print result into log file */
1532 fprintf(LOG,"%s: result: max u-error = %g, MAE = %g ",genid,maxerror,MAE);
1533 if (maxerror > u_resolution) {
1534 fprintf(LOG,"(NOT <= %g)\n",u_resolution);
1535 fprintf(LOG,"%s: Warning: precision problem, maxerror > u_resolution\n",genid);
1536 }
1537 else {
1538 fprintf(LOG,"(<= %g)\n",u_resolution);
1539 }
1540
1541 fprintf(LOG,"%s: score = %5.2f %%\t--> %s\n", genid,
1542 score*100, (score<0.001) ? "passed" : "failed");
1543
1544 /* print result of test on screen and return result */
1545 if (score == 0.) {
1546 printf("+"); fflush(stdout);
1547 return 0;
1548 }
1549 if (score < 0.001) {
1550 printf("(?+)"); fflush(stdout);
1551 return 1;
1552 }
1553 else {
1554 printf("(!+)"); fflush(stdout);
1555 return 2;
1556 }
1557
1558 } /* end of run_validate_u_error() */
1559
1560 /*---------------------------------------------------------------------------*/
1561