Basic structure for V2

This commit is contained in:
Leonardo Vencovsky committed 2023-01-06 21:56:35 +01:00
1 parent 9cadaeea85
commit 2c9759e5ec
213 files changed
+3305 -66141

No files matched your search

@@ -1,62 +0,0 @@
#ifndef COUNT
#error "Please define COUNT"
#endif
#include "murmurhash.h"
#include "macro_collections.h"
#include "../../util/twister.c"
CMC_CMC_HASHMAP_CORE(PUBLIC, HEADER, (hm, hashmap, , uint64_t, uint64_t))
CMC_CMC_HASHMAP_CORE(PUBLIC, SOURCE, (hm, hashmap, , uint64_t, uint64_t))
int cmp(uint64_t a, uint64_t b)
{
return (a > b) - (a < b);
}
// size_t hash(uint64_t a)
// {
// size_t x = (size_t)a;
// x = ((x >> 16) ^ x) * 0x45d9f3b;
// x = ((x >> 16) ^ x) * 0x45d9f3b;
// x = (x >> 16) ^ x;
// return x;
// }
size_t hash(uint64_t k)
{
static size_t seed = 211106232532969;
return MurMurHash(&k, sizeof(k), seed);
}
struct hashmap_fkey *fkey = &(struct hashmap_fkey) {
.cmp = cmp,
.hash = hash,
NULL
};
struct hashmap_fval *fval = &(struct hashmap_fval) {
.cmp = cmp,
.hash = hash,
NULL
};
int main(void)
{
mt_state tw;
twist_init(&tw, 50331653);
struct hashmap *map = hm_new(COUNT, 0.6, fkey, fval);
for (uint64_t i = 0; i < COUNT; i++)
{
uint64_t v = twist_uint64(&tw);
hm_insert(map, v, v);
}
hm_free(map);
return 0;
}
@@ -1,62 +0,0 @@
#ifndef COUNT
#error "Please define COUNT"
#endif
#include "murmurhash.h"
#include "macro_collections.h"
#include "../../util/twister.c"
CMC_CMC_HASHMULTIMAP_CORE(PUBLIC, HEADER, (hmm, hashmultimap, , uint64_t, uint64_t))
CMC_CMC_HASHMULTIMAP_CORE(PUBLIC, SOURCE, (hmm, hashmultimap, , uint64_t, uint64_t))
int cmp(uint64_t a, uint64_t b)
{
return (a > b) - (a < b);
}
// size_t hash(uint64_t a)
// {
// size_t x = (size_t)a;
// x = ((x >> 16) ^ x) * 0x45d9f3b;
// x = ((x >> 16) ^ x) * 0x45d9f3b;
// x = (x >> 16) ^ x;
// return x;
// }
size_t hash(uint64_t k)
{
static size_t seed = 211106232532969;
return MurMurHash(&k, sizeof(k), seed);
}
struct hashmultimap_fkey *fkey = &(struct hashmultimap_fkey) {
.cmp = cmp,
.hash = hash,
NULL
};
struct hashmultimap_fval *fval = &(struct hashmultimap_fval) {
.cmp = cmp,
.hash = hash,
NULL
};
int main(void)
{
mt_state tw;
twist_init(&tw, 50331653);
struct hashmultimap *map = hmm_new(COUNT, 0.6, fkey, fval);
for (uint64_t i = 0; i < COUNT; i++)
{
uint64_t v = twist_uint64(&tw);
hmm_insert(map, v, v);
}
hmm_free(map);
return 0;
}
@@ -1,58 +0,0 @@
// https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/hash_bytes.cc
#ifndef MURMURHASH
#define MURMURHASH
#include <string.h>
inline size_t unaligned_load(const char *p)
{
size_t result;
memcpy(&result, p, sizeof(result));
return result;
}
inline size_t load_bytes(const char *p, int n)
{
size_t result = 0;
--n;
do
{
result = (result << 8) + (unsigned char)(p[n]);
} while (--n >= 0);
return result;
}
inline size_t shift_mix(size_t v)
{
return v ^ (v >> 47);
}
size_t MurMurHash(const void *ptr, size_t len, size_t seed)
{
static const size_t mul = (((size_t)0xc6a4a793UL) << 32UL) + (size_t)0x5bd1e995UL;
const char *const buf = (const char *)(ptr);
// Remove the bytes not divisible by the sizeof(size_t). This
// allows the main loop to process the data as 64-bit integers.
const size_t len_aligned = len & ~(size_t)0x7;
const char *const end = buf + len_aligned;
size_t hash = seed ^ (len * mul);
for (const char *p = buf; p != end; p += 8)
{
const size_t data = shift_mix(unaligned_load(p) * mul) * mul;
hash ^= data;
hash *= mul;
}
if ((len & 0x7) != 0)
{
const size_t data = load_bytes(end, len & 0x7);
hash ^= data;
hash *= mul;
}
hash = shift_mix(hash) * mul;
hash = shift_mix(hash);
return hash;
}
#endif /* MURMURHASH */
@@ -1,57 +0,0 @@
import os
import sys
import time
import subprocess
ITERATIONS = 10
COUNT = 20000000
VERBOSE = False
NL = '\n'
INCLUDE = "../../../src"
CC = 'gcc'
CCPP = 'g++' # LoL
OPT = '-O3'
print(f'Using {CC} compiler')
def execute_command(commands):
print(' '.join(commands))
subprocess.run(commands, shell=True)
# Common args
args = ['-I', INCLUDE, OPT, f'-DCOUNT={COUNT}', '-DCMC_NO_CALLBACKS']
map_args = [CC, 'hashmap.c', '-o', 'hashmap.exe']
mmap_args = [CC, 'hashmultimap.c', '-o', 'hashmultimap.exe']
cpp_args = [CCPP, 'unorderedmap.cpp', '-I', INCLUDE, '-o', 'unorderedmap.exe', OPT, f'-DCOUNT={COUNT}']
map_args.extend(args)
mmap_args.extend(args)
cpp_args.extend(args)
execute_command(map_args)
execute_command(mmap_args)
execute_command(cpp_args)
programs = ['hashmap.exe', 'hashmultimap.exe', 'unorderedmap.exe']
for prog in programs:
total = 0
for i in range(ITERATIONS):
print(f'{i}...', end='')
sys.stdout.flush()
start_time = time.time()
subprocess.run(prog, shell=True)
delta = time.time() - start_time
total += delta
if VERBOSE:
print(f'({delta})')
avg = total / ITERATIONS
print(f'{"" if VERBOSE else NL}{avg} seconds for {COUNT} -> AVG[{int((avg * 1e9) / COUNT)} ns] [{prog}]{NL if VERBOSE else ""}')
@@ -1,34 +0,0 @@
#ifndef COUNT
#error "Please define COUNT"
#endif
#include "murmurhash.h"
#include <unordered_map>
#include "../../util/twister.c"
struct IntHasher
{
std::size_t operator()(const uint64_t& k) const
{
static size_t seed = 211106232532969;
return MurMurHash(&k, sizeof(k), seed);
}
};
int main(void)
{
mt_state tw;
twist_init(&tw, 50331653);
std::unordered_map<uint64_t, uint64_t, IntHasher> map(COUNT);
for (uint64_t i = 0; i < COUNT; i++)
{
uint64_t v = twist_uint64(&tw);
map.insert({v, v});
}
return 0;
}
-253
View File
@@ -1,253 +0,0 @@
/**
* benchmark.c
*
* Creation Date: 13/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Benchmarks:
* - Input
* - Search
* - Iteration
* - Output
*/
#include "macro_collections.h"
#include "util/twister.c"
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <math.h>
#include <inttypes.h>
#define NTOTAL UINT64_C(10000000)
#define NMIN UINT64_C(100)
// Percentage % macro
#define PC(x) x * 100.0
static int intcmp(int a, int b)
{
return a - b;
}
static size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
size_t randsize(size_t min, size_t max, mt_state_ptr st)
{
return (size_t)floor(twist_real(st) * ((double)max - (double)min + 1.0) + (double)min);
}
void shuffle(int *array, mt_state_ptr st)
{
for (size_t i = 0; i < NTOTAL; i++)
{
size_t j = randsize(0, NTOTAL - 1, st);
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int)
CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int)
CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int)
CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int)
CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int)
CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int)
CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int)
CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int)
CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* k */, int)
CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int)
CMC_COLLECTION_GENERATE(MULTISET, ms, mset, /* K */, int)
#define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, searchbody) \
void NAME##_io_benchmark(int *array, int *sarray, size_t s) \
{ \
printf("+------------------------------------------------------------ %10s\n", #NAME); \
printf("+------------------------------------------------------------ \n"); \
struct cmc_timer timer, total; \
int r, k, v; \
size_t j; \
\
struct sname *coll = initfunc; \
\
cmc_timer_start(total); \
cmc_timer_start(timer); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
insertbody; \
} \
\
cmc_timer_stop(timer); \
\
cmc_timer_calc(timer); \
\
size_t s1 = PFX##_count(coll); \
\
printf(" INPUT %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double input_time = timer.result; \
\
cmc_timer_start(timer); \
\
for (size_t i = 0; i < s; i++) \
{ \
searchbody; \
} \
\
cmc_timer_stop(timer); \
\
cmc_timer_calc(timer); \
\
printf(" SEARCH %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s); \
\
double search_time = timer.result; \
\
struct sname##_iter iter; \
\
cmc_timer_start(timer); \
\
for (PFX##_iter_init(&iter, coll); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
} \
\
cmc_timer_stop(timer); \
\
cmc_timer_calc(timer); \
\
printf("ITERATION %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double iter_time = timer.result; \
\
cmc_timer_start(timer); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
removebody; \
} \
\
cmc_timer_stop(timer); \
\
cmc_timer_calc(timer); \
\
size_t s2 = PFX##_count(coll); \
\
printf(" OUTPUT %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double output_time = timer.result; \
\
cmc_timer_stop(total); \
cmc_timer_calc(total); \
\
PFX##_free(coll, NULL); \
\
double adj_search_time = (total.result - search_time) + (search_time * (double)NTOTAL) / (double)s; \
double no_search = input_time + iter_time + output_time; \
\
printf("+------------------------------------------------------------ \n"); \
printf("TOTAL TIME : %.0lf milliseconds\n", total.result); \
printf("ADJUSTED TIME : %.0lf milliseconds\n", adj_search_time); \
\
printf("+------------------------------------------------------------ \n"); \
printf(" INPUT : %5.2lf%% (%5.2f%%)\n", PC(input_time / total.result), PC(input_time / no_search)); \
printf(" SEARCH : %5.2lf%%\n", PC(search_time / total.result)); \
printf("ITERATION : %5.2lf%% (%5.2f%%)\n", PC(iter_time / total.result), PC(iter_time / no_search)); \
printf(" OUTPUT : %5.2lf%% (%5.2f%%)\n", PC(output_time / total.result), PC(output_time / no_search)); \
printf("+------------------------------------------------------------ \n"); \
\
assert(s1 == NTOTAL && s2 == 0); \
\
printf("+------------------------------------------------------------ %10s\n\n", #NAME); \
}
BENCHMARK(DEQUE, d, deque, d_new(NTOTAL), d_push_back(coll, array[i]), d_pop_back(coll), d_contains(coll, sarray[i], intcmp))
BENCHMARK(HASHMAP, hm, hmap, hm_new(NTOTAL, 0.6, intcmp, inthash), hm_insert(coll, array[i], array[i]), hm_remove(coll, array[i], &r), hm_contains(coll, sarray[i]))
BENCHMARK(HASHSET, hs, hset, hs_new(NTOTAL, 0.6, intcmp, inthash), hs_insert(coll, array[i]), hs_remove(coll, array[i]), hs_contains(coll, sarray[i]))
BENCHMARK(HEAP, h, heap, h_new(NTOTAL, cmc_min_heap, intcmp), h_insert(coll, array[i]), h_remove(coll, &r), h_contains(coll, sarray[i]))
BENCHMARK(LINKEDLIST, ll, linked, ll_new(), ll_push_back(coll, array[i]), ll_pop_back(coll), ll_contains(coll, sarray[i], intcmp))
BENCHMARK(LIST, l, list, l_new(NTOTAL), l_push_back(coll, array[i]), l_pop_back(coll), l_contains(coll, sarray[i], intcmp))
BENCHMARK(QUEUE, q, queue, q_new(NTOTAL), q_enqueue(coll, array[i]), q_dequeue(coll), q_contains(coll, sarray[i], intcmp))
BENCHMARK(STACK, s, stack, s_new(NTOTAL), s_push(coll, array[i]), s_pop(coll), s_contains(coll, sarray[i], intcmp))
BENCHMARK(TREEMAP, tm, tmap, tm_new(intcmp), tm_insert(coll, array[i], array[i]), tm_remove(coll, array[i], &r), tm_contains(coll, sarray[i]))
BENCHMARK(TREESET, ts, tset, ts_new(intcmp), ts_insert(coll, array[i]), ts_remove(coll, array[i]), ts_contains(coll, sarray[i]))
BENCHMARK(INTERVALHEAP, ih, iheap, ih_new(NTOTAL, intcmp), ih_insert(coll, array[i]), ih_remove_max(coll, &r), ih_contains(coll, sarray[i]))
BENCHMARK(MULTIMAP, mm, mmap, mm_new(NTOTAL, 0.8, intcmp, inthash), mm_insert(coll, array[i], array[i]), mm_remove(coll, array[i], &r), mm_contains(coll, sarray[i]))
BENCHMARK(MULTISET, ms, mset, ms_new(NTOTAL, 0.6, intcmp, inthash), ms_insert(coll, array[i]), ms_remove(coll, array[i]), ms_contains(coll, sarray[i]))
int main(void)
{
// Using the Mersenne Twister to generate random numbers. This seed
// guarantees that everytime this program runs it will generate the same
// random numbers. The random numbers influence on the shuffling of the
// array.
mt_state st;
twist_init(&st, UINT64_C(12604951237));
int *array = malloc(NTOTAL * sizeof(int));
int *sarray = malloc(NTOTAL * sizeof(int));
if (!array)
{
printf("Allocation failed\n");
return 1;
}
for (int i = -5000000; i < 5000000; i++)
array[i + 5000000] = i;
shuffle(array, &st);
memcpy(sarray, array, NTOTAL * sizeof(int));
shuffle(sarray, &st);
printf("\nNote: Adjusted Time refers to if the container had done a search over all %" PRIuMAX " elements.\n\n", NTOTAL);
// Linear containers have to search for NMIN elements and non-linear (hash
// and tree) have to search for all elements.
struct cmc_timer timer;
cmc_timer_start(timer);
DEQUE_io_benchmark(array, sarray, NMIN);
HASHMAP_io_benchmark(array, sarray, NTOTAL);
HASHSET_io_benchmark(array, sarray, NTOTAL);
HEAP_io_benchmark(array, sarray, NMIN);
LINKEDLIST_io_benchmark(array, sarray, NMIN);
LIST_io_benchmark(array, sarray, NMIN);
QUEUE_io_benchmark(array, sarray, NMIN);
STACK_io_benchmark(array, sarray, NMIN);
TREEMAP_io_benchmark(array, sarray, NTOTAL);
TREESET_io_benchmark(array, sarray, NTOTAL);
INTERVALHEAP_io_benchmark(array, array, NMIN);
MULTIMAP_io_benchmark(array, array, NTOTAL);
MULTISET_io_benchmark(array, array, NTOTAL);
cmc_timer_stop(timer);
cmc_timer_calc(timer);
printf("+-----------------------------------------------------------+ \n");
printf("| Total Benchmark Running Time : %12.0lf seconds | \n", timer.result / 1000);
printf("+-----------------------------------------------------------+ \n");
free(array);
free(sarray);
return 0;
}
-2
View File
@@ -1,2 +0,0 @@
main:
gcc compile_time.c -c -O3 -ftime-report -I ../../src
-178
View File
@@ -1,178 +0,0 @@
/* Compilation time for over 90 collections */
#include <macro_collections.h>
struct imaginary
{
double real;
double imag;
};
enum app_state
{
TRACE = 1,
DEBUG = 2,
INFO = 3,
WARN = 4,
ERROR = 5,
FATAL = 6
};
CMC_COLLECTION_GENERATE(BIDIMAP, bd0, bidimap0, struct imaginary, struct imaginary)
CMC_COLLECTION_GENERATE(DEQUE, d0, deque0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(HASHMAP, hm0, hmap0, struct imaginary, struct imaginary)
CMC_COLLECTION_GENERATE(HASHSET, hs0, hset0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(HEAP, h0, heap0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih0, iheap0, struct imaginary, struct imaginary)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(LIST, l0, list0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(MULTIMAP, mm0, mmap0, struct imaginary, struct imaginary)
CMC_COLLECTION_GENERATE(MULTISET, ms0, mset0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(STACK, s0, stack0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl0, sotredlist0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(QUEUE, q0, queue0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(TREESET, ts0, tset0, /* K */, struct imaginary)
CMC_COLLECTION_GENERATE(TREEMAP, tm0, tmap0, struct imaginary, struct imaginary)
CMC_COLLECTION_GENERATE(BIDIMAP, bd1, bidimap1, int, int)
CMC_COLLECTION_GENERATE(DEQUE, d1, deque1, /* K */, int)
CMC_COLLECTION_GENERATE(HASHMAP, hm1, hmap1, int, int)
CMC_COLLECTION_GENERATE(HASHSET, hs1, hset1, /* K */, int)
CMC_COLLECTION_GENERATE(HEAP, h1, heap1, /* K */, int)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih1, iheap1, int, int)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, /* K */, int)
CMC_COLLECTION_GENERATE(LIST, l1, list1, /* K */, int)
CMC_COLLECTION_GENERATE(MULTIMAP, mm1, mmap1, int, int)
CMC_COLLECTION_GENERATE(MULTISET, ms1, mset1, /* K */, int)
CMC_COLLECTION_GENERATE(STACK, s1, stack1, /* K */, int)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl1, sotredlist1, /* K */, int)
CMC_COLLECTION_GENERATE(QUEUE, q1, queue1, /* K */, int)
CMC_COLLECTION_GENERATE(TREESET, ts1, tset1, /* K */, int)
CMC_COLLECTION_GENERATE(TREEMAP, tm1, tmap1, int, int)
CMC_COLLECTION_GENERATE(BIDIMAP, bd2, bidimap2, double, double)
CMC_COLLECTION_GENERATE(DEQUE, d2, deque2, /* K */, double)
CMC_COLLECTION_GENERATE(HASHMAP, hm2, hmap2, double, double)
CMC_COLLECTION_GENERATE(HASHSET, hs2, hset2, /* K */, double)
CMC_COLLECTION_GENERATE(HEAP, h2, heap2, /* K */, double)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih2, iheap2, double, double)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, /* K */, double)
CMC_COLLECTION_GENERATE(LIST, l2, list2, /* K */, double)
CMC_COLLECTION_GENERATE(MULTIMAP, mm2, mmap2, double, double)
CMC_COLLECTION_GENERATE(MULTISET, ms2, mset2, /* K */, double)
CMC_COLLECTION_GENERATE(STACK, s2, stack2, /* K */, double)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl2, sotredlist2, /* K */, double)
CMC_COLLECTION_GENERATE(QUEUE, q2, queue2, /* K */, double)
CMC_COLLECTION_GENERATE(TREESET, ts2, tset2, /* K */, double)
CMC_COLLECTION_GENERATE(TREEMAP, tm2, tmap2, double, double)
CMC_COLLECTION_GENERATE(BIDIMAP, bd3, bidimap3, size_t, size_t)
CMC_COLLECTION_GENERATE(DEQUE, d3, deque3, /* K */, size_t)
CMC_COLLECTION_GENERATE(HASHMAP, hm3, hmap3, size_t, size_t)
CMC_COLLECTION_GENERATE(HASHSET, hs3, hset3, /* K */, size_t)
CMC_COLLECTION_GENERATE(HEAP, h3, heap3, /* K */, size_t)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih3, iheap3, size_t, size_t)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, /* K */, size_t)
CMC_COLLECTION_GENERATE(LIST, l3, list3, /* K */, size_t)
CMC_COLLECTION_GENERATE(MULTIMAP, mm3, mmap3, size_t, size_t)
CMC_COLLECTION_GENERATE(MULTISET, ms3, mset3, /* K */, size_t)
CMC_COLLECTION_GENERATE(STACK, s3, stack3, /* K */, size_t)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl3, sotredlist3, /* K */, size_t)
CMC_COLLECTION_GENERATE(QUEUE, q3, queue3, /* K */, size_t)
CMC_COLLECTION_GENERATE(TREESET, ts3, tset3, /* K */, size_t)
CMC_COLLECTION_GENERATE(TREEMAP, tm3, tmap3, size_t, size_t)
CMC_COLLECTION_GENERATE(BIDIMAP, bd4, bidimap4, enum app_state, enum app_state)
CMC_COLLECTION_GENERATE(DEQUE, d4, deque4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(HASHMAP, hm4, hmap4, enum app_state, enum app_state)
CMC_COLLECTION_GENERATE(HASHSET, hs4, hset4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(HEAP, h4, heap4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih4, iheap4, enum app_state, enum app_state)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(LIST, l4, list4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(MULTIMAP, mm4, mmap4, enum app_state, enum app_state)
CMC_COLLECTION_GENERATE(MULTISET, ms4, mset4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(STACK, s4, stack4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl4, sotredlist4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(QUEUE, q4, queue4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(TREESET, ts4, tset4, /* K */, enum app_state)
CMC_COLLECTION_GENERATE(TREEMAP, tm4, tmap4, enum app_state, enum app_state)
CMC_COLLECTION_GENERATE(BIDIMAP, bd5, bidimap5, void *, void *)
CMC_COLLECTION_GENERATE(DEQUE, d5, deque5, /* K */, void *)
CMC_COLLECTION_GENERATE(HASHMAP, hm5, hmap5, void *, void *)
CMC_COLLECTION_GENERATE(HASHSET, hs5, hset5, /* K */, void *)
CMC_COLLECTION_GENERATE(HEAP, h5, heap5, /* K */, void *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih5, iheap5, void *, void *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, /* K */, void *)
CMC_COLLECTION_GENERATE(LIST, l5, list5, /* K */, void *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm5, mmap5, void *, void *)
CMC_COLLECTION_GENERATE(MULTISET, ms5, mset5, /* K */, void *)
CMC_COLLECTION_GENERATE(STACK, s5, stack5, /* K */, void *)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl5, sotredlist5, /* K */, void *)
CMC_COLLECTION_GENERATE(QUEUE, q5, queue5, /* K */, void *)
CMC_COLLECTION_GENERATE(TREESET, ts5, tset5, /* K */, void *)
CMC_COLLECTION_GENERATE(TREEMAP, tm5, tmap5, void *, void *)
CMC_COLLECTION_GENERATE(BIDIMAP, bd6, bidimap6, int *, int *)
CMC_COLLECTION_GENERATE(DEQUE, d6, deque6, /* K */, int *)
CMC_COLLECTION_GENERATE(HASHMAP, hm6, hmap6, int *, int *)
CMC_COLLECTION_GENERATE(HASHSET, hs6, hset6, /* K */, int *)
CMC_COLLECTION_GENERATE(HEAP, h6, heap6, /* K */, int *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih6, iheap6, int *, int *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, /* K */, int *)
CMC_COLLECTION_GENERATE(LIST, l6, list6, /* K */, int *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm6, mmap6, int *, int *)
CMC_COLLECTION_GENERATE(MULTISET, ms6, mset6, /* K */, int *)
CMC_COLLECTION_GENERATE(STACK, s6, stack6, /* K */, int *)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl6, sotredlist6, /* K */, int *)
CMC_COLLECTION_GENERATE(QUEUE, q6, queue6, /* K */, int *)
CMC_COLLECTION_GENERATE(TREESET, ts6, tset6, /* K */, int *)
CMC_COLLECTION_GENERATE(TREEMAP, tm6, tmap6, int *, int *)
CMC_COLLECTION_GENERATE(BIDIMAP, bd7, bidimap7, struct imaginary *, struct imaginary *)
CMC_COLLECTION_GENERATE(DEQUE, d7, deque7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(HASHMAP, hm7, hmap7, struct imaginary *, struct imaginary *)
CMC_COLLECTION_GENERATE(HASHSET, hs7, hset7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(HEAP, h7, heap7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih7, iheap7, struct imaginary *, struct imaginary *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(LIST, l7, list7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm7, mmap7, struct imaginary *, struct imaginary *)
CMC_COLLECTION_GENERATE(MULTISET, ms7, mset7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(STACK, s7, stack7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl7, sotredlist7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(QUEUE, q7, queue7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(TREESET, ts7, tset7, /* K */, struct imaginary *)
CMC_COLLECTION_GENERATE(TREEMAP, tm7, tmap7, struct imaginary *, struct imaginary *)
CMC_COLLECTION_GENERATE(BIDIMAP, bd8, bidimap8, double *, double *)
CMC_COLLECTION_GENERATE(DEQUE, d8, deque8, /* K */, double *)
CMC_COLLECTION_GENERATE(HASHMAP, hm8, hmap8, double *, double *)
CMC_COLLECTION_GENERATE(HASHSET, hs8, hset8, /* K */, double *)
CMC_COLLECTION_GENERATE(HEAP, h8, heap8, /* K */, double *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih8, iheap8, double *, double *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, /* K */, double *)
CMC_COLLECTION_GENERATE(LIST, l8, list8, /* K */, double *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm8, mmap8, double *, double *)
CMC_COLLECTION_GENERATE(MULTISET, ms8, mset8, /* K */, double *)
CMC_COLLECTION_GENERATE(STACK, s8, stack8, /* K */, double *)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl8, sotredlist8, /* K */, double *)
CMC_COLLECTION_GENERATE(QUEUE, q8, queue8, /* K */, double *)
CMC_COLLECTION_GENERATE(TREESET, ts8, tset8, /* K */, double *)
CMC_COLLECTION_GENERATE(TREEMAP, tm8, tmap8, double *, double *)
CMC_COLLECTION_GENERATE(BIDIMAP, bd9, bidimap9, enum app_state *, enum app_state *)
CMC_COLLECTION_GENERATE(DEQUE, d9, deque9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(HASHMAP, hm9, hmap9, enum app_state *, enum app_state *)
CMC_COLLECTION_GENERATE(HASHSET, hs9, hset9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(HEAP, h9, heap9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih9, iheap9, enum app_state *, enum app_state *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(LIST, l9, list9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm9, mmap9, enum app_state *, enum app_state *)
CMC_COLLECTION_GENERATE(MULTISET, ms9, mset9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(STACK, s9, stack9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(SORTEDLIST, sl9, sotredlist9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(QUEUE, q9, queue9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(TREESET, ts9, tset9, /* K */, enum app_state *)
CMC_COLLECTION_GENERATE(TREEMAP, tm9, tmap9, enum app_state *, enum app_state *)
-433
View File
@@ -1,433 +0,0 @@
#include <macro_collections.h>
/**
* HashMap, MultiMap and BidiMap use hashtables with different strategies. This
* benchmark is aimed to explore the pros and cons of each implementation.
*
* HashMap - A plain hashtable with no indirection using linear probing and
* robin hood hashing.
* Expectations:
* - Constant memory usage which leads to high memory usage per element
* ratio when the hashtable has few elements but the ratio is
* somewhat good as it starts to fill up;
* - Faster lookup due to no indirection and good caching;
* - Faster insertion and removal due to no calls to free or malloc.
*
* MultiMap - A hashtable using separate chaining where each bucket is a doubly
* linked list.
* Expectations:
* - High memory usage per element ratio due to the double linked
* lists;
* - Pointer indirection might lead to slower lookup and poor caching
* due to using nodes to store the key and the value;
* - A bit slower insertion and removal as calls to free and malloc are
* needed.
*
* BidiMap - Two arrays, one representing the key set and one the value set.
* Each array is made of pointers to an entry. This way one entry can
* be referenced by both the key set and the value set using only one
* node. Uses robin hood hashing to adjust the pointers.
* Expectations:
* - Overrall low memory usage compared to other implementations;
* - Pointer indirection might lead to slower lookupand poor caching
* due to using nodes to store the key and the value;
* - Very slow insertion and removal as a node needs to be added or
* removed on both arrays.
*/
/* Generate Code */
CMC_COLLECTION_GENERATE(HASHMAP, hmap, hmap, int, int)
CMC_COLLECTION_GENERATE(MULTIMAP, mmap, mmap, int, int)
CMC_COLLECTION_GENERATE(BIDIMAP, bmap, bmap, int, int)
/* Forward declaration of benchmarks */
void benchmark_bidimap(const char *collection, int total_elements,
double load_factor);
void benchmark_hashmap(const char *collection, int total_elements,
double load_factor);
void benchmark_multimap(const char *collection, int total_elements,
double load_factor);
/* Comparator and Hash function */
int cmp(int a, int b)
{
return a - b;
}
size_t hash(int a)
{
size_t x = (size_t)a;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = (x >> 16) ^ x;
return x;
}
/* Custom allocators to count memory usage */
size_t total_memory = 0;
/* Report Functions */
void print_overview(const char *collection, int total_elements,
double load_factor)
{
printf("Overview\n"
" Collection : %s\n"
" Total Elements : %d\n"
" Load Factor : %.4lf\n\n",
collection, total_elements, load_factor);
}
void print_time(const char *collection, double C, double R, double U, double D)
{
/* C - Create, R - Read, U - Update, D - Delete */
printf("Time [%s]: \n"
" Total : %8.0lf milliseconds \n"
" Create : %8.0lf milliseconds\n"
" Read : %8.0lf milliseconds\n"
" Update : %8.0lf milliseconds\n"
" Delete : %8.0lf milliseconds\n\n",
collection, C + R + U + D, C, R, U, D);
}
void print_memory(const char *s, size_t memory[11], int partition_size)
{
printf("Each Partition : %d elements\n\n", partition_size);
for (size_t i = 0; i < 11; i++)
{
printf(" %3" PRIuMAX "%% : %12" PRIuMAX " B | %10" PRIuMAX " kB | %8" PRIuMAX " MB (+ %2.0lf%%)\n",
i * 10, memory[i], memory[i] / 1000, memory[i] / 1000000, (1 - ((double)memory[0] / (double)memory[i])) * 100.0);
}
}
/* Custom allocation functions */
void *my_malloc(size_t size)
{
void *result = malloc(size);
if (result)
total_memory += size;
return result;
}
void *my_calloc(size_t count, size_t size)
{
void *result = calloc(count, size);
if (result)
total_memory += count * size;
return result;
}
void *my_realloc(void *buffer, size_t size)
{
/* This assumes that this benchmark never uses realloc */
return realloc(buffer, size);
}
void my_free(void *block)
{
free(block);
}
/* Default custom allocation node */
struct cmc_alloc_node alloc_default = { .malloc = my_malloc,
.calloc = my_calloc,
.realloc = my_realloc,
.free = my_free };
int main(int argc, char const *argv[])
{
if (argc != 4)
{
fprintf(
stderr,
"Usage:\n"
" %s collection_name total_elements load_factor\n"
"\nOPTIONS\n"
" - collection_name : (BIDIMAP|HASHMAP|MULTIMAP|ALL)\n"
" - total_elements : Total elements to be added to the hashtable (int > 0)\n"
" - load_factor : The hashtable's load factor (0 < l < 1.0)\n",
argv[0]);
return 1;
}
int total_elements = atoi(argv[2]);
double load_factor = atof(argv[3]);
bool error = false;
if (total_elements < 1)
{
error = true;
fprintf(stderr, "Invalid value for total_elements: %s\n", argv[2]);
}
if (load_factor <= 0.0 || load_factor >= 1.0)
{
error = true;
fprintf(stderr, "Invalid value for load_factor: %s\n", argv[3]);
}
if (error)
return 1;
const char *collection = argv[1];
if (strcmp(collection, "BIDIMAP") == 0)
{
benchmark_bidimap(collection, total_elements, load_factor);
}
else if (strcmp(collection, "HASHMAP") == 0)
{
benchmark_hashmap(collection, total_elements, load_factor);
}
else if (strcmp(collection, "MULTIMAP") == 0)
{
benchmark_multimap(collection, total_elements, load_factor);
}
else if (strcmp(collection, "ALL") == 0)
{
benchmark_bidimap("BIDIMAP", total_elements, load_factor);
benchmark_hashmap("HASHMAP", total_elements, load_factor);
benchmark_multimap("MULTIMAP", total_elements, load_factor);
}
else
{
fprintf(stderr, "Unknown parameter collection_name = %s\n", collection);
return 1;
}
return 0;
}
void benchmark_bidimap(const char *collection, int total_elements,
double load_factor)
{
printf("--------------------------------------------------------------------------------\n");
total_memory = 0;
/* Normalize total_elements to be a multiple of 10 and calculate partition size */
total_elements = total_elements % 10 == 0 ? total_elements : total_elements + (10 - total_elements % 10);
int partition = total_elements / 10;
print_overview(collection, total_elements, load_factor);
struct bmap *map = bmap_new_custom(total_elements, load_factor, cmp, hash,
cmp, hash, &alloc_default, NULL);
/* Create, Read, Update, Delete */
struct cmc_timer timers[4] = { 0 };
/* Memory Usage 0%, 10%, 20%, ... 100% */
size_t memory[11] = {0};
memory[0] = total_memory;
/* Create */
cmc_timer_start(timers[0]);
for (int i = 0; i < 10; i++)
{
for (int j = partition * i; j < partition * (i + 1); j++)
{
bmap_insert(map, j, j);
}
memory[i + 1] = total_memory;
}
cmc_timer_stop(timers[0]);
cmc_timer_calc(timers[0]);
/* Create End */
/* Read */
cmc_timer_start(timers[1]);
for (int i = 0; i < total_elements; i++)
bmap_contains_key(map, i);
cmc_timer_stop(timers[1]);
cmc_timer_calc(timers[1]);
/* Read End */
/* Update */
cmc_timer_start(timers[2]);
for (int i = 0; i < total_elements; i++)
bmap_update_val_by_key(map, i, total_elements - i - 1);
cmc_timer_stop(timers[2]);
cmc_timer_calc(timers[2]);
/* Update End */
/* Delete */
cmc_timer_start(timers[3]);
for (int i = 0; i < total_elements; i++)
bmap_remove_by_key(map, i, NULL, NULL);
cmc_timer_stop(timers[3]);
cmc_timer_calc(timers[3]);
/* Delete End */
print_time(collection, timers[0].result, timers[1].result, timers[2].result,
timers[3].result);
print_memory(collection, memory, partition);
bmap_free(map, NULL);
printf("--------------------------------------------------------------------------------\n");
}
void benchmark_hashmap(const char *collection, int total_elements,
double load_factor)
{
printf("--------------------------------------------------------------------------------\n");
total_memory = 0;
/* Normalize total_elements to be a multiple of 10 and calculate partition size */
total_elements = total_elements % 10 == 0 ? total_elements : total_elements + (10 - total_elements % 10);
int partition = total_elements / 10;
print_overview(collection, total_elements, load_factor);
struct hmap *map = hmap_new_custom(total_elements, load_factor, cmp, hash, &alloc_default, NULL);
/* Create, Read, Update, Delete */
struct cmc_timer timers[4] = { 0 };
/* Memory Usage 0%, 10%, 20%, ... 100% */
size_t memory[11] = {0};
memory[0] = total_memory;
/* Create */
cmc_timer_start(timers[0]);
for (int i = 0; i < 10; i++)
{
for (int j = partition * i; j < partition * (i + 1); j++)
{
hmap_insert(map, j, j);
}
memory[i + 1] = total_memory;
}
cmc_timer_stop(timers[0]);
cmc_timer_calc(timers[0]);
/* Create End */
/* Read */
cmc_timer_start(timers[1]);
for (int i = 0; i < total_elements; i++)
hmap_contains(map, i);
cmc_timer_stop(timers[1]);
cmc_timer_calc(timers[1]);
/* Read End */
/* Update */
cmc_timer_start(timers[2]);
for (int i = 0; i < total_elements; i++)
hmap_update(map, i, total_elements - i - 1, NULL);
cmc_timer_stop(timers[2]);
cmc_timer_calc(timers[2]);
/* Update End */
/* Delete */
cmc_timer_start(timers[3]);
for (int i = 0; i < total_elements; i++)
hmap_remove(map, i, NULL);
cmc_timer_stop(timers[3]);
cmc_timer_calc(timers[3]);
/* Delete End */
print_time(collection, timers[0].result, timers[1].result, timers[2].result,
timers[3].result);
print_memory(collection, memory, partition);
hmap_free(map, NULL);
printf("--------------------------------------------------------------------------------\n");
}
void benchmark_multimap(const char *collection, int total_elements,
double load_factor)
{
printf("--------------------------------------------------------------------------------\n");
total_memory = 0;
/* Normalize total_elements to be a multiple of 10 and calculate partition size */
total_elements = total_elements % 10 == 0 ? total_elements : total_elements + (10 - total_elements % 10);
int partition = total_elements / 10;
print_overview(collection, total_elements, load_factor);
struct mmap *map = mmap_new_custom(total_elements, load_factor, cmp, hash, &alloc_default, NULL);
/* Create, Read, Update, Delete */
struct cmc_timer timers[4] = { 0 };
/* Memory Usage 0%, 10%, 20%, ... 100% */
size_t memory[11] = {0};
memory[0] = total_memory;
/* Create */
cmc_timer_start(timers[0]);
for (int i = 0; i < 10; i++)
{
for (int j = partition * i; j < partition * (i + 1); j++)
{
mmap_insert(map, j, j);
}
memory[i + 1] = total_memory;
}
cmc_timer_stop(timers[0]);
cmc_timer_calc(timers[0]);
/* Create End */
/* Read */
cmc_timer_start(timers[1]);
for (int i = 0; i < total_elements; i++)
mmap_contains(map, i);
cmc_timer_stop(timers[1]);
cmc_timer_calc(timers[1]);
/* Read End */
/* Update */
cmc_timer_start(timers[2]);
for (int i = 0; i < total_elements; i++)
mmap_update(map, i, total_elements - i - 1, NULL);
cmc_timer_stop(timers[2]);
cmc_timer_calc(timers[2]);
/* Update End */
/* Delete */
cmc_timer_start(timers[3]);
for (int i = 0; i < total_elements; i++)
mmap_remove(map, i, NULL);
cmc_timer_stop(timers[3]);
cmc_timer_calc(timers[3]);
/* Delete End */
print_time(collection, timers[0].result, timers[1].result, timers[2].result,
timers[3].result);
print_memory(collection, memory, partition);
mmap_free(map, NULL);
printf("--------------------------------------------------------------------------------\n");
}
-8
View File
@@ -1,8 +0,0 @@
CFLAGS = -Wall -Wextra
INCLUDE = ../../src
main:
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DCMC_QUEUE
a.exe
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DSAC_QUEUE
a.exe
-76
View File
@@ -1,76 +0,0 @@
/**
* queue.c
*
* Creation Date: 24/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/* Showing off how different queue implementations affect runtime cost */
#include "utl/timer.h"
#include <stdio.h>
#include <inttypes.h>
#define MAX 200000
#if defined(CMC_QUEUE)
#include "cmc/queue.h"
CMC_GENERATE_QUEUE(q, queue, int)
#define TARGET "QUEUE"
#elif defined(SAC_QUEUE)
#include "sac/queue.h"
SAC_QUEUE_GENERATE(q, queue, , int, MAX)
#define TARGET "SAC QUEUE"
#else
#error Please define either CMC_QUEUE, SAC_QUEUE or EXT_QUEUE
#endif
int main(void)
{
#if defined(CMC_QUEUE)
struct queue *q = q_new(MAX);
#elif defined(SAC_QUEUE)
queue _q = q_new();
queue_ptr q = &_q;
#endif
size_t sum = 0;
int i = 0;
struct cmc_timer timer;
cmc_timer_start(timer);
while (q_count(q) != MAX)
{
q_enqueue(q, i++);
if (i % 10 == 0)
{
for (size_t i = 0; i < 9; i++)
{
sum += q_peek(q);
q_dequeue(q);
}
}
}
cmc_timer_stop(timer);
cmc_timer_calc(timer);
printf("----------------------------------------\n");
printf("%s\n", TARGET);
printf("Execution time: %.0lf milliseconds\n", timer.result);
printf("SUM: %" PRIuMAX "\n", sum);
printf("----------------------------------------\n");
#if defined(CMC_QUEUE)
q_free(q, NULL);
#endif
return 0;
}
-102
View File
@@ -1,102 +0,0 @@
/**
* twister.c
*
* Creation Date: 09/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Mersenne Twister PRNG utility
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define NN 312
#define MM 156
#define MATRIX_A UINT64_C(0xB5026F5AA96619E9)
#define UM UINT64_C(0xFFFFFFFF80000000) // Most significant 33 bits
#define LM UINT64_C(0x7FFFFFFF) // Least significant 31 bits
// State vector
typedef struct mt_state_s
{
uint64_t mt[NN];
int mti;
} mt_state, *mt_state_ptr;
// Initializes mt[NN] with a seed
void twist_init(mt_state_ptr st, uint64_t seed);
// Generates a random uint64_t in [0, 2^64-1] interval
uint64_t twist_uint64(mt_state_ptr st);
// Generates a double in [0, 1) interval
double twist_real(mt_state_ptr st);
//
// Implementation
//
// Initialize a state mt[NN] with a seed
void twist_init(mt_state_ptr st, uint64_t seed)
{
st->mti = NN + 1;
st->mt[0] = seed;
for (st->mti = 1; st->mti < NN; st->mti++)
{
st->mt[st->mti] = (UINT64_C(6364136223846793005) * (st->mt[st->mti - 1] ^ (st->mt[st->mti - 1] >> 62)) + st->mti);
}
}
// Generates a random uint64_t in [0, 2^64-1] interval
uint64_t twist_uint64(mt_state_ptr st)
{
int i;
uint64_t x;
static uint64_t mag01[2] = {UINT64_C(0), MATRIX_A};
if (st->mti >= NN)
{
// Generate NN words at one time if twist_init() has not been called
// A default initial seed is used
if (st->mti == NN + 1)
twist_init(st, UINT64_C(5489));
for (i = 0; i < NN - MM; i++)
{
x = (st->mt[i] & UM) | (st->mt[i + 1] & LM);
st->mt[i] = st->mt[i + MM] ^ (x >> 1) ^ mag01[(int)(x & UINT64_C(1))];
}
for (; i < NN - 1; i++)
{
x = (st->mt[i] & UM) | (st->mt[i + 1] & LM);
st->mt[i] = st->mt[i + (MM - NN)] ^ (x >> 1) ^ mag01[(int)(x & UINT64_C(1))];
}
x = (st->mt[NN - 1] & UM) | (st->mt[0] & LM);
st->mt[NN - 1] = st->mt[MM - 1] ^ (x >> 1) ^ mag01[(int)(x & UINT64_C(1))];
st->mti = 0;
}
x = st->mt[st->mti++];
x ^= (x >> 29) & UINT64_C(0x5555555555555555);
x ^= (x << 17) & UINT64_C(0x71D67FFFEDA60000);
x ^= (x << 37) & UINT64_C(0xFFF7EEE000000000);
x ^= (x >> 43);
return x;
}
// Generates a double in [0, 1) interval
double twist_real(mt_state_ptr st)
{
return (twist_uint64(st) >> 11) * (1.0 / 9007199254740992.0);
}