From dccf5afbef67ffd0201da26cc6603c1f42d3668f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 12 Jun 2016 00:38:49 +1000 Subject: BLI_rand: add BLI_rng_get_char_n Use to fill an array of bytes to random values. --- source/blender/blenlib/BLI_rand.h | 1 + source/blender/blenlib/intern/rand.c | 40 ++++++++++++++++++++++++++++ tests/gtests/blenlib/BLI_array_store_test.cc | 19 ++++--------- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 7b84dddcb68..f36d2faa1b8 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -49,6 +49,7 @@ void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1); void BLI_rng_seed(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1); void BLI_rng_srandom(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1); +void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) ATTR_NONNULL(1, 2); int BLI_rng_get_int(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); unsigned int BLI_rng_get_uint(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 66c568a7ff3..40d9a3da3d9 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -46,6 +46,7 @@ #define MULTIPLIER 0x5DEECE66Dll #define MASK 0x0000FFFFFFFFFFFFll +#define MASK_BYTES 2 #define ADDEND 0xB #define LOWSEED 0x330E @@ -107,6 +108,45 @@ BLI_INLINE void rng_step(RNG *rng) rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK; } +void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) +{ + size_t last_len = 0; + size_t trim_len = bytes_len; + +#define RAND_STRIDE (sizeof(rng->X) - MASK_BYTES) + + if (trim_len > RAND_STRIDE) { + last_len = trim_len % RAND_STRIDE; + trim_len = trim_len - last_len; + } + else { + trim_len = 0; + last_len = bytes_len; + } + + const char *data_src = (void *)&(rng->X); + size_t i = 0; + while (i != trim_len) { + BLI_assert(i < trim_len); +#ifdef __BIG_ENDIAN__ + for (size_t j = (RAND_STRIDE + MASK_BYTES) - 1; j != MASK_BYTES - 1; j--) +#else + for (size_t j = 0; j != RAND_STRIDE; j++) +#endif + { + bytes[i++] = data_src[j]; + } + rng_step(rng); + } + if (last_len) { + for (size_t j = 0; j != last_len; j++) { + bytes[i++] = data_src[j]; + } + } + +#undef RAND_STRIDE +} + int BLI_rng_get_int(RNG *rng) { rng_step(rng); diff --git a/tests/gtests/blenlib/BLI_array_store_test.cc b/tests/gtests/blenlib/BLI_array_store_test.cc index 33fb454ec2f..b71dc4575f1 100644 --- a/tests/gtests/blenlib/BLI_array_store_test.cc +++ b/tests/gtests/blenlib/BLI_array_store_test.cc @@ -528,15 +528,6 @@ static unsigned int rand_range_i(RNG *rng, unsigned int min_i, unsigned int max_ return min_i + value; } -static void rand_bytes(RNG *rng, char *data, int data_len) -{ - BLI_assert(data_len != 0); - while (data_len--) { - *data = BLI_rng_get_uint(rng) % 256; - data++; - } -} - static void testbuffer_list_state_random_data( ListBase *lb, const size_t stride, @@ -548,7 +539,7 @@ static void testbuffer_list_state_random_data( char *data = (char *)MEM_mallocN(data_len, __func__); if (lb->last == NULL) { - rand_bytes(rng, data, data_len); + BLI_rng_get_char_n(rng, data, data_len); } else { TestBuffer *tb_last = (TestBuffer *)lb->last; @@ -557,7 +548,7 @@ static void testbuffer_list_state_random_data( } else { memcpy(data, tb_last->data, tb_last->data_len); - rand_bytes(rng, &data[tb_last->data_len], data_len - tb_last->data_len); + BLI_rng_get_char_n(rng, &data[tb_last->data_len], data_len - tb_last->data_len); } /* perform multiple small mutations to the array. */ @@ -583,7 +574,7 @@ static void testbuffer_list_state_random_data( data_len += stride; data = (char *)MEM_reallocN((void *)data, data_len); memmove(&data[offset + stride], &data[offset], data_len - (offset + stride)); - rand_bytes(rng, &data[offset], stride); + BLI_rng_get_char_n(rng, &data[offset], stride); } break; } @@ -608,7 +599,7 @@ static void testbuffer_list_state_random_data( { if (data_len > 0) { const unsigned int offset = rand_range_i(rng, 0, data_len - stride, stride); - rand_bytes(rng, &data[offset], stride); + BLI_rng_get_char_n(rng, &data[offset], stride); } break; } @@ -667,7 +658,7 @@ static void random_chunk_generate( const size_t chunk_size_bytes = stride * chunk_count; for (int i = 0; i < chunks_per_buffer; i++) { char *data_chunk = (char *)MEM_mallocN(chunk_size_bytes, __func__); - rand_bytes(rng, data_chunk, chunk_size_bytes); + BLI_rng_get_char_n(rng, data_chunk, chunk_size_bytes); testchunk_list_add(lb, data_chunk, chunk_size_bytes); } BLI_rng_free(rng); -- cgit v1.2.3