1 /*
2  * Scythe Statistical Library
3  * Copyright (C) 2000-2002 Andrew D. Martin and Kevin M. Quinn;
4  * 2002-present Andrew D. Martin, Kevin M. Quinn, and Daniel
5  * Pemstein.  All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * under the terms of the GNU General Public License as published by
9  * Free Software Foundation; either version 2 of the License, or (at
10  * your option) any later version.  See the text files COPYING
11  * and LICENSE, distributed with this source code, for further
12  * information.
13  * --------------------------------------------------------------------
14  * scythestat/rng/lecuyer.h
15  *
16  * Provides the class definition for the L'Ecuyer random number
17  * generator, a rng capable of generating many independent substreams.
18  * This class extends the abstract rng class by implementing runif().
19  * Based on RngStream.cpp, by Pierre L'Ecuyer.
20  *
21  * Pierre L'Ecuyer agreed to the following dual-licensing terms in an
22  * email received 7 August 2004.  This dual-license was prompted by
23  * the Debian maintainers of R and MCMCpack.
24  *
25  * This software is Copyright (C) 2004 Pierre L'Ecuyer.
26  *
27  * License: this code can be used freely for personal, academic, or
28  * non-commercial purposes.  For commercial licensing, please contact
29  * P. L'Ecuyer at lecuyer@iro.umontreal.ca.
30  *
31  * This code may also be redistributed and modified under the terms of
32  * the GNU General Public License as published by the Free Software
33  * Foundation; either version 2 of the License, or (at your option) any
34  * later version.
35  *
36  * This program is distributed in the hope that it will be useful, but
37  * WITHOUT ANY WARRANTY; without even the implied warranty of
38  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39  * General Public License for more details.
40  *
41  * You should have received a copy of the GNU General Public License
42  * along with this program; if not, write to the Free Software
43  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
44  * USA.
45  *
46  */
47 /*! \file lecuyer.h
48  * \brief The L'Ecuyer random number generator.
49  *
50  * This file contains the lecuyer class, a class that extends Scythe's
51  * base random number generation class (scythe::rng) by providing an
52  * implementation of scythe::rng::runif(), using L'Ecuyer's algorithm.
53  *
54  */
55 #ifndef SCYTHE_LECUYER_H
56 #define SCYTHE_LECUYER_H
57 
58 #include<cstdlib>
59 #include<iostream>
60 #include<string>
61 
62 #ifdef SCYTHE_COMPILE_DIRECT
63 #include "rng.h"
64 #else
65 #include "scythestat/rng.h"
66 #endif
67 
68 /* We want to use an anonymous namespace to make the following consts
69  * and functions local to this file, but mingw doesn't play nice with
70  * anonymous namespaces so we do things differently when using the
71  * cross-compiler.
72  */
73 #ifdef __MINGW32__
74 #define SCYTHE_MINGW32_STATIC static
75 #else
76 #define SCYTHE_MINGW32_STATIC
77 #endif
78 
79 namespace scythe {
80 #ifndef __MINGW32__
81   namespace {
82 #endif
83 
84 	SCYTHE_MINGW32_STATIC const double m1   = 4294967087.0;
85 	SCYTHE_MINGW32_STATIC const double m2   = 4294944443.0;
86 	SCYTHE_MINGW32_STATIC const double norm = 1.0 / (m1 + 1.0);
87 	SCYTHE_MINGW32_STATIC const double a12  = 1403580.0;
88 	SCYTHE_MINGW32_STATIC const double a13n = 810728.0;
89 	SCYTHE_MINGW32_STATIC const double a21  = 527612.0;
90 	SCYTHE_MINGW32_STATIC const double a23n = 1370589.0;
91 	SCYTHE_MINGW32_STATIC const double two17 =131072.0;
92 	SCYTHE_MINGW32_STATIC const double two53 =9007199254740992.0;
93   /* 1/2^24 */
94 	SCYTHE_MINGW32_STATIC const double fact = 5.9604644775390625e-8;
95 
96 	// The following are the transition matrices of the two MRG
97 	// components (in matrix form), raised to the powers -1, 1, 2^76,
98 	// and 2^127, resp.
99 
100 	SCYTHE_MINGW32_STATIC const double InvA1[3][3] = { // Inverse of A1p0
101 				 { 184888585.0,   0.0,  1945170933.0 },
102 				 {         1.0,   0.0,           0.0 },
103 				 {         0.0,   1.0,           0.0 } };
104 
105 	SCYTHE_MINGW32_STATIC const double InvA2[3][3] = { // Inverse of A2p0
106 				 {      0.0,  360363334.0,  4225571728.0 },
107 				 {      1.0,          0.0,           0.0 },
108 				 {      0.0,          1.0,           0.0 } };
109 
110 	SCYTHE_MINGW32_STATIC const double A1p0[3][3] = {
111 				 {       0.0,        1.0,       0.0 },
112 				 {       0.0,        0.0,       1.0 },
113 				 { -810728.0,  1403580.0,       0.0 } };
114 
115 	SCYTHE_MINGW32_STATIC const double A2p0[3][3] = {
116 				 {        0.0,        1.0,       0.0 },
117 				 {        0.0,        0.0,       1.0 },
118 				 { -1370589.0,        0.0,  527612.0 } };
119 
120 	SCYTHE_MINGW32_STATIC const double A1p76[3][3] = {
121 				 {      82758667.0, 1871391091.0, 4127413238.0 },
122 				 {    3672831523.0,   69195019.0, 1871391091.0 },
123 				 {    3672091415.0, 3528743235.0,   69195019.0 } };
124 
125 	SCYTHE_MINGW32_STATIC const double A2p76[3][3] = {
126 				 {    1511326704.0, 3759209742.0, 1610795712.0 },
127 				 {    4292754251.0, 1511326704.0, 3889917532.0 },
128 				 {    3859662829.0, 4292754251.0, 3708466080.0 } };
129 
130 	SCYTHE_MINGW32_STATIC const double A1p127[3][3] = {
131 				 {    2427906178.0, 3580155704.0,  949770784.0 },
132 				 {     226153695.0, 1230515664.0, 3580155704.0 },
133 				 {    1988835001.0,  986791581.0, 1230515664.0 } };
134 
135 	SCYTHE_MINGW32_STATIC const double A2p127[3][3] = {
136 				 {    1464411153.0,  277697599.0, 1610723613.0 },
137 				 {      32183930.0, 1464411153.0, 1022607788.0 },
138 				 {    2824425944.0,   32183930.0, 2093834863.0 } };
139 
140 	// Return (a*s + c) MOD m; a, s, c and m must be < 2^35
141 	SCYTHE_MINGW32_STATIC double
MultModM(double a,double s,double c,double m)142 	MultModM (double a, double s, double c, double m)
143 	{
144 		double v;
145 		long a1;
146 
147 		v = a * s + c;
148 
149 		if (v >= two53 || v <= -two53) {
150 			a1 = static_cast<long> (a / two17);    a -= a1 * two17;
151 			v  = a1 * s;
152 			a1 = static_cast<long> (v / m);     v -= a1 * m;
153 			v = v * two17 + a * s + c;
154 		}
155 
156 		a1 = static_cast<long> (v / m);
157 		/* in case v < 0)*/
158 		if ((v -= a1 * m) < 0.0) return v += m;   else return v;
159 	}
160 
161 	// Compute the vector v = A*s MOD m. Assume that -m < s[i] < m.
162 	// Works also when v = s.
163 	SCYTHE_MINGW32_STATIC void
MatVecModM(const double A[3][3],const double s[3],double v[3],double m)164 	MatVecModM (const double A[3][3], const double s[3],
165 							double v[3], double m)
166 	{
167 		int i;
168 		double x[3];               // Necessary if v = s
169 
170 		for (i = 0; i < 3; ++i) {
171 			x[i] = MultModM (A[i][0], s[0], 0.0, m);
172 			x[i] = MultModM (A[i][1], s[1], x[i], m);
173 			x[i] = MultModM (A[i][2], s[2], x[i], m);
174 		}
175 		for (i = 0; i < 3; ++i)
176 			v[i] = x[i];
177 	}
178 
179 	// Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m.
180 	// Note: works also if A = C or B = C or A = B = C.
181 	SCYTHE_MINGW32_STATIC void
MatMatModM(const double A[3][3],const double B[3][3],double C[3][3],double m)182 	MatMatModM (const double A[3][3], const double B[3][3],
183 							double C[3][3], double m)
184 	{
185 		int i, j;
186 		double V[3], W[3][3];
187 
188 		for (i = 0; i < 3; ++i) {
189 			for (j = 0; j < 3; ++j)
190 				V[j] = B[j][i];
191 			MatVecModM (A, V, V, m);
192 			for (j = 0; j < 3; ++j)
193 				W[j][i] = V[j];
194 		}
195 		for (i = 0; i < 3; ++i)
196 			for (j = 0; j < 3; ++j)
197 				C[i][j] = W[i][j];
198 	}
199 
200 	// Compute the matrix B = (A^(2^e) Mod m);  works also if A = B.
201 	SCYTHE_MINGW32_STATIC void
MatTwoPowModM(const double A[3][3],double B[3][3],double m,long e)202 	MatTwoPowModM(const double A[3][3], double B[3][3],
203 								double m, long e)
204 	{
205 	 int i, j;
206 
207 	 /* initialize: B = A */
208 	 if (A != B) {
209 		 for (i = 0; i < 3; ++i)
210 			 for (j = 0; j < 3; ++j)
211 				 B[i][j] = A[i][j];
212 	 }
213 	 /* Compute B = A^(2^e) mod m */
214 	 for (i = 0; i < e; i++)
215 		 MatMatModM (B, B, B, m);
216 	}
217 
218 	// Compute the matrix B = (A^n Mod m);  works even if A = B.
219 	SCYTHE_MINGW32_STATIC void
MatPowModM(const double A[3][3],double B[3][3],double m,long n)220 	MatPowModM (const double A[3][3], double B[3][3], double m,
221 							long n)
222 	{
223 		int i, j;
224 		double W[3][3];
225 
226 		/* initialize: W = A; B = I */
227 		for (i = 0; i < 3; ++i)
228 			for (j = 0; j < 3; ++j) {
229 				W[i][j] = A[i][j];
230 				B[i][j] = 0.0;
231 			}
232 		for (j = 0; j < 3; ++j)
233 			B[j][j] = 1.0;
234 
235 		/* Compute B = A^n mod m using the binary decomposition of n */
236 		while (n > 0) {
237 			if (n % 2) MatMatModM (W, B, B, m);
238 			MatMatModM (W, W, W, m);
239 			n /= 2;
240 		}
241 	}
242 
243 	// Check that the seeds are legitimate values. Returns 0 if legal
244 	// seeds, -1 otherwise.
245 	SCYTHE_MINGW32_STATIC int
CheckSeed(const unsigned long seed[6])246 	CheckSeed (const unsigned long seed[6])
247 	{
248 		int i;
249 
250 		for (i = 0; i < 3; ++i) {
251 			if (seed[i] >= m1) {
252       SCYTHE_THROW(scythe_randseed_error,
253           "Seed[" << i << "] >= 4294967087, Seed is not set");
254 				return -1;
255 			}
256 		}
257 		for (i = 3; i < 6; ++i) {
258 			if (seed[i] >= m2) {
259       SCYTHE_THROW(scythe_randseed_error,
260           "Seed[" << i << "] >= 4294944443, Seed is not set");
261 				return -1;
262 			}
263 		}
264 		if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
265       SCYTHE_THROW(scythe_randseed_error, "First 3 seeds = 0");
266 			return -1;
267 		}
268 		if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
269       SCYTHE_THROW(scythe_randseed_error, "Last 3 seeds = 0");
270 			return -1;
271 		}
272 
273 		return 0;
274 	}
275 
276 #ifndef __MINGW32__
277   } // end anonymous namespace
278 #endif
279 
280    /*! \brief The L'Ecuyer random number generator.
281     *
282     * This class defines a random number generator, using Pierre
283     * L'Ecuyer's algorithm (2000) and source code (2001) for
284     * generating multiple simultaneous streams of random uniform
285     * variates.  The period of the underlying single-stream generator
286     * is approximately \f$3.1 \times 10^{57}\f$.  Each individual
287     * stream is implemented in terms of a sequence of substreams (see
288     * L'Ecuyer et al (2000) for details).
289     *
290     * The lecuyer class extends Scythe's basic random number
291     * generating class, scythe::rng, implementing the interface that
292     * it defines.
293     *
294     * \see rng
295     * \see mersenne
296     *
297     */
298   class lecuyer : public rng<lecuyer>
299   {
300     public:
301 
302       // Constructor
303       /*! \brief Constructor
304        *
305        * This constructor creates an object encapsulating a random
306        * number stream, with an optional name.  It also sets the seed
307        * of the stream to the package (default or user-specified) seed
308        * if this is the first stream generated, or, otherwise, to a
309        * value \f$2^{127}\f$ steps ahead of the seed of the previously
310        * constructed stream.
311        *
312        * \param streamname The optional name for the stream.
313        *
314        * \see SetPackageSeed(unsigned long seed[6])
315        * \see SetSeed(unsigned long seed[6])
316        * \see SetAntithetic(bool)
317        * \see IncreasedPrecis(bool)
318        * \see name()
319        */
320       lecuyer (std::string streamname = "")
321         : rng<lecuyer> (),
322           streamname_ (streamname)
323       {
324         anti = false;
325         incPrec = false;
326 
327         /* Information on a stream. The arrays {Cg, Bg, Ig} contain
328          * the current state of the stream, the starting state of the
329          * current SubStream, and the starting state of the stream.
330          * This stream generates antithetic variates if anti = true.
331          * It also generates numbers with extended precision (53 bits
332          * if machine follows IEEE 754 standard) if incPrec = true.
333          * nextSeed will be the seed of the next declared RngStream.
334          */
335 
336         for (int i = 0; i < 6; ++i) {
337           Bg[i] = Cg[i] = Ig[i] = nextSeed[i];
338         }
339 
340         MatVecModM (A1p127, nextSeed, nextSeed, m1);
341         MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2);
342       }
343 
344       /*! \brief Get the stream's name.
345        *
346        * This method returns a stream's name string.
347        *
348        * \see lecuyer(const char*)
349        */
350       std::string
name()351       name() const
352       {
353         return streamname_;
354       }
355 
356       /*! \brief Reset the stream.
357        *
358        * This method resets the stream to its initial seeded state.
359        *
360        * \see ResetStartSubstream()
361        * \see ResetNextSubstream()
362        * \see SetSeed(unsigned long seed[6])
363        */
364       void
ResetStartStream()365       ResetStartStream ()
366       {
367         for (int i = 0; i < 6; ++i)
368           Cg[i] = Bg[i] = Ig[i];
369       }
370 
371       /*! \brief Reset the current substream.
372        *
373        *
374        * This method resets the stream to the first state of its
375        * current substream.
376        *
377        * \see ResetStartStream()
378        * \see ResetNextSubstream()
379        * \see SetSeed(unsigned long seed[6])
380        *
381        */
382       void
ResetStartSubstream()383       ResetStartSubstream ()
384       {
385         for (int i = 0; i < 6; ++i)
386           Cg[i] = Bg[i];
387       }
388 
389       /*! \brief Jump to the next substream.
390        *
391        * This method resets the stream to the first state of its next
392        * substream.
393        *
394        * \see ResetStartStream()
395        * \see ResetStartSubstream()
396        * \see SetSeed(unsigned long seed[6])
397        *
398        */
399       void
ResetNextSubstream()400       ResetNextSubstream ()
401       {
402         MatVecModM(A1p76, Bg, Bg, m1);
403         MatVecModM(A2p76, &Bg[3], &Bg[3], m2);
404         for (int i = 0; i < 6; ++i)
405           Cg[i] = Bg[i];
406       }
407 
408       /*! \brief Set the package seed.
409        *
410        *  This method sets the overall package seed.  The default
411        *  initial seed is (12345, 12345, 12345, 12345, 12345, 12345).
412        *  The package seed is the seed used to initialize the first
413        *  constructed random number stream in a given program.
414        *
415        *  \param seed An array of six integers to seed the package.
416        *  The first three values cannot all equal 0 and must all be
417        *  less than 4294967087 while the second trio of integers must
418        *  all be less than 4294944443 and not all 0.
419        *
420        * \see SetSeed(unsigned long seed[6])
421        *
422        * \throw scythe_randseed_error (Level 0)
423        */
424       static void
SetPackageSeed(unsigned long seed[6])425       SetPackageSeed (unsigned long seed[6])
426       {
427          if (CheckSeed (seed)) return;
428          for (int i = 0; i < 6; ++i)
429             nextSeed[i] = seed[i];
430       }
431 
432       /*! \brief Set the stream seed.
433        *
434        *  This method sets the stream seed which is used to initialize
435        *  the state of the given stream.
436        *
437        *  \warning This method sets the stream seed in isolation and
438        *  does not coordinate with any other streams.  Therefore,
439        *  using this method without care can result in multiple
440        *  streams that overlap in the course of their runs.
441        *
442        *  \param seed An array of six integers to seed the stream.
443        *  The first three values cannot all equal 0 and must all be
444        *  less than 4294967087 while the second trio of integers must
445        *  all be less than 4294944443 and not all 0.
446        *
447        * \see SetPackageSeed(unsigned long seed[6])
448        * \see ResetStartStream()
449        * \see ResetStartSubstream()
450        * \see ResetNextSubstream()
451        *
452        * \throw scythe_randseed_error (Level 0)
453        */
454       void
SetSeed(unsigned long seed[6])455       SetSeed (unsigned long seed[6])
456       {
457         if (CheckSeed (seed)) return;
458           for (int i = 0; i < 6; ++i)
459             Cg[i] = Bg[i] = Ig[i] = seed[i];
460       }
461 
462       // XXX: get the cases formula working!
463       /*! \brief Advances the state of the stream.
464        *
465        * This method advances the input \f$n\f$ steps, using the rule:
466        * \f[
467        * n =
468        * \begin{cases}
469        *  2^e + c \quad if~e > 0, \\
470        *  -2^{-e} + c \quad if~e < 0, \\
471        *  c \quad if~e = 0.
472        * \end{cases}
473        * \f]
474        *
475        * \param e This parameter controls state advancement.
476        * \param c This parameter also controls state advancement.
477        *
478        * \see GetState()
479        * \see ResetStartStream()
480        * \see ResetStartSubstream()
481        * \see ResetNextSubstream()
482        */
483       void
AdvanceState(long e,long c)484       AdvanceState (long e, long c)
485       {
486         double B1[3][3], C1[3][3], B2[3][3], C2[3][3];
487 
488         if (e > 0) {
489           MatTwoPowModM (A1p0, B1, m1, e);
490           MatTwoPowModM (A2p0, B2, m2, e);
491         } else if (e < 0) {
492           MatTwoPowModM (InvA1, B1, m1, -e);
493           MatTwoPowModM (InvA2, B2, m2, -e);
494         }
495 
496         if (c >= 0) {
497           MatPowModM (A1p0, C1, m1, c);
498           MatPowModM (A2p0, C2, m2, c);
499         } else {
500           MatPowModM (InvA1, C1, m1, -c);
501           MatPowModM (InvA2, C2, m2, -c);
502         }
503 
504         if (e) {
505           MatMatModM (B1, C1, C1, m1);
506           MatMatModM (B2, C2, C2, m2);
507         }
508 
509         MatVecModM (C1, Cg, Cg, m1);
510         MatVecModM (C2, &Cg[3], &Cg[3], m2);
511       }
512 
513       /*! \brief Get the current state.
514        *
515        * This method places the current state of the stream, as
516        * represented by six integers, into the array argument.  This
517        * is useful for saving and restoring streams across program
518        * runs.
519        *
520        * \param seed An array of six integers that will hold the state values on return.
521        *
522        * \see AdvanceState()
523        */
524       void
GetState(unsigned long seed[6])525       GetState (unsigned long seed[6]) const
526       {
527         for (int i = 0; i < 6; ++i)
528           seed[i] = static_cast<unsigned long> (Cg[i]);
529       }
530 
531       /*! \brief Toggle generator precision.
532        *
533        * This method sets the precision level of the given stream.  By
534        * default, streams generate random numbers with 32 bit
535        * resolution.  If the user invokes this method with \a incp =
536        * true, then the stream will begin to generate variates with
537        * greater precision (53 bits on machines following the IEEE 754
538        * standard).  Calling this method again with \a incp = false
539        * will return the precision of generated numbers to 32 bits.
540        *
541        * \param incp A boolean value where true implies high (most
542        * likely 53 bit) precision and false implies low (32 bit)
543        * precision.
544        *
545        * \see SetAntithetic(bool)
546        */
547       void
IncreasedPrecis(bool incp)548       IncreasedPrecis (bool incp)
549       {
550         incPrec = incp;
551       }
552 
553       /*! \brief Toggle the orientation of generated random numbers.
554        *
555        * This methods causes the given stream to generate antithetic
556        * (1 - U, where U is the default number generated) when called
557        * with \a a = true.  Calling this method with \a a = false will
558        * return generated numbers to their default orientation.
559        *
560        * \param a A boolean value that selects regular or antithetic
561        * variates.
562        *
563        * \see IncreasedPrecis(bool)
564        */
565       void
SetAntithetic(bool a)566       SetAntithetic (bool a)
567       {
568         anti = a;
569       }
570 
571       /*! \brief Generate a random uniform variate on (0, 1).
572        *
573        * This routine returns a random double precision floating point
574        * number from the uniform distribution on the interval (0,
575        * 1).  This method overloads the pure virtual method of the
576        * same name in the rng base class.
577        *
578        * \see runif(unsigned int, unsigned int)
579        * \see RandInt(long, long)
580        * \see rng
581        */
582       double
runif()583       runif ()
584       {
585         if (incPrec)
586           return U01d();
587         else
588           return U01();
589       }
590 
591       /* We have to override the overloaded form of runif because
592        * overloading the no-arg runif() hides the base class
593        * definition; C++ stops looking once it finds the above.
594        */
595       /*! \brief Generate a Matrix of random uniform variates.
596        *
597        * This routine returns a Matrix of double precision random
598        * uniform variates. on the interval (0, 1).  This method
599        * overloads the virtual method of the same name in the rng base
600        * class.
601        *
602        * This is the general template version of this method and
603        * is called through explicit template instantiation.
604        *
605        * \param rows The number of rows in the returned Matrix.
606        * \param cols The number of columns in the returned Matrix.
607        *
608        * \see runif()
609        * \see rng
610        *
611        * \note We are forced to override this overloaded method
612        * because the 1-arg version of runif() hides the base class's
613        * definition of this method from the compiler, although it
614        * probably should not.
615        */
616       template <matrix_order O, matrix_style S>
runif(unsigned int rows,unsigned int cols)617       Matrix<double,O,S> runif(unsigned int rows, unsigned int cols)
618       {
619         return rng<lecuyer>::runif<O,S>(rows,cols);
620       }
621 
622       /*! \brief Generate a Matrix of random uniform variates.
623        *
624        * This routine returns a Matrix of double precision random
625        * uniform variates on the interval (0, 1).  This method
626        * overloads the virtual method of the same name in the rng base
627        * class.
628        *
629        * This is the default template version of this method and
630        * is called through implicit template instantiation.
631        *
632        * \param rows The number of rows in the returned Matrix.
633        * \param cols The number of columns in the returned Matrix.
634        *
635        * \see runif()
636        * \see rng
637        *
638        * \note We are forced to override this overloaded method
639        * because the 1-arg version of runif() hides the base class's
640        * definition of this method from the compiler, although it
641        * probably should not.
642        */
runif(unsigned int rows,unsigned int cols)643       Matrix<double,Col,Concrete> runif(unsigned int rows,
644                                         unsigned int cols)
645       {
646         return rng<lecuyer>::runif<Col,Concrete>(rows, cols);
647       }
648 
649       /*! \brief Generate the next random integer.
650        *
651        * This method generates a random integer from the discrete
652        * uniform distribution on the interval [\a low, \a high].
653        *
654        * \param low The lower bound of the interval to evaluate.
655        * \param high the upper bound of the interval to evaluate.
656        *
657        * \see runif()
658        */
659       long
RandInt(long low,long high)660       RandInt (long low, long high)
661       {
662         return low + static_cast<long> ((high - low + 1) * runif ());
663       }
664 
665     protected:
666       // Generate the next random number.
667       //
668       double
U01()669       U01 ()
670       {
671         long k;
672         double p1, p2, u;
673 
674         /* Component 1 */
675         p1 = a12 * Cg[1] - a13n * Cg[0];
676         k = static_cast<long> (p1 / m1);
677         p1 -= k * m1;
678         if (p1 < 0.0) p1 += m1;
679         Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1;
680 
681         /* Component 2 */
682         p2 = a21 * Cg[5] - a23n * Cg[3];
683         k = static_cast<long> (p2 / m2);
684         p2 -= k * m2;
685         if (p2 < 0.0) p2 += m2;
686         Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2;
687 
688         /* Combination */
689         u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
690 
691         return (anti == false) ? u : (1 - u);
692       }
693 
694       // Generate the next random number with extended (53 bits) precision.
695       double
U01d()696       U01d ()
697       {
698         double u;
699         u = U01();
700         if (anti) {
701           // Don't forget that U01() returns 1 - u in the antithetic case
702           u += (U01() - 1.0) * fact;
703           return (u < 0.0) ? u + 1.0 : u;
704         } else {
705           u += U01() * fact;
706           return (u < 1.0) ? u : (u - 1.0);
707         }
708       }
709 
710 
711       // Public members of the class start here
712 
713       // The default seed of the package; will be the seed of the first
714       // declared RngStream, unless SetPackageSeed is called.
715       static double nextSeed[6];
716 
717       /* Instance variables */
718       double Cg[6], Bg[6], Ig[6];
719 
720 
721       bool anti, incPrec;
722 
723 
724       std::string streamname_;
725 
726   };
727 
728 #ifndef SCYTHE_RPACK
729   /* Default seed definition */
730   double lecuyer::nextSeed[6] =
731       {
732          12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0
733       };
734 #endif
735 
736 }
737 
738 #endif /* SCYTHE_LECUYER_H */
739