// as per the Java implementation , uses one or more 32-bit divisions static inline uint32_t java_random_bounded(uint32_t bound) { uint32_t rkey = pcg32_random(); uint32_t candidate = rkey % bound; while(rkey - candidate > UINT32_MAX - bound + 1 ) { // will be predicted as false rkey = pcg32_random(); candidate = rkey % bound; } return candidate; }
// as per the Go implementation static inline uint32_t go_random_bounded(uint32_t bound) { uint32_t bits; if((bound & (bound - 1)) == 0) { return pcg32_random() & (bound - 1); } uint32_t t = 0xFFFFFFFF % bound; do { bits = pcg32_random(); } while(bits <= t); return bits % bound; }
int main(int argc, char** argv) { // Read command-line options int count = atoi(argv[1]); // use int64_t for Java convenience int64_t initState = strtoll(argv[2], NULL, 10); int64_t initSeq = strtoll(argv[3], NULL, 10); int i; // In this version of the code, we'll use the global rng, rather than a // local one. // You should *always* seed the RNG. The usual time to do it is the // point in time when you create RNG (typically at the beginning of the // program). // // pcg32_srandom_r takes two 64-bit constants (the initial state, and the // rng sequence selector; rngs with different sequence selectors will // *never* have random sequences that coincide, at all) - the code below // shows three possible ways to do so. pcg32_srandom((uint64_t) initState, (uint64_t) initSeq); for (i = 0; i < count; ++i) { printf("%d\n", (int32_t) pcg32_random()); } return 0; }
// map random value to [0,range), redraws to avoid bias if needed static inline uint32_t pcg32_random_bounded_divisionless(uint32_t range) { uint64_t random32bit, multiresult; uint32_t leftover; uint32_t threshold; random32bit = pcg32_random(); multiresult = random32bit * range; leftover = (uint32_t) multiresult; if(leftover < range ) { threshold = -range % range ; while (leftover < threshold) { random32bit = pcg32_random(); multiresult = random32bit * range; leftover = (uint32_t) multiresult; } } return multiresult >> 32; // [0, range) }
// as per the PCG implementation , uses two 32-bit divisions static inline uint32_t pcg32_random_bounded(uint32_t bound) { uint32_t threshold = -bound % bound; for (;;) { uint32_t r = pcg32_random(); if (r >= threshold) return r % bound; } }
int main() { int repeat = 500; int size = TESTSIZE; tellmeall(); printf("array container benchmarks\n"); array_container_t* B = array_container_create(); BEST_TIME(add_test(B), 0, repeat, size); int answer = contains_test(B); size = 1 << 16; BEST_TIME(contains_test(B), answer, repeat, size); size = (1 << 16) / 3; BEST_TIME(remove_test(B), 0, repeat, size); array_container_free(B); for (int howmany = 32; howmany <= (1 << 16); howmany *= 8) { array_container_t* Bt = array_container_create(); for (int j = 0; j < howmany; ++j) { array_container_add(Bt, (uint16_t)pcg32_random()); } size_t nbrtestvalues = 1024; uint16_t* testvalues = malloc(nbrtestvalues * sizeof(uint16_t)); printf("\n number of values in container = %d\n", Bt->cardinality); int card = array_container_cardinality(Bt); uint32_t* out = malloc(sizeof(uint32_t) * (unsigned long)card); BEST_TIME(array_container_to_uint32_array(out, Bt, 1234), card, repeat, card); free(out); BEST_TIME_PRE_ARRAY(Bt, array_container_contains, array_cache_prefetch, testvalues, nbrtestvalues); BEST_TIME_PRE_ARRAY(Bt, array_container_contains, array_cache_flush, testvalues, nbrtestvalues); free(testvalues); array_container_free(Bt); } printf("\n"); array_container_t* B1 = array_container_create(); for (int x = 0; x < 1 << 16; x += 3) { array_container_add(B1, (uint16_t)x); } array_container_t* B2 = array_container_create(); for (int x = 0; x < 1 << 16; x += 5) { array_container_add(B2, (uint16_t)x); } int32_t inputsize = B1->cardinality + B2->cardinality; array_container_t* BO = array_container_create(); printf("\nUnion and intersections...\n"); printf("\nNote:\n"); printf( "union times are expressed in cycles per number of input elements " "(both arrays)\n"); printf( "intersection times are expressed in cycles per number of output " "elements\n\n"); printf("==intersection and union test 1 \n"); printf("input 1 cardinality = %d, input 2 cardinality = %d \n", B1->cardinality, B2->cardinality); answer = union_test(B1, B2, BO); printf("union cardinality = %d \n", answer); printf("B1 card = %d B2 card = %d \n", B1->cardinality, B2->cardinality); BEST_TIME(union_test(B1, B2, BO), answer, repeat, inputsize); answer = intersection_test(B1, B2, BO); printf("intersection cardinality = %d \n", answer); BEST_TIME(intersection_test(B1, B2, BO), answer, repeat, answer); printf("==intersection and union test 2 \n"); array_container_clear(B1); array_container_clear(B2); for (int x = 0; x < 1 << 16; x += 16) { array_container_add(B1, (uint16_t)x); } for (int x = 1; x < 1 << 16; x += x) { array_container_add(B2, (uint16_t)x); } printf("input 1 cardinality = %d, input 2 cardinality = %d \n", B1->cardinality, B2->cardinality); answer = union_test(B1, B2, BO); printf("union cardinality = %d \n", answer); printf("B1 card = %d B2 card = %d \n", B1->cardinality, B2->cardinality); BEST_TIME(union_test(B1, B2, BO), answer, repeat, inputsize); answer = intersection_test(B1, B2, BO); printf("intersection cardinality = %d \n", answer); BEST_TIME(intersection_test(B1, B2, BO), answer, repeat, answer); array_container_free(B1); array_container_free(B2); array_container_free(BO); return 0; }
int main() { int repeat = 500; int size = (1 << 16) / 3; tellmeall(); printf("bitset container benchmarks\n"); bitset_container_t* B = bitset_container_create(); BEST_TIME(set_test(B), 0, repeat, size); int answer = get_test(B); size = 1 << 16; BEST_TIME(get_test(B), answer, repeat, size); BEST_TIME(bitset_container_cardinality(B), answer, repeat, 1); BEST_TIME(bitset_container_compute_cardinality(B), answer, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); size = (1 << 16) / 3; BEST_TIME(unset_test(B), 0, repeat, size); bitset_container_free(B); for (int howmany = 4096; howmany <= (1 << 16); howmany *= 2) { bitset_container_t* Bt = bitset_container_create(); while (bitset_container_cardinality(Bt) < howmany) { bitset_container_set(Bt, (uint16_t)pcg32_random()); } size_t nbrtestvalues = 1024; uint16_t* testvalues = malloc(nbrtestvalues * sizeof(uint16_t)); printf("\n number of values in container = %d\n", bitset_container_cardinality(Bt)); int card = bitset_container_cardinality(Bt); uint32_t* out = malloc(sizeof(uint32_t) * (unsigned)card + 32); BEST_TIME(bitset_container_to_uint32_array(out, Bt, 1234), card, repeat, card); free(out); BEST_TIME_PRE_ARRAY(Bt, bitset_container_get, bitset_cache_prefetch, testvalues, nbrtestvalues); BEST_TIME_PRE_ARRAY(Bt, bitset_container_get, bitset_cache_flush, testvalues, nbrtestvalues); free(testvalues); bitset_container_free(Bt); } printf("\n"); bitset_container_t* B1 = bitset_container_create(); for (int x = 0; x < 1 << 16; x += 3) { bitset_container_set(B1, (uint16_t)x); } bitset_container_t* B2 = bitset_container_create(); for (int x = 0; x < 1 << 16; x += 5) { bitset_container_set(B2, (uint16_t)x); } bitset_container_t* BO = bitset_container_create(); BEST_TIME(bitset_container_or_nocard(B1, B2, BO), -1, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); answer = bitset_container_compute_cardinality(BO); BEST_TIME(bitset_container_or(B1, B2, BO), answer, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); BEST_TIME(bitset_container_cardinality(BO), answer, repeat, 1); BEST_TIME(bitset_container_compute_cardinality(BO), answer, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); BEST_TIME(bitset_container_and_nocard(B1, B2, BO), -1, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); answer = bitset_container_compute_cardinality(BO); BEST_TIME(bitset_container_and(B1, B2, BO), answer, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); BEST_TIME(bitset_container_cardinality(BO), answer, repeat, 1); BEST_TIME(bitset_container_compute_cardinality(BO), answer, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); // next we are going to benchmark conversion from bitset to array (an // important step) bitset_container_clear(B1); for (int k = 0; k < 4096; ++k) { bitset_container_set(B1, (uint16_t)ranged_random(1 << 16)); } answer = get_cardinality_through_conversion_to_array(B1); BEST_TIME(get_cardinality_through_conversion_to_array(B1), answer, repeat, BITSET_CONTAINER_SIZE_IN_WORDS); bitset_container_free(BO); bitset_container_free(B1); bitset_container_free(B2); return 0; }
// map random value to [0,range) with slight bias static inline uint32_t pcg32_random_bounded_divisionless_with_slight_bias(uint32_t range) { uint64_t random32bit, multiresult; random32bit = pcg32_random(); multiresult = random32bit * range; return multiresult >> 32; // [0, range) }
uint32_t *create_random_array(size_t count) { uint32_t *targets = malloc(count * sizeof(uint32_t)); for (size_t i = 0; i < count; i++) targets[i] = (uint32_t) (pcg32_random() & 0x7FFFFFF); return targets; }
uint32_t *create_sorted_array(size_t length) { uint32_t *array = malloc(length * sizeof(uint32_t)); for (size_t i = 0; i < length; i++) array[i] = (uint32_t) pcg32_random(); qsort(array, length, sizeof(*array), qsort_compare_uint32_t); return array; }
/** Generates a random double in the interval [0, bound] */ double random_bounded_double(double bound) { double random = pcg32_random(); random /= UINT32_MAX; return random * bound; }
unsigned int test_rand_uint32(void) { return pcg32_random(); }
/** * Generate random double. * * @note Not perfectly distributed, but more than adequate for this use. * * @return random double in range [0;1) */ static double rand_double(void) { return pcg32_random() / (UINT32_MAX + 1.0); }