1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 /* random.c for gretl: RNGs */
21
22 #include "libgretl.h"
23 #include <time.h>
24
25 #ifdef HAVE_MPI
26 # include "gretl_mpi.h"
27 #endif
28
29 #if defined(USE_AVX) || defined(USE_SSE2)
30 # define HAVE_SSE2
31 #else
32 # ifdef HAVE_SSE2
33 # undef HAVE_SSE2
34 # endif
35 #endif
36
37 #if defined(_OPENMP) && !defined(OS_OSX)
38 # include <omp.h>
39 #endif
40
41 /* For optimizing the Ziggurat */
42 #if defined(i386) || defined (__i386__)
43 # define HAVE_X86_32 1
44 # define UMASK 0x80000000UL /* most significant w-r bits */
45 #else
46 # define HAVE_X86_32 0
47 #endif
48
49 #define SFMT_MEXP 19937
50
51 #include "../../rng/SFMT.c"
52 #include "../../dcmt/dc.h"
53
54 /**
55 * SECTION:random
56 * @short_description: generate pseudo-random values
57 * @title: PRNG
58 * @include: libgretl.h
59 *
60 * Libgretl uses the Mersenne Twister as its underlying engine
61 * for uniform random values, but offers added value in
62 * the form of generators for several distributions commonly
63 * used in econometrics.
64 *
65 * Note that before using the libgretl PRNG you must call
66 * either libgretl_init() or the specific initialization
67 * function shown below, gretl_rand_init(). And once you're
68 * finished with it, you may call gretl_rand_free() or the
69 * global libgretl function libgretl_cleanup().
70 */
71
72 static sfmt_t gretl_sfmt;
73 static guint32 sfmt_seed;
74
75 /* alternate SFMT */
76 static sfmt_t gretl_alt_sfmt;
77 static guint32 alt_sfmt_seed;
78
79 #define sfmt_rand32() sfmt_genrand_uint32(&gretl_sfmt)
80 #define sfmt_alt_rand32() sfmt_genrand_uint32(&gretl_alt_sfmt)
81
82 /* Find n independent "small" Mersenne Twisters with period 2^521-1;
83 set the one corresponding to @self as the one to use
84 */
85
86 static mt_struct *dcmt;
87 static guint32 dcmt_seed;
88 static int use_dcmt = 0;
89
90 #define dcmt_rand32() genrand_mt(dcmt)
91
set_up_dcmt(int n,int self,unsigned int seed)92 static int set_up_dcmt (int n, int self, unsigned int seed)
93 {
94 mt_struct **mtss;
95 int w = 32;
96 int p = 521; /* period = 2^521-1 =~ 6.9e+156 */
97 int dseed = 4172;
98 int i, count = 0;
99
100 mtss = get_mt_parameters_st(w, p, 0, n - 1, dseed, &count);
101 if (mtss == NULL) {
102 fprintf(stderr, "Couldn't get MT parameters\n");
103 return E_DATA;
104 }
105
106 #if 0
107 fprintf(stderr, "set_up_dcmt: set up %d MTs, self = %d\n", n, self);
108 #endif
109
110 use_dcmt = 1;
111 dcmt_seed = seed != 0 ? seed : time(NULL);
112
113 for (i=0; i<count; i++) {
114 if (i == self) {
115 dcmt = mtss[i];
116 sgenrand_mt(dcmt_seed, dcmt);
117 } else {
118 free_mt_struct(mtss[i]);
119 }
120 }
121
122 free(mtss);
123
124 return 0;
125 }
126
127 #ifdef HAVE_MPI
128
dcmt_late_start(void)129 static int dcmt_late_start (void)
130 {
131 int np = gretl_mpi_n_processes();
132 int self = gretl_mpi_rank();
133 int err = 0;
134
135 if (np > 0 && self >= 0 && self < np) {
136 set_up_dcmt(np, self, 0);
137 } else {
138 err = E_DATA;
139 }
140
141 return err;
142 }
143
144 #endif
145
gretl_rand_set_dcmt(int s)146 int gretl_rand_set_dcmt (int s)
147 {
148 int err = 0;
149
150 if (s == use_dcmt) {
151 /* no-op */
152 return 0;
153 }
154
155 if (s) {
156 /* sfmt in use, dcmt requested */
157 if (dcmt == NULL) {
158 /* dcmt not set up already */
159 #ifdef HAVE_MPI
160 err = dcmt_late_start();
161 #else
162 err = E_DATA;
163 #endif
164 } else {
165 /* reset seed */
166 dcmt_seed = time(NULL);
167 sgenrand_mt(dcmt_seed, dcmt);
168 }
169 } else {
170 /* dcmt in use, sfmt requested */
171 gretl_rand_init();
172 }
173
174 if (err) {
175 gretl_errmsg_set("dcmt: not available");
176 } else {
177 use_dcmt = s;
178 }
179
180 return err;
181 }
182
gretl_rand_get_dcmt(void)183 int gretl_rand_get_dcmt (void)
184 {
185 return use_dcmt;
186 }
187
188 /**
189 * gretl_rand_init:
190 *
191 * Initialize gretl's PRNG, using the system time as seed.
192 * Default version, as opposed to DCMT.
193 */
194
gretl_rand_init(void)195 void gretl_rand_init (void)
196 {
197 char *fseed = getenv("GRETL_FORCE_SEED");
198
199 if (fseed != NULL) {
200 sfmt_seed = atoi(fseed);
201 } else {
202 sfmt_seed = time(NULL);
203 }
204
205 sfmt_init_gen_rand(&gretl_sfmt, sfmt_seed);
206 }
207
208 /**
209 * gretl_dcmt_init:
210 *
211 * Initialize DCMT, if needed.
212 */
213
gretl_dcmt_init(int n,int self,unsigned int seed)214 void gretl_dcmt_init (int n, int self, unsigned int seed)
215 {
216 if (n > 0 && self >= 0 && self < n) {
217 set_up_dcmt(n, self, seed);
218 }
219 }
220
221 /**
222 * gretl_rand_free:
223 *
224 * Free the gretl_rand structure (may be called at program exit).
225 */
226
gretl_rand_free(void)227 void gretl_rand_free (void)
228 {
229 if (dcmt != NULL) {
230 free_mt_struct(dcmt);
231 dcmt = NULL;
232 }
233 }
234
235 /**
236 * gretl_rand_get_seed:
237 *
238 * Returns: the value of the seed for gretl's PRNG.
239 */
240
gretl_rand_get_seed(void)241 unsigned int gretl_rand_get_seed (void)
242 {
243 if (use_dcmt) {
244 return dcmt_seed;
245 } else {
246 return sfmt_seed;
247 }
248 }
249
gretl_dcmt_set_seed(unsigned int seed)250 static void gretl_dcmt_set_seed (unsigned int seed)
251 {
252 dcmt_seed = seed;
253 sgenrand_mt(dcmt_seed, dcmt);
254 }
255
gretl_sfmt_set_seed(unsigned int seed)256 static void gretl_sfmt_set_seed (unsigned int seed)
257 {
258 sfmt_seed = seed;
259 sfmt_init_gen_rand(&gretl_sfmt, sfmt_seed);
260 }
261
gretl_alt_sfmt_set_seed(unsigned int seed)262 static void gretl_alt_sfmt_set_seed (unsigned int seed)
263 {
264 alt_sfmt_seed = seed;
265 sfmt_init_gen_rand(&gretl_alt_sfmt, alt_sfmt_seed);
266 }
267
268 /**
269 * gretl_rand_set_seed:
270 * @seed: the chosen seed value.
271 *
272 * Set a specific (and hence reproducible) seed for gretl's PRNG.
273 * But if the value 0 is given for @seed, set the seed using
274 * the system time (which is the default when libgretl is
275 * initialized).
276 */
277
gretl_rand_set_seed(unsigned int seed)278 void gretl_rand_set_seed (unsigned int seed)
279 {
280 seed = (seed == 0)? time(NULL) : seed;
281
282 if (use_dcmt) {
283 gretl_dcmt_set_seed(seed);
284 } else {
285 gretl_sfmt_set_seed(seed);
286 }
287 }
288
gretl_alt_rand_set_seed(unsigned int seed)289 void gretl_alt_rand_set_seed (unsigned int seed)
290 {
291 seed = (seed == 0)? time(NULL) : seed;
292
293 gretl_alt_sfmt_set_seed(seed);
294 }
295
296 /**
297 * gretl_rand_01:
298 *
299 * Returns: the next random double, equally distributed over
300 * the range [0, 1).
301 */
302
gretl_rand_01(void)303 double gretl_rand_01 (void)
304 {
305 if (use_dcmt) {
306 return sfmt_to_real2(dcmt_rand32());
307 } else {
308 return sfmt_to_real2(sfmt_rand32());
309 }
310 }
311
312 /* Select which 32 bit generator to use for Ziggurat */
313
randi32(void)314 static inline uint32_t randi32 (void)
315 {
316 if (use_dcmt) {
317 return genrand_mt(dcmt);
318 } else {
319 return sfmt_genrand_uint32(&gretl_sfmt);
320 }
321 }
322
323 #if !(HAVE_X86_32)
324
325 /* 53 bits for mantissa + 1 bit sign */
326
randi54(void)327 static uint64_t randi54 (void)
328 {
329 const uint32_t lo = randi32();
330 const uint32_t hi = randi32() & 0x3FFFFF;
331
332 return (((uint64_t) (hi) << 32) | lo);
333 }
334
335 #endif
336
337 /* generates a uniform random double on (0,1) with 53-bit resolution */
338
randu53(void)339 static double randu53 (void)
340 {
341 const uint32_t a = randi32() >> 5;
342 const uint32_t b = randi32() >> 6;
343
344 return (a*67108864.0+b+0.4) * (1.0/9007199254740992.0);
345 }
346
347 /* Ziggurat normal generator: this Ziggurat code here is shamelessly
348 filched from GNU Octave (with minor modifications), since it turned
349 out to be faster than what we had (until 2016-10-08), with no loss
350 in quality of the random normal variates (in fact, perhaps a gain).
351
352 See randmtzig.c in the Octave code-base. It appears that David
353 Bateman was the main author; anyway, thanks to whoever wrote the
354 implementation!
355 */
356
357 #define ZIGGURAT_TABLE_SIZE 256
358 #define ZIGGURAT_NOR_R 3.6541528853610088
359 #define ZIGGURAT_NOR_INV_R 0.27366123732975828
360 #define NOR_SECTION_AREA 0.00492867323399
361
362 #define ZIGINT uint64_t
363 #define NMANTISSA 9007199254740992.0 /* 53 bit mantissa */
364
365 static ZIGINT ki[ZIGGURAT_TABLE_SIZE];
366 static double wi[ZIGGURAT_TABLE_SIZE];
367 static double fi[ZIGGURAT_TABLE_SIZE];
368
369 static int initt = 1;
370
create_ziggurat_tables(void)371 static void create_ziggurat_tables (void)
372 {
373 int i;
374 double x, x1;
375
376 x1 = ZIGGURAT_NOR_R;
377 wi[255] = x1 / NMANTISSA;
378 fi[255] = exp(-0.5 * x1 * x1);
379
380 /* Index zero is special for tail strip, where Marsaglia and Tsang
381 defines this as:
382 k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,
383 where v is the area of each strip of the ziggurat.
384 */
385 ki[0] = (ZIGINT) (x1 * fi[255] / NOR_SECTION_AREA * NMANTISSA);
386 wi[0] = NOR_SECTION_AREA / fi[255] / NMANTISSA;
387 fi[0] = 1.;
388
389 for (i = 254; i > 0; i--) {
390 /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
391 need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))
392 */
393 x = sqrt (-2. * log(NOR_SECTION_AREA / x1 + fi[i+1]));
394 ki[i+1] = (ZIGINT) (x / x1 * NMANTISSA);
395 wi[i] = x / NMANTISSA;
396 fi[i] = exp(-0.5 * x * x);
397 x1 = x;
398 }
399
400 ki[1] = 0;
401
402 initt = 0;
403 }
404
405 /**
406 * gretl_one_snormal:
407 *
408 * Returns: a single drawing from the standard normal distribution.
409 */
410
gretl_one_snormal(void)411 double gretl_one_snormal (void)
412 {
413 if (initt) {
414 create_ziggurat_tables();
415 }
416
417 while (1) {
418 #if HAVE_X86_32
419 /* Specialized for x86 32-bit architecture: 53-bit mantissa,
420 1-bit sign
421 */
422 double x;
423 int si, idx;
424 uint32_t lo, hi;
425 int64_t rabs;
426 uint32_t *p = (uint32_t *) &rabs;
427
428 lo = randi32();
429 idx = lo & 0xFF;
430 hi = randi32();
431 si = hi & UMASK;
432 p[0] = lo;
433 p[1] = hi & 0x1FFFFF;
434 x = (si ? -rabs : rabs) * wi[idx];
435 #else
436 const uint64_t r = randi54();
437 const int64_t rabs = r >> 1;
438 const int idx = (int) (rabs & 0xFF);
439 const double x = ((r & 1) ? -rabs : rabs) * wi[idx];
440 #endif
441
442 if (rabs < (int64_t) (ki[idx])) {
443 return x; /* 99.3% of the time we return here 1st try */
444 } else if (idx == 0) {
445 /* As stated in Marsaglia and Tsang:
446 For the normal tail, the method of Marsaglia provides:
447 generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,
448 then return r+x. Except that r+x is always in the positive
449 tail. Anything random might be used to determine the
450 sign, but as we already have r we might as well use it.
451 */
452 double xx, yy;
453
454 do {
455 xx = - ZIGGURAT_NOR_INV_R * log(randu53());
456 yy = - log(randu53());
457 } while (yy+yy <= xx*xx);
458 return (rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx;
459 } else if ((fi[idx-1] - fi[idx]) * randu53() + fi[idx] < exp(-0.5*x*x)) {
460 return x;
461 }
462 }
463 }
464
465 /**
466 * gretl_rand_normal:
467 * @a: target array
468 * @t1: start of the fill range
469 * @t2: end of the fill range
470 *
471 * Fill the selected range of array @a with pseudo-random drawings
472 * from the standard normal distribution, using the Mersenne Twister
473 * for uniform input and the Ziggurat method for converting to the
474 * normal distribution.
475 */
476
gretl_rand_normal(double * a,int t1,int t2)477 void gretl_rand_normal (double *a, int t1, int t2)
478 {
479 int t;
480
481 for (t=t1; t<=t2; t++) {
482 a[t] = gretl_one_snormal();
483 }
484 }
485
486 /**
487 * gretl_rand_normal_full:
488 * @a: target array
489 * @t1: start of the fill range
490 * @t2: end of the fill range
491 * @mean: mean of the distribution
492 * @sd: standard deviation
493 *
494 * Fill the selected range of array @a with pseudo-random drawings
495 * from the normal distribution with the given mean and standard
496 * deviation, using the Mersenne Twister for uniform input and
497 * the Ziggurat method for converting to the normal distribution.
498 *
499 * Returns: 0 on success, 1 on invalid input.
500 */
501
gretl_rand_normal_full(double * a,int t1,int t2,double mean,double sd)502 int gretl_rand_normal_full (double *a, int t1, int t2,
503 double mean, double sd)
504 {
505 int t;
506
507 if (na(mean) && na(sd)) {
508 mean = 0.0;
509 sd = 1.0;
510 } else if (na(mean) || na(sd) || sd <= 0.0) {
511 return E_INVARG;
512 }
513
514 gretl_rand_normal(a, t1, t2);
515
516 if (mean != 0.0 || sd != 1.0) {
517 for (t=t1; t<=t2; t++) {
518 a[t] = mean + a[t] * sd;
519 }
520 }
521
522 return 0;
523 }
524
mt_int_range(guint32 begin,guint32 end,int alt)525 static guint32 mt_int_range (guint32 begin,
526 guint32 end,
527 int alt)
528 {
529 guint32 dist = end - begin;
530 guint32 rval = 0;
531
532 if (dist > 0) {
533 /* maxval is set to the predecessor of the greatest
534 multiple of dist less than or equal to 2^32
535 */
536 guint32 maxval;
537
538 if (dist <= 0x80000000u) { /* 2^31 */
539 /* maxval = 2^32 - 1 - (2^32 % dist) */
540 guint32 rem = (0x80000000u % dist) * 2;
541
542 if (rem >= dist) rem -= dist;
543 maxval = 0xffffffffu - rem;
544 } else {
545 maxval = dist - 1;
546 }
547
548 if (use_dcmt) {
549 do {
550 rval = dcmt_rand32();
551 } while (rval > maxval);
552 } else if (alt) {
553 do {
554 rval = sfmt_alt_rand32();
555 } while (rval > maxval);
556 } else {
557 do {
558 rval = sfmt_rand32();
559 } while (rval > maxval);
560 }
561
562 rval %= dist;
563 }
564
565 return begin + rval;
566 }
567
568 /**
569 * gretl_rand_uniform_minmax:
570 * @a: target array.
571 * @t1: start of the fill range.
572 * @t2: end of the fill range.
573 * @min: lower bound of range.
574 * @max: upper bound of range.
575 *
576 * Fill the selected subset of array @a with pseudo-random drawings
577 * from the uniform distribution on @min to @max, using the Mersenne
578 * Twister.
579 *
580 * Returns: 0 on success, 1 on invalid input.
581 */
582
gretl_rand_uniform_minmax(double * a,int t1,int t2,double min,double max)583 int gretl_rand_uniform_minmax (double *a, int t1, int t2,
584 double min, double max)
585 {
586 int t;
587
588 if (na(min) && na(max)) {
589 min = 0.0;
590 max = 1.0;
591 } else if (na(min) || na(max) || max <= min) {
592 return E_INVARG;
593 }
594
595 for (t=t1; t<=t2; t++) {
596 if (use_dcmt) {
597 a[t] = sfmt_to_real2(dcmt_rand32()) * (max - min) + min;
598 } else {
599 a[t] = sfmt_to_real2(sfmt_rand32()) * (max - min) + min;
600 }
601 }
602
603 return 0;
604 }
605
real_gretl_rand_int_minmax(int * a,int n,int min,int max,int alt)606 static int real_gretl_rand_int_minmax (int *a, int n,
607 int min, int max,
608 int alt)
609 {
610 int i, err = 0;
611
612 if (max < min) {
613 err = E_INVARG;
614 } else if (min == max) {
615 for (i=0; i<n; i++) {
616 a[i] = min;
617 }
618 } else {
619 int offset = 0;
620
621 if (min < 0) {
622 offset = -min;
623 max += offset;
624 min += offset;
625 }
626
627 for (i=0; i<n; i++) {
628 a[i] = mt_int_range(min, max + 1, alt) - offset;
629 }
630 }
631
632 return err;
633 }
634
635 /**
636 * gretl_rand_int_minmax:
637 * @a: target array.
638 * @n: length of array.
639 * @min: lower closed bound of range.
640 * @max: upper closed bound of range.
641 *
642 * Fill array @a of length @n with pseudo-random drawings
643 * from the uniform distribution on [@min, @max], using the
644 * Mersenne Twister.
645 *
646 * Returns: 0 on success, 1 on invalid input.
647 */
648
gretl_rand_int_minmax(int * a,int n,int min,int max)649 int gretl_rand_int_minmax (int *a, int n, int min, int max)
650 {
651 return real_gretl_rand_int_minmax(a, n, min, max, 0);
652 }
653
654 /**
655 * gretl_alt_rand_int_minmax:
656 * @a: target array.
657 * @n: length of array.
658 * @min: lower closed bound of range.
659 * @max: upper closed bound of range.
660 *
661 * Fill array @a of length @n with pseudo-random drawings
662 * from the uniform distribution on [@min, @max], using a
663 * Mersenne Twister which is independent of the main one
664 * employed by libgretl.
665 *
666 * Returns: 0 on success, 1 on invalid input.
667 */
668
gretl_alt_rand_int_minmax(int * a,int n,int min,int max)669 int gretl_alt_rand_int_minmax (int *a, int n, int min, int max)
670 {
671 return real_gretl_rand_int_minmax(a, n, min, max, 1);
672 }
673
already_selected(double * a,int n,double val,int offset)674 static int already_selected (double *a, int n, double val,
675 int offset)
676 {
677 int i;
678
679 for (i=0; i<n; i++) {
680 if (offset > 0) {
681 if (a[i] == val - offset) {
682 return 1;
683 }
684 } else if (a[i] == val) {
685 return 1;
686 }
687 }
688
689 return 0;
690 }
691
692 /**
693 * gretl_rand_uniform_int_minmax:
694 * @a: target array.
695 * @t1: start of the fill range.
696 * @t2: end of the fill range.
697 * @min: lower closed bound of range.
698 * @max: upper closed bound of range.
699 * @opt: include OPT_O for sampling without replacement.
700 *
701 * Fill the selected subset of array @a with pseudo-random drawings
702 * from the uniform distribution on [@min, @max], using the
703 * Mersenne Twister.
704 *
705 * Returns: 0 on success, 1 on invalid input.
706 */
707
gretl_rand_uniform_int_minmax(double * a,int t1,int t2,int min,int max,gretlopt opt)708 int gretl_rand_uniform_int_minmax (double *a, int t1, int t2,
709 int min, int max,
710 gretlopt opt)
711 {
712 int t, err = 0;
713
714 if (max < min) {
715 err = E_INVARG;
716 } else if (max == min) {
717 for (t=t1; t<=t2; t++) {
718 a[t] = min;
719 }
720 } else {
721 int i = 0, offset = 0;
722 double x;
723
724 if (min < 0) {
725 offset = -min;
726 max += offset;
727 min += offset;
728 }
729
730 for (t=t1; t<=t2; t++) {
731 x = mt_int_range(min, max + 1, 0);
732 if (opt & OPT_O) {
733 while (already_selected(a, i, x, offset)) {
734 x = mt_int_range(min, max + 1, 0);
735 }
736 }
737 a[t] = x - offset;
738 i++;
739 }
740 }
741
742 return err;
743 }
744
745 /**
746 * gretl_rand_uniform:
747 * @a: target array
748 * @t1: start of the fill range
749 * @t2: end of the fill range
750 *
751 * Fill the selected range of array @a with pseudo-random drawings
752 * from the uniform distribution on [0-1), using the Mersenne
753 * Twister.
754 */
755
gretl_rand_uniform(double * a,int t1,int t2)756 void gretl_rand_uniform (double *a, int t1, int t2)
757 {
758 int t;
759
760 if (use_dcmt) {
761 for (t=t1; t<=t2; t++) {
762 a[t] = sfmt_to_real2(dcmt_rand32());
763 }
764 } else {
765 for (t=t1; t<=t2; t++) {
766 a[t] = sfmt_to_real2(sfmt_rand32());
767 }
768 }
769 }
770
gretl_rand_uniform_one(void)771 static double gretl_rand_uniform_one (void)
772 {
773 if (use_dcmt) {
774 return sfmt_to_real2(dcmt_rand32());
775 } else {
776 return sfmt_to_real2(sfmt_rand32());
777 }
778 }
779
gretl_rand_gamma_one(double shape,double scale)780 double gretl_rand_gamma_one (double shape, double scale)
781 {
782 double k = shape;
783 double d, c, x, v, u, dv;
784
785 if (shape <= 0 || scale <= 0) {
786 return NADBL;
787 }
788
789 if (shape < 1) {
790 k = shape + 1.0;
791 }
792
793 d = k - 1.0/3;
794 c = 1.0 / sqrt(9*d);
795
796 while (1) {
797 x = gretl_one_snormal();
798 v = pow(1 + c*x, 3);
799 if (v > 0.0) {
800 dv = d * v;
801 u = gretl_rand_01();
802 /* apply squeeze */
803 if (u < 1 - 0.0331 * pow(x, 4) ||
804 log(u) < 0.5*x*x + d*(1-v+log(v))) {
805 break;
806 }
807 }
808 }
809 if (shape < 1) {
810 u = gretl_rand_01();
811 dv *= pow(u, 1/shape);
812 }
813
814 return dv * scale;
815 }
816
817 /* Marsaglia-Tsang, "A Simple Method for Generating Gamma Variables",
818 ACM Transactions on Mathematical Software, Vol. 26, No. 3,
819 September 2000, Pages 363372.
820
821 (1) Setup: d=a-1/3, c=1/sqrt(9*d).
822 (2) Generate v=(1+c*x)^3 with x normal; repeat if v <= 0.
823 (3) Generate uniform U.
824 (4) If U < 1-0.0331*x^4 return d*v.
825 (5) If log(U) < 0.5*x^2+d*(1-v+log(v)) return d*v.
826 (6) Go to step 2.
827 */
828
829 /**
830 * gretl_rand_gamma:
831 * @a: target array.
832 * @t1: start of the fill range.
833 * @t2: end of the fill range.
834 * @shape: shape parameter.
835 * @scale: scale parameter.
836 *
837 * Fill the selected range of array @a with pseudo-random drawings
838 * from the specified gamma distribution.
839 *
840 * Returns: 0 on success, non-zero on error.
841 */
842
gretl_rand_gamma(double * a,int t1,int t2,double shape,double scale)843 int gretl_rand_gamma (double *a, int t1, int t2,
844 double shape, double scale)
845 {
846 double k = shape;
847 double d, c, x, v, u, dv;
848 int t;
849
850 if (shape <= 0 || scale <= 0) {
851 return E_DATA;
852 }
853
854 if (shape < 1) {
855 k = shape + 1.0;
856 }
857
858 d = k - 1.0/3;
859 c = 1.0 / sqrt(9*d);
860
861 for (t=t1; t<=t2; t++) {
862 while (1) {
863 x = gretl_one_snormal();
864 v = pow(1 + c*x, 3);
865 if (v > 0.0) {
866 dv = d * v;
867 u = gretl_rand_01();
868 /* apply squeeze */
869 if (u < 1 - 0.0331 * pow(x, 4) ||
870 log(u) < 0.5*x*x + d*(1-v+log(v))) {
871 break;
872 }
873 }
874 }
875 if (shape < 1) {
876 u = gretl_rand_01();
877 dv *= pow(u, 1/shape);
878 }
879 a[t] = dv * scale;
880 }
881
882 return 0;
883 }
884
885 /**
886 * gretl_rand_chisq:
887 * @a: target array.
888 * @t1: start of the fill range.
889 * @t2: end of the fill range.
890 * @v: degrees of freedom.
891 *
892 * Fill the selected range of array @a with pseudo-random drawings
893 * from the Chi-squared distribution with @v degrees of freedom,
894 * using the gamma r.v. generator.
895 *
896 * Returns: 0 on success, non-zero on error.
897 */
898
gretl_rand_chisq(double * a,int t1,int t2,int v)899 int gretl_rand_chisq (double *a, int t1, int t2, int v)
900 {
901 return gretl_rand_gamma(a, t1, t2, 0.5*v, 2);
902 }
903
904 /**
905 * gretl_rand_student:
906 * @a: target array.
907 * @t1: start of the fill range.
908 * @t2: end of the fill range.
909 * @v: degrees of freedom.
910 *
911 * Fill the selected range of array @a with pseudo-random drawings
912 * from the Student t distribution with @v degrees of freedom,
913 * using the Mersenne Twister for uniform input and the ziggurat
914 * method for converting to the normal distribution.
915 *
916 * Returns: 0 on success, non-zero on error.
917 */
918
gretl_rand_student(double * a,int t1,int t2,double v)919 int gretl_rand_student (double *a, int t1, int t2, double v)
920 {
921 double *X2 = NULL;
922 int T = t2 - t1 + 1;
923 int t;
924
925 if (v <= 0) {
926 return E_INVARG;
927 }
928
929 X2 = malloc(T * sizeof *X2);
930 if (X2 == NULL) {
931 return E_ALLOC;
932 }
933
934 gretl_rand_normal(a, t1, t2);
935 gretl_rand_gamma(X2, 0, T-1, 0.5*v, 2);
936
937 for (t=0; t<T; t++) {
938 a[t + t1] /= sqrt(X2[t] / v);
939 }
940
941 free(X2);
942
943 return 0;
944 }
945
946 /**
947 * gretl_rand_F:
948 * @a: target array.
949 * @t1: start of the fill range.
950 * @t2: end of the fill range.
951 * @v1: numerator degrees of freedom.
952 * @v2: denominator degrees of freedom.
953 *
954 * Fill the selected range of array @a with pseudo-random drawings
955 * from the F distribution with @v1 and @v2 degrees of freedom,
956 * using the Mersenne Twister for uniform input and the Ziggurat
957 * method for converting to the normal distribution.
958 *
959 * Returns: 0 on success, non-zero on error.
960 */
961
gretl_rand_F(double * a,int t1,int t2,int v1,int v2)962 int gretl_rand_F (double *a, int t1, int t2, int v1, int v2)
963 {
964 double *b = NULL;
965 int T = t2 - t1 + 1;
966 int s, t;
967
968 if (v1 < 1 || v2 < 1) {
969 return E_INVARG;
970 }
971
972 b = malloc(T * sizeof *b);
973 if (b == NULL) {
974 return E_ALLOC;
975 }
976
977 gretl_rand_chisq(a, t1, t2, v1);
978 gretl_rand_chisq(b, 0, T-1, v2);
979
980 for (t=0; t<T; t++) {
981 s = t + t1;
982 a[s] = (a[s]/v1) / (b[t]/v2);
983 }
984
985 free(b);
986
987 return 0;
988 }
989
990 /**
991 * gretl_rand_binomial:
992 * @a: target array.
993 * @t1: start of the fill range.
994 * @t2: end of the fill range.
995 * @n: number of trials.
996 * @p: success probability per trial.
997 *
998 * Fill the selected range of array @a with pseudo-random drawings
999 * from the binomial distribution with parameters @n and @p.
1000 *
1001 * Returns: 0 on success, non-zero on error.
1002 */
1003
gretl_rand_binomial(double * a,int t1,int t2,int n,double p)1004 int gretl_rand_binomial (double *a, int t1, int t2, int n, double p)
1005 {
1006 int t;
1007
1008 if (n < 0 || p < 0 || p > 1) {
1009 return E_INVARG;
1010 }
1011
1012 if (n == 0 || p == 0.0) {
1013 for (t=t1; t<=t2; t++) {
1014 a[t] = 0.0;
1015 }
1016 } else if (p == 1.0) {
1017 for (t=t1; t<=t2; t++) {
1018 a[t] = n;
1019 }
1020 } else {
1021 double *b = malloc(n * sizeof *b);
1022 int i;
1023
1024 if (b == NULL) {
1025 return E_ALLOC;
1026 }
1027
1028 for (t=t1; t<=t2; t++) {
1029 a[t] = 0.0;
1030 gretl_rand_uniform(b, 0, n - 1);
1031 for (i=0; i<n; i++) {
1032 if (b[i] <= p) {
1033 a[t] += 1;
1034 }
1035 }
1036 }
1037
1038 free(b);
1039 }
1040
1041 return 0;
1042 }
1043
gretl_rand_binomial_one(int n,double p,double * b)1044 static double gretl_rand_binomial_one (int n, double p,
1045 double *b)
1046 {
1047 double ret;
1048
1049 if (n < 0 || p < 0 || p > 1) {
1050 return NADBL;
1051 }
1052
1053 if (n == 0 || p == 0.0) {
1054 ret = 0.0;
1055 } else if (p == 1.0) {
1056 ret = n;
1057 } else {
1058 int i;
1059
1060 ret = 0.0;
1061 gretl_rand_uniform(b, 0, n - 1);
1062 for (i=0; i<n; i++) {
1063 if (b[i] <= p) {
1064 ret += 1;
1065 }
1066 }
1067 }
1068
1069 return ret;
1070 }
1071
1072 /* Poisson rv with mean m */
1073
genpois(const double m)1074 static double genpois (const double m)
1075 {
1076 double x;
1077
1078 if (m > 200) {
1079 x = (m + 0.5) + sqrt(m) * gretl_one_snormal();
1080 x = floor(x);
1081 } else {
1082 int y = 0;
1083
1084 x = exp(m) * gretl_rand_01();
1085 while (x > 1) {
1086 y++;
1087 x *= gretl_rand_01();
1088 }
1089 x = (double) y;
1090 }
1091
1092 return x;
1093 }
1094
1095 /**
1096 * gretl_rand_poisson:
1097 * @a: target array.
1098 * @t1: start of the fill range.
1099 * @t2: end of the fill range.
1100 * @m: mean (see below).
1101 * @vec: should be 1 if @m is an array, else 0.
1102 *
1103 * Fill the selected range of array @a with pseudo-random drawings
1104 * from the Poisson distribution with a mean determined by
1105 * @m, which can either be a pointer to a scalar, or an array
1106 * of length greater than or equal to @t2 + 1.
1107 *
1108 * Returns: 0 on success, non-zero on error.
1109 */
1110
gretl_rand_poisson(double * a,int t1,int t2,const double * m,int vec)1111 int gretl_rand_poisson (double *a, int t1, int t2, const double *m,
1112 int vec)
1113 {
1114 double mt;
1115 int t;
1116
1117 for (t=t1; t<=t2; t++) {
1118 mt = (vec)? m[t] : *m;
1119 a[t] = (mt <= 0)? NADBL : genpois(mt);
1120 }
1121
1122 return 0;
1123 }
1124
1125 /* f(x; k, \lambda) = (k/\lambda) (x/\lambda)^{k-1} e^{-(x/\lambda)^k} */
1126
1127 /**
1128 * gretl_rand_weibull:
1129 * @a: target array.
1130 * @t1: start of the fill range.
1131 * @t2: end of the fill range.
1132 * @shape: shape parameter > 0.
1133 * @scale: scale parameter > 0.
1134 *
1135 * Fill the selected range of array @a with pseudo-random drawings
1136 * from the Weibull distribution with shape @k and scale @lambda.
1137 *
1138 * Returns: 0 on success, non-zero if either parameter is out of
1139 * bounds.
1140 */
1141
gretl_rand_weibull(double * a,int t1,int t2,double shape,double scale)1142 int gretl_rand_weibull (double *a, int t1, int t2, double shape,
1143 double scale)
1144 {
1145 int err = 0;
1146
1147 if (shape <= 0 || scale <= 0) {
1148 err = E_DATA;
1149 } else {
1150 double u, kinv = 1.0 / shape;
1151 int t;
1152
1153 for (t=t1; t<=t2; t++) {
1154 u = gretl_rand_01();
1155 while (u == 0.0) {
1156 u = gretl_rand_01();
1157 }
1158 a[t] = scale * pow(-log(u), kinv);
1159 }
1160 }
1161
1162 return err;
1163 }
1164
1165 /**
1166 * gretl_rand_exponential:
1167 * @a: target array.
1168 * @t1: start of the fill range.
1169 * @t2: end of the fill range.
1170 * @mu: scale parameter > 0.
1171 *
1172 * Fill the selected range of array @a with pseudo-random drawings
1173 * from the exponential distribution with scale @mu.
1174 *
1175 * Returns: 0 on success, non-zero if @mu is out of
1176 * bounds.
1177 */
1178
gretl_rand_exponential(double * a,int t1,int t2,double mu)1179 int gretl_rand_exponential (double *a, int t1, int t2, double mu)
1180 {
1181 int err = 0;
1182
1183 if (mu <= 0) {
1184 err = E_DATA;
1185 } else {
1186 double u;
1187 int t;
1188
1189 for (t=t1; t<=t2; t++) {
1190 u = gretl_rand_01();
1191 while (u == 0.0) {
1192 u = gretl_rand_01();
1193 }
1194 a[t] = -mu * log(u);
1195 }
1196 }
1197
1198 return err;
1199 }
1200
1201 /**
1202 * gretl_rand_logistic:
1203 * @a: target array.
1204 * @t1: start of the fill range.
1205 * @t2: end of the fill range.
1206 * @loc: location parameter.
1207 * @scale: scale parameter > 0.
1208 *
1209 * Fill the selected range of array @a with pseudo-random drawings
1210 * from the logistic distribution with location @loc and scale @scale.
1211 *
1212 * Returns: 0 on success, non-zero if @scale is out of
1213 * bounds.
1214 */
1215
gretl_rand_logistic(double * a,int t1,int t2,double loc,double scale)1216 int gretl_rand_logistic (double *a, int t1, int t2,
1217 double loc, double scale)
1218 {
1219 int err = 0;
1220
1221 if (scale <= 0) {
1222 err = E_DATA;
1223 } else {
1224 double u;
1225 int t;
1226
1227 for (t=t1; t<=t2; t++) {
1228 u = gretl_rand_01();
1229 while (u == 0.0) {
1230 u = gretl_rand_01();
1231 }
1232 a[t] = loc + scale * log(u / (1 - u));
1233 }
1234 }
1235
1236 return err;
1237 }
1238
1239 /**
1240 * gretl_rand_GED:
1241 * @a: target array.
1242 * @t1: start of the fill range.
1243 * @t2: end of the fill range.
1244 * @nu: shape parameter > 0.
1245 *
1246 * Fill the selected range of array @a with pseudo-random drawings
1247 * from the GED distribution with shape @nu. We exploit the fact that
1248 * if x ~ GED(n), then |x/k|^n is a Gamma rv.
1249 *
1250 * Returns: 0 on success, non-zero if @nu is out of bounds.
1251 */
1252
gretl_rand_GED(double * a,int t1,int t2,double nu)1253 int gretl_rand_GED (double *a, int t1, int t2, double nu)
1254 {
1255 int err, t;
1256 double p, scale;
1257
1258 if (nu < 0) {
1259 return E_INVARG;
1260 }
1261
1262 p = 1.0/nu;
1263 scale = pow(0.5, p) * sqrt(gammafun(p) / gammafun(3.0*p));
1264 err = gretl_rand_gamma(a, t1, t2, p, 2);
1265
1266 if (!err) {
1267 for (t=t1; t<=t2; t++) {
1268 a[t] = scale * pow(a[t], p);
1269 if (gretl_rand_01() < 0.5) {
1270 a[t] = -a[t];
1271 }
1272 }
1273 }
1274
1275 return err;
1276 }
1277
1278 /**
1279 * gretl_rand_laplace:
1280 * @a: target array.
1281 * @t1: start of the fill range.
1282 * @t2: end of the fill range.
1283 * @mu: mean.
1284 * @b: shape parameter > 0.
1285 *
1286 * Fill the selected range of array @a with pseudo-random drawings
1287 * from the Laplace distribution with mean @mu and scale @b.
1288 *
1289 * Returns: 0 on success, non-zero if @b is out of bounds.
1290 */
1291
gretl_rand_laplace(double * a,int t1,int t2,double mu,double b)1292 int gretl_rand_laplace (double *a, int t1, int t2,
1293 double mu, double b)
1294 {
1295 int t, sgn;
1296 double U;
1297
1298 if (b < 0) {
1299 return E_INVARG;
1300 }
1301
1302 /* uniform on [0,1) */
1303 gretl_rand_uniform(a, t1, t2);
1304
1305 for (t=t1; t<=t2; t++) {
1306 /* convert to (-1/2,1/2] */
1307 U = 0.5 - a[t];
1308 sgn = U < 0 ? -1 : 1;
1309 a[t] = mu - b*sgn * log(1 - 2*fabs(U));
1310 }
1311
1312 return 0;
1313 }
1314
1315 /**
1316 * gretl_rand_beta:
1317 * @x: target array.
1318 * @t1: start of the fill range.
1319 * @t2: end of the fill range.
1320 * @s1: shape parameter > 0.
1321 * @s2: shape parameter > 0.
1322 *
1323 * Fill the selected range of array @a with pseudo-random drawings
1324 * from the beta distribution with shape parameters @s1 and @s2.
1325 * The code here is adapted from http://www.netlib.org/random/random.f90
1326 * which implements the method of R.C.H. Cheng, "Generating beta
1327 * variates with nonintegral shape parameters", Communications of the
1328 * ACM, 21(4), April 1978.
1329 *
1330 * Returns: 0 on success, non-zero if @s1 or @s2 are out of bounds.
1331 */
1332
gretl_rand_beta(double * x,int t1,int t2,double s1,double s2)1333 int gretl_rand_beta (double *x, int t1, int t2,
1334 double s1, double s2)
1335 {
1336 double aln4 = 1.3862944;
1337 double a, b, s, u, v, y, z;
1338 double d, f, h, u0, c;
1339 int t, j, swap;
1340 double val;
1341
1342 if (s1 <= 0 || s2 <= 0) {
1343 return E_DATA;
1344 }
1345
1346 /* initialization */
1347 a = s1;
1348 b = s2;
1349 swap = b > a;
1350 if (swap) {
1351 f = b;
1352 b = a;
1353 a = f;
1354 }
1355 d = a/b;
1356 f = a+b;
1357 if (b > 1) {
1358 h = sqrt((2*a*b - f)/(f - 2.0));
1359 u0 = 1.0;
1360 } else {
1361 h = b;
1362 u0 = 1.0/(1.0 + pow(a/(DBL_MAX*b), b));
1363 }
1364 c = a+h;
1365
1366 /* generation */
1367 for (t=t1; t<=t2; t++) {
1368 for (j=0; ; j++) {
1369 u = gretl_rand_uniform_one();
1370 v = gretl_rand_uniform_one();
1371 s = u * u * v;
1372 if (u < DBL_MIN || s <= 0) continue;
1373 if (u < u0) {
1374 v = log(u/(1.0 - u))/h;
1375 y = d*exp(v);
1376 z = c*v + f*log((1.0 + d)/(1.0 + y)) - aln4;
1377 if (s - 1.0 > z) {
1378 if (s - s*z > 1.0) continue;
1379 if (log(s) > z) continue;
1380 }
1381 val = y/(1.0 + y);
1382 } else {
1383 if (4.0*s > pow(1.0 + 1.0/d, f)) continue;
1384 val = 1.0;
1385 }
1386 break;
1387 }
1388
1389 x[t] = swap ? (1.0 - val) : val;
1390 }
1391
1392 return 0;
1393 }
1394
1395 /**
1396 * gretl_rand_beta_binomial:
1397 * @x: target array.
1398 * @t1: start of the fill range.
1399 * @t2: end of the fill range.
1400 * @n: number of trials.
1401 * @s1: beta shape parameter > 0.
1402 * @s2: beta shape parameter > 0.
1403 *
1404 * Fill the selected range of array @x with pseudo-random drawings
1405 * from the binomial distribution with @n trials and success
1406 * probability distributed according to the beta distribution with
1407 * shape parameters @s1 and @s2.
1408 *
1409 * Returns: 0 on success, non-zero if @n, @s1 or @s2 are out of bounds.
1410 */
1411
gretl_rand_beta_binomial(double * x,int t1,int t2,int n,double s1,double s2)1412 int gretl_rand_beta_binomial (double *x, int t1, int t2,
1413 int n, double s1, double s2)
1414 {
1415 int t, err;
1416
1417 err = gretl_rand_beta(x, t1, t2, s1, s2);
1418
1419 if (!err) {
1420 double *b = malloc(n * sizeof *b);
1421
1422 if (b == NULL) {
1423 return E_ALLOC;
1424 } else {
1425 for (t=t1; t<=t2; t++) {
1426 x[t] = gretl_rand_binomial_one(n, x[t], b);
1427 }
1428 free(b);
1429 }
1430 }
1431
1432 return err;
1433 }
1434
1435 /**
1436 * gretl_rand_int_max:
1437 * @max: the maximum value (open)
1438 *
1439 * Returns: a pseudo-random unsigned int in the interval
1440 * [0, max-1] using the Mersenne Twister.
1441 */
1442
gretl_rand_int_max(unsigned int max)1443 unsigned int gretl_rand_int_max (unsigned int max)
1444 {
1445 return mt_int_range(0, max, 0);
1446 }
1447
1448 /**
1449 * gretl_rand_int:
1450 *
1451 * Returns: a pseudo-random unsigned int on the interval
1452 * [0, 2^32-1] using the Mersenne Twister.
1453 */
1454
gretl_rand_int(void)1455 unsigned int gretl_rand_int (void)
1456 {
1457 if (use_dcmt) {
1458 return dcmt_rand32();
1459 } else {
1460 return sfmt_rand32();
1461 }
1462 }
1463
gretl_alt_rand_int(void)1464 unsigned int gretl_alt_rand_int (void)
1465 {
1466 return sfmt_alt_rand32();
1467 }
1468
halton(int i,int base)1469 static double halton (int i, int base)
1470 {
1471 double f = 1.0 / base;
1472 double h = 0.0;
1473
1474 while (i > 0) {
1475 h += f * (i % base);
1476 i = floor(i / base);
1477 f /= base;
1478 }
1479
1480 return h;
1481 }
1482
1483 /**
1484 * halton_matrix:
1485 * @m: number of rows (sequences); the maximum is 40.
1486 * @r: number of columns (elements in each sequence).
1487 * @offset: the number of initial values to discard.
1488 * @err: location to receive error code.
1489 *
1490 * Returns: an @m x @r matrix containing @m Halton
1491 * sequences. The sequences are contructed using the first
1492 * @m primes, and the first @offset elements of each sequence
1493 * are discarded.
1494 */
1495
halton_matrix(int m,int r,int offset,int * err)1496 gretl_matrix *halton_matrix (int m, int r, int offset, int *err)
1497 {
1498 const int bases[] = {
1499 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
1500 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
1501 79, 83, 89, 97, 101, 103, 107, 109, 113,
1502 127, 131, 137, 139, 149, 151, 157, 163,
1503 167, 173, 179, 181
1504 };
1505 gretl_matrix *H;
1506 double hij;
1507 int i, j, k, n;
1508
1509 if (m > 40 || offset < 0 || m <= 0 || r <= 0) {
1510 *err = E_DATA;
1511 return NULL;
1512 }
1513
1514 H = gretl_matrix_alloc(m, r);
1515 if (H == NULL) {
1516 *err = E_ALLOC;
1517 return NULL;
1518 }
1519
1520 /* we'll discard the first @offset elements */
1521 n = r + offset;
1522
1523 for (i=0; i<m; i++) {
1524 j = 0;
1525 for (k=1; k<n; k++) {
1526 hij = halton(k, bases[i]);
1527 if (k >= offset) {
1528 gretl_matrix_set(H, i, j++, hij);
1529 }
1530 }
1531 }
1532
1533 return H;
1534 }
1535
1536 static gretl_matrix *
cholesky_factor_of_inverse(const gretl_matrix * S,int * err)1537 cholesky_factor_of_inverse (const gretl_matrix *S, int *err)
1538 {
1539 gretl_matrix *C = gretl_matrix_copy(S);
1540
1541 if (C == NULL) {
1542 *err = E_ALLOC;
1543 } else {
1544 *err = gretl_invert_symmetric_matrix(C);
1545 if (!*err) {
1546 *err = gretl_matrix_cholesky_decomp(C);
1547 }
1548 }
1549
1550 return C;
1551 }
1552
wishart_workspace(gretl_matrix ** pW,gretl_matrix ** pB,double ** pZ,int p)1553 static int wishart_workspace (gretl_matrix **pW,
1554 gretl_matrix **pB,
1555 double **pZ,
1556 int p)
1557 {
1558 int err = 0;
1559
1560 *pW = gretl_matrix_alloc(p, p);
1561
1562 if (*pW == NULL) {
1563 return E_ALLOC;
1564 }
1565
1566 *pB = gretl_matrix_alloc(p, p);
1567
1568 if (*pB == NULL) {
1569 err = E_ALLOC;
1570 } else {
1571 int n = p * (p + 1) / 2;
1572
1573 *pZ = malloc(n * sizeof **pZ);
1574 if (*pZ == NULL) {
1575 err = E_ALLOC;
1576 } else {
1577 gretl_rand_normal(*pZ, 0, n - 1);
1578 }
1579 }
1580
1581 if (err) {
1582 gretl_matrix_free(*pW);
1583 gretl_matrix_free(*pB);
1584 }
1585
1586 return err;
1587 }
1588
wishart_inverse_finalize(const gretl_matrix * C,gretl_matrix * B,gretl_matrix * W)1589 static int wishart_inverse_finalize (const gretl_matrix *C,
1590 gretl_matrix *B,
1591 gretl_matrix *W)
1592 {
1593 gretl_matrix_qform(C, GRETL_MOD_NONE,
1594 W, B, GRETL_MOD_NONE);
1595 gretl_matrix_copy_values(W, B);
1596
1597 return gretl_invert_symmetric_matrix(W);
1598 }
1599
odell_feiveson_compute(gretl_matrix * W,double * Z,int v)1600 static void odell_feiveson_compute (gretl_matrix *W,
1601 double *Z,
1602 int v)
1603 {
1604 double Xi, Zri, Zrj;
1605 double wii, wij;
1606 int p = W->rows;
1607 int i, j, r;
1608
1609 for (i=0; i<p; i++) {
1610 gretl_rand_chisq(&Xi, 0, 0, v - i);
1611 wii = Xi;
1612 for (r=0; r<i; r++) {
1613 Zri = Z[ijton(r, i, p)];
1614 wii += Zri * Zri;
1615 }
1616 gretl_matrix_set(W, i, i, wii);
1617 for (j=i+1; j<p; j++) {
1618 wij = Z[ijton(i, j, p)] * sqrt(Xi);
1619 for (r=0; r<i; r++) {
1620 Zri = Z[ijton(r, i, p)];
1621 Zrj = Z[ijton(r, j, p)];
1622 wij += Zri * Zrj;
1623 }
1624 gretl_matrix_set(W, i, j, wij);
1625 gretl_matrix_set(W, j, i, wij);
1626 }
1627 }
1628 }
1629
1630 /**
1631 * inverse_wishart_matrix:
1632 * @S: p x p positive definite scale matrix.
1633 * @v: degrees of freedom.
1634 * @err: location to receive error code.
1635 *
1636 * Computes a draw from the Inverse Wishart distribution
1637 * with @v degrees of freedom, using the method of Odell and
1638 * Feiveson, "A numerical procedure to generate a sample
1639 * covariance matrix", JASA 61, pp. 199203, 1966.
1640 *
1641 * Returns: a p x p Inverse Wishart matrix, or NULL on error.
1642 */
1643
inverse_wishart_matrix(const gretl_matrix * S,int v,int * err)1644 gretl_matrix *inverse_wishart_matrix (const gretl_matrix *S,
1645 int v, int *err)
1646 {
1647 gretl_matrix *C, *B = NULL, *W = NULL;
1648 double *Z = NULL;
1649
1650 if (S == NULL || S->cols != S->rows || v < S->rows) {
1651 *err = E_INVARG;
1652 return NULL;
1653 }
1654
1655 *err = 0;
1656
1657 /* copy, invert and decompose S */
1658 C = cholesky_factor_of_inverse(S, err);
1659
1660 if (!*err) {
1661 *err = wishart_workspace(&W, &B, &Z, S->rows);
1662 }
1663
1664 if (*err) {
1665 gretl_matrix_free(C);
1666 return NULL;
1667 }
1668
1669 odell_feiveson_compute(W, Z, v);
1670 *err = wishart_inverse_finalize(C, B, W);
1671
1672 if (*err) {
1673 gretl_matrix_free(W);
1674 W = NULL;
1675 }
1676
1677 gretl_matrix_free(B);
1678 gretl_matrix_free(C);
1679 free(Z);
1680
1681 return W;
1682 }
1683
vech_into_row(gretl_matrix * targ,int row,const gretl_matrix * m)1684 static void vech_into_row (gretl_matrix *targ, int row,
1685 const gretl_matrix *m)
1686 {
1687 double mij;
1688 int n = m->rows;
1689 int i, j, jj = 0;
1690
1691 for (i=0; i<n; i++) {
1692 for (j=i; j<n; j++) {
1693 mij = gretl_matrix_get(m, i, j);
1694 gretl_matrix_set(targ, row, jj++, mij);
1695 }
1696 }
1697 }
1698
inverse_wishart_sequence(const gretl_matrix * S,int v,int replics,int * err)1699 gretl_matrix *inverse_wishart_sequence (const gretl_matrix *S,
1700 int v, int replics,
1701 int *err)
1702 {
1703 gretl_matrix *C, *B = NULL, *W = NULL;
1704 gretl_matrix *Seq = NULL;
1705 double *Z = NULL;
1706 int k, np = 0;
1707
1708 if (S == NULL || S->cols != S->rows || v < S->rows) {
1709 *err = E_INVARG;
1710 return NULL;
1711 }
1712
1713 if (replics < 1) {
1714 *err = E_INVARG;
1715 return NULL;
1716 }
1717
1718 *err = 0;
1719
1720 /* copy, invert and decompose S */
1721 C = cholesky_factor_of_inverse(S, err);
1722
1723 if (!*err) {
1724 *err = wishart_workspace(&W, &B, &Z, S->rows);
1725 }
1726
1727 if (!*err) {
1728 int p = S->rows;
1729
1730 np = p * (p + 1) / 2;
1731 Seq = gretl_matrix_alloc(replics, np);
1732 if (Seq == NULL) {
1733 *err = E_ALLOC;
1734 }
1735 }
1736
1737 for (k=0; k<replics && !*err; k++) {
1738 odell_feiveson_compute(W, Z, v);
1739 *err = wishart_inverse_finalize(C, B, W);
1740 if (!*err) {
1741 /* write vech of W into row k of Seq */
1742 vech_into_row(Seq, k, W);
1743 if (k < replics - 1) {
1744 /* refresh Normal draws */
1745 gretl_rand_normal(Z, 0, np - 1);
1746 }
1747 }
1748 }
1749
1750 gretl_matrix_free(C);
1751 gretl_matrix_free(W);
1752 gretl_matrix_free(B);
1753 free(Z);
1754
1755 if (*err && Seq != NULL) {
1756 gretl_matrix_free(Seq);
1757 Seq = NULL;
1758 }
1759
1760 return Seq;
1761 }
1762