diff --git a/arraylist.hpp b/arraylist.hpp index 8140ca9..1cfb27d 100644 --- a/arraylist.hpp +++ b/arraylist.hpp @@ -35,7 +35,7 @@ struct Array_List { return data[index]; } - proc _merge(int start, int mid, int end) -> void { + void _merge(int start, int mid, int end) { int start2 = mid + 1; /* If the direct merge is already sorted */ @@ -67,7 +67,7 @@ struct Array_List { } } - proc sort(int left=-1, int right=-1) -> void { + void sort(int left=-1, int right=-1) { if (left == -1) { sort(0, next_index - 1); return; @@ -83,7 +83,7 @@ struct Array_List { _merge(left, middle, right); } - proc sorted_find(type elem, int left=-1, int right=-1) -> int { + int sorted_find(type elem, int left=-1, int right=-1) { if (left == -1) { return sorted_find(elem, 0, next_index - 1); } else if (left == right) { diff --git a/hashmap.hpp b/hashmap.hpp index 5316586..259d959 100644 --- a/hashmap.hpp +++ b/hashmap.hpp @@ -11,159 +11,301 @@ // } // } -#define __for_hm_generator(key_type, hm) \ - if (key_type key = nullptr); else \ - if (void* value = nullptr); else \ - for(int index = 0; index < hm->current_capacity; ++index) \ - if (!((!hm->data[index].deleted) && \ - (key = hm->data[index].original) && \ - (value = hm->data[index].object))); else - - -#define define_hash_map(type, name) \ - bool hm_objects_match(type,type); \ - u32 hm_hash(type); \ - \ - struct name##_Hash_Map_Cell { \ - type original; \ - u64 hash; \ - bool deleted; \ - void* object; \ - }; \ - \ - struct name##_Hash_Map { \ - int current_capacity; \ - int cell_count; \ - name##_Hash_Map_Cell* data; \ - }; \ - \ - name##_Hash_Map* create_##name##_hashmap(int initial_capacity=8) { \ - name##_Hash_Map* hm = new name##_Hash_Map; \ - hm->current_capacity = initial_capacity; \ - hm->cell_count = 0; \ - /* set all data to nullptr */ \ - hm->data = (name##_Hash_Map_Cell*)calloc(initial_capacity, sizeof(name##_Hash_Map_Cell)); \ - /* printf("check: %s\n", hm->data[6].original_string); */ \ - return hm; \ - } \ - \ - int hm_get_index_of_living_cell_if_it_exists(name##_Hash_Map* hm, type key, u64 hash_val) { \ - int index = hash_val % hm->current_capacity; \ - name##_Hash_Map_Cell cell = hm->data[index]; \ - /* test if cell exists at that index */ \ - if (cell.original) { \ - /* check if strings match */ \ - if (hm_objects_match(key, cell.original)) { \ - /* we found it, now check it it is deleted: */ \ - if (cell.deleted) { \ - /* we found it but it was deleted, we */ \ - /* dont have to check for collisions then */ \ - return -1; \ - } else { \ - /* we found it and it is not deleted */ \ - return index; \ - } \ - } else { \ - /* strings dont match, this means we have */ \ - /* a collision. We just search forward */ \ - for (int i = 0; i < hm->current_capacity; ++i) { \ - int new_idx = (i + index) % hm->current_capacity; \ - cell = hm->data[new_idx]; \ - if (!cell.original) \ - return -1; \ - if (!hm_objects_match(key, cell.original)) \ - continue; \ - if (cell.deleted) \ - continue; \ - return new_idx; \ - } \ - /* not or only deleted cells found */ \ - return -1; \ - } \ - } else { \ - /* no cell exists at this index so the item was never in the */ \ - /* hashmap. Either it would be there or be ther and 'deleted' */ \ - /* or another item would be there and therefore a collistion */ \ - /* would exist */ \ - return -1; \ - } \ - } \ - \ - inline bool hm_key_exists(name##_Hash_Map* hm, type key) { \ - return hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)) != -1; \ - } \ - \ - inline void* hm_get_object(name##_Hash_Map* hm, type key) { \ - int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \ - if (index != -1) { \ - return hm->data[index].object; \ - } \ - return nullptr; \ - } \ - \ - inline void hm_delete_object(name##_Hash_Map* hm, type key) { \ - int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \ - if (index != -1) { \ - hm->data[index].deleted = true; \ - } \ - } \ - \ - void hm_set(name##_Hash_Map* hm, type key, void* obj) { \ - u64 hash_val = hm_hash(key); \ - int index = hash_val % hm->current_capacity; \ - \ - /* if we the desired cell is just empty, write to it and done :) */ \ - if (!hm->data[index].original) { \ - /* insert new cell into desired slot */ \ - ++hm->cell_count; \ - } else { \ - if (hm_objects_match(key, hm->data[index].original)) { \ - /* overwrite object with same key, dont increment cell */ \ - /* count */ \ - } else { \ - /* collision, check resize */ \ - ++hm->cell_count; \ - if ((hm->cell_count*1.0f / hm->current_capacity) > 0.666f) { \ - auto old_data = hm->data; \ - hm->data = (name##_Hash_Map_Cell*)calloc(hm->current_capacity*4, sizeof(name##_Hash_Map_Cell)); \ - hm->cell_count = 0; \ - hm->current_capacity *= 4; \ - \ - /* insert all old items again */ \ - for (int i = 0; i < hm->current_capacity/4; ++i) { \ - auto cell = old_data[i]; \ - if (cell.original) { \ - hm_set(hm, cell.original, cell.object); \ - } \ - } \ - free(old_data); \ - index = hash_val % hm->current_capacity; \ - } \ - /* search for empty slot for new cell starting at desired index; */ \ - /* preventing gotos using lambdas! */ \ - [&](){ \ - for (int i = index; i < hm->current_capacity; ++i) { \ - if (!hm->data[i].original || \ - hm_objects_match(hm->data[i].original, key)) \ - { \ - index = i; \ - return; \ - } \ - } \ - for (int i = 0; i < index; ++i) { \ - if (!hm->data[i].original || \ - hm_objects_match(hm->data[i].original, key)) \ - { \ - index = i; \ - return; \ - } \ - } \ - }(); \ - } \ - } \ - \ - hm->data[index].deleted = false; \ - hm->data[index].original = key; \ - hm->data[index].hash = hash_val; \ - hm->data[index].object = obj; \ - } \ +#define __for_hm_generator(key_type, value_type, hm) \ + if (key_type key = 0); else \ + if (value_type value = 0); else \ + for(int index = 0; index < hm.current_capacity; ++index) \ + if (!((!hm.data[index].deleted) && \ + (key = hm.data[index].original) && \ + (value = hm.data[index].object))); else + + +template +struct Hash_Map { + int current_capacity; + int cell_count; + struct HM_Cell { + key_type original; + u64 hash; + bool deleted; + value_type object; + }* data; + + Hash_Map(int initial_capacity = 8) { + current_capacity = initial_capacity; + cell_count = 0; + data = (HM_Cell*)calloc(initial_capacity, sizeof(HM_Cell)); + } + + int get_index_of_living_cell_if_it_exists(key_type key, u64 hash_val) { + // int index = hash_val & (current_capacity - 1); + int index = hash_val % current_capacity; + HM_Cell cell = data[index]; + /* test if cell exists at that index */ + if (cell.original) { + /* check if strings match */ + if (hm_objects_match(key, cell.original)) { + /* we found it, now check it it is deleted: */ + if (cell.deleted) { + /* we found it but it was deleted, we */ + /* dont have to check for collisions then */ + return -1; + } else { + /* we found it and it is not deleted */ + return index; + } + } else { + /* strings dont match, this means we have */ + /* a collision. We just search forward */ + for (int i = 0; i < current_capacity; ++i) { + int new_idx = (i + index) % current_capacity; + cell = data[new_idx]; + if (!cell.original) + return -1; + if (!hm_objects_match(key, cell.original)) + continue; + if (cell.deleted) + continue; + return new_idx; + } + /* not or only deleted cells found */ + return -1; + } + } else { + /* no cell exists at this index so the item was never in the */ + /* hashmap. Either it would be there or be ther and 'deleted' */ + /* or another item would be there and therefore a collistion */ + /* would exist */ + return -1; + } + } + + bool key_exists(key_type key) { + return get_index_of_living_cell_if_it_exists(key, hm_hash(key)) != -1; + } + + value_type get_object(key_type key) { + int index = get_index_of_living_cell_if_it_exists(key, hm_hash(key)); + if (index != -1) { + return data[index].object; + } + int a = *((int*)(nullptr)); + return 0; + } + + void delete_object(key_type key) { + int index = get_index_of_living_cell_if_it_exists(key, hm_hash(key)); + if (index != -1) { + data[index].deleted = true; + } + } + + void set_object(key_type key, value_type obj) { + u64 hash_val = hm_hash(key); + int index = hash_val % current_capacity; + + /* if we the desired cell is just empty, write to it and done :) */ + if (!data[index].original) { + /* insert new cell into desired slot */ + ++cell_count; + } else { + if (hm_objects_match(key, data[index].original)) { + /* overwrite object with same key, dont increment cell */ + /* count */ + } else { + /* collision, check resize */ + ++cell_count; + if ((cell_count*1.0f / current_capacity) > 0.666f) { + auto old_data = data; + data = (HM_Cell*)calloc(current_capacity*4, sizeof(HM_Cell)); + cell_count = 0; + current_capacity *= 4; + + /* insert all old items again */ + for (int i = 0; i < current_capacity/4; ++i) { + auto cell = old_data[i]; + if (cell.original) { + set_object(cell.original, cell.object); + } + } + free(old_data); + index = hash_val % current_capacity; + } + /* search for empty slot for new cell starting at desired index; */ + /* preventing gotos using lambdas! */ + [&](){ + for (int i = index; i < current_capacity; ++i) { + if (!data[i].original || + hm_objects_match(data[i].original, key)) + { + index = i; + return; + } + } + for (int i = 0; i < index; ++i) { + if (!data[i].original || + hm_objects_match(data[i].original, key)) + { + index = i; + return; + } + } + }(); + } + } + + data[index].deleted = false; + data[index].original = key; + data[index].hash = hash_val; + data[index].object = obj; + } + +}; + +// #define define_hash_map(type, name) \ +// bool hm_objects_match(type,type); \ +// u32 hm_hash(type); \ +// \ +// struct name##_Hash_Map_Cell { \ +// type original; \ +// u64 hash; \ +// bool deleted; \ +// void* object; \ +// }; \ +// \ +// struct name##_Hash_Map { \ +// int current_capacity; \ +// int cell_count; \ +// name##_Hash_Map_Cell* data; \ +// }; \ +// \ +// name##_Hash_Map* create_##name##_hashmap(int initial_capacity=8) { \ +// name##_Hash_Map* hm = new name##_Hash_Map; \ +// hm->current_capacity = initial_capacity; \ +// hm->cell_count = 0; \ +// /* set all data to nullptr */ \ +// hm->data = (name##_Hash_Map_Cell*)calloc(initial_capacity, sizeof(name##_Hash_Map_Cell)); \ +// /* printf("check: %s\n", hm->data[6].original_string); */ \ +// return hm; \ +// } \ +// \ +// int hm_get_index_of_living_cell_if_it_exists(name##_Hash_Map* hm, type key, u64 hash_val) { \ +// int index = hash_val % hm->current_capacity; \ +// name##_Hash_Map_Cell cell = hm->data[index]; \ +// /* test if cell exists at that index */ \ +// if (cell.original) { \ +// /* check if strings match */ \ +// if (hm_objects_match(key, cell.original)) { \ +// /* we found it, now check it it is deleted: */ \ +// if (cell.deleted) { \ +// /* we found it but it was deleted, we */ \ +// /* dont have to check for collisions then */ \ +// return -1; \ +// } else { \ +// /* we found it and it is not deleted */ \ +// return index; \ +// } \ +// } else { \ +// /* strings dont match, this means we have */ \ +// /* a collision. We just search forward */ \ +// for (int i = 0; i < hm->current_capacity; ++i) { \ +// int new_idx = (i + index) % hm->current_capacity; \ +// cell = hm->data[new_idx]; \ +// if (!cell.original) \ +// return -1; \ +// if (!hm_objects_match(key, cell.original)) \ +// continue; \ +// if (cell.deleted) \ +// continue; \ +// return new_idx; \ +// } \ +// /* not or only deleted cells found */ \ +// return -1; \ +// } \ +// } else { \ +// /* no cell exists at this index so the item was never in the */ \ +// /* hashmap. Either it would be there or be ther and 'deleted' */ \ +// /* or another item would be there and therefore a collistion */ \ +// /* would exist */ \ +// return -1; \ +// } \ +// } \ +// \ +// inline bool hm_key_exists(name##_Hash_Map* hm, type key) { \ +// return hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)) != -1; \ +// } \ +// \ +// inline void* hm_get_object(name##_Hash_Map* hm, type key) { \ +// int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \ +// if (index != -1) { \ +// return hm->data[index].object; \ +// } \ +// return nullptr; \ +// } \ +// \ +// inline void hm_delete_object(name##_Hash_Map* hm, type key) { \ +// int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \ +// if (index != -1) { \ +// hm->data[index].deleted = true; \ +// } \ +// } \ +// \ +// void hm_set(name##_Hash_Map* hm, type key, void* obj) { \ +// u64 hash_val = hm_hash(key); \ +// int index = hash_val % hm->current_capacity; \ +// \ +// /* if we the desired cell is just empty, write to it and done :) */ \ +// if (!hm->data[index].original) { \ +// /* insert new cell into desired slot */ \ +// ++hm->cell_count; \ +// } else { \ +// if (hm_objects_match(key, hm->data[index].original)) { \ +// /* overwrite object with same key, dont increment cell */ \ +// /* count */ \ +// } else { \ +// /* collision, check resize */ \ +// ++hm->cell_count; \ +// if ((hm->cell_count*1.0f / hm->current_capacity) > 0.666f) { \ +// auto old_data = hm->data; \ +// hm->data = (name##_Hash_Map_Cell*)calloc(hm->current_capacity*4, sizeof(name##_Hash_Map_Cell)); \ +// hm->cell_count = 0; \ +// hm->current_capacity *= 4; \ +// \ +// /* insert all old items again */ \ +// for (int i = 0; i < hm->current_capacity/4; ++i) { \ +// auto cell = old_data[i]; \ +// if (cell.original) { \ +// hm_set(hm, cell.original, cell.object); \ +// } \ +// } \ +// free(old_data); \ +// index = hash_val % hm->current_capacity; \ +// } \ +// /* search for empty slot for new cell starting at desired index; */ \ +// /* preventing gotos using lambdas! */ \ +// [&](){ \ +// for (int i = index; i < hm->current_capacity; ++i) { \ +// if (!hm->data[i].original || \ +// hm_objects_match(hm->data[i].original, key)) \ +// { \ +// index = i; \ +// return; \ +// } \ +// } \ +// for (int i = 0; i < index; ++i) { \ +// if (!hm->data[i].original || \ +// hm_objects_match(hm->data[i].original, key)) \ +// { \ +// index = i; \ +// return; \ +// } \ +// } \ +// }(); \ +// } \ +// } \ +// \ +// hm->data[index].deleted = false; \ +// hm->data[index].original = key; \ +// hm->data[index].hash = hash_val; \ +// hm->data[index].object = obj; \ +// } \