summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2020-07-27 22:47:18 +0200
committerTyge Løvset <[email protected]>2020-07-27 22:47:18 +0200
commitb5351558ac6d5f78750fe93ed9390fed5efa2ac4 (patch)
treef3831a1bf270bff95a241f30aa69b475abce2fbf
parentf7369895d19abfe3e68d20bbf865d5749da3edf8 (diff)
downloadSTC-modified-b5351558ac6d5f78750fe93ed9390fed5efa2ac4.tar.gz
STC-modified-b5351558ac6d5f78750fe93ed9390fed5efa2ac4.zip
Changed crandom.h API
-rw-r--r--README.md4
-rw-r--r--examples/benchmark.c6
-rw-r--r--examples/heap.c8
-rw-r--r--examples/list.c4
-rw-r--r--examples/priority.c4
-rw-r--r--examples/rngbirthday.c8
-rw-r--r--examples/rngtest.c12
-rw-r--r--stc/clist.h4
-rw-r--r--stc/cmap.h4
-rw-r--r--stc/crandom.h210
-rw-r--r--stc/cvecpq.h4
11 files changed, 79 insertions, 189 deletions
diff --git a/README.md b/README.md
index 385c205e..7d5cb132 100644
--- a/README.md
+++ b/README.md
@@ -296,9 +296,9 @@ declare_clist(i, uint64_t);
int main() {
clist_i list = clist_init;
int N = 2000000, n;
- crandom64_t rng = crandom64_seed(time(NULL));
+ crandom64_t rng = crandom64_uniform_engine(time(NULL));
for (int i=0; i<N; ++i) // two million random numbers
- clist_i_pushBack(&list, crandom64(&rng));
+ clist_i_pushBack(&list, crandom64_uinform_int(&rng));
n = 0;
c_foreach (i, clist_i, list)
if (++n % (N/50) == 0) printf("%10d: %zu\n", n, i.item->value);
diff --git a/examples/benchmark.c b/examples/benchmark.c
index 8b9f33c2..7ac6481e 100644
--- a/examples/benchmark.c
+++ b/examples/benchmark.c
@@ -22,8 +22,8 @@ size_t seed;
static const float maxLoadFactor = 0.77f;
crandom64_t rng;
-#define SEED(s) rng = crandom64_init(seed)
-#define RAND(N) (crandom64(&rng) & ((1 << N) - 1))
+#define SEED(s) rng = crandom64_uniform_engine(seed)
+#define RAND(N) (crandom64_uniform_int(&rng) & ((1 << N) - 1))
#define CMAP_SETUP(tag, Key, Value) cmap_##tag map = cmap_init \
@@ -32,7 +32,7 @@ crandom64_t rng;
#define CMAP_ERASE(tag, key) cmap_##tag##_erase(&map, key)
#define CMAP_FIND(tag, key) (cmap_##tag##_find(map, key) != NULL)
#define CMAP_SIZE(tag) cmap_size(map)
-#define CMAP_BUCKETS(tag) cmap_bucketCount(map)
+#define CMAP_BUCKETS(tag) (map).bucketCount
#define CMAP_CLEAR(tag) cmap_##tag##_destroy(&map)
#define KMAP_SETUP(tag, Key, Value) khash_t(ii)* map = kh_init(ii); khiter_t ki; int ret
diff --git a/examples/heap.c b/examples/heap.c
index 94409371..f91642ac 100644
--- a/examples/heap.c
+++ b/examples/heap.c
@@ -9,12 +9,12 @@ declare_cvec_priority_queue(f, >);
int main()
{
uint32_t seed = time(NULL);
- crandom32_t pcg = crandom32_init(seed);
+ crandom32_t pcg = crandom32_uniform_engine(seed);
int N = 30000000, M = 100;
cvec_f vec = cvec_init;
clock_t start = clock();
for (int i=0; i<N; ++i)
- cvec_f_pushBack(&vec, crandom32(&pcg));
+ cvec_f_pushBack(&vec, crandom32_uniform_int(&pcg));
cvecpq_f_build(&vec);
printf("Built priority queue: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
@@ -25,10 +25,10 @@ int main()
cvecpq_f_pop(&vec);
printf("\n\npopped PQ: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
- pcg = crandom32_init(seed);
+ pcg = crandom32_uniform_engine(seed);
start = clock();
for (int i=0; i<N; ++i)
- cvecpq_f_push(&vec, crandom32(&pcg));
+ cvecpq_f_push(&vec, crandom32_uniform_int(&pcg));
printf("pushed PQ: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
for (int i=0; i<M; ++i)
printf("%.0f ", cvecpq_f_top(&vec)), cvecpq_f_pop(&vec);
diff --git a/examples/list.c b/examples/list.c
index 2eb1f4c0..2c8d17cd 100644
--- a/examples/list.c
+++ b/examples/list.c
@@ -6,10 +6,10 @@ declare_clist(ix, uint64_t);
int main() {
clist_ix list = clist_init;
- crandom32_t pcg = crandom32_init(time(NULL));
+ crandom32_t pcg = crandom32_uniform_engine(time(NULL));
int n;
for (int i=0; i<10000000; ++i) // ten million
- clist_ix_pushBack(&list, crandom32(&pcg));
+ clist_ix_pushBack(&list, crandom32_uniform_int(&pcg));
n = 100;
c_foreach (i, clist_ix, list)
if (n--) printf("%8d: %10zu\n", 100 - n, i.item->value); else break;
diff --git a/examples/priority.c b/examples/priority.c
index 37e7be60..1aee8f58 100644
--- a/examples/priority.c
+++ b/examples/priority.c
@@ -9,12 +9,12 @@ declare_cvec(i, uint32_t);
declare_cvec_priority_queue(i, >); // min-heap (increasing values)
int main() {
- crandom32_t pcg = crandom32_init(time(NULL));
+ crandom32_t pcg = crandom32_uniform_engine(time(NULL));
cvec_i heap = cvec_init;
// Push ten million random numbers to queue
for (int i=0; i<10000000; ++i)
- cvecpq_i_push(&heap, crandom32(&pcg));
+ cvecpq_i_push(&heap, crandom32_uniform_int(&pcg));
// Extract the hundred smallest.
for (int i=0; i<100; ++i) {
diff --git a/examples/rngbirthday.c b/examples/rngbirthday.c
index 5e77fe43..69d510e6 100644
--- a/examples/rngbirthday.c
+++ b/examples/rngbirthday.c
@@ -15,12 +15,12 @@ const static uint64_t mask = (1ull << 52) - 1;
void repeats(void)
{
- crandom64_t rng = crandom64_init(seed);
+ crandom64_t rng = crandom64_uniform_engine(seed);
cmap_ic m = cmap_init;
cmap_ic_reserve(&m, N);
clock_t now = clock();
for (size_t i = 0; i < N; ++i) {
- uint64_t k = crandom64(&rng) & mask;
+ uint64_t k = crandom64_uniform_int(&rng) & mask;
int v = ++cmap_ic_insert(&m, k, 0)->value;
if (v > 1) printf("%zu: %x - %d\n", i, k, v);
}
@@ -34,12 +34,12 @@ declare_cvec(x, uint64_t);
void distribution(void)
{
- crandom32_t rng = crandom32_init(seed); // time(NULL), time(NULL));
+ crandom32_t rng = crandom32_uniform_engine(seed); // time(NULL), time(NULL));
const size_t N = 1ull << 28, M = 1ull << 9; // 1ull << 10;
cmap_x map = cmap_x_make(M);
clock_t now = clock();
for (size_t i = 0; i < N; ++i) {
- ++cmap_x_insert(&map, crandom32b(&rng, M), 0)->value;
+ ++cmap_x_insert(&map, crandom32_uniform_int_bounded(&rng, M), 0)->value;
}
float diff = (float) (clock() - now) / CLOCKS_PER_SEC;
diff --git a/examples/rngtest.c b/examples/rngtest.c
index af7c7dca..296cdc3a 100644
--- a/examples/rngtest.c
+++ b/examples/rngtest.c
@@ -14,26 +14,26 @@ int main(void)
uint64_t v;
printf("start\n");
- crandom32_t pcg = crandom32_init(time(NULL));
+ crandom32_t pcg = crandom32_uniform_engine(time(NULL));
before = clock(); \
v = 0;
for (size_t i=0; i<NN; i++) {
- v += crandom32(&pcg);
+ v += crandom32_uniform_int(&pcg);
}
difference = clock() - before;
printf("pcg32: %.02f, %zu\n", (float) difference / CLOCKS_PER_SEC, v);
- crandom64_t sfc = crandom64_init(time(NULL));
+ crandom64_t sfc = crandom64_uniform_engine(time(NULL));
before = clock(); \
v = 0;
for (size_t i=0; i<NN; i++) {
- v += crandom64(&sfc) & 0xffffffff;
+ v += crandom64_uniform_int(&sfc) & 0xffffffff;
}
difference = clock() - before;
printf("sfc64: %.02f, %zu\n", (float) difference / CLOCKS_PER_SEC, v);
- for (int i=0; i<8; ++i) printf("%f ", crandom64f(&sfc));
+ for (int i=0; i<8; ++i) printf("%f ", crandom32_uniform_real(&pcg));
puts("");
- for (int i=0; i<8; ++i) printf("%f ", crandom32f(&pcg));
+ for (int i=0; i<8; ++i) printf("%f ", crandom64_uniform_real(&sfc));
puts("");
} \ No newline at end of file
diff --git a/stc/clist.h b/stc/clist.h
index 8da0e79d..2a86d4b2 100644
--- a/stc/clist.h
+++ b/stc/clist.h
@@ -39,10 +39,10 @@
int main() {
clist_ix list = clist_init;
- pcg32_random_t pcg = pcg32_seed(123, 0);
+ crandom32_t pcg = crandom32_uniform_engine(12345);
int n;
for (int i=0; i<1000000; ++i) // one million
- clist_ix_pushBack(&list, pcg32_random(&pcg));
+ clist_ix_pushBack(&list, crandom32_uniform_int(&pcg));
n = 0;
c_foreach (i, clist_ix, list)
if (++n % 10000 == 0) printf("%8d: %10zd\n", n, i.item->value);
diff --git a/stc/cmap.h b/stc/cmap.h
index e811d390..74d255f0 100644
--- a/stc/cmap.h
+++ b/stc/cmap.h
@@ -55,10 +55,8 @@ int main(void) {
#define cmap_init {NULL, NULL, 0, 0, 0.85f, 0.15f}
#define cmap_size(m) ((size_t) (m).size)
-#define cmap_bucketCount(m) ((size_t) (m).bucketCount)
#define cset_init cmap_init
#define cset_size(s) cmap_size(s)
-#define cset_bucketCount(s) cmap_bucketCount(s)
/* https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction */
#define chash_reduce(x, N) ((uint32_t) (((uint64_t) (x) * (N)) >> 32))
@@ -160,6 +158,8 @@ typedef struct { \
\
STC_INLINE ctype##_##tag \
ctype##_##tag##_init(void) {ctype##_##tag x = cmap_init; return x;} \
+STC_INLINE size_t \
+ctype##_##tag##_size(ctype##_##tag m) {return m.size;} \
STC_API ctype##_##tag \
ctype##_##tag##_make(size_t initialSize); \
STC_API void \
diff --git a/stc/crandom.h b/stc/crandom.h
index af7070bc..f37f89dc 100644
--- a/stc/crandom.h
+++ b/stc/crandom.h
@@ -27,192 +27,82 @@
#include "cdefs.h"
#include <string.h>
-/*
- * PCG32 random number generator: https://www.pcg-random.org/index.html
- */
-typedef struct {uint64_t state; uint64_t inc;} crandom32_t;
+typedef struct {uint64_t state, inc;} crandom32_t;
-STC_INLINE uint32_t crandom32(crandom32_t* rng)
-{
- uint64_t old = rng->state;
- rng->state = old * 6364136223846793005ull + rng->inc;
- uint32_t xos = ((old >> 18u) ^ old) >> 27u;
- uint32_t rot = old >> 59u;
- return (xos >> rot) | (xos << ((-rot) & 31));
+/* 32 bit random number generator engine */
+STC_API crandom32_t crandom32_uniform_engine2(uint64_t seed, uint64_t seq);
+
+STC_INLINE crandom32_t crandom32_uniform_engine(uint64_t seed) {
+ return crandom32_uniform_engine2(seed, 0);
}
+/* int random number generator, range [0, 2^32) */
+STC_API uint32_t crandom32_uniform_int(crandom32_t* rng);
-/* float random int number in range [0, 1). Note: 23 bit resolution. */
-STC_INLINE float crandom32f(crandom32_t* rng) {
- union {uint32_t i; float f;} u = {0x3F800000u | (crandom32(rng) >> 9)};
+/* float random number in range [0.0f, 1.0f). Note: 23 bit resolution. */
+STC_INLINE float crandom32_uniform_real(crandom32_t* rng) {
+ union {uint32_t i; float f;} u = {0x3F800000u | (crandom32_uniform_int(rng) >> 9)};
return u.f - 1.0f;
}
-/* Uniform random number in range [0, bound) */
-STC_INLINE uint32_t crandom32b(crandom32_t* rng, uint32_t bound) {
- return (uint32_t) (((uint64_t) crandom32(rng) * bound) >> 32);
+/* int random number generator in range [0, bound) */
+STC_INLINE uint32_t crandom32_uniform_int_bounded(crandom32_t* rng, uint32_t bound) {
+ return (uint32_t) (((uint64_t) crandom32_uniform_int(rng) * bound) >> 32);
}
-STC_INLINE crandom32_t crandom32_init2(uint64_t seed, uint64_t seq) {
+
+typedef struct {uint64_t state[4];} crandom64_t;
+
+/* 64 bit random number generator engine */
+STC_API crandom64_t crandom64_uniform_engine(const uint64_t seed);
+
+/* int random number generator, range [0, 2^64) */
+STC_API uint64_t crandom64_uniform_int(crandom64_t* rng);
+
+/* float64 random number in range [0.0, 1.0), 52 bit resolution */
+STC_INLINE double crandom64_uniform_real(crandom64_t* rng) {
+ union {uint64_t i; double f;} u = {0x3FF0000000000000ull | (crandom64_uniform_int(rng) >> 12)};
+ return u.f - 1.0;
+}
+
+
+#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
+
+/* PCG32 random number generator: https://www.pcg-random.org/index.html */
+
+STC_API crandom32_t crandom32_uniform_engine2(uint64_t seed, uint64_t seq) {
crandom32_t rng = {0u, (seq << 1u) | 1u}; /* inc must be odd */
- crandom32(&rng);
+ crandom32_uniform_int(&rng);
rng.state += seed;
- crandom32(&rng);
+ crandom32_uniform_int(&rng);
return rng;
}
-STC_INLINE crandom32_t crandom32_init(uint64_t seed) {
- return crandom32_init2(seed, seed);
+STC_API uint32_t crandom32_uniform_int(crandom32_t* rng) {
+ uint64_t old = rng->state;
+ rng->state = old * 6364136223846793005ull + rng->inc;
+ uint32_t xos = ((old >> 18u) ^ old) >> 27u;
+ uint32_t rot = old >> 59u;
+ return (xos >> rot) | (xos << ((-rot) & 31));
}
+/* SFC64 random number generator: http://pracrand.sourceforge.net */
-/* Rotate bits left */
-STC_INLINE uint64_t c_rotateLeft64(uint64_t x, int bits) {
- return (x << bits) | (x >> (64 - bits));
+STC_API crandom64_t crandom64_uniform_engine(const uint64_t seed) {
+ crandom64_t state = {{seed, seed, seed, 1}};
+ for (int i = 0; i < 12; ++i) crandom64_uniform_int(&state);
+ return state;
}
-/*
- * SFC64 random number generator: http://pracrand.sourceforge.net
- */
-typedef struct {uint64_t state[4];} crandom64_t;
-
-STC_API uint64_t crandom64(crandom64_t* rng) {
+STC_API uint64_t crandom64_uniform_int(crandom64_t* rng) {
enum {LR=24, RS=11, LS=3};
uint64_t *s = rng->state;
const uint64_t result = s[0] + s[1] + s[3]++;
s[0] = s[1] ^ (s[1] >> RS);
s[1] = s[2] + (s[2] << LS);
- s[2] = c_rotateLeft64(s[2], LR) + result;
+ s[2] = (s[2] << LR) | (s[2] >> (64 - LR));
return result;
}
-/* float64 random int number in range [0, 1), 52 bit resolution */
-STC_INLINE double crandom64f(crandom64_t* rng) {
- union {uint64_t i; double f;} u = {0x3FF0000000000000ull | (crandom64(rng) >> 12)};
- return u.f - 1.0;
-}
-
-STC_API crandom64_t crandom64_init(const uint64_t seed) {
- crandom64_t state = {{seed, seed, seed, 1}};
- for (int i = 0; i < 12; ++i) crandom64(&state);
- return state;
-}
-
-/*
- * SipHash implementation.
- */
-#if defined(_WIN32) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
- STC_INLINE uint64_t c_le64ToHost(uint64_t x) { return x; }
-#elif defined(__APPLE__)
- #include <libkern/OSByteOrder.h>
- STC_INLINE uint64_t c_le64ToHost(uint64_t x) { return OSSwapLittleToHostInt64(x); }
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
- #include <sys/endian.h>
- STC_INLINE uint64_t c_le64ToHost(uint64_t x) { return letoh64(x); }
-#elif defined(__linux__) || defined(__CYGWIN__) || defined(__GNUC__) || defined(__GNU_LIBRARY__)
- #include <endian.h>
- STC_INLINE uint64_t c_le64ToHost(uint64_t x) { return le64toh(x); }
#endif
-typedef struct siphash_t {
- uint64_t v[4], padding;
- size_t length;
- int c, d;
-} siphash_t;
-
-/* c=2, d=4 or c=1, d=3 */
-STC_INLINE void siphash_init_c_d(siphash_t* s, const uint64_t key[2], const int c, const int d) {
- s->c = c;
- s->d = d;
- s->length = 0;
- s->padding = 0;
- s->v[0] = key[0] ^ 0x736f6d6570736575;
- s->v[1] = key[1] ^ 0x646f72616e646f6d;
- s->v[2] = key[0] ^ 0x6c7967656e657261;
- s->v[3] = key[1] ^ 0x7465646279746573;
-}
-
-/* default init 2-4 */
-STC_API siphash_t siphash_init(const uint64_t key[2]) {
- siphash_t state;
- siphash_init_c_d(&state, key, 2, 4);
- return state;
-}
-
-#define _siphash_halfRound(i, j, a, b, c, d) \
- (a += b, \
- c += d, \
- b = c_rotateLeft64(b, i) ^ a, \
- d = c_rotateLeft64(d, j) ^ c, \
- a = c_rotateLeft64(a, 32))
-
-#define _siphash_compress(rounds, v) \
- for (int r = 0; r < rounds; ++r) { \
- _siphash_halfRound(13, 16, v[0], v[1], v[2], v[3]); \
- _siphash_halfRound(17, 21, v[2], v[1], v[0], v[3]); \
- }
-
-#define _siphash_digest(rounds, v, m) { \
- const uint64_t _m = m; \
- v[3] ^= _m; \
- _siphash_compress(rounds, v); \
- v[0] ^= _m; \
- }
-
-STC_API void siphash_update(siphash_t* s, const void* bytes, size_t size) {
- union { const uint8_t* u8; const uint64_t* u64; } in;
- in.u8 = (const uint8_t*) bytes;
- size_t offset = s->length & 7;
- uint64_t *v = s->v;
- s->length += size;
-
- if (offset) {
- const size_t end = offset + size;
- size -= 8 - offset;
- while (offset < end && offset < 8) {
- s->padding |= ((uint64_t) *in.u8++) << (offset++ << 3);
- }
- if (end < 8) return;
-
- _siphash_digest(s->c, v, s->padding);
- s->padding = 0;
- }
- size_t n_words = size >> 3;
- uint64_t m;
-
- while (n_words--) {
- memcpy(&m, in.u64++, 8);
- _siphash_digest(s->c, v, c_le64ToHost(m));
- }
- switch (s->length & 7) {
- case 7: s->padding |= ((uint64_t) in.u8[6]) << 48;
- case 6: s->padding |= ((uint64_t) in.u8[5]) << 40;
- case 5: s->padding |= ((uint64_t) in.u8[4]) << 32;
- case 4: s->padding |= ((uint64_t) in.u8[3]) << 24;
- case 3: s->padding |= ((uint64_t) in.u8[2]) << 16;
- case 2: s->padding |= ((uint64_t) in.u8[1]) << 8;
- case 1: s->padding |= ((uint64_t) in.u8[0]);
- }
-}
-
-STC_API uint64_t siphash_finalize(siphash_t* s) {
- uint64_t *v = s->v;
- _siphash_digest(s->c, v, s->padding | (s->length << 56));
- v[2] ^= 0xff;
- _siphash_compress(s->d, v);
- return v[0] ^ v[1] ^ v[2] ^ v[3];
-}
-
-/* c=2, d=4 or c=1, d=3 */
-STC_API uint64_t siphash_hash_c_d(const uint64_t key[2], const void* bytes, const uint64_t size, const int c, const int d) {
- siphash_t state;
- siphash_init_c_d(&state, key, c, d);
- siphash_update(&state, bytes, size);
- return siphash_finalize(&state);
-}
-
-/* default hash 2-4 */
-STC_INLINE uint64_t siphash_hash(const uint64_t key[2], const void* bytes, const uint64_t size) {
- return siphash_hash_c_d(key, bytes, size, 2, 4);
-}
-
#endif
diff --git a/stc/cvecpq.h b/stc/cvecpq.h
index 3256f98a..f78adf04 100644
--- a/stc/cvecpq.h
+++ b/stc/cvecpq.h
@@ -28,11 +28,11 @@
declare_cvec(i, int);
declare_cvec_priority_queue(i, >); // min-heap (increasing values)
int main() {
- pcg32_random_t pcg = pcg32_seed(1234, 0);
+ crandom32_t pcg = crandom32_uniform_engine(1234);
cvec_i heap = cvec_init;
// Push one million random numbers onto the queue.
for (int i=0; i<1000000; ++i)
- cvecpq_i_push(&heap, pcg32_random(&pcg));
+ cvecpq_i_push(&heap, crandom32_uniform_int(&pcg));
// Extract the 100 smallest.
for (int i=0; i<100; ++i) {
printf("%d ", cvecpq_i_top(&heap));