SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
RadicalInverse.java
1/*
2 * Class: RadicalInverse
3 * Description: Implements radical inverses of integers in an arbitrary basis
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.hups;
26
88public class RadicalInverse {
89 private static final int NP = 168; // First NP primes in table below.
90 private static final int PLIM = 1000; // NP primes < PLIM
91
92 // The first NP prime numbers
93 private static final int[] PRIMES = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
94 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
95 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
96 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457,
97 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
98 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
99 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,
100 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 };
101
102 // Multiplicative factors for permutations as proposed by Faure & Lemieux
103 // (2008).
104 // The index corresponds to the coordinate.
105 private static final int[] FAURE_LEMIEUX_FACTORS = { 1, 1, 3, 3, 4, 9, 7, 5, 9, 18, 18, 8, 13, 31, 9, 19, 36, 33, 21,
106 44, 43, 61, 60, 56, 26, 71, 32, 77, 26, 95, 92, 47, 29, 61, 57, 69, 115, 63, 92, 31, 104, 126, 50, 80, 55, 152,
107 114, 80, 83, 97, 95, 150, 148, 55, 80, 192, 71, 76, 82, 109, 105, 173, 58, 143, 56, 177, 203, 239, 196, 143,
108 278, 227, 87, 274, 264, 84, 226, 163, 231, 177, 95, 116, 165, 131, 156, 105, 188, 142, 105, 125, 269, 292, 215,
109 182, 294, 152, 148, 144, 382, 194, 346, 323, 220, 174, 133, 324, 215, 246, 159, 337, 254, 423, 484, 239, 440,
110 362, 464, 376, 398, 174, 149, 418, 306, 282, 434, 196, 458, 313, 512, 450, 161, 315, 441, 549, 555, 431, 295,
111 557, 172, 343, 472, 604, 297, 524, 251, 514, 385, 531, 663, 674, 255, 519, 324, 391, 394, 533, 253, 717, 651,
112 399, 596, 676, 425, 261, 404, 691, 604, 274, 627, 777, 269, 217, 599, 447, 581, 640, 666, 595, 669, 686, 305,
113 460, 599, 335, 258, 649, 771, 619, 666, 669, 707, 737, 854, 925, 818, 424, 493, 463, 535, 782, 476, 451, 520,
114 886, 340, 793, 390, 381, 274, 500, 581, 345, 363, 1024, 514, 773, 932, 556, 954, 793, 294, 863, 393, 827, 527,
115 1007, 622, 549, 613, 799, 408, 856, 601, 1072, 938, 322, 1142, 873, 629, 1071, 1063, 1205, 596, 973, 984, 875,
116 918, 1133, 1223, 933, 1110, 1228, 1017, 701, 480, 678, 1172, 689, 1138, 1022, 682, 613, 635, 984, 526, 1311,
117 459, 1348, 477, 716, 1075, 682, 1245, 401, 774, 1026, 499, 1314, 743, 693, 1282, 1003, 1181, 1079, 765, 815,
118 1350, 1144, 1449, 718, 805, 1203, 1173, 737, 562, 579, 701, 1104, 1105, 1379, 827, 1256, 759, 540, 1284, 1188,
119 776, 853, 1140, 445, 1265, 802, 932, 632, 1504, 856, 1229, 1619, 774, 1229, 1300, 1563, 1551, 1265, 905, 1333,
120 493, 913, 1397, 1250, 612, 1251, 1765, 1303, 595, 981, 671, 1403, 820, 1404, 1661, 973, 1340, 1015, 1649, 855,
121 1834, 1621, 1704, 893, 1033, 721, 1737, 1507, 1851, 1006, 994, 923, 872, 1860 };
122
123 private static final int NRILIM = 1000; // For nextRadicalInverse
124 private int b; // Base
125 private double invb; // 1/b
126 private double logb; // natural log(b)
127 private int JMAX; // b^JMAX = 2^32
128 private int co; // Counter for nextRadicalInverse
129 private double xx; // Current value of x
130 private long ix; // xx = RadicalInverse (ix)
131 /*
132 * // For Struckmeier's algorithm private static final int PARTITION_MAX = 54;
133 * // Size of partitionL, bi private int partM; // Effective size of partitionL,
134 * bi private double[] bi; // bi[i] = (b + 1)/b^i - 1 private double[]
135 * partitionL; // L[i] = 1 - 1/b^i // Boundaries of Struckmeier partitions Lkp
136 * of [0, 1]
137 */
138
146 public RadicalInverse(int b, double x0) {
147 co = 0;
148 this.b = b;
149 invb = 1.0 / b;
150 logb = Math.log(b);
151 JMAX = (int) (32.0 * 0.69314718055994530941 / logb);
152 xx = x0;
153 ix = computeI(x0);
154// initStruckmeier (b);
155 }
156
157 private long computeI(double x) {
158 // Compute i such that x = RadicalInverse (i).
159 int[] digits = new int[JMAX]; // Digits of x
160 int j;
161 for (j = 0; (j < JMAX) && (x > 0.5e-15); j++) {
162 x *= b;
163 digits[j] = (int) x;
164 x -= digits[j];
165 }
166 long i = 0;
167 for (j = JMAX - 1; j >= 0; j--) {
168 i = i * b + digits[j];
169 }
170 return i;
171 }
172
182 public static int[] getPrimes(int n) {
183 // Allocates an array of size n filled with the first n prime
184 // numbers. n must be positive (n > 0). Routine may fail if not enough
185 // memory for the array is available. The first prime number is 2.
186 int i;
187 boolean moreTests;
188 int[] prime = new int[n];
189
190 int n1 = Math.min(NP, n);
191 for (i = 0; i < n1; i++)
192 prime[i] = PRIMES[i];
193 if (NP < n) {
194 i = NP;
195 for (int candidate = PLIM + 1; i < n; candidate += 2) {
196 prime[i] = candidate;
197 for (int j = 1; (moreTests = prime[j] <= candidate / prime[j]) && ((candidate % prime[j]) > 0); j++)
198 ;
199 if (!moreTests)
200 i++;
201 }
202 }
203 return prime;
204 }
205
215 public static double radicalInverse(int b, long i) {
216 double digit, radical, inverse;
217 digit = radical = 1.0 / (double) b;
218 for (inverse = 0.0; i > 0; i /= b) {
219 inverse += digit * (double) (i % b);
220 digit *= radical;
221 }
222 return inverse;
223 }
224
239 public static int radicalInverseInteger(int b, double x) {
240 int digit = 1;
241 int inverse = 0;
242 int precision = Integer.MAX_VALUE / (2 * b * b);
243 while (x > 0 && inverse < precision) {
244 int p = digit * b;
245 double y = Math.floor(x * p);
246 inverse += digit * (int) y;
247 x -= y / (double) p;
248 digit *= b;
249 }
250 return inverse;
251 }
252
267 public static long radicalInverseLong(int b, double x) {
268 long digit = 1;
269 long inverse = 0;
270 long precision = Long.MAX_VALUE / (b * b * b);
271 while (x > 0 && inverse < precision) {
272 long p = digit * b;
273 double y = Math.floor(x * p);
274 inverse += digit * (long) y;
275 x -= y / (double) p;
276 digit *= b;
277 }
278 return inverse;
279 }
280
295 public static double nextRadicalInverse(double invb, double x) {
296 // Calculates the next radical inverse from x in base b.
297 // Repeated application causes a loss of accuracy.
298 // Note that x can be any number from [0,1).
299
300 final double ALMOST_ONE = 1.0 - 1e-10;
301 double nextInverse = x + invb;
302 if (nextInverse < ALMOST_ONE)
303 return nextInverse;
304 else {
305 double digit1 = invb;
306 double digit2 = invb * invb;
307 while (x + digit2 >= ALMOST_ONE) {
308 digit1 = digit2;
309 digit2 *= invb;
310 }
311 return x + (digit1 - 1.0) + digit2;
312 }
313 }
314
326 public double nextRadicalInverse() {
327 // Calculates the next radical inverse from xx in base b.
328 // Repeated application causes a loss of accuracy.
329 // For each NRILIM calls, a direct calculation via radicalInverse
330 // is inserted.
331
332 co++;
333 if (co >= NRILIM) {
334 co = 0;
335 ix += NRILIM;
336 xx = radicalInverse(b, ix);
337 return xx;
338 }
339 final double ALMOST_ONE = 1.0 - 1e-10;
340 double nextInverse = xx + invb;
341 if (nextInverse < ALMOST_ONE) {
342 xx = nextInverse;
343 return xx;
344 } else {
345 double digit1 = invb;
346 double digit2 = invb * invb;
347 while (xx + digit2 >= ALMOST_ONE) {
348 digit1 = digit2;
349 digit2 *= invb;
350 }
351 xx += (digit1 - 1.0) + digit2;
352 return xx;
353 }
354 }
355
373 /*
374 * private void initStruckmeier (int b) { bi = new double[1 + PARTITION_MAX];
375 * partitionL = new double[1 + PARTITION_MAX]; logb = Math.log (b);
376 * partitionL[0] = 0.0; bi[0] = 1.0; int i = 0; while ((i < PARTITION_MAX) &&
377 * (partitionL[i] < 1.0)) { ++i; bi[i] = bi[i - 1] / b; partitionL[i] = 1.0 -
378 * bi[i]; } partM = i - 1;
379 *
380 * for (i = 0; i <= partM + 1; ++i) bi[i] = (b + 1) * bi[i] - 1.0; }
381 */
382
383 /*
384 * public double nextRadicalInverse (double x) { int k; if (x <
385 * partitionL[partM]) { k = 1; // Find k such: partitionL[k-1] <= x <
386 * partitionL[k] while (x >= partitionL[k]) ++k;
387 *
388 * } else { // x >= partitionL [partM] k = 1 + (int)(-Math.log(1.0 - x) / logb);
389 * } return x + bi[k]; }
390 */
391
401 public static void reverseDigits(int k, int bdigits[], int idigits[]) {
402 for (int l = 0; l < k; l++)
403 idigits[l] = bdigits[k - l];
404 }
405
414 public static int integerRadicalInverse(int b, int i) {
415 // Simply flips digits of i in base b.
416 int inverse;
417 for (inverse = 0; i > 0; i /= b)
418 inverse = inverse * b + (i % b);
419 return inverse;
420 }
421
433 public static int nextRadicalInverseDigits(int b, int k, int idigits[]) {
434 int l;
435 for (l = k - 1; l >= 0; l--)
436 if (idigits[l] == b - 1)
437 idigits[l] = 0;
438 else {
439 idigits[l]++;
440 return k;
441 }
442 if (l == 0) {
443 idigits[k] = 1;
444 return ++k;
445 }
446 return 0;
447 }
448
457 public static void getFaureLemieuxPermutation(int coordinate, int[] pi) {
458 int f = FAURE_LEMIEUX_FACTORS[coordinate];
459 int b = PRIMES[coordinate];
460 for (int k = 0; k < pi.length; k++)
461 pi[k] = f * k % b;
462 }
463
472 public static void getFaurePermutation(int b, int[] pi) {
473 // This is a recursive implementation.
474 // Perhaps not the most efficient...
475 int i;
476 if (b == 2) {
477 pi[0] = 0;
478 pi[1] = 1;
479 } else if ((b & 1) != 0) {
480 // b is odd.
481 b--;
482 getFaurePermutation(b, pi);
483 for (i = 0; i < b; i++)
484 if (pi[i] >= b / 2)
485 pi[i]++;
486 for (i = b; i > b / 2; i--)
487 pi[i] = pi[i - 1];
488 pi[b / 2] = b / 2;
489 } else {
490 b /= 2;
491 getFaurePermutation(b, pi);
492 for (i = 0; i < b; i++) {
493 pi[i] *= 2;
494 pi[i + b] = pi[i] + 1;
495 }
496 }
497 }
498
511 public static double permutedRadicalInverse(int b, int[] pi, long i) {
512 double digit, radical, inverse;
513 digit = radical = 1.0 / (double) b;
514 for (inverse = 0.0; i > 0; i /= b) {
515 inverse += digit * (double) pi[(int) (i % b)];
516 digit *= radical;
517 }
518 return inverse;
519 }
520
521}
static void reverseDigits(int k, int bdigits[], int idigits[])
A fast method that incrementally computes the radical inverse.
static double permutedRadicalInverse(int b, int[] pi, long i)
Computes the radical inverse of in base , where the digits are permuted using the permutation .
static double radicalInverse(int b, long i)
Computes the radical inverse of in base .
static void getFaureLemieuxPermutation(int coordinate, int[] pi)
Computes the permutations as proposed in vfau09a .
static int integerRadicalInverse(int b, int i)
Computes the integer radical inverse of in base , equal to if has -ary digits.
static int nextRadicalInverseDigits(int b, int k, int idigits[])
Given the digits of the integer radical inverse of in bdigits, in base , this method replaces them ...
static void getFaurePermutation(int b, int[] pi)
Computes the Faure permutation rfau92a  of the set and puts it in array pi.
static int radicalInverseInteger(int b, double x)
Computes the radical inverse of in base .
static double nextRadicalInverse(double invb, double x)
A fast method that incrementally computes the radical inverse.
static long radicalInverseLong(int b, double x)
Computes the radical inverse of in base .
static int[] getPrimes(int n)
Provides an elementary method for obtaining the first prime numbers larger than 1.
double nextRadicalInverse()
A fast method that incrementally computes the radical inverse.
RadicalInverse(int b, double x0)
Initializes the base of this object to and its first value of to x0.