디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

러스트가 개떡같은 EU

나르시갤로그로 이동합니다. 2025.07.23 14:59:03
조회 40 추천 0 댓글 0

러스트로는 이런거 못 짠다.

ㅋㅋㅋ

/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */

/*

  c-hash-map.c

  Copyright (C) 2021-2024 Hodong Kim, All rights reserved.

  Unauthorized copying of this software, via any medium is strictly prohibited.

  Proprietary and confidential.

  Written by Hodong Kim <hodong@nimfsoft.art>

 */

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  #include <sys/endian.h>

#else

  #define _DEFAULT_SOURCE

  #include <endian.h>

  #include <sys/random.h>

#endif

#include "c-hash-map.h"

#include <stdlib.h>

#include <string.h>

#include "c-array.h"

#include "c-mem.h"

#include "c-list.h"


/*****************************************************************************/


typedef struct _CEntry CEntry;

struct _CEntry {

  CEntry* next;

  CEntry* prev;

  void*   key;

  void*   value;

};


static CEntry* c_entry_new (void* key, void* value)

{

  CEntry* entry = c_malloc (sizeof (CEntry));

  entry->key    = key;

  entry->value  = value;

  return entry;

}


static void c_entry_free (CEntry*   entry,

                          CFreeFunc key_free_func,

                          CFreeFunc value_free_func)

{

  if (key_free_func)

    key_free_func (entry->key);


  if (value_free_func)

    value_free_func (entry->value);


  free (entry);

}


/*****************************************************************************/


uint32_t c_murmur3_32 (const uint8_t* key, size_t len, uint32_t seed)

{

  uint32_t h = seed;

  uint32_t k;


  for (size_t i = len >> 2; i; i--)

  {

    k = htole32 (*(uint32_t*) key);

    key += sizeof (uint32_t);

    k *= 0xcc9e2d51;

    k = (k << 15) | (k >> 17);

    k *= 0x1b873593;

    h ^= k;

    h = (h << 13) | (h >> 19);

    h = h * 5 + 0xe6546b64;

  }


  k = 0;


  for (size_t i = len & 3; i; i--)

  {

    k <<= 8;

    k |= key[i - 1];

  }


  k *= 0xcc9e2d51;

  k = (k << 15) | (k >> 17);

  k *= 0x1b873593;

  h ^= k;


  h ^= len;

  h ^= h >> 16;

  h *= 0x85ebca6b;

  h ^= h >> 13;

  h *= 0xc2b2ae35;

  h ^= h >> 16;


  return h;

}


uintptr_t c_str_hash (const void* str, uint32_t seed)

{

  return c_murmur3_32 (str, strlen (str), seed);

}


/*****************************************************************************/


// RAND_MAX:      0x7fffffffU  This is a prime number

// UINT32_MAX:    0xffffffffU

#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__)

  #define PRIME     0xfffffffbU /* for arc4random_uniform() or getrandom() */

#else

  #define PRIME     0x7fffffffU /* for rand() */

#endif


typedef struct _CBucket CBucket;

struct _CBucket {

  unsigned random;      // 1 <= k <= prime - 1

  unsigned entries_len; // entries_len = 2 * m * (m - 1)

  unsigned m;           // entries_len = 2 * m * (m - 1)

  unsigned b;           // rehash: b = lists[i]->len, insert: b = b + 1

  CEntry** entries;

};


// constant

#define DYNFECT_C  1 // m = (1 + c) * C_MAX (count, 4) in rehash()

#define DYNFECT_S  1 // buckets_len = S(M) = DYNFECT_S * dynfect->m


typedef struct _CDynfect CDynfect;

struct _CDynfect {

  unsigned   random;      /* 1 <= k <= prime - 1 */

  unsigned   buckets_len; /* buckets_len = S(M) = DYNFECT_S * dynfect->m */

  CHashFunc  key_hash_func;

  CEqualFunc key_equal_func;

  CFreeFunc  key_free_func;

  CFreeFunc  value_free_func;

  CList*     list;

  CBucket*   buckets;

  unsigned   op_count; /* count++ when add, remove */

  unsigned   m;        /* m = (1 + c) * C_MAX (count, 4) in rehash() */

};


static unsigned c_dynfect_gen_random ()

{

#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__linux__)

  #if RAND_MAX != 0x7fffffffU

    #error "Debug this source code"

  #endif

  static unsigned seed;


  if (!seed)

  {

    /* This is insecure */

    seed = time (NULL);

    srand (seed);

  }

#endif

  /* h(x) = (kx mod p) mod s; 1 <= k <= prime - 1 */

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  return arc4random_uniform (PRIME - 1) + 1; /* uint32_t */

#elif defined __linux__

  uint32_t buf;

  if (getrandom (&buf, sizeof (uint32_t), 0) != -1)

    return buf % (PRIME - 1) + 1;

  else

    return rand() % (PRIME - 1) + 1; /* int */

#else

  return rand() % (PRIME - 1) + 1; /* int */

#endif

}


uintptr_t c_ptr_hash (const void* p, uint32_t seed)

{

  return (seed * (uintptr_t) p) % PRIME;

}


bool c_ptr_equal (const void* a, const void* b)

{

  return a == b;

}


static bool c_dynfect_condition (CDynfect* dynfect)

{

  unsigned sum = 0;

  // 32 * M * M / S(M) + 4 * M

  // S(M) is buckets_len

  // buckets_len is DYNFECT_S * dynfect->m

  unsigned bound = 32 * dynfect->m / DYNFECT_S + 4 * dynfect->m;


  for (unsigned i = 0; i < dynfect->buckets_len; i++)

  {

    sum = sum + dynfect->buckets[i].m;


    if (sum > bound)

      return false;

  }


  return true;

}


static bool c_dynfect_inject (CDynfect* dynfect, CArray* list, CBucket* bucket)

{

  bucket->random = c_dynfect_gen_random ();


  for (unsigned i = 0; i < list->len; i++)

  {

    CEntry*  entry = list->data[i];

    unsigned index = dynfect->key_hash_func (entry->key, bucket->random) %

                     (unsigned long) bucket->entries_len;

    if (bucket->entries[index])

      return false;


    bucket->entries[index] = entry;

  }


  return true;

}


static bool c_dynfect_contains (CDynfect* dynfect, const void* key)

{

  unsigned i = dynfect->key_hash_func (key, dynfect->random) % (unsigned long) dynfect->buckets_len;

  CBucket* bucket = &dynfect->buckets[i];


  if (bucket->entries_len > 0)

  {

    int pos = dynfect->key_hash_func (key, bucket->random) % (unsigned long) bucket->entries_len;

    CEntry* entry = bucket->entries[pos];


    if (entry && dynfect->key_equal_func (entry->key, key))

      return true;

  }


  return false;

}


static void c_dynfect_rehash (CDynfect* dynfect, CEntry* new_entry)

{

  CArray*  list;

  CArray** lists;


  list = c_array_new (NULL, true);


  for (unsigned i = 0; i < dynfect->buckets_len; i++)

  {

    CBucket* bucket = &dynfect->buckets[i];

    for (unsigned j = 0; j < bucket->entries_len; j++)

      if (bucket->entries[j])

        c_array_add (list, bucket->entries[j]);


    free (bucket->entries);

  }


  if (new_entry)

    c_array_add (list, new_entry);


  dynfect->op_count = list->len;

  dynfect->m = (1 + DYNFECT_C) * C_MAX (dynfect->op_count, 4);

  dynfect->buckets_len = DYNFECT_S * dynfect->m;


  dynfect->buckets = c_realloc (dynfect->buckets,

                                dynfect->buckets_len * sizeof (CBucket));

  memset (dynfect->buckets, 0, dynfect->buckets_len * sizeof (CBucket));

  lists = c_calloc (dynfect->buckets_len, sizeof (CArray*));


  do {

    dynfect->random = c_dynfect_gen_random ();


    for (unsigned i = 0; i < dynfect->buckets_len; i++)

      if (lists[i] && lists[i]->len)

        c_array_clear (lists[i]);


    for (unsigned i = 0; i < list->len; i++)

    {

      CEntry* entry = list->data[i];

      unsigned pos = dynfect->key_hash_func (entry->key, dynfect->random) % (unsigned long) dynfect->buckets_len;


      if (!lists[pos])

        lists[pos] = c_array_new (NULL, true);


      c_array_add (lists[pos], entry);

    }


    for (unsigned i = 0; i < dynfect->buckets_len; i++)

    {

      CBucket* bucket = &dynfect->buckets[i];

      memset (bucket, 0, sizeof (CBucket));

      bucket->b = lists[i] ? lists[i]->len : 0;

      bucket->m = 2 * bucket->b;

      bucket->entries_len = 2 * bucket->m * (bucket->m - 1);

    }

  } while (!c_dynfect_condition (dynfect));


  c_array_free (list);


  for (unsigned i = 0; i < dynfect->buckets_len; i++)

  {

    CBucket* bucket = &dynfect->buckets[i];


    if (lists[i] && (lists[i]->len > 0))

    {

      bucket->entries = c_calloc (bucket->entries_len, sizeof (CEntry*));


      do {

        memset (bucket->entries, 0, bucket->entries_len * sizeof (CEntry*));

      } while (!c_dynfect_inject (dynfect, lists[i], bucket));

    }


    if (lists[i])

      c_array_free (lists[i]);

  }


  free (lists);

}


static CDynfect* c_dynfect_new (CHashFunc  key_hash_func,

                                CEqualFunc key_equal_func,

                                CFreeFunc  key_free_func,

                                CFreeFunc  value_free_func,

                                CList*     list)

{

  CDynfect* dynfect = c_malloc (sizeof (CDynfect));


  dynfect->key_hash_func   = key_hash_func;

  dynfect->key_equal_func  = key_equal_func;

  dynfect->key_free_func   = key_free_func;

  dynfect->value_free_func = value_free_func;

  dynfect->list            = list;

  dynfect->op_count        = 0;

  dynfect->buckets_len     = 0;

  dynfect->buckets         = NULL;

  dynfect->m               = 0;

  c_dynfect_rehash (dynfect, NULL);


  return dynfect;

}


static bool

c_dynfect_insert (CDynfect* dynfect, void* key, void* value, CEntry* new_entry)

{

  if (new_entry)

    key = new_entry->key;


  unsigned index  = dynfect->key_hash_func (key, dynfect->random) %

                    (unsigned long) dynfect->buckets_len;

  CBucket* bucket = &dynfect->buckets[index];

  unsigned pos    = 0; // avoid maybe-uninitialized


  if (bucket->entries_len > 0)

  {

    pos = dynfect->key_hash_func (key, bucket->random) %

          (unsigned long) bucket->entries_len;

    CEntry* entry = bucket->entries[pos];


    if (entry)

    {

      if (dynfect->key_equal_func (entry->key, key))

      {

        if (dynfect->key_free_func)

          dynfect->key_free_func (entry->key);


        if (dynfect->value_free_func)

          dynfect->value_free_func (entry->value);


        entry->key   = key;

        entry->value = value;


        return false;

      }

    }

  }


  if (!new_entry)

  {

    new_entry = c_entry_new (key, value);

    c_list_insert_end (dynfect->list, (CNode*) new_entry);

  }


  dynfect->op_count++;


  if (dynfect->op_count > dynfect->m)

  {

    c_dynfect_rehash (dynfect, new_entry);


    return true;

  }


  bucket->b++;


  if (bucket->b <= bucket->m)

  {

    /* bucket->entries_len > 0 is true, so 'pos' NOT maybe-uninitialized */

    if (!bucket->entries[pos])

    {

      bucket->entries[pos] = new_entry;

    }

    else

    {

      CArray* list;


      list = c_array_new (NULL, true);


      for (unsigned i = 0; i < bucket->entries_len; i++)

        if (bucket->entries[i])

          c_array_add (list, bucket->entries[i]);


      c_array_add (list, new_entry);


      do {

        if (bucket->entries == NULL)

          bucket->entries = c_calloc (bucket->entries_len, sizeof (CEntry*));

        else

          memset (bucket->entries,

                  0, bucket->entries_len * sizeof (CEntry*));

      } while (!c_dynfect_inject (dynfect, list, bucket));


      c_array_free (list);

    }

  }

  else

  {

    if (c_dynfect_condition (dynfect))

    {

      CArray* list;


      list = c_array_new (NULL, true);


      if (bucket->entries)

        for (unsigned j = 0; j < bucket->entries_len; j++)

          if (bucket->entries[j])

            c_array_add (list, bucket->entries[j]);


      c_array_add (list, new_entry);


      bucket->m = 2 * C_MAX (bucket->m, 1);

      bucket->entries_len = 2 * (bucket->m) * (bucket->m - 1);

      bucket->entries = c_realloc (bucket->entries,

                                   bucket->entries_len * sizeof (CEntry*));

      do {

        memset (bucket->entries, 0, bucket->entries_len * sizeof (CEntry*));

      } while (!c_dynfect_inject (dynfect, list, bucket));


      c_array_free (list);

    }

    else

    {

      c_dynfect_rehash (dynfect, new_entry);

    }

  }


  return true;

}


static bool c_dynfect_remove (CDynfect* dynfect, const void* key)

{

  dynfect->op_count++;


  unsigned i = dynfect->key_hash_func (key, dynfect->random) %

                                       (unsigned long) dynfect->buckets_len;

  CBucket* bucket = &dynfect->buckets[i];


  if (bucket->entries_len < 1)

    return false;


  int pos = dynfect->key_hash_func (key, bucket->random) %

                                    (unsigned long) bucket->entries_len;

  CEntry* entry = bucket->entries[pos];


  if (entry == NULL)

    return false;


  c_list_remove_link (dynfect->list, (CNode*) entry);

  bucket->entries[pos] = NULL;


  if (dynfect->op_count >= dynfect->m)

    c_dynfect_rehash (dynfect, NULL);


  c_entry_free (entry, dynfect->key_free_func, dynfect->value_free_func);


  return true;

}


static void* c_dynfect_lookup (CDynfect* dynfect, const void* key)

{

  unsigned i = dynfect->key_hash_func (key, dynfect->random) % (unsigned long) dynfect->buckets_len;

  CBucket* bucket = &dynfect->buckets[i];


  if (bucket->entries_len > 0)

  {

    int pos = dynfect->key_hash_func (key, bucket->random) % (unsigned long) bucket->entries_len;

    CEntry* entry = bucket->entries[pos];


    if (entry && dynfect->key_equal_func (entry->key, key))

      return entry->value;

  }


  return NULL;

}


static void c_dynfect_free (CDynfect* dynfect)

{

  for (unsigned i = 0; i < dynfect->buckets_len; i++)

  {

    CBucket* bucket = &dynfect->buckets[i];

    free (bucket->entries);

  }


  free (dynfect->buckets);

  free (dynfect);

}



추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 반응이 재밌어서 자꾸만 놀리고 싶은 리액션 좋은 스타는? 운영자 25/07/28 - -
공지 프로그래밍 갤러리 이용 안내 [92] 운영자 20.09.28 45822 65
2875644 한국 좌파의 문제점은 상징 자본만 던지면서 실질 재분배에 관심이 없고 ㅆㅇㅆ(124.216) 11:11 5 0
2875643 특검만 하면 사람이 죽는데 왜그런거냐? [4] 헬마스터갤로그로 이동합니다. 11:07 13 0
2875642 보통 좌파가 말하는 상징자본이라는 걸 프갤 보수는 이해할 대가리가 안됨 ㅆㅇㅆ(124.216) 11:07 9 0
2875641 인간의 시선은 상하가 편하지 좌우면 불편함 ♥불사신냥덩♥갤로그로 이동합니다. 11:06 4 0
2875640 한국 부도나기전에 빨리 도망칠 준비해라 [1] ♥불사신냥덩♥갤로그로 이동합니다. 11:01 11 0
2875639 찢명구정물 여론조작 실패 ㅋㅅㅋ ♥불사신냥덩♥갤로그로 이동합니다. 10:59 6 0
2875638 학생운동도 해봤는데 운동권 위선도 프레임이지. 솔직하게 말하자면 ㅆㅇㅆ(124.216) 10:58 16 0
2875637 사무실좀큰공단으로옮겼는데함바집퀄리티ㅅㅌㅊ [2] 현무E공인(1.237) 10:55 26 0
2875636 [대한민국] 저출산의 근본적인 원인 [1] 프갤러(121.172) 10:51 11 0
2875635 문재인 정부의 실책을 학습한 민주당 [5] 아스카영원히사랑해갤로그로 이동합니다. 10:49 33 0
2875634 겜 개발할때 다렉, 컴파일러 이지랄하는 새끼가 좆병신인걸 비유해줌 ㅆㅇㅆ(124.216) 10:48 18 0
2875633 설계를 잘해놓고 시작해야지 ♥불사신냥덩♥갤로그로 이동합니다. 10:46 8 0
2875632 좆도그 담당 말마따나 컴파일러, 다렉 파는 새끼들이 제일 악질임 [2] ㅆㅇㅆ(124.216) 10:43 18 0
2875631 후..6년차32살모솔연봉3500개발자의하루가시작됬노 [2] 현무E공인(1.237) 10:40 24 0
2875630 다시보는 준스기햄 짤 [1] 루도그담당(211.184) 10:38 24 0
2875629 잘게 쪼개서 우직하게 나아가라 ♥불사신냥덩♥갤로그로 이동합니다. 10:37 7 0
2875628 솔직하게 말하자면 이재명씨 말고 이준석이랑 김문수는 수준 미달임.. ㅆㅇㅆ(124.216) 10:36 21 0
2875627 아패 베타 올리고 싶은데 슬라이드오버 없어져서 망설여진당 ♥불사신냥덩♥갤로그로 이동합니다. 10:34 7 0
2875626 개웃기넹 ㅋㅅㅋ ♥불사신냥덩♥갤로그로 이동합니다. 10:32 10 0
2875625 컴공과목 재밌는거도 있지않나 현무E공인(1.237) 10:32 28 0
2875624 이재명씨 생각보다 친미노선이 탄탄하네요 [3] 헬마스터갤로그로 이동합니다. 10:25 35 0
2875621 내가 느끼는게 대학 공부는 전공이라도 너무 분야가 많아 [6] ㅆㅇㅆ(124.216) 09:59 51 0
2875620 오히려 대학을 컴공으로 갔으면 난 프로그래밍에 흥미떨어졌을듯ㅋㅋㅋ [2] ㅆㅇㅆ(124.216) 09:55 30 0
2875619 눈으로 보고도 인지하지 못하는게 지능 차이 ♥불사신냥덩♥갤로그로 이동합니다. 09:53 16 0
2875617 난 개발에너무늦게입문했어 [1] 밀우갤로그로 이동합니다. 09:46 38 0
2875615 오늘의 작업 플레이리스트 프갤러(113.59) 09:33 23 0
2875614 RAG 완성 9월 초까지하는게 목표다 ㅆㅇㅆ(124.216) 09:16 22 0
2875613 프리랜서 계약 종료 2달전이다. [7] 찍먹갤로그로 이동합니다. 09:14 52 0
2875611 여직원한테 스윗하면 노추지 프갤러(218.154) 08:43 23 0
2875610 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08:33 14 0
2875609 하루 한 번 헤르미온느 찬양 헤르 미온느갤로그로 이동합니다. 08:32 17 0
2875604 후 영포티 상사 볼 생각에 ㅈ같노 [2] ㅇㅇ(211.234) 07:58 41 0
2875603 후.. 현무E공인(211.235) 07:26 23 0
2875602 앱히키 씨발넘아 어디갔냐 프갤러(222.108) 07:25 23 0
2875601 프갤러 고수님들 혹시 리액트 늅이 읽기 좋은 책 추천해줄실 수 잇으심? 프갤러(211.176) 06:55 21 0
2875600 Clair 오늘 중으로 안 끝나겠네 ㅠㅠ 나르시갤로그로 이동합니다. 06:52 16 0
2875598 Ada 책 쓸 계획입니다. ㅎㅎ 나르시갤로그로 이동합니다. 04:53 29 0
2875583 고시원 후기 [1] 발명도둑잡기(118.216) 02:48 60 0
2875582 음기 충전 발명도둑잡기(118.216) 02:40 33 0
2875570 자기전에 이거 들으면서 자는건 어떤가요 [6] 개멍청한유라갤로그로 이동합니다. 00:57 60 0
2875568 프갤 첫페이지 ㄹㅈㄷ네ㅋㅋㅋㅋ [1] ㅇㅇ(60.253) 00:56 78 0
2875566 올해 폭염·열대야 '0일'…가장 시원한 도시 어디? 발명도둑잡기(118.216) 00:51 22 0
2875565 스펙트럼 故김동윤, 향년 20세 데뷔 두 달만에 비보 발명도둑잡기(118.216) 00:46 22 0
2875547 요런식으로 FASTMCP쓰면 파이썬으로도 가능함 ㅆㅇㅆ(124.216) 00:23 39 0
2875544 우리 서로 사랑해요 [4] 개멍청한유라갤로그로 이동합니다. 00:18 50 0
2875538 정처기 뭘로 공부해야함? [6] 프갤러(221.167) 07.27 96 0
2875535 지금 MCP 서버 시스템 노드로 구현한것들 파이썬으로 마이그레이션해서 [5] ㅆㅇㅆ(124.216) 07.27 67 0
2875532 정병 마냥 독백 글 쓰는 애들도 [6] 루도그담당(58.239) 07.27 96 0
2875530 자폭앱 만들었음 [7] 어린이노무현갤로그로 이동합니다. 07.27 105 0
뉴스 김용임, 오늘 28일 데뷔 40주년 기념 앨범 ‘역대급여자’ 발표 “거침 없는 자신감” 디시트렌드 10:00
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2