SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
DigitalNet.java
1/*
2 * Class: DigitalNet
3 * Description:
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001--2018 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.hups;
26
27import umontreal.ssj.util.PrintfFormat;
28import umontreal.ssj.rng.*;
29
138public class DigitalNet extends PointSet {
139
140 // Variables to be initialized by the constructor subclasses.
141 protected int b = 0; // Base.
142 protected int numCols = 0; // The number of columns in each C_j. (= k)
143 protected int numRows = 0; // The number of nonzero rows in the original C_j. (= r)
144 // This r is used sometimes to save computations.
145 protected int outDigits = 0; // Number of output digits (= w >= r)
146 private int[][] originalMat; // Original gen. matrices without randomization
147 protected transient int[][] genMat; // The current generator matrices.
148 // genMat[j*numCols+c][l] is element in column c and row l of C_j.
149 protected int[][] digitalShift; // The digital shift, initially zero (null).
150 // Entry [j][l] is for dimension j, digit l,
151 // for 0 <= l < outDigits.
152 protected double normFactor; // To convert output to (0,1); 1/b^outDigits.
153 protected double[] factor; // Lookup table in ascending order: factor[i]
154 // = 1/b^{i+1} for 0 <= i < outDigits.
155 protected int interlacing = 1; // Interlacing factor.
156
157 // primes gives the first index in array FaureFactor
158 // for the prime p. If primes[i] = p, then
159 // FaureFactor[p][j] contains the Faure ordered factors of base p.
160 private int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 };
161
162 // Factors on the diagonal corresponding to base b = prime[i] ordered by
163 // increasing Bounds.
164 // Warning: Every `DigitalNet` holds this large array !!! Do we need this here? *****
165 private int[][] FaureFactor = { { 1 }, { 1, 2 }, { 2, 3, 1, 4 }, { 2, 3, 4, 5, 1, 6 },
166 { 3, 4, 7, 8, 2, 5, 6, 9, 1, 10 }, { 5, 8, 3, 4, 9, 10, 2, 6, 7, 11, 1, 12 },
167 { 5, 7, 10, 12, 3, 6, 11, 14, 4, 13, 2, 8, 9, 15, 1, 16 },
168 { 7, 8, 11, 12, 4, 5, 14, 15, 3, 6, 13, 16, 2, 9, 10, 17, 1, 18 },
169 { 5, 9, 14, 18, 7, 10, 13, 16, 4, 6, 17, 19, 3, 8, 15, 20, 2, 11, 12, 21, 1, 22 },
170 { 8, 11, 18, 21, 12, 17, 9, 13, 16, 20, 5, 6, 23, 24, 4, 7, 22, 25, 3, 10, 19, 26, 2, 14, 15, 27, 1, 28 },
171 { 12, 13, 18, 19, 11, 14, 17, 20, 7, 9, 22, 24, 4, 8, 23, 27, 5, 6, 25, 26, 3, 10, 21, 28, 2, 15, 16, 29, 1,
172 30 },
173 { 8, 14, 23, 29, 10, 11, 26, 27, 13, 17, 20, 24, 7, 16, 21, 30, 5, 15, 22, 32, 6, 31, 4, 9, 28, 33, 3, 12, 25,
174 34, 2, 18, 19, 35, 1, 36 },
175 { 16, 18, 23, 25, 11, 15, 26, 30, 12, 17, 24, 29, 9, 32, 13, 19, 22, 28, 6, 7, 34, 35, 5, 8, 33, 36, 4, 10, 31,
176 37, 3, 14, 27, 38, 2, 20, 21, 39, 1, 40 },
177 { 12, 18, 25, 31, 9, 19, 24, 34, 8, 16, 27, 35, 10, 13, 30, 33, 15, 20, 23, 28, 5, 17, 26, 38, 6, 7, 36, 37, 4,
178 11, 32, 39, 3, 14, 29, 40, 2, 21, 22, 41, 1, 42 },
179 { 13, 18, 29, 34, 11, 17, 30, 36, 10, 14, 33, 37, 7, 20, 27, 40, 9, 21, 26, 38, 15, 22, 25, 32, 6, 8, 39, 41,
180 5, 19, 28, 42, 4, 12, 35, 43, 3, 16, 31, 44, 2, 23, 24, 45, 1, 46 },
181 { 14, 19, 34, 39, 23, 30, 12, 22, 31, 41, 8, 11, 20, 24, 29, 33, 42, 45, 10, 16, 37, 43, 7, 15, 38, 46, 17, 25,
182 28, 36, 5, 21, 32, 48, 6, 9, 44, 47, 4, 13, 40, 49, 3, 18, 35, 50, 2, 26, 27, 51, 1, 52 },
183 { 25, 26, 33, 34, 18, 23, 36, 41, 14, 21, 38, 45, 24, 27, 32, 35, 11, 16, 43, 48, 9, 13, 46, 50, 8, 22, 37, 51,
184 7, 17, 42, 52, 19, 28, 31, 40, 6, 10, 49, 53, 5, 12, 47, 54, 4, 15, 44, 55, 3, 20, 39, 56, 2, 29, 30, 57,
185 1, 58 },
186 { 22, 25, 36, 39, 17, 18, 43, 44, 24, 28, 33, 37, 13, 14, 47, 48, 16, 19, 42, 45, 9, 27, 34, 52, 8, 23, 38, 53,
187 11, 50, 7, 26, 35, 54, 21, 29, 32, 40, 6, 10, 51, 55, 5, 12, 49, 56, 4, 15, 46, 57, 3, 20, 41, 58, 2, 30,
188 31, 59, 1, 60 },
189 { 18, 26, 41, 49, 14, 24, 43, 53, 12, 28, 39, 55, 29, 30, 37, 38, 10, 20, 47, 57, 16, 21, 46, 51, 8, 25, 42,
190 59, 13, 31, 36, 54, 9, 15, 52, 58, 7, 19, 48, 60, 23, 32, 35, 44, 5, 27, 40, 62, 6, 11, 56, 61, 4, 17,
191 50, 63, 3, 22, 45, 64, 2, 33, 34, 65, 1, 66 } };
192
196 public DigitalNet() {
197 }
198
202 public int getInterlacing() {
203 return interlacing;
204 }
205
209 public void setInterlacing(int interlacing) {
210 this.interlacing = interlacing;
211 }
212
221 public double getCoordinate(int i, int j) {
222 // convert i to Gray representation, put digits in gdigit[].
223 int l, c, sum;
224 int[] bdigit = new int[numCols];
225 int[] gdigit = new int[numCols];
226 int idigits = intToDigitsGray(b, i, numCols, bdigit, gdigit);
227 double result = 0;
228 if (digitalShift != null && dimShift < j)
229 addRandomShift(dimShift, j, shiftStream); // Extends the random shift up to j if
230 // needed.
231 for (l = 0; l < outDigits; l++) {
232 if (digitalShift == null)
233 sum = 0;
234 else
235 sum = digitalShift[j][l];
236 if (l < numRows)
237 for (c = 0; c < idigits; c++)
238 sum += genMat[j * numCols + c][l] * gdigit[c];
239 result += (sum % b) * factor[l];
240 }
241 if (digitalShift != null)
242 result += EpsilonHalf;
243 return result;
244 }
245
250 return new DigitalNetIterator();
251 }
252
261 public double getCoordinateNoGray(int i, int j) {
262 // convert i to b-ary representation, put digits in bdigit[].
263 int l, c, sum;
264 int[] bdigit = new int[numCols];
265 int idigits = 0;
266 for (c = 0; i > 0; c++) {
267 idigits++;
268 bdigit[c] = i % b;
269 i = i / b;
270 }
271 if (digitalShift != null && dimShift < j)
272 addRandomShift(dimShift, j, shiftStream); // Extends the random shift up to j if needed.
273 double result = 0;
274 for (l = 0; l < outDigits; l++) {
275 if (digitalShift == null)
276 sum = 0;
277 else
278 sum = digitalShift[j][l];
279 if (l < numRows)
280 for (c = 0; c < idigits; c++)
281 sum += genMat[j * numCols + c][l] * bdigit[c];
282 result += (sum % b) * factor[l];
283 }
284 if (digitalShift != null)
285 result += EpsilonHalf;
286 return result;
287 }
288
295 return new DigitalNetIteratorNoGray();
296 }
297
310 public void addRandomShift(int d1, int d2, RandomStream stream) {
311 if (null == stream)
312 throw new IllegalArgumentException(PrintfFormat.NEWLINE + " Calling addRandomShift with null stream");
313 if (0 == d2)
314 d2 = Math.max(1, dim);
315 if (digitalShift == null) {
316 digitalShift = new int[d2][outDigits];
317 capacityShift = d2;
318 } else if (d2 > capacityShift) {
319 int d3 = Math.max(4, capacityShift);
320 while (d2 > d3)
321 d3 *= 2;
322 int[][] temp = new int[d3][outDigits];
323 capacityShift = d3;
324 for (int i = 0; i < d1; i++)
325 for (int j = 0; j < outDigits; j++)
326 temp[i][j] = digitalShift[i][j];
327 digitalShift = temp;
328 }
329 for (int i = d1; i < d2; i++)
330 for (int j = 0; j < outDigits; j++)
331 digitalShift[i][j] = stream.nextInt(0, b - 1);
332 dimShift = d2;
333 shiftStream = stream;
334 }
335
342 public void addRandomShift(RandomStream stream) {
343 addRandomShift(0, dim, stream);
344 }
345
349 public void clearRandomShift() {
350 super.clearRandomShift();
351 digitalShift = null;
352 }
353
359 public String toString() {
360 StringBuffer sb = new StringBuffer(100);
361 if (b > 0) {
362 sb.append(", base = ");
363 sb.append(b);
364 }
365 sb.append(", Num cols = ");
366 sb.append(numCols);
367 sb.append(", Num rows = ");
368 sb.append(numRows);
369 sb.append(", outDigits = ");
370 sb.append(outDigits);
371 return sb.toString();
372 }
373
374 // Print matrices A for dimensions 0 to N-1.
375 protected void printMat(int N, int[][][] A, String name) {
376 for (int i = 0; i < N; i++) {
377 System.out.println("-------------------------------------" + PrintfFormat.NEWLINE + name + " dim = " + i);
378 int l, c; // row l, column c, dimension i for A[i][l][c].
379 for (l = 0; l < numRows; l++) {
380 for (c = 0; c < numCols; c++) {
381 System.out.print(A[i][l][c] + " ");
382 }
383 System.out.println("");
384 }
385 }
386 System.out.println("");
387 }
388
389 // Print matrix A
390 protected void printMat0(int[][] A, String name) {
391 System.out.println("-------------------------------------" + PrintfFormat.NEWLINE + name);
392 int l, c; // row l, column c for A[l][c].
393 for (l = 0; l < numCols; l++) {
394 for (c = 0; c < numCols; c++) {
395 System.out.print(A[l][c] + " ");
396 }
397 System.out.println("");
398 }
399 System.out.println("");
400 }
401
402 // Left-multiplies lower-triangular matrix Mj by original C_j,
403 // where original C_j is in originalMat and result is in genMat.
404 // This implementation is safe only if (numRows*(b-1)^2) is a valid int.
405 private void leftMultiplyMat(int j, int[][] Mj) {
406 int l, c, i, sum; // Dimension j, row l, column c for new C_j.
407 for (l = 0; l < numRows; l++) {
408 for (c = 0; c < numCols; c++) {
409 // Multiply row l of M_j by column c of C_j.
410 sum = 0;
411 for (i = 0; i <= l; i++)
412 sum += Mj[l][i] * originalMat[j * numCols + c][i];
413 genMat[j * numCols + c][l] = sum % b;
414 }
415 }
416 }
417
418 // Left-multiplies diagonal matrix Mj by original C_j,
419 // where original C_j is in originalMat and result is in genMat.
420 // This implementation is safe only if (numRows*(b-1)^2) is a valid int.
421 private void leftMultiplyMatDiag(int j, int[][] Mj) {
422 int l, c, sum; // Dimension j, row l, column c for new C_j.
423 for (l = 0; l < numRows; l++) {
424 for (c = 0; c < numCols; c++) {
425 // Multiply row l of M_j by column c of C_j.
426 sum = Mj[l][l] * originalMat[j * numCols + c][l];
427 genMat[j * numCols + c][l] = sum % b;
428 }
429 }
430 }
431
432 // Right-multiplies original C_j by upper-triangular matrix Mj,
433 // where original C_j is in originalMat and result is in genMat.
434 // This implementation is safe only if (numCols*(b-1)^2) is a valid int.
435 private void rightMultiplyMat(int j, int[][] Mj) {
436 int l, c, i, sum; // Dimension j, row l, column c for new C_j.
437 for (l = 0; l < numRows; l++) {
438 for (c = 0; c < numCols; c++) {
439 // Multiply row l of C_j by column c of M_j.
440 sum = 0;
441 for (i = 0; i <= c; i++)
442 sum += originalMat[j * numCols + i][l] * Mj[i][c];
443 genMat[j * numCols + c][l] = sum % b;
444 }
445 }
446 }
447
448 private int getFaureIndex(String method, int sb, int flag) {
449 // Check for errors in ...FaurePermut. Returns the index ib of the
450 // base b in primes, i.e. b = primes[ib].
451 if (sb >= b)
452 throw new IllegalArgumentException(PrintfFormat.NEWLINE + " sb >= base in " + method);
453 if (sb < 1)
454 throw new IllegalArgumentException(PrintfFormat.NEWLINE + " sb = 0 in " + method);
455 if ((flag > 2) || (flag < 0))
456 throw new IllegalArgumentException(PrintfFormat.NEWLINE + " lowerFlag not in {0, 1, 2} in " + method);
457
458 // Find index ib of base in array primes
459 int ib = 0;
460 while ((ib < primes.length) && (primes[ib] < b))
461 ib++;
462 if (ib >= primes.length)
463 throw new IllegalArgumentException("base too large in " + method);
464 if (b != primes[ib])
465 throw new IllegalArgumentException("Faure factors are not implemented for this base in " + method);
466 return ib;
467 }
468
487 public void leftMatrixScramble(RandomStream stream) {
488 int j, l, c; // dimension j, row l, column c.
489
490 // If genMat contains the original gen. matrices, copy to originalMat.
491 if (originalMat == null) { // This is done only once.
492 originalMat = genMat;
493 genMat = new int[dim * numCols][numRows];
494 }
495 // Constructs the lower-triangular scrambling matrices M_j, r by r.
496 // *** Pierre: We should avoid creating and storing these matrices! *****
497 int[][][] scrambleMat = new int[dim][numRows][numRows];
498 for (j = 0; j < dim; j++) {
499 for (l = 0; l < numRows; l++) {
500 for (c = 0; c < numRows; c++) {
501 if (c == l) // No zero on the diagonal.
502 scrambleMat[j][l][c] = stream.nextInt(1, b - 1);
503 else if (c < l)
504 scrambleMat[j][l][c] = stream.nextInt(0, b - 1);
505 else
506 scrambleMat[j][l][c] = 0; // Zeros above the diagonal;
507 }
508 }
509 }
510 // Multiply M_j by the generator matrix C_j for each j.
511 for (j = 0; j < dim; j++)
512 leftMultiplyMat(j, scrambleMat[j]);
513 }
514
523 int j, l, c; // dimension j, row l, column c.
524
525 // If genMat contains the original gen. matrices, copy to originalMat.
526 if (originalMat == null) {
527 originalMat = genMat;
528 genMat = new int[dim * numCols][numRows];
529 }
530 // Constructs the diagonal scrambling matrices M_j, r by r.
531 int[][][] scrambleMat = new int[dim][numRows][numRows];
532 for (j = 0; j < dim; j++) {
533 for (l = 0; l < numRows; l++) {
534 for (c = 0; c < numRows; c++) {
535 if (c == l) // No zero on the diagonal.
536 scrambleMat[j][l][c] = stream.nextInt(1, b - 1);
537 else
538 scrambleMat[j][l][c] = 0; // Only 0 elsewhere.
539 }
540 }
541 }
542 // Multiply M_j by the generator matrix C_j for each j.
543 for (j = 0; j < dim; j++)
544 leftMultiplyMatDiag(j, scrambleMat[j]);
545 }
546
547 private void LMSFaurePermut(String method, RandomStream stream, int sb, int lowerFlag) {
548 /*
549 * If \texttt{lowerFlag = 2}, the off-diagonal elements below the diagonal of
550 * $\mathbf{M}_j$ are chosen as in \method{leftMatrixScramble}{}. If
551 * \texttt{lowerFlag = 1}, the off-diagonal elements below the diagonal of
552 * $\mathbf{M}_j$ are also chosen from the restricted set. If \texttt{lowerFlag
553 * = 0}, the off-diagonal elements of $\mathbf{M}_j$ are all 0.
554 */
555 int ib = getFaureIndex(method, sb, lowerFlag);
556
557 // If genMat contains the original gen. matrices, copy to originalMat.
558 if (originalMat == null) {
559 originalMat = genMat;
560 genMat = new int[dim * numCols][numRows];
561 }
562
563 // Constructs the lower-triangular scrambling matrices M_j, r by r.
564 int jb;
565 int j, l, c; // dimension j, row l, column c.
566 int[][][] scrambleMat = new int[dim][numRows][numRows];
567 for (j = 0; j < dim; j++) {
568 for (l = 0; l < numRows; l++) {
569 for (c = 0; c < numRows; c++) {
570 if (c == l) {
571 jb = stream.nextInt(0, sb - 1);
572 scrambleMat[j][l][c] = FaureFactor[ib][jb];
573 } else if (c < l) {
574 if (lowerFlag == 2) {
575 scrambleMat[j][l][c] = stream.nextInt(0, b - 1);
576 } else if (lowerFlag == 1) {
577 jb = stream.nextInt(0, sb - 1);
578 scrambleMat[j][l][c] = FaureFactor[ib][jb];
579 } else { // lowerFlag == 0
580 scrambleMat[j][l][c] = 0;
581 }
582 } else
583 scrambleMat[j][l][c] = 0; // Zeros above the diagonal;
584 }
585 }
586 }
587 // printMat (dim, scrambleMat, method);
588
589 // Multiply M_j by the generator matrix C_j for each j.
590 if (lowerFlag == 0)
591 for (j = 0; j < dim; j++)
592 leftMultiplyMatDiag(j, scrambleMat[j]);
593 else
594 for (j = 0; j < dim; j++)
595 leftMultiplyMat(j, scrambleMat[j]);
596 }
597
610 public void leftMatrixScrambleFaurePermut(RandomStream stream, int sb) {
611 LMSFaurePermut("leftMatrixScrambleFaurePermut", stream, sb, 2);
612 }
613
622 LMSFaurePermut("leftMatrixScrambleFaurePermutDiag", stream, sb, 0);
623 }
624
633 public void leftMatrixScrambleFaurePermutAll(RandomStream stream, int sb) {
634 LMSFaurePermut("leftMatrixScrambleFaurePermutAll", stream, sb, 1);
635 }
636
648 int j, l, c; // dimension j, row l, column c.
649 int diag; // random entry on the diagonal;
650 int col1; // random entries below the diagonal;
651
652 // If genMat is original generator matrices, copy it to originalMat.
653 if (originalMat == null) {
654 originalMat = genMat;
655 genMat = new int[dim * numCols][numRows];
656 }
657
658 // Constructs the lower-triangular scrambling matrices M_j, r by r.
659 int[][][] scrambleMat = new int[dim][numRows][numRows];
660 for (j = 0; j < dim; j++) {
661 diag = stream.nextInt(1, b - 1);
662 for (l = 0; l < numRows; l++) {
663 // Single random nonzero element on the diagonal.
664 scrambleMat[j][l][l] = diag;
665 for (c = l + 1; c < numRows; c++)
666 scrambleMat[j][l][c] = 0;
667 }
668 for (l = 1; l < numRows; l++) {
669 col1 = stream.nextInt(0, b - 1);
670 for (c = 0; l + c < numRows; c++)
671 scrambleMat[j][l + c][c] = col1;
672 }
673 }
674 // printMat (dim, scrambleMat, "iBinomialMatrixScramble");
675 for (j = 0; j < dim; j++)
676 leftMultiplyMat(j, scrambleMat[j]);
677 }
678
679 private void iBMSFaurePermut(String method, RandomStream stream, int sb, int lowerFlag) {
680 int ib = getFaureIndex(method, sb, lowerFlag);
681
682 // If genMat is original generator matrices, copy it to originalMat.
683 if (originalMat == null) {
684 originalMat = genMat;
685 genMat = new int[dim * numCols][numRows];
686 }
687
688 // Constructs the lower-triangular scrambling matrices M_j, r by r.
689 int j, l, c; // dimension j, row l, column c.
690 int diag; // random entry on the diagonal;
691 int col1; // random entries below the diagonal;
692 int jb;
693 int[][][] scrambleMat = new int[dim][numRows][numRows];
694 for (j = 0; j < dim; j++) {
695 jb = stream.nextInt(0, sb - 1);
696 diag = FaureFactor[ib][jb];
697 for (l = 0; l < numRows; l++) {
698 // Single random nonzero element on the diagonal.
699 scrambleMat[j][l][l] = diag;
700 for (c = l + 1; c < numRows; c++)
701 scrambleMat[j][l][c] = 0;
702 }
703 for (l = 1; l < numRows; l++) {
704 if (lowerFlag == 2) {
705 col1 = stream.nextInt(0, b - 1);
706 } else if (lowerFlag == 1) {
707 jb = stream.nextInt(0, sb - 1);
708 col1 = FaureFactor[ib][jb];
709 } else { // lowerFlag == 0
710 col1 = 0;
711 }
712 for (c = 0; l + c < numRows; c++)
713 scrambleMat[j][l + c][c] = col1;
714 }
715 }
716 // printMat (dim, scrambleMat, method);
717
718 if (lowerFlag > 0)
719 for (j = 0; j < dim; j++)
720 leftMultiplyMat(j, scrambleMat[j]);
721 else
722 for (j = 0; j < dim; j++)
723 leftMultiplyMatDiag(j, scrambleMat[j]);
724 }
725
734 iBMSFaurePermut("iBinomialMatrixScrambleFaurePermut", stream, sb, 2);
735 }
736
745 iBMSFaurePermut("iBinomialMatrixScrambleFaurePermutDiag", stream, sb, 0);
746 }
747
757 iBMSFaurePermut("iBinomialMatrixScrambleFaurePermutAll", stream, sb, 1);
758 }
759
775 int j, l, c; // dimension j, row l, column c.
776 int diag; // random entry on the diagonal;
777 // int col1; // random entries below the diagonal;
778
779 // If genMat contains original gener. matrices, copy it to originalMat.
780 if (originalMat == null) {
781 originalMat = genMat;
782 genMat = new int[dim * numCols][numRows];
783 }
784
785 // Constructs the lower-triangular scrambling matrices M_j, r by r.
786 int[][][] scrambleMat = new int[dim][numRows][numRows];
787 for (j = 0; j < dim; j++) {
788 for (c = 0; c < numRows; c++) {
789 diag = stream.nextInt(1, b - 1); // Random entry in this column.
790 for (l = 0; l < c; l++)
791 scrambleMat[j][l][c] = 0;
792 for (l = c; l < numRows; l++)
793 scrambleMat[j][l][c] = diag;
794 }
795 }
796 // printMat (dim, scrambleMat, "stripedMatrixScramble");
797 for (j = 0; j < dim; j++)
798 leftMultiplyMat(j, scrambleMat[j]);
799 }
800
810 int ib = getFaureIndex("stripedMatrixScrambleFaurePermutAll", sb, 1);
811
812 // If genMat contains original gener. matrices, copy it to originalMat.
813 if (originalMat == null) {
814 originalMat = genMat;
815 genMat = new int[dim * numCols][numRows];
816 }
817
818 // Constructs the lower-triangular scrambling matrices M_j, r by r.
819 int j, l, c; // dimension j, row l, column c.
820 int diag; // random entry on the diagonal;
821 // int col1; // random entries below the diagonal;
822 int jb;
823 int[][][] scrambleMat = new int[dim][numRows][numRows];
824 for (j = 0; j < dim; j++) {
825 for (c = 0; c < numRows; c++) {
826 jb = stream.nextInt(0, sb - 1);
827 diag = FaureFactor[ib][jb]; // Random entry in this column.
828 for (l = 0; l < c; l++)
829 scrambleMat[j][l][c] = 0;
830 for (l = c; l < numRows; l++)
831 scrambleMat[j][l][c] = diag;
832 }
833 }
834 // printMat (dim, scrambleMat, "stripedMatrixScrambleFaurePermutAll");
835 for (j = 0; j < dim; j++)
836 leftMultiplyMat(j, scrambleMat[j]);
837 }
838
855 public void rightMatrixScramble(RandomStream stream) {
856 int j, c, l; // dimension j, row l, column c, of genMat.
857
858 // SaveOriginalMat();
859 if (originalMat == null) {
860 originalMat = genMat;
861 genMat = new int[dim * numCols][numRows];
862 }
863
864 // Generate an upper triangular matrix for Faure-Tezuka right-scramble.
865 // Entry [l][c] is in row l, col c.
866 int[][] scrambleMat = new int[numCols][numCols];
867 for (c = 0; c < numCols; c++) {
868 for (l = 0; l < c; l++)
869 scrambleMat[l][c] = stream.nextInt(0, b - 1);
870 scrambleMat[c][c] = stream.nextInt(1, b - 1);
871 for (l = c + 1; l < numCols; l++)
872 scrambleMat[l][c] = 0;
873 }
874
875 // printMat0 (scrambleMat, "rightMatrixScramble");
876 // Right-multiply the generator matrices by the scrambling matrix.
877 for (j = 0; j < dim; j++)
878 rightMultiplyMat(j, scrambleMat);
879 }
880
884 public void unrandomize() {
886 digitalShift = null;
887 }
888
894 if (originalMat != null) {
895 genMat = originalMat;
896 originalMat = null;
897 }
898 }
899
906 originalMat = null;
907 }
908
912 public void printGeneratorMatrices(int s) {
913 // row l, column c, dimension j.
914 for (int j = 0; j < s; j++) {
915 System.out.println("dim = " + (j + 1) + PrintfFormat.NEWLINE);
916 for (int l = 0; l < numRows; l++) {
917 for (int c = 0; c < numCols; c++)
918 System.out.print(genMat[j * numCols + c][l] + " ");
919 System.out.println("");
920 }
921 System.out.println("----------------------------------");
922 }
923 }
924
925 // Computes the digital expansion of $i$ in base $b$, and the digits
926 // of the Gray code of $i$.
927 // These digits are placed in arrays \texttt{bary} and \texttt{gray},
928 // respectively, and the method returns the number of digits in the
929 // expansion. The two arrays are assumed to be of sizes larger or
930 // equal to this new number of digits.
931 protected int intToDigitsGray(int b, int i, int numDigits, int[] bary, int[] gray) {
932 if (i == 0)
933 return 0;
934 int idigits = 0; // Num. of digits in b-ary and Gray repres.
935 int c;
936 // convert i to b-ary representation, put digits in bary[].
937 for (c = 0; i > 0; c++) {
938 idigits++;
939 bary[c] = i % b;
940 i = i / b;
941 }
942 // convert b-ary representation to Gray code.
943 gray[idigits - 1] = bary[idigits - 1];
944 int diff;
945 for (c = 0; c < idigits - 1; c++) {
946 diff = bary[c] - bary[c + 1];
947 if (diff < 0)
948 gray[c] = diff + b;
949 else
950 gray[c] = diff;
951 }
952 for (c = idigits; c < numDigits; c++)
953 gray[c] = bary[c] = 0;
954 return idigits;
955 }
956
957 // ************************************************************************
958
959 protected class DigitalNetIterator extends PointSet.DefaultPointSetIterator {
960
961 protected int idigits; // Num. of digits in current code.
962 protected int[] bdigit; // b-ary code of current point index.
963 protected int[] gdigit; // Gray code of current point index.
964 protected int dimS; // = dim except in the shift iterator
965 // children where it is = dim + 1.
966 protected int[] cachedCurPoint; // Digits of coords of the current point,
967 // with digital shift already applied.
968 // Digit l of coord j is at pos. [j*outDigits + l].
969 // Has one more dimension for the shift iterators.
970
971 public DigitalNetIterator() {
972 // EpsilonHalf = 0.5 / Math.pow ((double) b, (double) outDigits);
973 bdigit = new int[numCols];
974 gdigit = new int[numCols];
975 dimS = dim;
976 cachedCurPoint = new int[(dim + 1) * outDigits];
977 init(); // This call is important so that subclasses do not
978 // automatically call 'resetCurPointIndex' at the time
979 // of construction as this may cause a subtle
980 // 'NullPointerException'
981 }
982
983 public void init() { // See constructor
985 }
986
987 // We want to avoid generating 0 or 1
988 public double nextDouble() {
989 return nextCoordinate() + EpsilonHalf;
990 }
991
992 public double nextCoordinate() {
993 if (curPointIndex >= numPoints || curCoordIndex >= dimS)
994 outOfBounds();
995 int start = outDigits * curCoordIndex++;
996 double sum = 0;
997 // Can always have up to outDigits digits, because of digital shift.
998 for (int k = 0; k < outDigits; k++)
999 sum += cachedCurPoint[start + k] * factor[k];
1000 if (digitalShift != null)
1001 sum += EpsilonHalf;
1002 return sum;
1003 }
1004
1005 public void resetCurPointIndex() {
1006 if (digitalShift == null)
1007 for (int i = 0; i < cachedCurPoint.length; i++)
1008 cachedCurPoint[i] = 0;
1009 else {
1010 if (dimShift < dimS)
1011 addRandomShift(dimShift, dimS, shiftStream); // Extends the random shift to
1012 // more coordinates!
1013 for (int j = 0; j < dimS; j++)
1014 for (int k = 0; k < outDigits; k++)
1015 cachedCurPoint[j * outDigits + k] = digitalShift[j][k];
1016 }
1017 for (int i = 0; i < numCols; i++)
1018 bdigit[i] = 0;
1019 for (int i = 0; i < numCols; i++)
1020 gdigit[i] = 0;
1021 curPointIndex = 0;
1022 curCoordIndex = 0;
1023 idigits = 0;
1024 }
1025
1026 public void setCurPointIndex(int i) {
1027 if (i == 0) {
1029 return;
1030 }
1031 curPointIndex = i;
1032 curCoordIndex = 0;
1033 if (digitalShift != null && dimShift < dimS)
1035
1036 // Digits of Gray code, used to reconstruct cachedCurPoint.
1037 idigits = intToDigitsGray(b, i, numCols, bdigit, gdigit);
1038 int c, j, l, sum;
1039 for (j = 0; j < dimS; j++) {
1040 for (l = 0; l < outDigits; l++) {
1041 if (digitalShift == null)
1042 sum = 0;
1043 else
1044 sum = digitalShift[j][l];
1045 if (l < numRows)
1046 for (c = 0; c < idigits; c++)
1047 sum += genMat[j * numCols + c][l] * gdigit[c];
1048 cachedCurPoint[j * outDigits + l] = sum % b;
1049 }
1050 }
1051 }
1052
1053 public int resetToNextPoint() {
1054 // incremental computation.
1055 curPointIndex++;
1056 curCoordIndex = 0;
1057 if (curPointIndex >= numPoints)
1058 return curPointIndex;
1059
1060 // Update the digital expansion of i in base b, and find the
1061 // position of change in the Gray code. Set all digits == b-1 to 0
1062 // and increase the first one after by 1.
1063 int pos; // Position of change in the Gray code.
1064 for (pos = 0; gdigit[pos] == b - 1; pos++)
1065 gdigit[pos] = 0;
1066 gdigit[pos]++;
1067
1068 // Update the cachedCurPoint by adding the column of the gener.
1069 // matrix that corresponds to the Gray code digit that has changed.
1070 // The digital shift is already incorporated in the cached point.
1071 int j, l;
1072 int lsup = numRows; // Max index l
1073 if (outDigits < numRows)
1074 lsup = outDigits;
1075 for (j = 0; j < dimS; j++) {
1076 for (l = 0; l < lsup; l++) {
1077 cachedCurPoint[j * outDigits + l] += genMat[j * numCols + pos][l];
1078 cachedCurPoint[j * outDigits + l] %= b;
1079 }
1080 }
1081 return curPointIndex;
1082 }
1083 }
1084
1085 // ************************************************************************
1086
1087 protected class DigitalNetIteratorNoGray extends DigitalNetIterator {
1088
1089 public DigitalNetIteratorNoGray() {
1090 super();
1091 }
1092
1093 public void setCurPointIndex(int i) {
1094 if (i == 0) {
1096 return;
1097 }
1098 curPointIndex = i;
1099 curCoordIndex = 0;
1100 if (dimShift < dimS)
1102
1103 // Convert i to b-ary representation, put digits in bdigit.
1104 idigits = intToDigitsGray(b, i, numCols, bdigit, gdigit);
1105 int c, j, l, sum;
1106 for (j = 0; j < dimS; j++) {
1107 for (l = 0; l < outDigits; l++) {
1108 if (digitalShift == null)
1109 sum = 0;
1110 else
1111 sum = digitalShift[j][l];
1112 if (l < numRows)
1113 for (c = 0; c < idigits; c++)
1114 sum += genMat[j * numCols + c][l] * bdigit[c];
1115 cachedCurPoint[j * outDigits + l] = sum % b;
1116 }
1117 }
1118 }
1119
1120 public int resetToNextPoint() {
1121 curPointIndex++;
1122 curCoordIndex = 0;
1123 if (curPointIndex >= numPoints)
1124 return curPointIndex;
1125
1126 // Find the position of change in the digits of curPointIndex in base
1127 // b. Set all digits = b-1 to 0; increase the first one after by 1.
1128 int pos;
1129 for (pos = 0; bdigit[pos] == b - 1; pos++)
1130 bdigit[pos] = 0;
1131 bdigit[pos]++;
1132
1133 // Update the digital expansion of curPointIndex in base b.
1134 // Update the cachedCurPoint by adding 1 unit at the digit pos.
1135 // If pos > 0, remove b-1 units in the positions < pos. Since
1136 // calculations are mod b, this is equivalent to adding 1 unit.
1137 // The digital shift is already incorporated in the cached point.
1138 int c, j, l;
1139 int lsup = numRows; // Max index l
1140 if (outDigits < numRows)
1141 lsup = outDigits;
1142 for (j = 0; j < dimS; j++) {
1143 for (l = 0; l < lsup; l++) {
1144 for (c = 0; c <= pos; c++)
1145 cachedCurPoint[j * outDigits + l] += genMat[j * numCols + c][l];
1146 cachedCurPoint[j * outDigits + l] %= b;
1147 }
1148 }
1149 return curPointIndex;
1150 }
1151 }
1152
1153}
void setCurPointIndex(int i)
Resets the current point index to i and current coordinate to 0.
int resetToNextPoint()
Resets the current point index to the next one and current coordinate to 0, and returns the new curre...
void resetCurPointIndex()
Resets both the current point index and the current coordinate to 0.
void setCurPointIndex(int i)
Resets the current point index to i and current coordinate to 0.
double nextDouble()
Same as nextCoordinate().
int resetToNextPoint()
Resets the current point index to the next one and current coordinate to 0, and returns the new curre...
void addRandomShift(int d1, int d2, RandomStream stream)
Generates a random digital shift for coordinates from d1 to d2-1, using stream to generate the rando...
String toString()
Formats a string that contains information on this digital net.
void leftMatrixScrambleFaurePermutDiag(RandomStream stream, int sb)
Similar to leftMatrixScrambleFaurePermut except that all off-diagonal elements are 0.
double getCoordinate(int i, int j)
Returns , the coordinate of point , where is the Gray code for .
DigitalNet()
Empty constructor.
void setInterlacing(int interlacing)
Sets the interlacing factor.
void leftMatrixScrambleDiag(RandomStream stream)
Similar to leftMatrixScramble except that all the off-diagonal elements of the are 0.
void addRandomShift(RandomStream stream)
Same as addRandomShift(0, dim, stream), where dim is the dimension of the digital net.
void iBinomialMatrixScrambleFaurePermut(RandomStream stream, int sb)
Similar to iBinomialMatrixScramble except that the diagonal elements of each matrix are chosen as in...
void rightMatrixScramble(RandomStream stream)
Applies a linear scramble by multiplying each on the right by a single nonsingular upper-triangular...
PointSetIterator iterator()
void printGeneratorMatrices(int s)
Prints the generator matrices in standard form for dimensions 1 to .
void eraseOriginalGeneratorMatrices()
Erases the original generator matrices and replaces them by the current ones.
void unrandomize()
Restores the original generator matrices and removes the random shift.
void leftMatrixScramble(RandomStream stream)
Applies a linear scramble by multiplying each on the left by a nonsingular lower-triangular matrix.
void leftMatrixScrambleFaurePermut(RandomStream stream, int sb)
Similar to leftMatrixScramble except that the diagonal elements of each matrix are chosen from a res...
void stripedMatrixScrambleFaurePermutAll(RandomStream stream, int sb)
Similar to stripedMatrixScramble except that the elements on and under the diagonal of each matrix a...
void resetGeneratorMatrices()
Restores the original generator matrices.
void iBinomialMatrixScrambleFaurePermutDiag(RandomStream stream, int sb)
Similar to iBinomialMatrixScrambleFaurePermut except that all the off-diagonal elements are 0.
double getCoordinateNoGray(int i, int j)
Returns , the coordinate of point , the points being enumerated in the standard order (no Gray code)...
void iBinomialMatrixScramble(RandomStream stream)
Applies the -binomial matrix scramble proposed by Tezuka.
void stripedMatrixScramble(RandomStream stream)
Applies the striped matrix scramble proposed by Owen.
void iBinomialMatrixScrambleFaurePermutAll(RandomStream stream, int sb)
Similar to iBinomialMatrixScrambleFaurePermut except that the elements under the diagonal are also ch...
void clearRandomShift()
Erases the current digital random shift, if any.
PointSetIterator iteratorNoGray()
Returns an iterator that does not use the Gray code.
void leftMatrixScrambleFaurePermutAll(RandomStream stream, int sb)
Similar to leftMatrixScrambleFaurePermut except that the elements under the diagonal are also chosen ...
int getInterlacing()
Returns the interlacing factor.
This class implements a default point set iterator.
int curPointIndex
Index of the current point.
int curCoordIndex
Index of the current coordinate.
double EpsilonHalf
Default constant epsilon/2 added to the points after a random shift.
void outOfBounds()
Error message for index out of bounds.
This abstract class represents a general point set.
Definition PointSet.java:99
int dimShift
Current dimension of the shift.
void addRandomShift()
Same as addRandomShift(0, dim), where dim is the dimension of the point set.
int numPoints
Number of points.
double EpsilonHalf
To avoid 0 for nextCoordinate when random shifting, we add this to each coordinate.
int capacityShift
Number of array elements in the shift vector, always >= dimShift.
int dim
Dimension of the points.
RandomStream shiftStream
Stream used to generate the random shifts.
This class acts like a StringBuffer which defines new types of append methods.
static final String NEWLINE
End-of-line symbol or line separator.
This is the interface for iterators that permit one to go through the points of a PointSet and the su...
This interface defines the basic structures to handle multiple streams of uniform (pseudo)random numb...
int nextInt(int i, int j)
Returns a (pseudo)random number from the discrete uniform distribution over the integers ,...