1 /*
2     vcflib C++ library for parsing and manipulating VCF files
3 
4     Copyright © 2010-2020 Erik Garrison
5     Copyright © 2020      Pjotr Prins
6 
7     This software is published under the MIT License. See the LICENSE file.
8 */
9 
10 # include <cstdlib>
11 # include <iostream>
12 # include <iomanip>
13 # include <ctime>
14 
15 using namespace std;
16 
17 # include "rnglib.hpp"
18 
19 //****************************************************************************80
20 
advance_state(int k)21 void advance_state ( int k )
22 
23 //****************************************************************************80
24 //
25 //  Purpose:
26 //
27 //    ADVANCE_STATE advances the state of the current generator.
28 //
29 //  Discussion:
30 //
31 //    This procedure advances the state of the current generator by 2^K
32 //    values and resets the initial seed to that value.
33 //
34 //  Licensing:
35 //
36 //    This code is distributed under the GNU LGPL license.
37 //
38 //  Modified:
39 //
40 //    30 March 2013
41 //
42 //  Author:
43 //
44 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
45 //    C++ version by John Burkardt.
46 //
47 //  Reference:
48 //
49 //    Pierre LEcuyer, Serge Cote,
50 //    Implementing a Random Number Package with Splitting Facilities,
51 //    ACM Transactions on Mathematical Software,
52 //    Volume 17, Number 1, March 1991, pages 98-111.
53 //
54 //  Parameters:
55 //
56 //    Input, int K, indicates that the generator is to be
57 //    advanced by 2^K values.
58 //    0 <= K.
59 //
60 {
61   const int a1 = 40014;
62   const int a2 = 40692;
63   int b1;
64   int b2;
65   int cg1;
66   int cg2;
67   int g;
68   int i;
69   const int m1 = 2147483563;
70   const int m2 = 2147483399;
71 
72   if ( k < 0 )
73   {
74     cerr << "\n";
75     cerr << "ADVANCE_STATE - Fatal error!\n";
76     cerr << "  Input exponent K is out of bounds.\n";
77     exit ( 1 );
78   }
79 //
80 //  Check whether the package must be initialized.
81 //
82   if ( ! initialized_get ( ) )
83   {
84     cout << "\n";
85     cout << "ADVANCE_STATE - Note:\n";
86     cout << "  Initializing RNGLIB package.\n";
87     initialize ( );
88   }
89 //
90 //  Get the current generator index.
91 //
92   g = cgn_get ( );
93 
94   b1 = a1;
95   b2 = a2;
96 
97   for ( i = 1; i <= k; k++ )
98   {
99     b1 = multmod ( b1, b1, m1 );
100     b2 = multmod ( b2, b2, m2 );
101   }
102 
103   cg_get ( g, cg1, cg2 );
104   cg1 = multmod ( b1, cg1, m1 );
105   cg2 = multmod ( b2, cg2, m2 );
106   cg_set ( g, cg1, cg2 );
107 
108   return;
109 }
110 //****************************************************************************80
111 
antithetic_get()112 bool antithetic_get ( )
113 
114 //***************************************************************************80
115 //
116 //  Purpose:
117 //
118 //    ANTITHETIC_GET queries the antithetic value for a given generator.
119 //
120 //  Licensing:
121 //
122 //    This code is distributed under the GNU LGPL license.
123 //
124 //  Modified:
125 //
126 //    02 April 2013
127 //
128 //  Author:
129 //
130 //    John Burkardt
131 //
132 //  Parameters:
133 //
134 //    Output, bool ANTITHETIC_GET, is TRUE if generator G is antithetic.
135 //
136 {
137   int i;
138   bool value;
139 
140   i = -1;
141   antithetic_memory ( i, value );
142 
143   return value;
144 }
145 //****************************************************************************80
146 
antithetic_memory(int i,bool & value)147 void antithetic_memory ( int i, bool &value )
148 
149 //****************************************************************************80
150 //
151 //  Purpose:
152 //
153 //    ANTITHETIC_MEMORY stores the antithetic value for all generators.
154 //
155 //  Licensing:
156 //
157 //    This code is distributed under the GNU LGPL license.
158 //
159 //  Modified:
160 //
161 //    02 April 2013
162 //
163 //  Author:
164 //
165 //    John Burkardt
166 //
167 //  Parameters:
168 //
169 //    Input, int I, the desired action.
170 //    -1, get a value.
171 //    0, initialize all values.
172 //    1, set a value.
173 //
174 //    Input/output, bool &VALUE.  For I = -1, VALUE is an output
175 //    quantity, if I = +1, then VALUE is an input quantity.
176 //
177 {
178 # define G_MAX 32
179 
180   static bool a_save[G_MAX];
181   int g;
182   const int g_max = 32;
183   int j;
184 
185   if ( i < 0 )
186   {
187     g = cgn_get ( );
188     value = a_save[g];
189   }
190   else if ( i == 0 )
191   {
192     for ( j = 0; j < g_max; j++ )
193     {
194       a_save[j] = false;
195     }
196   }
197   else if ( 0 < i )
198   {
199     g = cgn_get ( );
200     a_save[g] = value;
201   }
202 
203   return;
204 # undef G_MAX
205 }
206 //****************************************************************************80
207 
antithetic_set(bool value)208 void antithetic_set ( bool value )
209 
210 //****************************************************************************80
211 //
212 //  Purpose:
213 //
214 //    ANTITHETIC_SET sets the antithetic value for a given generator.
215 //
216 //  Licensing:
217 //
218 //    This code is distributed under the GNU LGPL license.
219 //
220 //  Modified:
221 //
222 //    02 April 2013
223 //
224 //  Author:
225 //
226 //    John Burkardt
227 //
228 //  Parameters:
229 //
230 //    Input, bool VALUE, is TRUE if generator G is to be antithetic.
231 //
232 {
233   int i;
234 
235   i = +1;
236   antithetic_memory ( i, value );
237 
238   return;
239 }
240 //****************************************************************************80
241 
cg_get(int g,int & cg1,int & cg2)242 void cg_get ( int g, int &cg1, int &cg2 )
243 
244 //****************************************************************************80
245 //
246 //  Purpose:
247 //
248 //    CG_GET queries the CG values for a given generator.
249 //
250 //  Licensing:
251 //
252 //    This code is distributed under the GNU LGPL license.
253 //
254 //  Modified:
255 //
256 //    27 March 2013
257 //
258 //  Author:
259 //
260 //    John Burkardt
261 //
262 //  Parameters:
263 //
264 //    Input, int G, the index of the generator.
265 //    0 <= G <= 31.
266 //
267 //    Output, int &CG1, &CG2, the CG values for generator G.
268 //
269 {
270   int i;
271 
272   i = -1;
273   cg_memory ( i, g, cg1, cg2 );
274 
275   return;
276 }
277 //****************************************************************************80
278 
cg_memory(int i,int g,int & cg1,int & cg2)279 void cg_memory ( int i, int g, int &cg1, int &cg2 )
280 
281 //****************************************************************************80
282 //
283 //  Purpose:
284 //
285 //    CG_MEMORY stores the CG values for all generators.
286 //
287 //  Licensing:
288 //
289 //    This code is distributed under the GNU LGPL license.
290 //
291 //  Modified:
292 //
293 //    30 March 2013
294 //
295 //  Author:
296 //
297 //    John Burkardt
298 //
299 //  Parameters:
300 //
301 //    Input, int I, the desired action.
302 //    -1, get a value.
303 //    0, initialize all values.
304 //    1, set a value.
305 //
306 //    Input, int G, for I = -1 or +1, the index of
307 //    the generator, with 0 <= G <= 31.
308 //
309 //    Input/output, int &CG1, &CG2.  For I = -1,
310 //    these are output, for I = +1, these are input, for I = 0,
311 //    these arguments are ignored.  When used, the arguments are
312 //    old or new values of the CG parameter for generator G.
313 //
314 {
315 # define G_MAX 32
316 
317   static int cg1_save[G_MAX];
318   static int cg2_save[G_MAX];
319   const int g_max = 32;
320   int j;
321 
322   if ( g < 0 || g_max <= g )
323   {
324     cerr << "\n";
325     cerr << "CG_MEMORY - Fatal error!\n";
326     cerr << "  Input generator index G is out of bounds.\n";
327     exit ( 1 );
328   }
329 
330   if ( i < 0 )
331   {
332     cg1 = cg1_save[g];
333     cg2 = cg2_save[g];
334   }
335   else if ( i == 0 )
336   {
337     for ( j = 0; j < g_max; j++ )
338     {
339       cg1_save[j] = 0;
340       cg2_save[j] = 0;
341     }
342   }
343   else if ( 0 < i )
344   {
345     cg1_save[g] = cg1;
346     cg2_save[g] = cg2;
347   }
348 
349   return;
350 # undef G_MAX
351 }
352 //****************************************************************************80
353 
cg_set(int g,int cg1,int cg2)354 void cg_set ( int g, int cg1, int cg2 )
355 
356 //****************************************************************************80
357 //
358 //  Purpose:
359 //
360 //    CG_SET sets the CG values for a given generator.
361 //
362 //  Licensing:
363 //
364 //    This code is distributed under the GNU LGPL license.
365 //
366 //  Modified:
367 //
368 //    27 March 2013
369 //
370 //  Author:
371 //
372 //    John Burkardt
373 //
374 //  Parameters:
375 //
376 //    Input, int G, the index of the generator.
377 //    0 <= G <= 31.
378 //
379 //    Input, int CG1, CG2, the CG values for generator G.
380 //
381 {
382   int i;
383 
384   i = +1;
385   cg_memory ( i, g, cg1, cg2 );
386 
387   return;
388 }
389 //****************************************************************************80
390 
cgn_get()391 int cgn_get ( )
392 
393 //****************************************************************************80
394 //
395 //  Purpose:
396 //
397 //    CGN_GET gets the current generator index.
398 //
399 //  Licensing:
400 //
401 //    This code is distributed under the GNU LGPL license.
402 //
403 //  Modified:
404 //
405 //    30 March 2013
406 //
407 //  Author:
408 //
409 //    John Burkardt
410 //
411 //  Parameters:
412 //
413 //    Output, int CGN_GET, the current generator index.
414 //
415 {
416   int g;
417   int i;
418 
419   i = -1;
420   cgn_memory ( i, g );
421 
422   return g;
423 }
424 //****************************************************************************80
425 
cgn_memory(int i,int & g)426 void cgn_memory ( int i, int &g )
427 
428 //****************************************************************************80
429 //
430 //  Purpose:
431 //
432 //    CGN_MEMORY stores the current generator index.
433 //
434 //  Licensing:
435 //
436 //    This code is distributed under the GNU LGPL license.
437 //
438 //  Modified:
439 //
440 //    02 April 2013
441 //
442 //  Author:
443 //
444 //    John Burkardt
445 //
446 //  Parameters:
447 //
448 //    Input, int I, the desired action.
449 //    -1, get the value.
450 //    0, initialize the value.
451 //    1, set the value.
452 //
453 //    Input/output, int &G.  For I = -1 or 0, this is output.
454 //    For I = +1, this is input.
455 //
456 {
457 # define G_MAX 32
458 
459   static int g_save = 0;
460   const int g_max = 32;
461 
462   if ( i < 0 )
463   {
464     g = g_save;
465   }
466   else if ( i == 0 )
467   {
468     g_save = 0;
469     g = g_save;
470   }
471   else if ( 0 < i )
472   {
473 
474     if ( g < 0 || g_max <= g )
475     {
476       cerr << "\n";
477       cerr << "CGN_MEMORY - Fatal error!\n";
478       cerr << "  Input generator index G is out of bounds.\n";
479       exit ( 1 );
480     }
481 
482     g_save = g;
483   }
484 
485   return;
486 # undef G_MAX
487 }
488 //****************************************************************************80
489 
cgn_set(int g)490 void cgn_set ( int g )
491 
492 //****************************************************************************80
493 //
494 //  Purpose:
495 //
496 //    CGN_SET sets the current generator index.
497 //
498 //  Licensing:
499 //
500 //    This code is distributed under the GNU LGPL license.
501 //
502 //  Modified:
503 //
504 //    30 March 2013
505 //
506 //  Author:
507 //
508 //    John Burkardt
509 //
510 //  Parameters:
511 //
512 //    Input, int G, the current generator index.
513 //    0 <= G <= 31.
514 //
515 {
516   int i;
517 
518   i = +1;
519   cgn_memory ( i, g );
520 
521   return;
522 }
523 //****************************************************************************80
524 
get_state(int & cg1,int & cg2)525 void get_state ( int &cg1, int &cg2 )
526 
527 //****************************************************************************80
528 //
529 //  Purpose:
530 //
531 //    GET_STATE returns the state of the current generator.
532 //
533 //  Licensing:
534 //
535 //    This code is distributed under the GNU LGPL license.
536 //
537 //  Modified:
538 //
539 //    30 March 2013
540 //
541 //  Author:
542 //
543 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
544 //    C++ version by John Burkardt.
545 //
546 //  Reference:
547 //
548 //    Pierre LEcuyer, Serge Cote,
549 //    Implementing a Random Number Package with Splitting Facilities,
550 //    ACM Transactions on Mathematical Software,
551 //    Volume 17, Number 1, March 1991, pages 98-111.
552 //
553 //  Parameters:
554 //
555 //    Output, int *CG1, *CG2, the CG values for the current generator.
556 //
557 {
558   int g;
559 //
560 //  Check whether the package must be initialized.
561 //
562   if ( ! initialized_get ( ) )
563   {
564     cout << "\n";
565     cout << "GET_STATE - Note:\n";
566     cout << "  Initializing RNGLIB package.\n";
567     initialize ( );
568   }
569 //
570 //  Get the current generator index.
571 //
572   g = cgn_get ( );
573 //
574 //  Retrieve the seed values for this generator.
575 //
576   cg_get ( g, cg1, cg2 );
577 
578   return;
579 }
580 //****************************************************************************80
581 
i4_uni()582 int i4_uni ( )
583 
584 //****************************************************************************80
585 //
586 //  Purpose:
587 //
588 //    I4_UNI generates a random positive integer.
589 //
590 //  Discussion:
591 //
592 //    This procedure returns a random integer following a uniform distribution
593 //    over (1, 2147483562) using the current generator.
594 //
595 //    The original name of this function was "random()", but this conflicts
596 //    with a standard library function name in C.
597 //
598 //  Licensing:
599 //
600 //    This code is distributed under the GNU LGPL license.
601 //
602 //  Modified:
603 //
604 //    05 August 2013
605 //
606 //  Author:
607 //
608 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
609 //    C++ version by John Burkardt.
610 //
611 //  Reference:
612 //
613 //    Pierre LEcuyer, Serge Cote,
614 //    Implementing a Random Number Package with Splitting Facilities,
615 //    ACM Transactions on Mathematical Software,
616 //    Volume 17, Number 1, March 1991, pages 98-111.
617 //
618 //  Parameters:
619 //
620 //    Output, int I4_UNI, the random integer.
621 //
622 {
623   const int a1 = 40014;
624   const int a2 = 40692;
625   int cg1;
626   int cg2;
627   int g;
628   int k;
629   const int m1 = 2147483563;
630   const int m2 = 2147483399;
631   bool value;
632   int z;
633 //
634 //  Check whether the package must be initialized.
635 //
636   if ( ! initialized_get ( ) )
637   {
638     cout << "\n";
639     cout << "I4_UNI - Note:\n";
640     cout << "  Initializing RNGLIB package.\n";
641     initialize ( );
642   }
643 //
644 //  Get the current generator index.
645 //
646   g = cgn_get ( );
647 //
648 //  Retrieve the current seeds.
649 //
650   cg_get ( g, cg1, cg2 );
651 //
652 //  Update the seeds.
653 //
654   k = cg1 / 53668;
655   cg1 = a1 * ( cg1 - k * 53668 ) - k * 12211;
656 
657   if ( cg1 < 0 )
658   {
659     cg1 = cg1 + m1;
660   }
661 
662   k = cg2 / 52774;
663   cg2 = a2 * ( cg2 - k * 52774 ) - k * 3791;
664 
665   if ( cg2 < 0 )
666   {
667     cg2 = cg2 + m2;
668   }
669 //
670 //  Store the updated seeds.
671 //
672   cg_set ( g, cg1, cg2 );
673 //
674 //  Form the random integer.
675 //
676   z = cg1 - cg2;
677 
678   if ( z < 1 )
679   {
680     z = z + m1 - 1;
681   }
682 //
683 //  If the generator is antithetic, reflect the value.
684 //
685   value = antithetic_get ( );
686 
687   if ( value )
688   {
689     z = m1 - z;
690   }
691   return z;
692 }
693 //****************************************************************************80
694 
ig_get(int g,int & ig1,int & ig2)695 void ig_get ( int g, int &ig1, int &ig2 )
696 
697 //****************************************************************************80
698 //
699 //  Purpose:
700 //
701 //    IG_GET queries the IG values for a given generator.
702 //
703 //  Licensing:
704 //
705 //    This code is distributed under the GNU LGPL license.
706 //
707 //  Modified:
708 //
709 //    27 March 2013
710 //
711 //  Author:
712 //
713 //    John Burkardt
714 //
715 //  Parameters:
716 //
717 //    Input, int G, the index of the generator.
718 //    0 <= G <= 31.
719 //
720 //    Output, int &IG1, &IG2, the IG values for generator G.
721 //
722 {
723   int i;
724 
725   i = -1;
726   ig_memory ( i, g, ig1, ig2 );
727 
728   return;
729 }
730 //****************************************************************************80
731 
ig_memory(int i,int g,int & ig1,int & ig2)732 void ig_memory ( int i, int g, int &ig1, int &ig2 )
733 
734 //****************************************************************************80
735 //
736 //  Purpose:
737 //
738 //    IG_MEMORY stores the IG values for all generators.
739 //
740 //  Licensing:
741 //
742 //    This code is distributed under the GNU LGPL license.
743 //
744 //  Modified:
745 //
746 //    30 March 2013
747 //
748 //  Author:
749 //
750 //    John Burkardt
751 //
752 //  Parameters:
753 //
754 //    Input, int I, the desired action.
755 //    -1, get a value.
756 //    0, initialize all values.
757 //    1, set a value.
758 //
759 //    Input, int G, for I = -1 or +1, the index of
760 //    the generator, with 0 <= G <= 31.
761 //
762 //    Input/output, int &IG1, &IG2.  For I = -1,
763 //    these are output, for I = +1, these are input, for I = 0,
764 //    these arguments are ignored.  When used, the arguments are
765 //    old or new values of the IG parameter for generator G.
766 //
767 {
768 # define G_MAX 32
769 
770   const int g_max = 32;
771   static int ig1_save[G_MAX];
772   static int ig2_save[G_MAX];
773   int j;
774 
775   if ( g < 0 || g_max <= g )
776   {
777     cerr << "\n";
778     cerr << "IG_MEMORY - Fatal error!\n";
779     cerr << "  Input generator index G is out of bounds.\n";
780     exit ( 1 );
781   }
782 
783   if ( i < 0 )
784   {
785     ig1 = ig1_save[g];
786     ig2 = ig2_save[g];
787   }
788   else if ( i == 0 )
789   {
790     for ( j = 0; j < g_max; j++ )
791     {
792       ig1_save[j] = 0;
793       ig2_save[j] = 0;
794     }
795   }
796   else if ( 0 < i )
797   {
798     ig1_save[g] = ig1;
799     ig2_save[g] = ig2;
800   }
801 
802   return;
803 # undef G_MAX
804 }
805 //****************************************************************************80
806 
ig_set(int g,int ig1,int ig2)807 void ig_set ( int g, int ig1, int ig2 )
808 
809 //****************************************************************************80
810 //
811 //  Purpose:
812 //
813 //    IG_SET sets the IG values for a given generator.
814 //
815 //  Licensing:
816 //
817 //    This code is distributed under the GNU LGPL license.
818 //
819 //  Modified:
820 //
821 //    27 March 2013
822 //
823 //  Author:
824 //
825 //    John Burkardt
826 //
827 //  Parameters:
828 //
829 //    Input, int G, the index of the generator.
830 //    0 <= G <= 31.
831 //
832 //    Input, int IG1, IG2, the IG values for generator G.
833 //
834 {
835   int i;
836 
837   i = +1;
838   ig_memory ( i, g, ig1, ig2 );
839 
840   return;
841 }
842 //****************************************************************************80
843 
init_generator(int t)844 void init_generator ( int t )
845 
846 //****************************************************************************80
847 //
848 //  Purpose:
849 //
850 //    INIT_GENERATOR sets the state of generator G to initial, last or new seed.
851 //
852 //  Licensing:
853 //
854 //    This code is distributed under the GNU LGPL license.
855 //
856 //  Modified:
857 //
858 //    02 April 2013
859 //
860 //  Author:
861 //
862 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
863 //    C++ version by John Burkardt.
864 //
865 //  Reference:
866 //
867 //    Pierre LEcuyer, Serge Cote,
868 //    Implementing a Random Number Package with Splitting Facilities,
869 //    ACM Transactions on Mathematical Software,
870 //    Volume 17, Number 1, March 1991, pages 98-111.
871 //
872 //  Parameters:
873 //
874 //    Input, int T, the seed type:
875 //    0, use the seed chosen at initialization time.
876 //    1, use the last seed.
877 //    2, use a new seed set 2^30 values away.
878 //
879 {
880   const int a1_w = 1033780774;
881   const int a2_w = 1494757890;
882   int cg1;
883   int cg2;
884   int g;
885   int ig1;
886   int ig2;
887   int lg1;
888   int lg2;
889   const int m1 = 2147483563;
890   const int m2 = 2147483399;
891 //
892 //  Check whether the package must be initialized.
893 //
894   if ( ! initialized_get ( ) )
895   {
896     cout << "\n";
897     cout << "INIT_GENERATOR - Note:\n";
898     cout << "  Initializing RNGLIB package.\n";
899     initialize ( );
900   }
901 //
902 //  Get the current generator index.
903 //
904   g = cgn_get ( );
905 //
906 //  0: restore the initial seed.
907 //
908   if ( t == 0 )
909   {
910     ig_get ( g, ig1, ig2 );
911     lg1 = ig1;
912     lg2 = ig2;
913     lg_set ( g, lg1, lg2 );
914   }
915 //
916 //  1: restore the last seed.
917 //
918   else if ( t == 1 )
919   {
920     lg_get ( g, lg1, lg2 );
921   }
922 //
923 //  2: Advance to a new seed.
924 //
925   else if ( t == 2 )
926   {
927     lg_get ( g, lg1, lg2 );
928     lg1 = multmod ( a1_w, lg1, m1 );
929     lg2 = multmod ( a2_w, lg2, m2 );
930     lg_set ( g, lg1, lg2 );
931   }
932   else
933   {
934     cerr << "\n";
935     cerr << "INIT_GENERATOR - Fatal error!\n";
936     cerr << "  Input parameter T out of bounds.\n";
937     exit ( 1 );
938   }
939 //
940 //  Store the new seed.
941 //
942   cg1 = lg1;
943   cg2 = lg2;
944   cg_set ( g, cg1, cg2 );
945 
946   return;
947 }
948 //****************************************************************************80
949 
initialize()950 void initialize ( )
951 
952 //****************************************************************************80
953 //
954 //  Purpose:
955 //
956 //    INITIALIZE initializes the random number generator library.
957 //
958 //  Licensing:
959 //
960 //    This code is distributed under the GNU LGPL license.
961 //
962 //  Modified:
963 //
964 //    30 March 2013
965 //
966 //  Author:
967 //
968 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
969 //    C++ version by John Burkardt.
970 //
971 //  Reference:
972 //
973 //    Pierre LEcuyer, Serge Cote,
974 //    Implementing a Random Number Package with Splitting Facilities,
975 //    ACM Transactions on Mathematical Software,
976 //    Volume 17, Number 1, March 1991, pages 98-111.
977 //
978 //  Parameters:
979 //
980 //    None
981 //
982 {
983   int g;
984   const int g_max = 32;
985   int ig1;
986   int ig2;
987   int value;
988 //
989 //  Remember that we have called INITIALIZE().
990 //
991   initialized_set ( );
992 //
993 //  Initialize all generators to have FALSE antithetic value.
994 //
995   value = 0;
996   for ( g = 0; g < g_max; g++ )
997   {
998     cgn_set ( g );
999     antithetic_set ( value );
1000   }
1001 //
1002 //  Set the initial seeds.
1003 //
1004   ig1 = 1234567890;
1005   ig2 = 123456789;
1006   set_initial_seed ( ig1, ig2 );
1007 //
1008 //  Initialize the current generator index to 0.
1009 //
1010   g = 0;
1011   cgn_set ( g );
1012 
1013   cout << "\n";
1014   cout << "INITIALIZE - Note:\n";
1015   cout << "  The RNGLIB package has been initialized.\n";
1016 
1017   return;
1018 }
1019 //****************************************************************************80
1020 
initialized_get()1021 bool initialized_get ( )
1022 
1023 //****************************************************************************80
1024 //
1025 //  Purpose:
1026 //
1027 //    INITIALIZED_GET queries the INITIALIZED value.
1028 //
1029 //  Licensing:
1030 //
1031 //    This code is distributed under the GNU LGPL license.
1032 //
1033 //  Modified:
1034 //
1035 //    28 March 2013
1036 //
1037 //  Author:
1038 //
1039 //    John Burkardt
1040 //
1041 //  Parameters:
1042 //
1043 //    Output, bool INITIALIZED_GET, is TRUE (1) if the package has been initialized.
1044 //
1045 {
1046   int i;
1047   bool value;
1048 
1049   i = -1;
1050   initialized_memory ( i, value );
1051 
1052   return value;
1053 }
1054 //****************************************************************************80
1055 
initialized_memory(int i,bool & initialized)1056 void initialized_memory ( int i, bool &initialized )
1057 
1058 //****************************************************************************80
1059 //
1060 //  Purpose:
1061 //
1062 //    INITIALIZED_MEMORY stores the INITIALIZED value for the package.
1063 //
1064 //  Licensing:
1065 //
1066 //    This code is distributed under the GNU LGPL license.
1067 //
1068 //  Modified:
1069 //
1070 //    28 March 2013
1071 //
1072 //  Author:
1073 //
1074 //    John Burkardt
1075 //
1076 //  Parameters:
1077 //
1078 //    Input, int I, the desired action.
1079 //    -1, get the value.
1080 //    0, initialize the value.
1081 //    1, set the value.
1082 //
1083 //    Input/output, bool &INITIALIZED.  For I = -1, this is an output
1084 //    quantity.  If I = +1, this is an input quantity.  If I = 0,
1085 //    this is ignored.
1086 //
1087 {
1088   static bool initialized_save = false;
1089 
1090   if ( i < 0 )
1091   {
1092     initialized = initialized_save;
1093   }
1094   else if ( i == 0 )
1095   {
1096     initialized_save = false;
1097   }
1098   else if ( 0 < i )
1099   {
1100     initialized_save = initialized;
1101   }
1102 
1103   return;
1104 }
1105 //****************************************************************************80
1106 
initialized_set()1107 void initialized_set ( )
1108 
1109 //****************************************************************************80
1110 //
1111 //  Purpose:
1112 //
1113 //    INITIALIZED_SET sets the INITIALIZED value true.
1114 //
1115 //  Licensing:
1116 //
1117 //    This code is distributed under the GNU LGPL license.
1118 //
1119 //  Modified:
1120 //
1121 //    28 March 2013
1122 //
1123 //  Author:
1124 //
1125 //    John Burkardt
1126 //
1127 //  Parameters:
1128 //
1129 //    None
1130 //
1131 {
1132   int i;
1133   bool initialized;
1134 
1135   i = +1;
1136   initialized = true;
1137   initialized_memory ( i, initialized );
1138 
1139   return;
1140 }
1141 //****************************************************************************80
1142 
lg_get(int g,int & lg1,int & lg2)1143 void lg_get ( int g, int &lg1, int &lg2 )
1144 
1145 //****************************************************************************80
1146 //
1147 //  Purpose:
1148 //
1149 //    LG_GET queries the LG values for a given generator.
1150 //
1151 //  Licensing:
1152 //
1153 //    This code is distributed under the GNU LGPL license.
1154 //
1155 //  Modified:
1156 //
1157 //    27 March 2013
1158 //
1159 //  Author:
1160 //
1161 //    John Burkardt
1162 //
1163 //  Parameters:
1164 //
1165 //    Input, int G, the index of the generator.
1166 //    0 <= G <= 31.
1167 //
1168 //    Output, int &LG1, &LG2, the LG values for generator G.
1169 //
1170 {
1171   int i;
1172 
1173   i = -1;
1174   lg_memory ( i, g, lg1, lg2 );
1175 
1176   return;
1177 }
1178 //****************************************************************************80
1179 
lg_memory(int i,int g,int & lg1,int & lg2)1180 void lg_memory ( int i, int g, int &lg1, int &lg2 )
1181 
1182 //****************************************************************************80
1183 //
1184 //  Purpose:
1185 //
1186 //    LG_MEMORY stores the LG values for all generators.
1187 //
1188 //  Licensing:
1189 //
1190 //    This code is distributed under the GNU LGPL license.
1191 //
1192 //  Modified:
1193 //
1194 //    30 March 2013
1195 //
1196 //  Author:
1197 //
1198 //    John Burkardt
1199 //
1200 //  Parameters:
1201 //
1202 //    Input, int I, the desired action.
1203 //    -1, get a value.
1204 //    0, initialize all values.
1205 //    1, set a value.
1206 //
1207 //    Input, int G, for I = -1 or +1, the index of
1208 //    the generator, with 0 <= G <= 31.
1209 //
1210 //    Input/output, int &LG1, &LG2.  For I = -1,
1211 //    these are output, for I = +1, these are input, for I = 0,
1212 //    these arguments are ignored.  When used, the arguments are
1213 //    old or new values of the LG parameter for generator G.
1214 //
1215 {
1216 # define G_MAX 32
1217 
1218   const int g_max = 32;
1219 
1220   int j;
1221   static int lg1_save[G_MAX];
1222   static int lg2_save[G_MAX];
1223 
1224   if ( g < 0 || g_max <= g )
1225   {
1226     cerr << "\n";
1227     cerr << "LG_MEMORY - Fatal error!\n";
1228     cerr << "  Input generator index G is out of bounds.\n";
1229     exit ( 1 );
1230   }
1231 
1232   if ( i < 0 )
1233   {
1234     lg1 = lg1_save[g];
1235     lg2 = lg2_save[g];
1236   }
1237   else if ( i == 0 )
1238   {
1239     for ( j = 0; j < g_max; j++ )
1240     {
1241       lg1_save[j] = 0;
1242       lg2_save[j] = 0;
1243     }
1244   }
1245   else if ( 0 < i )
1246   {
1247     lg1_save[g] = lg1;
1248     lg2_save[g] = lg2;
1249   }
1250   return;
1251 # undef G_MAX
1252 }
1253 //****************************************************************************80
1254 
lg_set(int g,int lg1,int lg2)1255 void lg_set ( int g, int lg1, int lg2 )
1256 
1257 //****************************************************************************80
1258 //
1259 //  Purpose:
1260 //
1261 //    LG_SET sets the LG values for a given generator.
1262 //
1263 //  Licensing:
1264 //
1265 //    This code is distributed under the GNU LGPL license.
1266 //
1267 //  Modified:
1268 //
1269 //    27 March 2013
1270 //
1271 //  Author:
1272 //
1273 //    John Burkardt
1274 //
1275 //  Parameters:
1276 //
1277 //    Input, int G, the index of the generator.
1278 //    0 <= G <= 31.
1279 //
1280 //    Input, int LG1, LG2, the LG values for generator G.
1281 //
1282 {
1283   int i;
1284 
1285   i = +1;
1286   lg_memory ( i, g, lg1, lg2 );
1287 
1288   return;
1289 }
1290 //****************************************************************************80
1291 
multmod(int a,int s,int m)1292 int multmod ( int a, int s, int m )
1293 
1294 //****************************************************************************80
1295 //
1296 //  Purpose:
1297 //
1298 //    MULTMOD carries out modular multiplication.
1299 //
1300 //  Discussion:
1301 //
1302 //    This procedure returns
1303 //
1304 //      ( A * S ) mod M
1305 //
1306 //  Licensing:
1307 //
1308 //    This code is distributed under the GNU LGPL license.
1309 //
1310 //  Modified:
1311 //
1312 //    27 March 2013
1313 //
1314 //  Author:
1315 //
1316 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
1317 //    C++ version by John Burkardt.
1318 //
1319 //  Reference:
1320 //
1321 //    Pierre LEcuyer, Serge Cote,
1322 //    Implementing a Random Number Package with Splitting Facilities,
1323 //    ACM Transactions on Mathematical Software,
1324 //    Volume 17, Number 1, March 1991, pages 98-111.
1325 //
1326 //  Parameters:
1327 //
1328 //    Input, int A, S, M, the arguments.
1329 //
1330 //    Output, int MULTMOD, the value of the product of A and S,
1331 //    modulo M.
1332 //
1333 {
1334   int a0;
1335   int a1;
1336   const int h = 32768;
1337   int k;
1338   int p;
1339   int q;
1340   int qh;
1341   int rh;
1342 
1343   if ( a <= 0 )
1344   {
1345     cerr << "\n";
1346     cerr << "MULTMOD - Fatal error!\n";
1347     cerr << "  A <= 0.\n";
1348     exit ( 1 );
1349   }
1350 
1351   if ( m <= a )
1352   {
1353     cerr << "\n";
1354     cerr << "MULTMOD - Fatal error!\n";
1355     cerr << "  M <= A.\n";
1356     exit ( 1 );
1357   }
1358 
1359   if ( s <= 0 )
1360   {
1361     cerr << "\n";
1362     cerr << "MULTMOD - Fatal error!\n";
1363     cerr << "  S <= 0.\n";
1364     exit ( 1 );
1365   }
1366 
1367   if ( m <= s )
1368   {
1369     cerr << "\n";
1370     cerr << "MULTMOD - Fatal error!\n";
1371     cerr << "  M <= S.\n";
1372     exit ( 1 );
1373   }
1374 
1375   if ( a < h )
1376   {
1377     a0 = a;
1378     p = 0;
1379   }
1380   else
1381   {
1382     a1 = a / h;
1383     a0 = a - h * a1;
1384     qh = m / h;
1385     rh = m - h * qh;
1386 
1387     if ( h <= a1 )
1388     {
1389       a1 = a1 - h;
1390       k = s / qh;
1391       p = h * ( s - k * qh ) - k * rh;
1392 
1393       while ( p < 0 )
1394       {
1395         p = p + m;
1396       }
1397     }
1398     else
1399     {
1400       p = 0;
1401     }
1402 
1403     if ( a1 != 0 )
1404     {
1405       q = m / a1;
1406       k = s / q;
1407       p = p - k * ( m - a1 * q );
1408 
1409       if ( 0 < p )
1410       {
1411         p = p - m;
1412       }
1413 
1414       p = p + a1 * ( s - k * q );
1415 
1416       while ( p < 0 )
1417       {
1418         p = p + m;
1419       }
1420     }
1421 
1422     k = p / qh;
1423     p = h * ( p - k * qh ) - k * rh;
1424 
1425     while ( p < 0 )
1426     {
1427       p = p + m;
1428     }
1429   }
1430 
1431   if ( a0 != 0 )
1432   {
1433     q = m / a0;
1434     k = s / q;
1435     p = p - k * ( m - a0 * q );
1436 
1437     if ( 0 < p )
1438     {
1439       p = p - m;
1440     }
1441 
1442     p = p + a0 * ( s - k * q );
1443 
1444     while ( p < 0 )
1445     {
1446       p = p + m;
1447     }
1448   }
1449   return p;
1450 }
1451 //****************************************************************************80
1452 
r4_uni_01()1453 float r4_uni_01 ( )
1454 
1455 //****************************************************************************80
1456 //
1457 //  Purpose:
1458 //
1459 //    R4_UNI_01 returns a uniform random real number in [0,1].
1460 //
1461 //  Discussion:
1462 //
1463 //    This procedure returns a random floating point number from a uniform
1464 //    distribution over (0,1), not including the endpoint values, using the
1465 //    current random number generator.
1466 //
1467 //  Licensing:
1468 //
1469 //    This code is distributed under the GNU LGPL license.
1470 //
1471 //  Modified:
1472 //
1473 //    05 August 2013
1474 //
1475 //  Author:
1476 //
1477 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
1478 //    C++ version by John Burkardt.
1479 //
1480 //  Reference:
1481 //
1482 //    Pierre LEcuyer, Serge Cote,
1483 //    Implementing a Random Number Package with Splitting Facilities,
1484 //    ACM Transactions on Mathematical Software,
1485 //    Volume 17, Number 1, March 1991, pages 98-111.
1486 //
1487 //  Parameters:
1488 //
1489 //    Output, float R4_UNI_01, a uniform random value in [0,1].
1490 //
1491 {
1492   int i;
1493   float value;
1494 //
1495 //  Check whether the package must be initialized.
1496 //
1497   if ( ! initialized_get ( ) )
1498   {
1499     cout << "\n";
1500     cout << "R4_UNI_01 - Note:\n";
1501     cout << "  Initializing RNGLIB package.\n";
1502     initialize ( );
1503   }
1504 //
1505 //  Get a random integer.
1506 //
1507   i = i4_uni ( );
1508 //
1509 //  Scale it to [0,1].
1510 //
1511   value = ( float ) ( i ) * 4.656613057E-10;
1512 
1513   return value;
1514 }
1515 //****************************************************************************80
1516 
r8_uni_01()1517 double r8_uni_01 ( )
1518 
1519 //****************************************************************************80
1520 //
1521 //  Purpose:
1522 //
1523 //    R8_UNI_01 returns a uniform random double in [0,1].
1524 //
1525 //  Discussion:
1526 //
1527 //    This procedure returns a random valule from a uniform
1528 //    distribution over (0,1), not including the endpoint values, using the
1529 //    current random number generator.
1530 //
1531 //  Licensing:
1532 //
1533 //    This code is distributed under the GNU LGPL license.
1534 //
1535 //  Modified:
1536 //
1537 //    05 August 2013
1538 //
1539 //  Author:
1540 //
1541 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
1542 //    C++ version by John Burkardt.
1543 //
1544 //  Reference:
1545 //
1546 //    Pierre LEcuyer, Serge Cote,
1547 //    Implementing a Random Number Package with Splitting Facilities,
1548 //    ACM Transactions on Mathematical Software,
1549 //    Volume 17, Number 1, March 1991, pages 98-111.
1550 //
1551 //  Parameters:
1552 //
1553 //    Output, double R8_UNI_01, a uniform random value in [0,1].
1554 //
1555 {
1556   int i;
1557   double value;
1558 //
1559 //  Check whether the package must be initialized.
1560 //
1561   if ( ! initialized_get ( ) )
1562   {
1563     cout << "\n";
1564     cout << "R8_UNI_01 - Note:\n";
1565     cout << "  Initializing RNGLIB package.\n";
1566     initialize ( );
1567   }
1568 //
1569 //  Get a random integer.
1570 //
1571   i = i4_uni ( );
1572 //
1573 //  Scale it to [0,1].
1574 //
1575   value = ( double ) ( i ) * 4.656613057E-10;
1576 
1577   return value;
1578 }
1579 //****************************************************************************80
1580 
set_initial_seed(int ig1,int ig2)1581 void set_initial_seed ( int ig1, int ig2 )
1582 
1583 //****************************************************************************80
1584 //
1585 //  Purpose:
1586 //
1587 //    SET_INITIAL_SEED resets the initial seed and state for all generators.
1588 //
1589 //  Licensing:
1590 //
1591 //    This code is distributed under the GNU LGPL license.
1592 //
1593 //  Modified:
1594 //
1595 //    27 March 2013
1596 //
1597 //  Author:
1598 //
1599 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
1600 //    C++ version by John Burkardt.
1601 //
1602 //  Reference:
1603 //
1604 //    Pierre LEcuyer, Serge Cote,
1605 //    Implementing a Random Number Package with Splitting Facilities,
1606 //    ACM Transactions on Mathematical Software,
1607 //    Volume 17, Number 1, March 1991, pages 98-111.
1608 //
1609 //  Parameters:
1610 //
1611 //    Input, int IG1, IG2, the initial seed values
1612 //    for the first generator.
1613 //    1 <= IG1 < 2147483563
1614 //    1 <= IG2 < 2147483399
1615 //
1616 {
1617   const int a1_vw = 2082007225;
1618   const int a2_vw = 784306273;
1619   int g;
1620   const int g_max = 32;
1621   int i;
1622   const int m1 = 2147483563;
1623   const int m2 = 2147483399;
1624   int t;
1625 
1626   if ( ig1 < 1 || m1 <= ig1 )
1627   {
1628     cerr << "\n";
1629     cerr << "SET_INITIAL_SEED - Fatal error!\n";
1630     cerr << "  Input parameter IG1 out of bounds.\n";
1631     exit ( 1 );
1632   }
1633 
1634   if ( ig2 < 1 || m2 <= ig2 )
1635   {
1636     cerr << "\n";
1637     cerr << "SET_INITIAL_SEED - Fatal error!\n";
1638     cerr << "  Input parameter IG2 out of bounds.\n";
1639     exit ( 1 );
1640   }
1641 //
1642 //  Because INITIALIZE calls SET_INITIAL_SEED, it's not easy to correct
1643 //  the error that arises if SET_INITIAL_SEED is called before INITIALIZE.
1644 //  So don't bother trying.
1645 //
1646   if ( ! initialized_get ( ) )
1647   {
1648     cout << "\n";
1649     cout << "SET_INITIAL_SEED - Fatal error!\n";
1650     cout << "  The RNGLIB package has not been initialized.\n";
1651     exit ( 1 );
1652   }
1653 //
1654 //  Set the initial seed, then initialize the first generator.
1655 //
1656   g = 0;
1657   cgn_set ( g );
1658 
1659   ig_set ( g, ig1, ig2 );
1660 
1661   t = 0;
1662   init_generator ( t );
1663 //
1664 //  Now do similar operations for the other generators.
1665 //
1666   for ( g = 1; g < g_max; g++ )
1667   {
1668     cgn_set ( g );
1669     ig1 = multmod ( a1_vw, ig1, m1 );
1670     ig2 = multmod ( a2_vw, ig2, m2 );
1671     ig_set ( g, ig1, ig2 );
1672     init_generator ( t );
1673   }
1674 //
1675 //  Now choose the first generator.
1676 //
1677   g = 0;
1678   cgn_set ( g );
1679 
1680   return;
1681 }
1682 //****************************************************************************80
1683 
set_seed(int cg1,int cg2)1684 void set_seed ( int cg1, int cg2 )
1685 
1686 //****************************************************************************80
1687 //
1688 //  Purpose:
1689 //
1690 //    SET_SEED resets the initial seed and the state of generator G.
1691 //
1692 //  Licensing:
1693 //
1694 //    This code is distributed under the GNU LGPL license.
1695 //
1696 //  Modified:
1697 //
1698 //    02 April 2013
1699 //
1700 //  Author:
1701 //
1702 //    Original Pascal version by Pierre L'Ecuyer, Serge Cote.
1703 //    C++ version by John Burkardt.
1704 //
1705 //  Reference:
1706 //
1707 //    Pierre LEcuyer, Serge Cote,
1708 //    Implementing a Random Number Package with Splitting Facilities,
1709 //    ACM Transactions on Mathematical Software,
1710 //    Volume 17, Number 1, March 1991, pages 98-111.
1711 //
1712 //  Parameters:
1713 //
1714 //    Input, int CG1, CG2, the CG values for generator G.
1715 //    1 <= CG1 < 2147483563
1716 //    1 <= CG2 < 2147483399
1717 //
1718 {
1719   int g;
1720   int i;
1721   const int m1 = 2147483563;
1722   const int m2 = 2147483399;
1723   int t;
1724 
1725   if ( cg1 < 1 || m1 <= cg1 )
1726   {
1727     cerr << "\n";
1728     cerr << "SET_SEED - Fatal error!\n";
1729     cerr << "  Input parameter CG1 out of bounds.\n";
1730     exit ( 1 );
1731   }
1732 
1733   if ( cg2 < 1 || m2 <= cg2 )
1734   {
1735     cerr << "\n";
1736     cerr << "SET_SEED - Fatal error!\n";
1737     cerr << "  Input parameter CG2 out of bounds.\n";
1738     exit ( 1 );
1739   }
1740 //
1741 //  Check whether the package must be initialized.
1742 //
1743   if ( ! initialized_get ( ) )
1744   {
1745     cout << "\n";
1746     cout << "SET_SEED - Note:\n";
1747     cout << "  Initializing RNGLIB package.\n";
1748     initialize ( );
1749   }
1750 //
1751 //  Retrieve the current generator index.
1752 //
1753   g = cgn_get ( );
1754 //
1755 //  Set the seeds.
1756 //
1757   cg_set ( g, cg1, cg2 );
1758 //
1759 //  Initialize the generator.
1760 //
1761   t = 0;
1762   init_generator ( t );
1763 
1764   return;
1765 }
1766 //****************************************************************************80
1767 
1768 #if !defined(TIMESTAMP)
1769 #define TIMESTAMP
timestamp()1770 void timestamp ( )
1771 
1772 //****************************************************************************80
1773 //
1774 //  Purpose:
1775 //
1776 //    TIMESTAMP prints the current YMDHMS date as a time stamp.
1777 //
1778 //  Example:
1779 //
1780 //    31 May 2001 09:45:54 AM
1781 //
1782 //  Licensing:
1783 //
1784 //    This code is distributed under the GNU LGPL license.
1785 //
1786 //  Modified:
1787 //
1788 //    08 July 2009
1789 //
1790 //  Author:
1791 //
1792 //    John Burkardt
1793 //
1794 //  Parameters:
1795 //
1796 //    None
1797 //
1798 {
1799 # define TIME_SIZE 40
1800 
1801   static char time_buffer[TIME_SIZE];
1802   const struct std::tm *tm_ptr;
1803   size_t len;
1804   std::time_t now;
1805 
1806   now = std::time ( NULL );
1807   tm_ptr = std::localtime ( &now );
1808 
1809   len = std::strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm_ptr );
1810 
1811   std::cout << time_buffer << "\n";
1812 
1813   return;
1814 # undef TIME_SIZE
1815 }
1816 #endif
1817