This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-rng.git
The following commit(s) were added to refs/heads/master by this push: new 50dc28c Update stdin2testuO1 to have a true 64 bit reader of stdin. 50dc28c is described below commit 50dc28cddb017c79fc156164098f1509a3bad766 Author: Alex Herbert <aherb...@apache.org> AuthorDate: Fri Oct 11 20:47:18 2019 +0100 Update stdin2testuO1 to have a true 64 bit reader of stdin. Drop endianness check. --- .../examples-stress/src/main/c/stdin2testu01.c | 82 +++++++++++++++------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/commons-rng-examples/examples-stress/src/main/c/stdin2testu01.c b/commons-rng-examples/examples-stress/src/main/c/stdin2testu01.c index 3def771..fc0ffb7 100644 --- a/commons-rng-examples/examples-stress/src/main/c/stdin2testu01.c +++ b/commons-rng-examples/examples-stress/src/main/c/stdin2testu01.c @@ -52,13 +52,20 @@ #define TU_B "BigCrush" #define T_RAW_32 "raw32" #define T_RAW_64 "raw64" -#define BUFFER_LENGTH 2048 +#define BUFFER_LENGTH_32 2048 +/* The 64-bit buffer must be the same size. */ +#define BUFFER_LENGTH_64 (BUFFER_LENGTH_32 / 2) typedef struct { - uint32_t buffer[BUFFER_LENGTH]; + uint32_t buffer[BUFFER_LENGTH_32]; uint32_t index; } StdinReader_state; +typedef struct { + uint64_t buffer[BUFFER_LENGTH_64]; + uint32_t index; +} Stdin64Reader_state; + /* Lookup table for binary representation of bytes. */ const char *bit_rep[16] = { [ 0] = "0000", [ 1] = "0001", [ 2] = "0010", [ 3] = "0011", @@ -124,9 +131,13 @@ void printLong(uint64_t value) putchar(' '); printByte((uint8_t)( value & 0xff)); /* Write the unsigned and signed int value */ - printf(" %20lu %20ld\n", value, (int64_t) value); + printf(" %20llu %20lld\n", value, (int64_t) value); } +/* + * Method to read 32-bit input from stdin. + * Matches the signature for generators in TestU01. + */ unsigned long nextInt(void *par, void *sta) { static size_t last_read = 0; @@ -134,8 +145,8 @@ unsigned long nextInt(void *par, StdinReader_state *state = (StdinReader_state *) sta; if (state->index >= last_read) { /* Refill. */ - last_read = fread(state->buffer, sizeof(uint32_t), BUFFER_LENGTH, stdin); - if (last_read != BUFFER_LENGTH) { + last_read = fread(state->buffer, sizeof(uint32_t), BUFFER_LENGTH_32, stdin); + if (last_read != BUFFER_LENGTH_32) { // Allow reading less than the buffer length, but not zero if (last_read == 0) { // Error handling @@ -161,6 +172,44 @@ unsigned long nextInt(void *par, return random; } +/* + * Dedicated method to read 64-bit input from stdin. + * Not used for TestU01. Used to test reading 64-bit binary data. + */ +uint64_t nextLong(void *sta) { + static size_t last_read = 0; + + /* This works because the 64-bit state is the same size. */ + Stdin64Reader_state *state = (Stdin64Reader_state *) sta; + if (state->index >= last_read) { + /* Refill. */ + last_read = fread(state->buffer, sizeof(uint64_t), BUFFER_LENGTH_64, stdin); + if (last_read != BUFFER_LENGTH_64) { + // Allow reading less than the buffer length, but not zero + if (last_read == 0) { + // Error handling + if (feof(stdin)) { + // End of stream, just exit. This is used for testing. + exit(0); + } else if (ferror(stdin)) { + // perror will contain a description of the error code + perror("[ERROR] Failed to read stdin"); + exit(1); + } else { + printf("[ERROR] No data from stdin\n"); + exit(1); + } + } + } + state->index = 0; + } + + uint64_t random = state->buffer[state->index]; + ++state->index; /* Next request. */ + + return random; +} + double nextDouble(void *par, void *sta) { return nextInt(par, sta) / 4294967296.0; @@ -194,7 +243,7 @@ unif01_Gen *createStdinReader(void) { // Read binary input. freopen(NULL, "rb", stdin); - state->index = BUFFER_LENGTH; + state->index = BUFFER_LENGTH_32; return gen; } @@ -225,26 +274,9 @@ int main(int argc, printInt(nextInt(0, gen->state)); } } else if (strcmp(spec, T_RAW_64) == 0) { - /* Detect endianness required to join two 32-bit values. */ - uint32_t val = 0x01; - /* - * Use a raw view of the bytes with a char* to determine if - * the first byte is unset (big endian) or set (little endian). - */ - char * buff = (char *)&val; - - int littleEndian = (buff[0] != 0); - - /* Print to stdout until stdin closes. */ + /* Print to stdout until stdin closes. Use dedicated 64-bit reader. */ while (1) { - /* Read 2 values. */ - uint64_t hi = nextInt(0, gen->state); - uint64_t lo = nextInt(0, gen->state); - if (littleEndian) { - printLong((lo << 32) | hi); - } else { - printLong((hi << 32) | lo); - } + printLong(nextLong(gen->state)); } } else { printf("[ERROR] Unknown specification: '%s'\n", spec);