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); }
static void MatPowModM (double A[3][3], double B[3][3], double m, long c) /* Compute matrix D = A^c Mod m ; works even if A = B */ { int i, j, n = c; double W[3][3]; /* initialize: W = A; B = I */ for (i = 0; i <= 2; i++) { for (j = 0; j <= 2; ++j) { W[i][j] = A[i][j]; B[i][j] = 0.0; } } for (j = 0; j <= 2; ++j) B[j][j] = 1.0; /* Compute B = A^c mod m using the binary decomposition of c */ while (n > 0) { if (n % 2) MatMatModM (W, B, B, m); MatMatModM (W, W, W, m); n /= 2; } }
static void MatTwoPowModM (double A[3][3], double B[3][3], double m, long e) /* Compute matrix B = (A^(2^e) Mod m); works even if A = B */ { int i, j; /* initialize: B = A */ if (A != B) { for (i = 0; i <= 2; i++) { for (j = 0; j <= 2; ++j) B[i][j] = A[i][j]; } } /* Compute B = A^{2^e} */ for (i = 0; i < e; i++) MatMatModM (B, B, B, m); }