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