summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authortylo <[email protected]>2020-03-10 10:52:26 +0100
committertylo <[email protected]>2020-03-10 10:52:26 +0100
commit5aab7dcd61c70cb33794f79f2e88b8d82538fa65 (patch)
treee46599654013fdc0c4358f9fb435df9aafe1a0e0
parentdd30f5c701609a8c6dc09b9b48967df54767b7ed (diff)
parent1f93cd63a5e2f13d5954c7519c7869ba6c870427 (diff)
downloadSTC-modified-5aab7dcd61c70cb33794f79f2e88b8d82538fa65.tar.gz
STC-modified-5aab7dcd61c70cb33794f79f2e88b8d82538fa65.zip
Merge branch 'master' of https://github.com/tylo-work/C99Containers
# Conflicts: # cmap.h
-rw-r--r--cdef.h4
-rw-r--r--cmap.h54
-rw-r--r--cstring.h8
3 files changed, 36 insertions, 30 deletions
diff --git a/cdef.h b/cdef.h
index 3282f9ac..865436a0 100644
--- a/cdef.h
+++ b/cdef.h
@@ -37,8 +37,8 @@
// #define foo_1(X) foo_2(X, 100)
// #define foo_2(X, Y) X + Y
-#define _cdef_max_alloca (1000)
-#define _cdef_swap(T, x, y) { T __t = x; x = y; y = __t; }
+#define cdef_max_alloca (1000)
+#define cdef_swap(T, x, y) { T __t = x; x = y; y = __t; }
#define cdef_initRaw(x) (x)
#define cdef_getRaw(x) (x)
diff --git a/cmap.h b/cmap.h
index fb3845a4..0ec86672 100644
--- a/cmap.h
+++ b/cmap.h
@@ -25,16 +25,15 @@
#include "cvector.h"
-#define cmap_initializer {cvector_initializer, 0, 80, 167}
+#define cmap_initializer {cvector_initializer, 0, 0.8f}
#define cmap_size(cm) ((size_t) (cm)._size)
#define cmap_buckets(cm) cvector_capacity((cm)._vec)
-#define cmap_maxLoadFactor(cm) ((cm).maxLoadPercentage / 100.0)
// CMapEntry:
enum { CMapEntry_VACANT = 0,
CMapEntry_INUSE = 1,
- CMapEntry_REMOVED = 2
+ CMapEntry_ERASED = 2
};
#define declare_CMapEntry(tag, Key, Value, keyDestroy, valueDestroy) \
struct CMapEntry_##tag { \
@@ -79,8 +78,7 @@ typedef struct CMapEntry_##tag CMapEntry_##tag
typedef struct CMap_##tag { \
CVector_map_##tag _vec; \
size_t _size; \
- uint16_t maxLoadPercentage; \
- uint16_t expandPercentage; \
+ float maxLoadFactor; \
} CMap_##tag; \
\
typedef struct cmap_##tag##_iter_t { \
@@ -111,28 +109,38 @@ static inline void cmap_##tag##_clear(CMap_##tag* self) { \
\
static inline void cmap_##tag##_swap(CMap_##tag* a, CMap_##tag* b) { \
cvector_map_##tag##_swap(&a->_vec, &b->_vec); \
- _cdef_swap(size_t, a->_size, b->_size); \
+ cdef_swap(size_t, a->_size, b->_size); \
} \
\
-static inline void cmap_##tag##_setMaxLoadFactor(CMap_##tag* self, float loadFactor) { \
- self->maxLoadPercentage = (uint16_t) (loadFactor * 100.99); \
- if (cmap_size(*self) > cmap_buckets(*self) * loadFactor) \
- cmap_##tag##_reserve(self, 7 + cmap_size(*self) / self->maxLoadPercentage); \
+static inline void cmap_##tag##_setMaxLoadFactor(CMap_##tag* self, float fac) { \
+ self->maxLoadFactor = fac; \
+ if (cmap_size(*self) > cmap_buckets(*self) * fac) \
+ cmap_##tag##_reserve(self, 7 + (size_t) (cmap_size(*self) / fac)); \
} \
\
static inline size_t cmap_##tag##_bucket(CMap_##tag cm, KeyRaw rawKey) { \
size_t cap = cvector_capacity(cm._vec); \
- size_t idx = keyHasher(&rawKey, sizeof(Key)) % cap; \
- size_t first = idx, found = cap, state = cm._vec.data[idx].state; \
+ size_t idx = cmap_reduce(keyHasher(&rawKey, sizeof(Key)), cap); \
+ size_t first = idx, erased_idx = cap, state = cm._vec.data[idx].state; \
FIBONACCI_DECL; \
do { \
- if (state == CMapEntry_INUSE && keyCompare(&cm._vec.data[idx].key, &rawKey, sizeof(Key)) == 0) \
+ switch (state) { \
+ case CMapEntry_VACANT: \
+ return erased_idx != cap ? erased_idx : idx; \
+ case CMapEntry_INUSE: \
+ if (keyCompare(&cm._vec.data[idx].key, &rawKey, sizeof(Key)) != 0) \
+ break; \
+ if (erased_idx != cap) { \
+ cdef_swap(CMapEntry_##tag, cm._vec.data[erased_idx], cm._vec.data[idx]); \
+ return erased_idx; \
+ } \
return idx; \
- if (state == CMapEntry_REMOVED && found == cap) \
- found = idx; \
+ case CMapEntry_ERASED: \
+ if (erased_idx == cap) erased_idx = idx; \
+ break; \
+ } \
state = cm._vec.data[ idx = (first + FIBONACCI_NEXT) % cap ].state; \
- } while (state != CMapEntry_VACANT); \
- return found == cap ? idx : found; \
+ } while (1); \
} \
\
static inline CMapEntry_##tag* cmap_##tag##_get(CMap_##tag cm, KeyRaw rawKey) { \
@@ -143,8 +151,8 @@ static inline CMapEntry_##tag* cmap_##tag##_get(CMap_##tag cm, KeyRaw rawKey) {
\
static inline CMapEntry_##tag* cmap_##tag##_put(CMap_##tag* self, KeyRaw rawKey, Value value) { \
size_t cap = cvector_capacity(self->_vec); \
- if (cmap_size(*self) >= cap * self->maxLoadPercentage / 100) \
- cap = cmap_##tag##_reserve(self, cap * self->expandPercentage / 100); \
+ if (cmap_size(*self) >= cap * self->maxLoadFactor) \
+ cap = cmap_##tag##_reserve(self, (size_t) (cap * 1.8)); \
size_t idx = cmap_##tag##_bucket(*self, rawKey); \
CMapEntry_##tag* e = &self->_vec.data[idx]; \
e->value = value; \
@@ -175,7 +183,7 @@ static inline bool cmap_##tag##_erase(CMap_##tag* self, KeyRaw rawKey) { \
CMapEntry_##tag* e = cmap_##tag##_get(*self, rawKey); \
if (e) { \
cmapentry_##tag##_destroy(e); \
- e->state = CMapEntry_REMOVED; \
+ e->state = CMapEntry_ERASED; \
--self->_size; \
return true; \
} \
@@ -208,10 +216,8 @@ typedef Value cmap_##tag##_value_t
#define FIBONACCI_NEXT (fibx = fib1 + fib2, fib1 = fib2, fib2 = fibx)
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
-//
-static inline uint32_t fast_reduce(uint32_t x, uint32_t N) {
- return ((uint64_t) x * (uint64_t) N) >> 32;
+static inline uint32_t cmap_reduce(uint32_t x, uint32_t N) {
+ return ((uint64_t) x * (uint64_t) N) >> 32 ;
}
-#define cmap_reduce(x, N) ((uint32_t)(((uint64_t) (x) * (uint64_t) (N)) >> 32))
#endif
diff --git a/cstring.h b/cstring.h
index 02dd3446..f877847c 100644
--- a/cstring.h
+++ b/cstring.h
@@ -138,10 +138,10 @@ static inline void _cstring_internalMove(CString* self, size_t pos1, size_t pos2
}
static inline void cstring_insertN(CString* self, size_t pos, const char* str, size_t n) {
- char* xstr = (char *) memcpy(n > _cdef_max_alloca ? malloc(n) : alloca(n), str, n);
+ char* xstr = (char *) memcpy(n > cdef_max_alloca ? malloc(n) : alloca(n), str, n);
_cstring_internalMove(self, pos, pos + n);
memcpy(&self->str[pos], xstr, n);
- if (n > _cdef_max_alloca) free(xstr);
+ if (n > cdef_max_alloca) free(xstr);
}
static inline void cstring_insert(CString* self, size_t pos, const char* str) {
@@ -161,10 +161,10 @@ static inline size_t cstring_findN(CString cs, size_t pos, const char* needle, s
static inline size_t cstring_replaceN(CString* self, size_t pos, const char* s1, size_t n1, const char* s2, size_t n2) {
size_t pos2 = cstring_findN(*self, pos, s1, n1);
if (pos2 == cstring_npos) return cstring_npos;
- char* xs2 = (char *) memcpy(n2 > _cdef_max_alloca ? malloc(n2) : alloca(n2), s2, n2);
+ char* xs2 = (char *) memcpy(n2 > cdef_max_alloca ? malloc(n2) : alloca(n2), s2, n2);
_cstring_internalMove(self, pos2 + n1, pos2 + n2);
memcpy(&self->str[pos2], xs2, n2);
- if (n2 > _cdef_max_alloca) free(xs2);
+ if (n2 > cdef_max_alloca) free(xs2);
return pos2;
}