SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
ArithmeticMod.java
1/*
2 * Class: ArithmeticMod
3 * Description: multiplications of scalars, vectors and matrices modulo m
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.util;
26
35public class ArithmeticMod {
36
37 // private constants
38 private static final double two17 = 131072.0;
39 private static final double two53 = 9007199254740992.0;
40
41 // prevent the creation of the object
42 private ArithmeticMod() {
43 };
44
48
60 public static double multModM(double a, double s, double c, double m) {
61 int a1;
62 double v = a * s + c;
63 if (v >= two53 || v <= -two53) {
64 a1 = (int) (a / two17);
65 a -= a1 * two17;
66 v = a1 * s;
67 a1 = (int) (v / m);
68 v -= a1 * m;
69 v = v * two17 + a * s + c;
70 }
71 a1 = (int) (v / m);
72 if ((v -= a1 * m) < 0.0)
73 return v += m;
74 else
75 return v;
76 }
77
88 public static void matVecModM(double A[][], double s[], double v[], double m) {
89 int i;
90 double x[] = new double[v.length];
91 for (i = 0; i < v.length; ++i) {
92 x[i] = 0.0;
93 for (int j = 0; j < s.length; j++)
94 x[i] = multModM(A[i][j], s[j], x[i], m);
95 }
96 for (i = 0; i < v.length; ++i)
97 v[i] = x[i];
98 }
99
109 public static void matMatModM(double A[][], double B[][], double C[][], double m) {
110 int i, j;
111 int r = C.length; // # of rows of C
112 int c = C[0].length; // # of columns of C
113 double V[] = new double[r];
114 double W[][] = new double[r][c];
115 for (i = 0; i < c; ++i) {
116 for (j = 0; j < r; ++j)
117 V[j] = B[j][i];
118 matVecModM(A, V, V, m);
119 for (j = 0; j < r; ++j)
120 W[j][i] = V[j];
121 }
122 for (i = 0; i < r; ++i) {
123 for (j = 0; j < c; ++j)
124 C[i][j] = W[i][j];
125 }
126 }
127
137 public static void matTwoPowModM(double A[][], double B[][], double m, int e) {
138 int i, j;
139 /* initialize: B = A */
140 if (A != B) {
141 for (i = 0; i < A.length; i++) {
142 for (j = 0; j < A.length; ++j) // A is square
143 B[i][j] = A[i][j];
144 }
145 }
146 /* Compute B = A^{2^e} */
147 for (i = 0; i < e; i++)
148 matMatModM(B, B, B, m);
149 }
150
160 public static void matPowModM(double A[][], double B[][], double m, int c) {
161 int i, j;
162 int n = c;
163 int s = A.length; // we suppose that A is square
164 double W[][] = new double[s][s];
165
166 /* initialize: W = A; B = I */
167 for (i = 0; i < s; i++) {
168 for (j = 0; j < s; ++j) {
169 W[i][j] = A[i][j];
170 B[i][j] = 0.0;
171 }
172 }
173 for (j = 0; j < s; ++j)
174 B[j][j] = 1.0;
175
176 /* Compute B = A^c mod m using the binary decomp. of c */
177 while (n > 0) {
178 if ((n % 2) == 1)
179 matMatModM(W, B, B, m);
180 matMatModM(W, W, W, m);
181 n /= 2;
182 }
183 }
184
188
192
204 public static int multModM(int a, int s, int c, int m) {
205 int r = (int) (((long) a * s + c) % m);
206 return r < 0 ? r + m : r;
207 }
208
218 public static void matVecModM(int A[][], int s[], int v[], int m) {
219 int i;
220 int x[] = new int[v.length];
221 for (i = 0; i < v.length; ++i) {
222 x[i] = 0;
223 for (int j = 0; j < s.length; j++)
224 x[i] = multModM(A[i][j], s[j], x[i], m);
225 }
226 for (i = 0; i < v.length; ++i)
227 v[i] = x[i];
228
229 }
230
240 public static void matMatModM(int A[][], int B[][], int C[][], int m) {
241 int i, j;
242 int r = C.length; // # of rows of C
243 int c = C[0].length; // # of columns of C
244 int V[] = new int[r];
245 int W[][] = new int[r][c];
246 for (i = 0; i < c; ++i) {
247 for (j = 0; j < r; ++j)
248 V[j] = B[j][i];
249 matVecModM(A, V, V, m);
250 for (j = 0; j < r; ++j)
251 W[j][i] = V[j];
252 }
253 for (i = 0; i < r; ++i) {
254 for (j = 0; j < c; ++j)
255 C[i][j] = W[i][j];
256 }
257 }
258
268 public static void matTwoPowModM(int A[][], int B[][], int m, int e) {
269 int i, j;
270 /* initialize: B = A */
271 if (A != B) {
272 for (i = 0; i < A.length; i++) {
273 for (j = 0; j < A.length; ++j) // A is square
274 B[i][j] = A[i][j];
275 }
276 }
277 /* Compute B = A^{2^e} */
278 for (i = 0; i < e; i++)
279 matMatModM(B, B, B, m);
280 }
281
291 public static void matPowModM(int A[][], int B[][], int m, int c) {
292 int i, j;
293 int n = c;
294 int s = A.length; // we suppose that A is square (it must be)
295 int W[][] = new int[s][s];
296
297 /* initialize: W = A; B = I */
298 for (i = 0; i < s; i++) {
299 for (j = 0; j < s; ++j) {
300 W[i][j] = A[i][j];
301 B[i][j] = 0;
302 }
303 }
304 for (j = 0; j < s; ++j)
305 B[j][j] = 1;
306
307 /* Compute B = A^c mod m using the binary decomp. of c */
308 while (n > 0) {
309 if ((n % 2) == 1)
310 matMatModM(W, B, B, m);
311 matMatModM(W, W, W, m);
312 n /= 2;
313 }
314 }
315
319
323
335 public static long multModM(long a, long s, long c, long m) {
336
337 /*
338 * Suppose que 0 < a < m et 0 < s < m. Retourne (a*s + c) % m. Cette procedure
339 * est tiree de : L'Ecuyer, P. et Cote, S., A Random Number Package with
340 * Splitting Facilities, ACM TOMS, 1991. On coupe les entiers en blocs de d
341 * bits. H doit etre egal a 2^d.
342 */
343
344 final long H = 2147483648L; // = 2^d used in MultMod
345 long a0, a1, q, qh, rh, k, p;
346 if (a < H) {
347 a0 = a;
348 p = 0;
349 } else {
350 a1 = a / H;
351 a0 = a - H * a1;
352 qh = m / H;
353 rh = m - H * qh;
354 if (a1 >= H) {
355 a1 = a1 - H;
356 k = s / qh;
357 p = H * (s - k * qh) - k * rh;
358 if (p < 0)
359 p = (p + 1) % m + m - 1;
360 } else /* p = (A2 * s * h) % m. */
361 p = 0;
362 if (a1 != 0) {
363 q = m / a1;
364 k = s / q;
365 p -= k * (m - a1 * q);
366 if (p > 0)
367 p -= m;
368 p += a1 * (s - k * q);
369 if (p < 0)
370 p = (p + 1) % m + m - 1;
371 } /* p = ((A2 * h + a1) * s) % m. */
372 k = p / qh;
373 p = H * (p - k * qh) - k * rh;
374 if (p < 0)
375 p = (p + 1) % m + m - 1;
376 } /* p = ((A2 * h + a1) * h * s) % m */
377 if (a0 != 0) {
378 q = m / a0;
379 k = s / q;
380 p -= k * (m - a0 * q);
381 if (p > 0)
382 p -= m;
383 p += a0 * (s - k * q);
384 if (p < 0)
385 p = (p + 1) % m + m - 1;
386 }
387 p = (p - m) + c;
388 if (p < 0)
389 p += m;
390 return p;
391 }
392
402 public static void matVecModM(long A[][], long s[], long v[], long m) {
403 int i;
404 long x[] = new long[v.length];
405 for (i = 0; i < v.length; ++i) {
406 x[i] = 0;
407 for (int j = 0; j < s.length; j++)
408 x[i] = multModM(A[i][j], s[j], x[i], m);
409 }
410 for (i = 0; i < v.length; ++i)
411 v[i] = x[i];
412
413 }
414
424 public static void matMatModM(long A[][], long B[][], long C[][], long m) {
425 int i, j;
426 int r = C.length; // # of rows of C
427 int c = C[0].length; // # of columns of C
428 long V[] = new long[r];
429 long W[][] = new long[r][c];
430 for (i = 0; i < c; ++i) {
431 for (j = 0; j < r; ++j)
432 V[j] = B[j][i];
433 matVecModM(A, V, V, m);
434 for (j = 0; j < r; ++j)
435 W[j][i] = V[j];
436 }
437 for (i = 0; i < r; ++i) {
438 for (j = 0; j < c; ++j)
439 C[i][j] = W[i][j];
440 }
441 }
442
452 public static void matTwoPowModM(long A[][], long B[][], long m, int e) {
453 int i, j;
454 /* initialize: B = A */
455 if (A != B) {
456 for (i = 0; i < A.length; i++) {
457 for (j = 0; j < A.length; ++j) // A is square
458 B[i][j] = A[i][j];
459 }
460 }
461 /* Compute B = A^{2^e} */
462 for (i = 0; i < e; i++)
463 matMatModM(B, B, B, m);
464 }
465
475 public static void matPowModM(long A[][], long B[][], long m, int c) {
476 int i, j;
477 int n = c;
478 int s = A.length; // we suppose that A is square (it must be)
479 long W[][] = new long[s][s];
480
481 /* initialize: W = A; B = I */
482 for (i = 0; i < s; i++) {
483 for (j = 0; j < s; ++j) {
484 W[i][j] = A[i][j];
485 B[i][j] = 0;
486 }
487 }
488 for (j = 0; j < s; ++j)
489 B[j][j] = 1;
490
491 /* Compute B = A^c mod m using the binary decomp. of c */
492 while (n > 0) {
493 if ((n % 2) == 1)
494 matMatModM(W, B, B, m);
495 matMatModM(W, W, W, m);
496 n /= 2;
497 }
498 }
499
500}
501
static void matVecModM(double A[][], double s[], double v[], double m)
Computes the result of and puts the result in v.
static void matMatModM(long A[][], long B[][], long C[][], long m)
Exactly like matMatModM(double[][],double[][],double[][],double) using double, but with long instead ...
static void matVecModM(int A[][], int s[], int v[], int m)
Exactly like matVecModM(double[][],double[],double[],double) using double, but with int instead of do...
static void matTwoPowModM(double A[][], double B[][], double m, int e)
Computes and puts the result in B.
static void matPowModM(double A[][], double B[][], double m, int c)
Computes and puts the result in B.
static double multModM(double a, double s, double c, double m)
Computes .
static void matPowModM(int A[][], int B[][], int m, int c)
Exactly like matPowModM(double[][],double[][],double,int) using double, but with int instead of doubl...
static void matVecModM(long A[][], long s[], long v[], long m)
Exactly like matVecModM(double[][],double[],double[],double) using double, but with long instead of d...
static void matMatModM(double A[][], double B[][], double C[][], double m)
Computes and puts the result in C.
static long multModM(long a, long s, long c, long m)
Computes .
static int multModM(int a, int s, int c, int m)
Computes .
static void matPowModM(long A[][], long B[][], long m, int c)
Exactly like matPowModM(double[][],double[][],double,int) using double, but with long instead of doub...
static void matTwoPowModM(int A[][], int B[][], int m, int e)
Exactly like matTwoPowModM(double[][],double[][],double,int) using double, but with int instead of do...
static void matTwoPowModM(long A[][], long B[][], long m, int e)
Exactly like matTwoPowModM(double[][],double[][],double,int) using double, but with long instead of d...
static void matMatModM(int A[][], int B[][], int C[][], int m)
Exactly like matMatModM(double[][],double[][],double[][],double) using double, but with int instead o...