commit 255506e3fb4c87f2a1cb0c792e26a43a509511a8 parent dd83f3ffa357932a71888aedb7e614e829b5e922 Author: Vincent Forest <vincent.forest@meso-star.com> Date: Wed, 16 Mar 2022 09:48:20 +0100 Merge branch 'release_0.13' Diffstat:
39 files changed, 601 insertions(+), 64 deletions(-)
diff --git a/README.md b/README.md @@ -34,6 +34,31 @@ variable to the directory that contains the `boost` include directory. ## Release notes +### Version 0.13 + +#### Index of the RNG proxy sequence + +Add the `sequence_id` variable to the RNG proxy. A sequence is a set of random +numbers consumed by the buckets managed by the RNG proxy. This new variable +saves the index of the current sequence relative to the initial state of the +RNG proxy. It thus identifies the set of random numbers already consumed and +currently reserved by an RNG proxy. This data is provided to allow the caller +to synchronize multiple RNG proxies. + +The new `ssp_rng_proxy_get_sequence_id` function allows the caller to retrieve +the index of the current sequence while the `ssp_rng_proxy_flush_sequences` +function allows to remove random numbers from the current sequence and those +from the next one. + +#### Issues in RNG proxy + + +- Fixes the `ssp_rng_proxy_read` function: cached RNG states were not being + cleaned up when updating the proxy state, resulting in the use of random + numbers generated from the wrong state. +- Fixes critical issues in the caching mechanism of the RNG proxy: a cache size + smaller than the size of an RNG state led to critical bugs. + ### Version 0.12.1 Fix creating a random number proxy generator using the KISS type: this type was @@ -141,7 +166,7 @@ CMake 3.20, version 2 has become obsolete. ## License -Copyright (C) 2015-2021 |Meso|Star> (<contact@meso-star.com>). Star-Sampling is +Copyright (C) 2015-2022 |Meso|Star> (<contact@meso-star.com>). Star-Sampling is free software released under the CeCILLv2.1 license. You are welcome to redistribute it under certain conditions; refer to the COPYING files for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +# Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) # # This software is a computer program whose purpose is to generate files # used to build the Star-SP library. @@ -79,8 +79,8 @@ endif() # Configure and define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 12) -set(VERSION_PATCH 1) +set(VERSION_MINOR 13) +set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SSP_FILES_SRC diff --git a/src/ssp.h b/src/ssp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. @@ -37,6 +37,8 @@ #include <rsys/math.h> #include <rsys/rsys.h> +#include <stdint.h> /* SIZE_MAX */ + /* Library symbol management */ #if defined(SSP_SHARED_BUILD) /* Build shared library */ #define SSP_API extern EXPORT_SYM @@ -55,6 +57,8 @@ #define SSP(Func) ssp_ ## Func #endif +#define SSP_SEQUENCE_ID_NONE SIZE_MAX + /* Forward declaration of opaque types */ struct ssp_rng; struct ssp_rng_proxy; @@ -266,6 +270,25 @@ ssp_rng_proxy_get_type (const struct ssp_rng_proxy* proxy, enum ssp_rng_type* type); +/* Returns the index of the current sequence. This index is independent of the + * original seed used by the proxy. When creating the proxy, the sequence index + * is 0. It is then incremented by one each time a new sequence is required. + * This index is used to identify the state of the proxy relative to the + * original seed. */ +SSP_API res_T +ssp_rng_proxy_get_sequence_id + (const struct ssp_rng_proxy* proxy, + size_t* sequence_id); + +/* Discard the random numbers of `n' sequences. If `n' is 0, nothing happens. + * If `n' is greater than or equal to one, the random numbers of the current + * sequence are ignored as well as the random numbers of the following + * sequences until the sequence identifier has been incremented by `n-1'. */ +SSP_API res_T +ssp_rng_proxy_flush_sequences + (struct ssp_rng_proxy* proxy, + const size_t n); + /******************************************************************************* * Miscellaneous distributions ******************************************************************************/ diff --git a/src/ssp_ran.c b/src/ssp_ran.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/ssp_ranst_discrete.c b/src/ssp_ranst_discrete.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/ssp_ranst_gaussian.c b/src/ssp_ranst_gaussian.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/ssp_ranst_piecewise_linear.c b/src/ssp_ranst_piecewise_linear.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/ssp_rng.c b/src/ssp_rng.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/ssp_rng_c.h b/src/ssp_rng_c.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. @@ -40,7 +40,14 @@ #include <limits.h> #define BUCKET_SIZE_DEFAULT 1000000 /* #RNs per bucket */ -#define STATE_CACHE_HINT_MAX_SIZE (32*(1024*1024)) /* 32 MB */ + +/* Cache size to use. This is just a hint: the effective size of the cache is + * actually a multiple of the size of the RNG state it should store. */ +#if 1 + #define STATE_CACHE_HINT_MAX_SIZE (32*(1024*1024)) /* 32 MB */ +#else + #define STATE_CACHE_HINT_MAX_SIZE 0 /* Disable the cache */ +#endif /* Cache of RNG states */ struct rng_state_cache { @@ -57,7 +64,7 @@ struct rng_state_cache { CLBK(rng_proxy_cb_T, ARG1(const struct ssp_rng_proxy*)); enum rng_proxy_sig { - RNG_PROXY_SIG_READ, + RNG_PROXY_SIG_SET_STATE, RNG_PROXY_SIGS_COUNT__ }; @@ -83,11 +90,28 @@ struct ssp_rng_proxy { /* The following arrays have the same size */ ATOMIC* buckets; /* Flag that defines which bucket RNGs are created */ + size_t sequence_size; /* #RNs in a sequence */ size_t sequence_bias; /* #RNs to discard between 2 consecutive sequence */ size_t bucket_size; /* #random numbers per bucket */ struct ssp_rng** pools; /* `type' RNGs wrapped by bucket RNGs */ struct rng_state_cache* states; /* Cache of `type' RNG states */ + /* Index of the last queried sequence. This index is independent of the + * original seed used by the proxy and is designed to identify the status of + * the proxy relative to that original seed. When the proxy is created, the + * sequence index is SSP_SEQUENCE_ID_NONE, i.e. no sequence was queried. At + * the first request for a random number, the first sequence is consumed and + * this sequence index is then 0. It is then incremented by one each time a + * new sequence is required. + * + * Each bucket stores the sequence ID of its local RNG. The proxy sequence ID + * is the maximum between these local sequence indices. Note that we also + * keep track of the RNG proxy's sequence index (main_sequence_id); it is + * equal to the proxy sequence identifier only when the caching mechanism is + * still in use. */ + size_t* per_bucket_sequence_id; + size_t main_sequence_id; + signal_T signals[RNG_PROXY_SIGS_COUNT__]; struct mutex* mutex; @@ -106,7 +130,7 @@ struct ssp_rng_proxy { * |######| Bucket 0 | ... | Bucket N-1 |####| Bucket 0 | ... * |######| 1st pool | | 1st pool |####| 2nd pool | * +------+------------+- -+------------+----+------------+- - * \ / \_________sequence_size_______/ / + * \ / \_________sequence_size_______/ / * sequence \________sequence_pitch__________/ * offset */ @@ -179,6 +203,22 @@ rng_state_cache_release(struct rng_state_cache* cache) darray_char_release(&cache->state_scratch); } +static res_T +rng_state_cache_clear(struct rng_state_cache* cache) +{ + if(!cache->stream) { + cache->stream = tmpfile(); + if(!cache->stream) return RES_IO_ERR; + } else { + rewind(cache->stream); + cache->read = cache->write = ftell(cache->stream); + } + cache->nstates = 0; + cache->no_wstream = 0; + cache->no_rstream = 0; + return RES_OK; +} + static char rng_state_cache_is_empty(struct rng_state_cache* cache) { @@ -187,15 +227,22 @@ rng_state_cache_is_empty(struct rng_state_cache* cache) } static res_T -rng_state_cache_read(struct rng_state_cache* cache, struct ssp_rng* rng) +rng_state_cache_read + (struct rng_state_cache* cache, + struct ssp_rng* rng, + struct mutex* mutex) /* Proxy mutex */ { res_T res = RES_OK; - ASSERT(cache && rng && !rng_state_cache_is_empty(cache)); + ASSERT(cache && rng && mutex); + + mutex_lock(mutex); + ASSERT(!rng_state_cache_is_empty(cache)); if(!cache->no_rstream + && cache->no_wstream && cache->read == cache->write && cache->nstates == 1/* A state is saved in 'cache->state' */) { - /* There is not more data cached into the stream. Close the stream and do + /* There is no more data cached into the stream. Close the stream and do * not rely anymore on the proxy RNG to generate the RNG states */ fclose(cache->stream); cache->stream = NULL; @@ -206,7 +253,10 @@ rng_state_cache_read(struct rng_state_cache* cache, struct ssp_rng* rng) if(!cache->no_rstream) { fseek(cache->stream, cache->read, SEEK_SET); res = ssp_rng_read(rng, cache->stream); - if(res != RES_OK) goto error; + if(res != RES_OK) { + mutex_unlock(mutex); + goto error; + } cache->read = ftell(cache->stream); /* The fp reaches the end of the cached data */ @@ -217,8 +267,13 @@ rng_state_cache_read(struct rng_state_cache* cache, struct ssp_rng* rng) /* Remove one cached states */ cache->nstates -= 1; + mutex_unlock(mutex); + /* Generate the next RNG state and load the cached one */ } else { + /* All is done locally to the RNG. We can thus unlock the proxy mutex */ + mutex_unlock(mutex); + /* Copy the cached RNG state */ res = darray_char_copy(&cache->state_scratch, &cache->state); if(res != RES_OK) goto error; @@ -255,7 +310,8 @@ rng_state_cache_write(struct rng_state_cache* cache, struct ssp_rng* rng) if(cache->no_wstream) goto exit; /* Do not cache the submitted state */ fseek(cache->stream, cache->write, SEEK_SET); - if(rng_state_cache_is_empty(cache) || cache->write > cache->read) { + if(STATE_CACHE_HINT_MAX_SIZE > 0 + && (rng_state_cache_is_empty(cache) || cache->write > cache->read)) { /* Directly write the RNG state into the cache stream */ res = ssp_rng_write(rng, cache->stream); if(res != RES_OK) goto error; @@ -305,11 +361,11 @@ struct rng_bucket { struct ssp_rng_proxy* proxy; /* The RNG proxy */ size_t name; /* Unique bucket identifier in [0, #buckets) */ size_t count; /* Remaining unique random numbers in `pool' */ - rng_proxy_cb_T cb_on_proxy_read; + rng_proxy_cb_T cb_on_proxy_set_state; }; static void -rng_bucket_on_proxy_read(const struct ssp_rng_proxy* proxy, void* ctx) +rng_bucket_on_proxy_set_state(const struct ssp_rng_proxy* proxy, void* ctx) { struct rng_bucket* rng = (struct rng_bucket*)ctx; ASSERT(proxy && ctx && rng->proxy == proxy); @@ -395,7 +451,7 @@ rng_bucket_release(void* data) struct rng_bucket* rng = (struct rng_bucket*)data; ASSERT(data && rng->proxy); ATOMIC_SET(&rng->proxy->buckets[rng->name], 0); - CLBK_DISCONNECT(&rng->cb_on_proxy_read); + CLBK_DISCONNECT(&rng->cb_on_proxy_set_state); SSP(rng_proxy_ref_put(rng->proxy)); } @@ -411,7 +467,7 @@ rng_bucket_discard(void* data, uint64_t n) { struct rng_bucket* rng = (struct rng_bucket*)data; ASSERT(data); - while (rng->count <= n) { + while (rng->count < n) { n -= rng->count; rng_bucket_next_ran_pool(rng); } @@ -446,9 +502,12 @@ rng_proxy_next_ran_pool const size_t bucket_name) { res_T res = RES_OK; - ASSERT(proxy && bucket_name <= sa_size(proxy->buckets)); + ASSERT(proxy); + ASSERT(bucket_name <= sa_size(proxy->buckets)); + ASSERT(bucket_name <= sa_size(proxy->per_bucket_sequence_id)); mutex_lock(proxy->mutex); + if(rng_state_cache_is_empty(proxy->states + bucket_name)) { size_t ibucket; /* Register a new state for *all* buckets */ @@ -459,13 +518,21 @@ rng_proxy_next_ran_pool } /* Discard RNs to reach the next sequence */ ssp_rng_discard(proxy->rng, proxy->sequence_bias); + + /* Increment the sequence id of the main RNG */ + proxy->main_sequence_id += 1; } + mutex_unlock(proxy->mutex); /* Read the RNG pool state of `bucket_name' */ res = rng_state_cache_read - (proxy->states + bucket_name, proxy->pools[bucket_name]); + (proxy->states + bucket_name, + proxy->pools[bucket_name], + proxy->mutex); if(res != RES_OK) FATAL("RNG proxy: cannot read from state cache\n"); - mutex_unlock(proxy->mutex); + + /* Update the sequence of the bucket RNG */ + proxy->per_bucket_sequence_id[bucket_name] += 1; return proxy->pools[bucket_name]; } @@ -503,6 +570,7 @@ rng_proxy_setup sa_add(proxy->states, nbuckets); sa_add(proxy->pools, nbuckets); sa_add(proxy->buckets, nbuckets); + sa_add(proxy->per_bucket_sequence_id, nbuckets); FOR_EACH(ibucket, 0, nbuckets) { res = rng_state_cache_init @@ -511,6 +579,11 @@ rng_proxy_setup res = ssp_rng_create(proxy->allocator, proxy->type, proxy->pools+ibucket); if(res != RES_OK) goto error; proxy->buckets[ibucket] = 0; + + /* Set the sequence index to SIZE_MAX because no sequence is active until a + * random number query is made. On the first query, the index will be + * incremented to 0 */ + proxy->per_bucket_sequence_id[ibucket] = SSP_SEQUENCE_ID_NONE/*<=> SIZE_MAX*/; } exit: @@ -520,6 +593,22 @@ error: goto exit; } +static res_T +rng_proxy_clear_caches(struct ssp_rng_proxy* proxy) +{ + size_t ibucket; + res_T res = RES_OK; + ASSERT(proxy); + + mutex_lock(proxy->mutex); + FOR_EACH(ibucket, 0, sa_size(proxy->pools)) { + res = rng_state_cache_clear(proxy->states+ibucket); + if(res != RES_OK) break; + } + mutex_unlock(proxy->mutex); + return res; +} + void rng_proxy_release(ref_T* ref) { @@ -530,6 +619,7 @@ rng_proxy_release(ref_T* ref) sa_release(proxy->states); sa_release(proxy->pools); sa_release(proxy->buckets); + sa_release(proxy->per_bucket_sequence_id); if(proxy->rng) SSP(rng_ref_put(proxy->rng)); if(proxy->mutex) mutex_destroy(proxy->mutex); MEM_RM(proxy->allocator, proxy); @@ -606,9 +696,12 @@ ssp_rng_proxy_create2 proxy->allocator = allocator; ref_init(&proxy->ref); proxy->bucket_size = args->sequence_size / args->nbuckets; + proxy->sequence_size = args->sequence_size; proxy->sequence_bias = args->sequence_pitch - (proxy->bucket_size * args->nbuckets); + proxy->main_sequence_id = SSP_SEQUENCE_ID_NONE; + /* Create the proxy RNG in its default state */ if(!args->rng) { res = ssp_rng_create(allocator, args->type, &proxy->rng); @@ -683,7 +776,13 @@ ssp_rng_proxy_read(struct ssp_rng_proxy* proxy, FILE* stream) mutex_unlock(proxy->mutex); if(res != RES_OK) return res; - SIG_BROADCAST(proxy->signals+RNG_PROXY_SIG_READ, rng_proxy_cb_T, ARG1(proxy)); + /* Discard the cached RNG states */ + res = rng_proxy_clear_caches(proxy); + if(res != RES_OK) return res; + + /* Notify to bucket RNGs that the proxy RNG state was updated */ + SIG_BROADCAST + (proxy->signals+RNG_PROXY_SIG_SET_STATE, rng_proxy_cb_T, ARG1(proxy)); return RES_OK; } @@ -752,9 +851,11 @@ ssp_rng_proxy_create_rng /* The bucket RNG listens the "write" signal of the proxy to reset its * internal RNs counter on "write" invocation. */ - CLBK_INIT(&bucket->cb_on_proxy_read); - CLBK_SETUP(&bucket->cb_on_proxy_read, rng_bucket_on_proxy_read, bucket); - SIG_CONNECT_CLBK(proxy->signals+RNG_PROXY_SIG_READ, &bucket->cb_on_proxy_read); + CLBK_INIT(&bucket->cb_on_proxy_set_state); + CLBK_SETUP + (&bucket->cb_on_proxy_set_state, rng_bucket_on_proxy_set_state, bucket); + SIG_CONNECT_CLBK + (proxy->signals+RNG_PROXY_SIG_SET_STATE, &bucket->cb_on_proxy_set_state); exit: if(out_rng) *out_rng = rng; @@ -776,3 +877,81 @@ ssp_rng_proxy_get_type *type = proxy->type; return RES_OK; } + +res_T +ssp_rng_proxy_get_sequence_id(const struct ssp_rng_proxy* proxy, size_t* out_id) +{ + size_t id = SSP_SEQUENCE_ID_NONE; + size_t i; + + if(!proxy || !out_id) return RES_BAD_ARG; + + mutex_lock(proxy->mutex); + FOR_EACH(i, 0, sa_size(proxy->per_bucket_sequence_id)) { + if(proxy->per_bucket_sequence_id[i] == SSP_SEQUENCE_ID_NONE) continue; + id = id == SSP_SEQUENCE_ID_NONE + ? proxy->per_bucket_sequence_id[i] + : MMAX(id, proxy->per_bucket_sequence_id[i]); + } + mutex_unlock(proxy->mutex); + + *out_id = id; + return RES_OK; +} + +res_T +ssp_rng_proxy_flush_sequences + (struct ssp_rng_proxy* proxy, + const size_t nseqs) +{ + size_t nseqs_proxy = 0; + size_t iseq; + size_t i; + res_T res = RES_OK; + + if(!proxy) { + res = RES_BAD_ARG; + goto error; + } + + /* Nothing to discard */ + if(nseqs == 0) goto exit; + + res = ssp_rng_proxy_get_sequence_id(proxy, &iseq); + if(res != RES_OK) goto error; + + /* Calculate the number of sequences to flush for the main RNG, i.e. the one + * used when the cache is in use. We want to dump the 'nseqs' sequences. That + * said, since the status of the RNG is set to the status of the 1st random + * number of the next sequence, it is enough to 'nseqs-1' sequences and clear + * the cache. Anyway, note that the sequence identifier of the main RNG may + * be behind the global sequence identifier. This happens when the cache + * mechanism is no longer used. In this case, we need to dump the extra + * sequences from the main RNG to match the current sequence index of the + * proxy. */ + nseqs_proxy = (nseqs - 1) + (iseq - proxy->main_sequence_id); + + mutex_lock(proxy->mutex); + res = ssp_rng_discard(proxy->rng, proxy->sequence_size * nseqs_proxy); + mutex_unlock(proxy->mutex); + if(res != RES_OK) goto error; + + proxy->main_sequence_id += nseqs_proxy; + + /* Discard the cached RNG states */ + rng_proxy_clear_caches(proxy); + + /* Reset the RNGs sequence id */ + FOR_EACH(i, 0, sa_size(proxy->per_bucket_sequence_id)) { + proxy->per_bucket_sequence_id[i] = proxy->main_sequence_id; + } + + /* Notify to bucket RNGs that the proxy RNG state was updated */ + SIG_BROADCAST + (proxy->signals+RNG_PROXY_SIG_SET_STATE, rng_proxy_cb_T, ARG1(proxy)); + +exit: + return res; +error: + goto exit; +} diff --git a/src/test_ssp_ran_circle.c b/src/test_ssp_ran_circle.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_circle.h b/src/test_ssp_ran_circle.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_discrete.c b/src/test_ssp_ran_discrete.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/test_ssp_ran_discrete.h b/src/test_ssp_ran_discrete.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_ran_gaussian.c b/src/test_ssp_ran_gaussian.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_ran_gaussian.h b/src/test_ssp_ran_gaussian.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a library whose purpose is to generate [pseudo] random * numbers and random variates. diff --git a/src/test_ssp_ran_hemisphere.c b/src/test_ssp_ran_hemisphere.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_hemisphere.h b/src/test_ssp_ran_hemisphere.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_hg.c b/src/test_ssp_ran_hg.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_hg.h b/src/test_ssp_ran_hg.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_piecewise_linear.c b/src/test_ssp_ran_piecewise_linear.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_ran_piecewise_linear.h b/src/test_ssp_ran_piecewise_linear.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_ran_sphere.c b/src/test_ssp_ran_sphere.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_sphere.h b/src/test_ssp_ran_sphere.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_sphere_cap.c b/src/test_ssp_ran_sphere_cap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_sphere_cap.h b/src/test_ssp_ran_sphere_cap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_spherical_zone.c b/src/test_ssp_ran_spherical_zone.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_spherical_zone.h b/src/test_ssp_ran_spherical_zone.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_tetrahedron.c b/src/test_ssp_ran_tetrahedron.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_tetrahedron.h b/src/test_ssp_ran_tetrahedron.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_triangle.c b/src/test_ssp_ran_triangle.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_triangle.h b/src/test_ssp_ran_triangle.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, diff --git a/src/test_ssp_ran_uniform_disk.c b/src/test_ssp_ran_uniform_disk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_ran_uniform_disk.h b/src/test_ssp_ran_uniform_disk.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_rng.c b/src/test_ssp_rng.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_rng.h b/src/test_ssp_rng.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_rng_proxy.c b/src/test_ssp_rng_proxy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * @@ -395,25 +395,28 @@ test_read(void) CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK); CHK(ssp_rng_discard(rng, COUNT) == RES_OK); + /* Create a RNG state */ stream = tmpfile(); CHK(stream != NULL); CHK(ssp_rng_write(rng, stream) == RES_OK); rewind(stream); + /* Create a proxy from the RNG state */ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 4, &proxy) == RES_OK); CHK(ssp_rng_proxy_read(NULL, NULL) == RES_BAD_ARG); CHK(ssp_rng_proxy_read(proxy, NULL) == RES_BAD_ARG); CHK(ssp_rng_proxy_read(NULL, stream) == RES_BAD_ARG); CHK(ssp_rng_proxy_read(proxy, stream) == RES_OK); + /* Create the list of RNG managed by the proxy */ FOR_EACH(i, 0, 4) CHK(ssp_rng_proxy_create_rng(proxy, i, &rng1[i]) == RES_OK); + /* Check the random number sequences */ r[0] = ssp_rng_get(rng); CHK(r[0] == ssp_rng_get(rng1[0])); CHK(r[0] != ssp_rng_get(rng1[1])); CHK(r[0] != ssp_rng_get(rng1[2])); CHK(r[0] != ssp_rng_get(rng1[3])); - FOR_EACH(i, 0, NRANDS) { FOR_EACH(j, 0, 4) { r[j] = ssp_rng_get(rng1[j]); @@ -424,7 +427,116 @@ test_read(void) CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); CHK(ssp_rng_ref_put(rng) == RES_OK); FOR_EACH(i, 0, 4) CHK(ssp_rng_ref_put(rng1[i]) == RES_OK); - fclose(stream); + + CHK(fclose(stream) == 0); +} + +static void +test_read_with_cached_states(void) +{ + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; + struct ssp_rng_proxy* proxy; + struct ssp_rng* rng; + struct ssp_rng* rng0; + struct ssp_rng* rng1; + FILE* stream; + size_t iseq; + size_t i; + + CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK); + + /* Create a proxy with a very small sequence size of 2 RNs per bucket in + * order to maximize the number of cached states. Furthermore, use the + * Mersenne Twister RNG type since its internal state is the greatest one of + * the proposed builtin type and is thus the one that will fill quickly the + * cache stream. */ + args.type = SSP_RNG_MT19937_64; + args.sequence_size = 10; + args.sequence_pitch = 10; + args.nbuckets = 2; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); + CHK(ssp_rng_proxy_create_rng(proxy, 0, &rng0) == RES_OK); + CHK(ssp_rng_proxy_create_rng(proxy, 1, &rng1) == RES_OK); + + /* Check RNG states */ + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + } + + /* Discard several RNs for the 1st RNG to cache several states for the rng1 */ + CHK(ssp_rng_discard(rng0, 103) == RES_OK); + + /* Generate a RNG state */ + stream = tmpfile(); + CHK(stream != NULL); + CHK(ssp_rng_discard(rng, 100000) == RES_OK); + CHK(ssp_rng_write(rng, stream) == RES_OK); + rewind(stream); + + /* Setup the proxy state and check that the RNGs managed by the proxy now use + * the new state properly, even though RNG states were previously cached */ + CHK(ssp_rng_proxy_read(proxy, stream) == RES_OK); + FOR_EACH(iseq, 0, 100) { + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + } + } + + /* Discard several RNs for the first RNG only to make under pressure the + * cache stream of 'rng1'. The cache stream limit is set to 32 MB and the + * size of a Mersenne Twister RNG state is greater than 6 KB. Consquently, + * ~5500 RNG states will exceed the cache stream, i.e. 5500*2 = 11000 + * random generations (since there is 2 RNs per bucket). Above this limit, + * 'rng1' will not rely anymore on the proxy RNG to manage its state. */ + CHK(ssp_rng_discard(rng0, 20000) == RES_OK); + + /* Generate a new RNG state */ + rewind(stream); + CHK(ssp_rng_discard(rng, 100000) == RES_OK); + CHK(ssp_rng_write(rng, stream) == RES_OK); + rewind(stream); + + /* Now setup a new proxy state and check that the RNGs managed by the proxy + * correctly use the new state */ + CHK(ssp_rng_proxy_read(proxy, stream) == RES_OK); + FOR_EACH(iseq, 0, 100) { + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + } + } + + /* Discard several RNs for the 1st RNG to cache several states for the rng1 */ + CHK(ssp_rng_discard(rng0, 100) == RES_OK); + + /* Finally verify that the cache was reset on proxy read */ + FOR_EACH(iseq, 0, 100) { + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_discard(rng, 1) == RES_OK); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + } + } + + CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); + CHK(ssp_rng_ref_put(rng0) == RES_OK); + CHK(ssp_rng_ref_put(rng1) == RES_OK); + CHK(ssp_rng_ref_put(rng) == RES_OK); + + CHK(fclose(stream) == 0); } static void @@ -460,7 +572,7 @@ test_write(void) CHK(ssp_rng_ref_put(rng0) == RES_OK); CHK(ssp_rng_ref_put(rng1) == RES_OK); - fclose(stream); + CHK(fclose(stream) == 0); } static void @@ -484,7 +596,7 @@ test_cache(void) args.sequence_pitch = 4; args.nbuckets = 2; - /* Simply test that the RNs generated by the proxy are the same thant the + /* Simply test that the RNs generated by the proxy are the same than the * ones generated by a regular RNG. Since each RNG invocation are * interleaved, the cache pressure is very low, at most 1 RNG state is * cached. */ @@ -536,7 +648,202 @@ test_cache(void) CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); CHK(ssp_rng_ref_put(rng0) == RES_OK); CHK(ssp_rng_ref_put(rng1) == RES_OK); +} + +static void +test_sequence(void) +{ + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; + struct ssp_rng_proxy* proxy; + struct ssp_rng* rng0; + struct ssp_rng* rng1; + struct ssp_rng* rng; + size_t id; + size_t iseq; + size_t i; + + args.type = SSP_RNG_MT19937_64; + args.sequence_offset = 0; + args.sequence_size = 16; + args.sequence_pitch = 16; + args.nbuckets = 2; + + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); + CHK(ssp_rng_proxy_create_rng(proxy, 0, &rng0) == RES_OK); + CHK(ssp_rng_proxy_create_rng(proxy, 1, &rng1) == RES_OK); + CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK); + + CHK(ssp_rng_proxy_get_sequence_id(NULL, &id) == RES_BAD_ARG); + CHK(ssp_rng_proxy_get_sequence_id(proxy, NULL) == RES_BAD_ARG); + + /* Check that directly after its creation, the proxy has a the sequence index + * of SSP_SEQUENCE_ID_NONE */ + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == SSP_SEQUENCE_ID_NONE); + + /* Generate 4 sequences of random numbers and check the progression of the + * sequence index */ + FOR_EACH(iseq, 0, 4) { + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == iseq); + } + } + + /* Generate 1 more RN to go to the next sequence. Then, discard the remaining + * random numbers of the first RNG and check the the sequence is the same + * until a new RN is discarded */ + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 4); + CHK(ssp_rng_discard(rng0, args.sequence_size/2 - 1) == RES_OK); + CHK(ssp_rng_discard(rng, args.sequence_size/2 - 1) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 4); + CHK(ssp_rng_discard(rng0, 1) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 5); + + /* Check the random sequence of the second RNG */ + FOR_EACH(i, 0, args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + + /* Check the sequence of the first RNG */ + CHK(ssp_rng_discard(rng, 1) == RES_OK); + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + + /* Discard the random numbers of the current sequence associated to the + * second RNG. Check the the sequence is the same until a new random number + * is discarded */ + CHK(ssp_rng_discard(rng1, args.sequence_size/2) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 5); + CHK(ssp_rng_discard(rng1, 1) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 6); + + /* Synchronise the RNGs through sequence 6 */ + CHK(ssp_rng_discard(rng0, args.sequence_size/2-2) == RES_OK); + CHK(ssp_rng_discard(rng, args.sequence_size-2) == RES_OK); + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else if(i == args.sequence_size/2) { + CHK(ssp_rng_discard(rng, 1) == RES_OK); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + } + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 6); + + /* Move in sequence 7 */ + CHK(ssp_rng_discard(rng0, 3) == RES_OK); + CHK(ssp_rng_discard(rng1, 7) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 7); + + CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); + CHK(ssp_rng_ref_put(rng1) == RES_OK); + CHK(ssp_rng_ref_put(rng0) == RES_OK); + CHK(ssp_rng_ref_put(rng) == RES_OK); +} + +static void +test_flush_sequence() +{ + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; + struct ssp_rng_proxy* proxy; + struct ssp_rng* rng0; + struct ssp_rng* rng1; + struct ssp_rng* rng; + size_t id; + size_t i; + + args.type = SSP_RNG_MT19937_64; + args.sequence_offset = 0; + args.sequence_size = 10; + args.sequence_pitch = 10; + args.nbuckets = 2; + + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); + CHK(ssp_rng_proxy_create_rng(proxy, 0, &rng0) == RES_OK); + CHK(ssp_rng_proxy_create_rng(proxy, 1, &rng1) == RES_OK); + CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK); + + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == SSP_SEQUENCE_ID_NONE); + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + + /* Flush 0 sequence, i.e. do nothing */ + CHK(ssp_rng_proxy_flush_sequences(NULL, 0) == RES_BAD_ARG); + CHK(ssp_rng_proxy_flush_sequences(proxy, 0) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 0); + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + + /* Discard several numbers of the rng1 to fill the cache of rng0. We will + * thus be able to check the cache clearing when we will flush sequences */ + CHK(ssp_rng_discard(rng1, 314) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 62); + + /* Flush the remaining random number of the current sequence */ + CHK(ssp_rng_proxy_flush_sequences(proxy, 1) == RES_OK); + + /* We are still in the sequence 62 but without any available random numbers */ + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 62); + + /* Synchronize RNG with the current state of the proxy */ + CHK(ssp_rng_discard + (rng, args.sequence_size*63 /*#random number to discard */ + - 2/*... minus the 2 already consumed random numbers*/) == RES_OK); + + /* Check RNG states */ + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 63); + } + + /* Fill the cache of the rng1 */ + CHK(ssp_rng_discard(rng0, 1013) == RES_OK); + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 63 + 203/*ceil(1023/(args.sequence_size*0.5))*/); + + /* Discard several sequences */ + CHK(ssp_rng_proxy_flush_sequences(proxy, 314) == RES_OK); + + /* Synchronize RNG with the current state of the proxy */ + CHK(ssp_rng_discard(rng, args.sequence_size*(203 + 314 - 1)) == RES_OK); + + /* Check RNG states */ + FOR_EACH(i, 0, args.sequence_size) { + if(i < args.sequence_size/2) { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng0)); + } else { + CHK(ssp_rng_get(rng) == ssp_rng_get(rng1)); + } + CHK(ssp_rng_proxy_get_sequence_id(proxy, &id) == RES_OK); + CHK(id == 63 + 203 + 314); + } + + CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); + CHK(ssp_rng_ref_put(rng1) == RES_OK); + CHK(ssp_rng_ref_put(rng0) == RES_OK); + CHK(ssp_rng_ref_put(rng) == RES_OK); } int @@ -550,8 +857,11 @@ main(int argc, char** argv) test_multi_proxies(); test_proxy_from_rng(); test_read(); + test_read_with_cached_states(); test_write(); test_cache(); + test_sequence(); + test_flush_sequence(); CHK(mem_allocated_size() == 0); return 0; } diff --git a/src/test_ssp_rng_proxy.h b/src/test_ssp_rng_proxy.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is a program whose purpose is to test the spp library. * diff --git a/src/test_ssp_utils.h b/src/test_ssp_utils.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2015-2022 |Meso|Star> (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use,