From e39d6b2401c6cc409c82d0c02615d0de3a5f9ade Mon Sep 17 00:00:00 2001 From: Dmitrii Krosh Date: Mon, 13 Jul 2026 23:38:49 +0300 Subject: [PATCH] few more lines --- reimplement/newset.c | 64 +++++++++++++++++++++++++++++++++++++++++--- reimplement/plans.md | 6 +++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/reimplement/newset.c b/reimplement/newset.c index fecd954..f6ab8cc 100644 --- a/reimplement/newset.c +++ b/reimplement/newset.c @@ -1,10 +1,25 @@ +#include "stdint.h" +#include "stdio.h" #include "system.h" +uint64_t hash(const char* str) { + uint64_t h = 0xcbf29ce484222325ULL; + + while (*str) { + h ^= (uint64_t)(unsigned char)(*str++); + h *= 0x100000001b3ULL; + } + + return h; +} + +// --- + struct set { - int cnt; + size_t cnt; struct symbols { const char* str; - unsigned hash; + uint64_t hash; }* symbols_v; }; @@ -20,7 +35,7 @@ struct set* set_new() { void set_add(struct set* set, const char* sym) { const int delta = 1024; - if ((set->cnt & (delta - 1)) == 0) { + if (set->cnt % delta == 0) { set->symbols_v = xrealloc(set->symbols_v, sizeof(*set->symbols_v) * (set->cnt + delta)); } @@ -33,7 +48,7 @@ void set_add(struct set* set, const char* sym) { struct set* set_free(struct set* set) { if (set) { - for (int i = 0; i < set->cnt; i++) { + for (size_t i = 0; i < set->cnt; ++i) { _free((char*)set->symbols_v[i].str); } @@ -46,7 +61,48 @@ struct set* set_free(struct set* set) { // --- +int cmp(const void* arg1, const void* arg2) { + const struct symbols* s1 = arg1; + const struct symbols* s2 = arg2; + + if (s1->hash > s2->hash) return 1; + if (s2->hash > s1->hash) return -1; + + return 0; +} + const char* set_fini(struct set* set, int bpp) { // Implementation for finalizing the set + + assert(set != NULL); + assert(set->cnt > 0); + assert(bpp >= 10 && bpp <= 63); + + uint64_t mask = (1ULL << bpp) - 1; + + for (size_t i = 0; i < set->cnt; ++i) { + set->symbols_v[i].hash = hash(set->symbols_v[i].str) & mask; + } + + qsort(set->symbols_v, set->cnt, sizeof *set->symbols_v, cmp); + + for (size_t i = 0; i < set->cnt - 1; ++i) { + if (set->symbols_v[i].hash != set->symbols_v[i + 1].hash) continue; + if (!strcmp(set->symbols_v[i].str, set->symbols_v[i + 1].str)) continue; + + fprintf(stderr, "warning: hash collision: %s %s\n", set->symbols_v[i].str, + set->symbols_v[i + 1].str); + } + + uint64_t unique_hash[set->cnt]; + size_t unique_cnt = 0; + + for (size_t i = 0; i < set->cnt; ++i) { + while (i + 1 < set->cnt && set->symbols_v[i].hash == set->symbols_v[i + 1].hash) { + ++i; + } + unique_hash[unique_cnt++] = set->symbols_v[i].hash; + } + return NULL; } diff --git a/reimplement/plans.md b/reimplement/plans.md index 76eb40e..40374bd 100644 --- a/reimplement/plans.md +++ b/reimplement/plans.md @@ -21,6 +21,7 @@ 7. Оптимизации при создании строк: - сторонняя хэш функция - также даёт преимущество на 64 бит хэше ("на всякий") + - пока что всё равно остановимся на 64 8. Возможно изменение структуры кода для читаемости, например: - много init функций @@ -28,4 +29,9 @@ 9. А какую реализацию оставляем?.. +## notes + +все оптимизации с таблицей более не имеют смысла, т.к. раскодирование сразу по 6 бит гарантированно +И даже если такую делать, то размер бинаря +19 Мб. А вот создание хэша для такого теоритически возможно. + !!! `lib/rpmds.c` стоит исследовать, т.к. сейчас есть шанс, что это единственное место, где используется оптимизация кэширования, если исользуется вовсе