You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2019/10/11 19:47:22 UTC
[commons-rng] branch master updated: Update stdin2testuO1 to have a
true 64 bit reader of stdin.
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 <ah...@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);