From: Attractive Chaos Date: Mon, 6 Jan 2025 05:39:14 +0000 (-0500) Subject: updated khashl to r30 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=ba6b352f2dc56d5863d71575ed669005d78b7bec;p=klib.git updated khashl to r30 --- diff --git a/kexpr.c b/kexpr.c index 79f110f..f608588 100644 --- a/kexpr.c +++ b/kexpr.c @@ -553,11 +553,11 @@ int main(int argc, char *argv[]) return 1; } ke = ke_parse(argv[optind], &err); - ke_set_default_func(ke); if (err) { fprintf(stderr, "Parse error: 0x%x\n", err); return 1; } + ke_set_default_func(ke); if (!to_print) { int64_t vi; double vr; diff --git a/khashl.h b/khashl.h index 7f2a81a..2e7ef5d 100644 --- a/khashl.h +++ b/khashl.h @@ -1,6 +1,6 @@ /* The MIT License - Copyright (c) 2019-2024 by Attractive Chaos + Copyright (c) 2019- by Attractive Chaos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ #ifndef __AC_KHASHL_H #define __AC_KHASHL_H -#define AC_VERSION_KHASHL_H "r20" +#define AC_VERSION_KHASHL_H "r30" #include #include @@ -73,25 +73,19 @@ typedef const char *kh_cstr_t; * Configurable macros * ***********************/ -#ifndef kh_max_count +#ifndef kh_max_count /* set the max load factor */ #define kh_max_count(cap) (((cap)>>1) + ((cap)>>2)) /* default load factor: 75% */ #endif -#ifndef kh_packed +#ifndef kh_packed /* pack the key-value struct */ #define kh_packed __attribute__ ((__packed__)) #endif -#ifndef kcalloc -#define kcalloc(N,Z) calloc(N,Z) -#endif -#ifndef kmalloc -#define kmalloc(Z) malloc(Z) -#endif -#ifndef krealloc -#define krealloc(P,Z) realloc(P,Z) -#endif -#ifndef kfree -#define kfree(P) free(P) +#if !defined(Kmalloc) || !defined(Kcalloc) || !defined(Krealloc) || !defined(Kfree) +#define Kmalloc(km, type, cnt) ((type*)malloc((cnt) * sizeof(type))) +#define Kcalloc(km, type, cnt) ((type*)calloc((cnt), sizeof(type))) +#define Krealloc(km, type, ptr, cnt) ((type*)realloc((ptr), (cnt) * sizeof(type))) +#define Kfree(km, ptr) free(ptr) #endif /**************************** @@ -104,7 +98,7 @@ typedef const char *kh_cstr_t; #define __kh_fsize(m) ((m) < 32? 1 : (m)>>5) -static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 2654435769U >> (32 - bits); } +static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 2654435769U >> (32 - bits); } /* Fibonacci hashing */ /******************* * Hash table base * @@ -112,6 +106,7 @@ static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 26 #define __KHASHL_TYPE(HType, khkey_t) \ typedef struct HType { \ + void *km; \ khint_t bits, count; \ khint32_t *used; \ khkey_t *keys; \ @@ -119,6 +114,7 @@ static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 26 #define __KHASHL_PROTOTYPES(HType, prefix, khkey_t) \ extern HType *prefix##_init(void); \ + extern HType *prefix##_init2(void *km); \ extern void prefix##_destroy(HType *h); \ extern void prefix##_clear(HType *h); \ extern khint_t prefix##_getp(const HType *h, const khkey_t *key); \ @@ -127,13 +123,16 @@ static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 26 extern void prefix##_del(HType *h, khint_t k); #define __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \ - SCOPE HType *prefix##_init(void) { \ - return (HType*)kcalloc(1, sizeof(HType)); \ + SCOPE HType *prefix##_init2(void *km) { \ + HType *h = Kcalloc(km, HType, 1); \ + h->km = km; \ + return h; \ } \ + SCOPE HType *prefix##_init(void) { return prefix##_init2(0); } \ SCOPE void prefix##_destroy(HType *h) { \ if (!h) return; \ - kfree((void *)h->keys); kfree(h->used); \ - kfree(h); \ + Kfree(h->km, (void*)h->keys); Kfree(h->km, h->used); \ + Kfree(h->km, h); \ } \ SCOPE void prefix##_clear(HType *h) { \ if (h && h->used) { \ @@ -168,13 +167,13 @@ static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 26 new_bits = j > 2? j : 2; \ new_n_buckets = (khint_t)1U << new_bits; \ if (h->count > kh_max_count(new_n_buckets)) return 0; /* requested size is too small */ \ - new_used = (khint32_t*)kmalloc(__kh_fsize(new_n_buckets) * sizeof(khint32_t)); \ + new_used = Kmalloc(h->km, khint32_t, __kh_fsize(new_n_buckets)); \ memset(new_used, 0, __kh_fsize(new_n_buckets) * sizeof(khint32_t)); \ if (!new_used) return -1; /* not enough memory */ \ n_buckets = h->keys? (khint_t)1U<bits : 0U; \ if (n_buckets < new_n_buckets) { /* expand */ \ - khkey_t *new_keys = (khkey_t*)krealloc((void*)h->keys, new_n_buckets * sizeof(khkey_t)); \ - if (!new_keys) { kfree(new_used); return -1; } \ + khkey_t *new_keys = Krealloc(h->km, khkey_t, h->keys, new_n_buckets); \ + if (!new_keys) { Kfree(h->km, new_used); return -1; } \ h->keys = new_keys; \ } /* otherwise shrink */ \ new_mask = new_n_buckets - 1; \ @@ -198,8 +197,8 @@ static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 26 } \ } \ if (n_buckets > new_n_buckets) /* shrink the hash table */ \ - h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - kfree(h->used); /* free the working space */ \ + h->keys = Krealloc(h->km, khkey_t, (void*)h->keys, new_n_buckets); \ + Kfree(h->km, h->used); /* free the working space */ \ h->used = new_used, h->bits = new_bits; \ return 0; \ } @@ -272,21 +271,23 @@ typedef struct { #define KHASHE_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ KHASHL_INIT(KH_LOCAL, HType##_sub, prefix##_sub, khkey_t, __hash_fn, __hash_eq) \ typedef struct HType { \ + void *km; \ khint64_t count:54, bits:8; \ HType##_sub *sub; \ } HType; \ - SCOPE HType *prefix##_init(int bits) { \ + SCOPE HType *prefix##_init2(void *km, int bits) { \ HType *g; \ - g = (HType*)kcalloc(1, sizeof(*g)); \ - g->bits = bits; \ - g->sub = (HType##_sub*)kcalloc(1U<sub)); \ + g = Kcalloc(km, HType, 1); \ + g->bits = bits, g->km = km; \ + g->sub = Kcalloc(km, HType##_sub, 1U<bits; ++t) { kfree((void*)g->sub[t].keys); kfree(g->sub[t].used); } \ - kfree(g->sub); kfree(g); \ + for (t = 0; t < 1<bits; ++t) { Kfree(g->km, (void*)g->sub[t].keys); Kfree(g->km, g->sub[t].used); } \ + Kfree(g->km, g->sub); Kfree(g->km, g); \ } \ SCOPE kh_ensitr_t prefix##_getp(const HType *g, const khkey_t *key) { \ khint_t hash, low, ret; \ @@ -320,16 +321,32 @@ typedef struct { ret = prefix##_sub_del(h, itr.pos); \ if (ret) --g->count; \ return ret; \ + } \ + SCOPE void prefix##_clear(HType *g) { \ + int i; \ + for (i = 0; i < 1U<bits; ++i) prefix##_sub_clear(&g->sub[i]); \ + g->count = 0; \ } /***************************** * More convenient interface * *****************************/ -#define __kh_cached_hash(x) ((x).hash) +/* common */ #define KHASHL_SET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - KHASHL_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) + typedef struct { khkey_t key; } kh_packed HType##_s_bucket_t; \ + static kh_inline khint_t prefix##_s_hash(HType##_s_bucket_t x) { return __hash_fn(x.key); } \ + static kh_inline int prefix##_s_eq(HType##_s_bucket_t x, HType##_s_bucket_t y) { return __hash_eq(x.key, y.key); } \ + KHASHL_INIT(KH_LOCAL, HType, prefix##_s, HType##_s_bucket_t, prefix##_s_hash, prefix##_s_eq) \ + SCOPE HType *prefix##_init(void) { return prefix##_s_init(); } \ + SCOPE HType *prefix##_init2(void *km) { return prefix##_s_init2(km); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_s_destroy(h); } \ + SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_s_resize(h, new_n_buckets); } \ + SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_s_bucket_t t; t.key = key; return prefix##_s_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_s_del(h, k); } \ + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_s_bucket_t t; t.key = key; return prefix##_s_putp(h, &t, absent); } \ + SCOPE void prefix##_clear(HType *h) { prefix##_s_clear(h); } #define KHASHL_MAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ typedef struct { khkey_t key; kh_val_t val; } kh_packed HType##_m_bucket_t; \ @@ -337,10 +354,17 @@ typedef struct { static kh_inline int prefix##_m_eq(HType##_m_bucket_t x, HType##_m_bucket_t y) { return __hash_eq(x.key, y.key); } \ KHASHL_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \ SCOPE HType *prefix##_init(void) { return prefix##_m_init(); } \ + SCOPE HType *prefix##_init2(void *km) { return prefix##_m_init2(km); } \ SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \ + SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_m_resize(h, new_n_buckets); } \ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_m_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); } + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); } \ + SCOPE void prefix##_clear(HType *h) { prefix##_m_clear(h); } + +/* cached hashes to trade memory for performance when hashing and comparison are expensive */ + +#define __kh_cached_hash(x) ((x).hash) #define KHASHL_CSET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ typedef struct { khkey_t key; khint_t hash; } kh_packed HType##_cs_bucket_t; \ @@ -350,7 +374,8 @@ typedef struct { SCOPE void prefix##_destroy(HType *h) { prefix##_cs_destroy(h); } \ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cs_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cs_getp(h, &t); } \ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cs_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cs_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cs_putp(h, &t, absent); } + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cs_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cs_putp(h, &t, absent); } \ + SCOPE void prefix##_clear(HType *h) { prefix##_cs_clear(h); } #define KHASHL_CMAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ typedef struct { khkey_t key; kh_val_t val; khint_t hash; } kh_packed HType##_cm_bucket_t; \ @@ -360,21 +385,34 @@ typedef struct { SCOPE void prefix##_destroy(HType *h) { prefix##_cm_destroy(h); } \ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cm_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cm_getp(h, &t); } \ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cm_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cm_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cm_putp(h, &t, absent); } + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cm_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cm_putp(h, &t, absent); } \ + SCOPE void prefix##_clear(HType *h) { prefix##_cm_clear(h); } + +/* ensemble for huge hash tables */ #define KHASHE_SET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - KHASHE_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) + typedef struct { khkey_t key; } kh_packed HType##_es_bucket_t; \ + static kh_inline khint_t prefix##_es_hash(HType##_es_bucket_t x) { return __hash_fn(x.key); } \ + static kh_inline int prefix##_es_eq(HType##_es_bucket_t x, HType##_es_bucket_t y) { return __hash_eq(x.key, y.key); } \ + KHASHE_INIT(KH_LOCAL, HType, prefix##_es, HType##_es_bucket_t, prefix##_es_hash, prefix##_es_eq) \ + SCOPE HType *prefix##_init(int bits) { return prefix##_es_init(bits); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_es_destroy(h); } \ + SCOPE kh_ensitr_t prefix##_get(const HType *h, khkey_t key) { HType##_es_bucket_t t; t.key = key; return prefix##_es_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, kh_ensitr_t k) { return prefix##_es_del(h, k); } \ + SCOPE kh_ensitr_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_es_bucket_t t; t.key = key; return prefix##_es_putp(h, &t, absent); } \ + SCOPE void prefix##_clear(HType *h) { prefix##_es_clear(h); } #define KHASHE_MAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ - typedef struct { khkey_t key; kh_val_t val; } kh_packed HType##_m_bucket_t; \ - static kh_inline khint_t prefix##_m_hash(HType##_m_bucket_t x) { return __hash_fn(x.key); } \ - static kh_inline int prefix##_m_eq(HType##_m_bucket_t x, HType##_m_bucket_t y) { return __hash_eq(x.key, y.key); } \ - KHASHE_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \ - SCOPE HType *prefix##_init(int bits) { return prefix##_m_init(bits); } \ - SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \ - SCOPE kh_ensitr_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \ - SCOPE int prefix##_del(HType *h, kh_ensitr_t k) { return prefix##_m_del(h, k); } \ - SCOPE kh_ensitr_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); } + typedef struct { khkey_t key; kh_val_t val; } kh_packed HType##_em_bucket_t; \ + static kh_inline khint_t prefix##_em_hash(HType##_em_bucket_t x) { return __hash_fn(x.key); } \ + static kh_inline int prefix##_em_eq(HType##_em_bucket_t x, HType##_em_bucket_t y) { return __hash_eq(x.key, y.key); } \ + KHASHE_INIT(KH_LOCAL, HType, prefix##_em, HType##_em_bucket_t, prefix##_em_hash, prefix##_em_eq) \ + SCOPE HType *prefix##_init(int bits) { return prefix##_em_init(bits); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_em_destroy(h); } \ + SCOPE kh_ensitr_t prefix##_get(const HType *h, khkey_t key) { HType##_em_bucket_t t; t.key = key; return prefix##_em_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, kh_ensitr_t k) { return prefix##_em_del(h, k); } \ + SCOPE kh_ensitr_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_em_bucket_t t; t.key = key; return prefix##_em_putp(h, &t, absent); } \ + SCOPE void prefix##_clear(HType *h) { prefix##_em_clear(h); } /************************** * Public macro functions * @@ -425,10 +463,8 @@ static kh_inline khint_t kh_hash_uint64(khint64_t x) { /* splitmix64; see https: return (khint_t)x; } -#define KH_FNV_SEED 11 - static kh_inline khint_t kh_hash_str(kh_cstr_t s) { /* FNV1a */ - khint_t h = KH_FNV_SEED ^ 2166136261U; + khint_t h = 2166136261U; const unsigned char *t = (const unsigned char*)s; for (; *t; ++t) h ^= *t, h *= 16777619; @@ -436,7 +472,7 @@ static kh_inline khint_t kh_hash_str(kh_cstr_t s) { /* FNV1a */ } static kh_inline khint_t kh_hash_bytes(int len, const unsigned char *s) { - khint_t h = KH_FNV_SEED ^ 2166136261U; + khint_t h = 2166136261U; int i; for (i = 0; i < len; ++i) h ^= s[i], h *= 16777619;