From e8de6a46e210d56bf2c1d5b8d5ea255d0ab2e768 Mon Sep 17 00:00:00 2001 From: David Young Date: Mon, 28 Oct 2019 15:50:57 -0500 Subject: Fix HDFFV-10937: use a more reliable (and probably faster) scheme for visiting all elements of a matrix in an arbitrary order. --- test/dsets.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 121 insertions(+), 32 deletions(-) diff --git a/test/dsets.c b/test/dsets.c index 21d5431..d33b7db 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -7022,6 +7022,70 @@ error: return FAIL; } /* end test_missing_chunk() */ +/* Using Euclid's algorithm, find the greatest common divisor (GCD) of + * the two arguments and return it. + * + * The GCD is negative if the arguments have opposite sign. Otherwise, + * it is positive. + * + * If either argument is zero, then the result is undefined. + */ +static long +gcd(const long l0, const long r0) +{ + long magnitude, remainder; + bool negative = ((l0 < 0) != (r0 < 0)); + long l = labs(l0), r = labs(r0); + + do { + if (l < r) { + r = r % l; + remainder = r; + } else /* r <= l */ { + l = l % r; + remainder = l; + } + } while (remainder != 0); + + magnitude = (l == 0) ? r : l; + return negative ? -magnitude : magnitude; +} + +/* Choose a random offset into an array `nelts` elements long, and store + * it at `offsetp`. The offset will be in the range [0, nelts - 1]. + * Also choose a random increment, `inc`, that "generates" all + * indices in [0, nelts - 1] when it is added to itself repeatedly. + * That is, the range of the discrete function `f(i) = (i * inc) + * mod nelts` on the domain [0, nelts - 1] is [0, nelts - 1]. Store + * `inc` at `incp`. + * + * If `nelts <= 0`, results are undefined. + */ +static void +make_random_offset_and_increment(long nelts, long *offsetp, long *incp) +{ + long inc; + + assert(0 < nelts); + + *offsetp = random() % nelts; + + /* `maxinc` is chosen so that for any `x` in [0, nelts - 1], + * `x + maxinc` does not overflow a long. + */ + const long maxinc = MIN(nelts - 1, LONG_MAX - nelts); + + /* Choose a random number in [1, nelts - 1]. If its greatest divisor + * in common with `nelts` is 1, then it will "generate" the additive ring + * [0, nelts - 1], so let it be our increment. Otherwise, choose a new + * number. + */ + do { + inc = 1 + random() % maxinc; + } while (gcd(inc, nelts) != 1); + + *incp = inc; +} /*------------------------------------------------------------------------- * Function: test_random_chunks_real @@ -7046,7 +7110,7 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) rbuf[NPOINTS], check2[20][20]; hsize_t coord[NPOINTS][2]; - hsize_t dsize[2]={100,100}, dmax[2]={H5S_UNLIMITED, H5S_UNLIMITED}, csize[2]={10,10}, nsize[2]={200,200}; + const hsize_t dsize[2]={100,100}, dmax[2]={H5S_UNLIMITED, H5S_UNLIMITED}, csize[2]={10,10}, nsize[2]={200,200}; hsize_t fixed_dmax[2] = {1000, 1000}; hsize_t msize[1]={NPOINTS}; const char dname[]="dataset"; @@ -7054,7 +7118,9 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) size_t i, j; H5D_chunk_index_t idx_type; /* Dataset chunk index type */ H5F_libver_t low; /* File format low bound */ - + long ofs, inc; + long rows; + long cols; TESTING(testname); @@ -7088,12 +7154,16 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) for(j=0; j