int randlcg_selftest() { unsigned i; int is_success = 0; uint64_t m, a, c; m = 3015 * 3; for (i=0; i<5; i++) { a = 0; c = 0; m += 10 + i; lcg_calculate_constants(m, &a, &c, 0); is_success = lcg_verify(a, c, m, m); if (!is_success) { fprintf(stderr, "LCG: randomization failed\n"); return 1; /*fail*/ } } return 0; /*success*/ }
int randlcg_selftest() { int is_success; uint64_t m, a, c; m = 3015 * 3; a = 0; c = 0; lcg_calculate_constants(m, &a, &c, 0); is_success = lcg_verify(a, c, m, m); if (!is_success) { fprintf(stderr, "LCG: randomization failed\n"); return 1; /*fail*/ } else { return 0; /*success*/ } }
/**************************************************************************** * Given a range, calculate some possible constants for the LCG algorithm * for randomizing the order of the array. * @parm m * The range for which we'll be finding random numbers. If we are * looking for random numbers between [0..100), this number will * be 100. * @parm a * The LCG 'a' constant that will be the result of this function. * @param c * The LCG 'c' constant that will be the result of this function. This * should be set to 0 on the input to this function, or a suggested * value. ****************************************************************************/ void lcg_calculate_constants(uint64_t m, uint64_t *out_a, uint64_t *inout_c, int is_debug) { uint64_t a; uint64_t c = *inout_c; double elapsed = 0.0; /* Benchmark of 'sieve' algorithm */ PRIMEFACTORS factors; /* List of prime factors of 'm' */ PRIMEFACTORS non_factors; unsigned i; /* * Find all the prime factors of the number. This step can take several * seconds for 48 bit numbers, which is why we benchmark how long it * takes. */ sieve_prime_factors(m, factors, non_factors, &elapsed); /* * Calculate the 'a-1' constant. It must share all the prime factors * with the range, and if the range is a multiple of 4, must also * be a multiple of 4 */ if (factors[0] == m) { /* this number has no prime factors, so we can choose anything. * Therefore, we are going to pick something at random */ unsigned j; a = 1; for (j=0; non_factors[j] && j < 5; j++) a *= non_factors[j]; } else { unsigned j; a = 1; for (i=0; factors[i]; i++) a = a * factors[i]; if ((m % 4) == 0) a *= 2; for (j=0; j<0 && non_factors[j]; j++) a *= non_factors[j]; } a += 1; /* * Calculate the 'c' constant. It must have no prime factors in * common with the range. */ if (c == 0) c = 2531011 ; /* something random */ while (has_factors_in_common(c, factors)) c++; if (is_debug) { /* * print the results */ //printf("sizeof(int) = %llu-bits\n", (uint64_t)(sizeof(size_t)*8)); printf("elapsed = %5.3f-seconds\n", elapsed); printf("factors = "); for (i=0; factors[i]; i++) printf("%llu ", factors[i]); printf("%s\n", factors[0]?"":"(none)"); printf("m = %-24llu (0x%llx)\n", m, m); printf("a = %-24llu (0x%llx)\n", a, a); printf("c = %-24llu (0x%llx)\n", c, c); printf("c%%m = %-24llu (0x%llx)\n", c%m, c%m); printf("a%%m = %-24llu (0x%llx)\n", a%m, a%m); if (m < 1000000000) { if (lcg_verify(a, c+1, m, 280)) printf("verify = success\n"); else printf("verify = failure\n"); } else { printf("verify = too big to check\n"); } /* * Print some first numbers. We use these to visually inspect whether * the results are random or not. */ { unsigned count = 0; uint64_t x = 0; unsigned digits = count_digits(m); for (i=0; i<100 && i < m; i++) { x = lcg_rand(x, a, c, m); count += printf("%*llu ", digits, x); if (count >= 70) { count = 0; printf("\n"); } } printf("\n"); } } *out_a = a; *inout_c = c; }