void RngStream_AdvanceState (RngStream g, long e, long c) { double B1[3][3], C1[3][3], B2[3][3], C2[3][3]; if (e > 0) { MatTwoPowModM (A1p0, B1, m1, e); MatTwoPowModM (A2p0, B2, m2, e); } else if (e < 0) { MatTwoPowModM (InvA1, B1, m1, -e); MatTwoPowModM (InvA2, B2, m2, -e); } if (c >= 0) { MatPowModM (A1p0, C1, m1, c); MatPowModM (A2p0, C2, m2, c); } else { MatPowModM (InvA1, C1, m1, -c); MatPowModM (InvA2, C2, m2, -c); } if (e) { MatMatModM (B1, C1, C1, m1); MatMatModM (B2, C2, C2, m2); } MatVecModM (C1, g->Cg, g->Cg, m1); MatVecModM (C2, &g->Cg[3], &g->Cg[3], m2); }
RngStream RngStream_CreateStream (const char name[]) { int i; RngStream g; size_t len; g = (RngStream) malloc (sizeof (struct RngStream_InfoState)); if (g == NULL) { printf ("RngStream_CreateStream: No more memory\n\n"); exit (EXIT_FAILURE); } if (name) { len = strlen (name); g->name = (char *) malloc ((len + 1) * sizeof (char)); strncpy (g->name, name, len + 1); } else g->name = 0; g->Anti = 0; g->IncPrec = 0; for (i = 0; i < 6; ++i) { g->Bg[i] = g->Cg[i] = g->Ig[i] = nextSeed[i]; } MatVecModM (A1p127, nextSeed, nextSeed, m1); MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2); return g; }
void Rand_CreateStream (RngStream *pg, char name[32]) { int i; RngStream g; ulongint V[6]; g = (RngStream) malloc (sizeof (struct InfoStream)); if (!g) { printf ("CreateStream: No more memory\n\n"); exit (1); } g->anti = 0; for (i = 0; i < 32; ++i) g->name[i] = name[i]; if (First) /* the first stream */ { for (i = 0; i < 6; ++i) V[i] = (ulongint) defseed[i]; Rand_SetSeed (g, V); for (i = 0; i < 6; ++i) lastseed[i] = defseed[i]; First = 0; } else { MatVecModM (A1p127, lastseed, lastseed, m1); MatVecModM (A2p127, &lastseed[3], &lastseed[3], m2); for (i = 0; i < 6; ++i) V[i] = (ulongint) lastseed[i]; Rand_SetSeed (g, V); } *pg = g; }
//------------------------------------------------------------------------- // Reset Stream to NextSubStream. // void RngStream::ResetNextSubstream () { MatVecModM(A1p76, Bg, Bg, m1); MatVecModM(A2p76, &Bg[3], &Bg[3], m2); for (int i = 0; i < 6; ++i) Cg[i] = Bg[i]; }
void RngStream_ResetNextSubstream (RngStream g) { int i; MatVecModM (A1p76, g->Bg, g->Bg, m1); MatVecModM (A2p76, &g->Bg[3], &g->Bg[3], m2); for (i = 0; i < 6; ++i) g->Cg[i] = g->Bg[i]; }
void Rand_ResetStream (RngStream g, SeedType where) { int i; switch (where) { case StartStream: for (i = 0; i <= 5; ++i) g->Cg[i] = g->Bg[i] = g->Ig[i]; break; case StartBlock: for (i = 0; i <= 5; ++i) g->Cg[i] = g->Bg[i]; break; case NextBlock: MatVecModM (A1p76, g->Bg, g->Bg, m1); MatVecModM (A2p76, &g->Bg[3], &g->Bg[3], m2); for (i = 0; i <= 5; ++i) g->Cg[i] = g->Bg[i]; break; } }
//------------------------------------------------------------------------- // constructor // RngStream::RngStream () { anti = false; incPrec = false; /* Information on a stream. The arrays {Cg, Bg, Ig} contain the current state of the stream, the starting state of the current SubStream, and the starting state of the stream. This stream generates antithetic variates if anti = true. It also generates numbers with extended precision (53 bits if machine follows IEEE 754 standard) if incPrec = true. nextSeed will be the seed of the next declared RngStream. */ for (int i = 0; i < 6; ++i) { Bg[i] = Cg[i] = Ig[i] = nextSeed[i]; } MatVecModM (A1p127, nextSeed, nextSeed, m1); MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2); }
static void MatMatModM (double A[3][3], double B[3][3], double C[3][3], double m) /* Returns C = A*B MOD m */ /* Note: work even if A = C or B = C or A = B = C. */ { int i, j; double V[3], W[3][3]; for (i = 0; i <= 2; ++i) { for (j = 0; j <= 2; ++j) V[j] = B[j][i]; MatVecModM (A, V, V, m); for (j = 0; j <= 2; ++j) W[j][i] = V[j]; } for (i = 0; i <= 2; ++i) { for (j = 0; j <= 2; ++j) C[i][j] = W[i][j]; } }