diff --git a/.idea/customTargets.xml b/.idea/customTargets.xml new file mode 100644 index 0000000..4b31099 --- /dev/null +++ b/.idea/customTargets.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Autoarr2/Autoarr2.hpp b/src/Autoarr2/Autoarr2.hpp index aa712e0..ae3e39f 100644 --- a/src/Autoarr2/Autoarr2.hpp +++ b/src/Autoarr2/Autoarr2.hpp @@ -1,6 +1,6 @@ #pragma once -#define Autoarr2_NO_REZULT -1 +#define Autoarr2_NO_REZULT (uint32)-1 template @@ -20,13 +20,16 @@ public: T get(uint32 index); void set(uint32 index, T value); void add(T value); + void remove(uint32 index); // returns index of the first inclusion // using to compare values - using cmp_func_t=bool (*)(T, T); - uint32 search(T& value, cmp_func_t cmpf, uint32 fromIndex, uint32 toIndex); - uint32 search(T& value, cmp_func_t cmpf, uint32 fromIndex); - uint32 search(T& value, cmp_func_t cmpf); + template + uint32 search(T& value, cmp_func_lambda cmpf, uint32 fromIndex, uint32 toIndex); + template + uint32 search(T& value, cmp_func_lambda cmpf, uint32 fromIndex); + template + uint32 search(T& value, cmp_func_lambda cmpf); }; @@ -49,7 +52,7 @@ Autoarr2::Autoarr2(uint16 _max_block_length) : Autoarr2() { template Autoarr2::~Autoarr2() { for (uint16 i=0;i::set(uint32 index, T value) { template void Autoarr2::add(T value) { if(!values){ - //values=(T**)malloc(sizeof(T*)); values=new T*[1]; goto create_block; } @@ -83,9 +85,9 @@ create_block: T** new_values=new T*[blocks_count+1]; for(uint32 i=0;i -uint32 Autoarr2::search(T& value, cmp_func_t cmpf, uint32 fromIndex, uint32 toIndex){ +template +uint32 Autoarr2::search(T& value, cmp_func_lambda cmpf, uint32 fromIndex, uint32 toIndex){ uint32 index=fromIndex; for(; index::search(T& value, cmp_func_t cmpf, uint32 fromIndex, uint32 t } template -uint32 Autoarr2::search(T& value, cmp_func_t cmpf, uint32 fromIndex){ +template +uint32 Autoarr2::search(T& value, cmp_func_lambda cmpf, uint32 fromIndex){ return search(value, cmpf, fromIndex, length); } template -uint32 Autoarr2::search(T& value, cmp_func_t cmpf){ +template +uint32 Autoarr2::search(T& value, cmp_func_lambda cmpf){ return search(value, cmpf, 0, length); } + +template +void Autoarr2::remove(uint32 index){ + throw_id(ERR_NOTIMPLEMENTED); +} \ No newline at end of file diff --git a/src/Hashtable2/Hashtable2.hpp b/src/Hashtable2/Hashtable2.hpp index eaa2c0b..67bb2e4 100644 --- a/src/Hashtable2/Hashtable2.hpp +++ b/src/Hashtable2/Hashtable2.hpp @@ -4,11 +4,10 @@ #include "../Autoarr2/Autoarr2.hpp" // amount of rows -typedef uint16 HT_HEIGHT_T; +typedef uint32 HT_HEIGHT_T; typedef uint32 HT_HASH_T; -#define HT_HASH(K) hashb_sdbm32(K, sizeof(K)) -#define STORE_HASHES 1 +#define STORE_HASHES 0 static const HT_HEIGHT_T HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521}; #define _HT_HEIN_MIN 0 @@ -20,162 +19,187 @@ static const HT_HEIGHT_T HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521}; template class Hashtable2{ - using cmp_func_t=bool (*)(TKey, TKey); - +// internal types + struct KeyValue{ + TKey key; + TVal value; #if STORE_HASHES - Autoarr2** hashes; - + HT_HASH_T hash; #endif - cmp_func_t keyComparFunc; - Autoarr2** keys; - Autoarr2** values; + }; + using HashKeyFunc_t=HT_HASH_T (*)(TKey); + using KeyCmpFunc_t=bool (*)(TKey, TKey); + +// fields + Autoarr2** rows; + + HashKeyFunc_t hashKeyFunc; +#if !STORE_HASHES + KeyCmpFunc_t keyComparFunc; +#endif +public: + HT_HEIGHT_T height; +private: uint8 hein; - HT_HEIGHT_T _height; - void expand(); - bool uint32_compare(uint32& a, uint32& b) { return a==b; } + +// constructors #if STORE_HASHES public: #endif - Hashtable2(); + Hashtable2(HashKeyFunc_t _hashKeyFunc); #if !STORE_HASHES public: - explicit Hashtable2(cmp_func_t _keyComparFunc); + explicit Hashtable2(HashKeyFunc_t _hashKeyFunc, KeyCmpFunc_t _keyComparFunc); #endif + +// methods +private: + void free_rows(); + TVal* getptr(TKey key, HT_HASH_T& keyHash, HT_HEIGHT_T& rowN); + void expand(); + void add(TKey& key, TVal& value, HT_HASH_T keyHash, HT_HEIGHT_T rowN); + +public: virtual ~Hashtable2(); - inline HT_HEIGHT_T height(){ return _height; } TVal* getptr(TKey key); TVal get(TKey key); - bool addOrSet(TKey key, TVal); - bool remove(TKey); + bool tryGet(TKey key, TVal* output); + void add(TKey key, TVal value); + void addOrSet(TKey key, TVal value); + void remove(TKey key); }; template -Hashtable2::Hashtable2(){ +Hashtable2::Hashtable2(HashKeyFunc_t _hashKeyFunc){ + hashKeyFunc=_hashKeyFunc; hein=_HT_HEIN_MIN; - _height=HT_HEIGHTS[hein]; -#if STORE_HASHES - hashes=new Autoarr2*[_height]; -#endif - keys=new Autoarr2*[_height]; - values=new Autoarr2*[_height]; - for(HT_HEIGHT_T i=0; i<_height; i++){ -#if STORE_HASHES - hashes[i]=new Autoarr2(_HT_ARR_BL); - keyComparFunc=NULL; -#endif - keys[i]=new Autoarr2(_HT_ARR_BL); - values[i]=new Autoarr2(_HT_ARR_BL); - } + height=HT_HEIGHTS[hein]; + rows=new Autoarr2*[height]; + for(HT_HEIGHT_T i=0; i(_HT_ARR_BL); } #if !STORE_HASHES template -Hashtable2::Hashtable2(cmp_func_t _keyComparFunc) : Hashtable2() { +Hashtable2::Hashtable2(HashKeyFunc_t _hashKeyFunc, KeyCmpFunc_t _keyComparFunc) : Hashtable2(_hashKeyFunc) { keyComparFunc=_keyComparFunc; } #endif -template -Hashtable2::~Hashtable2(){ - for(uint32 i=0; i< _height; i++){ - delete keys[i]; - delete values[i]; -#if STORE_HASHES - delete hashes[i]; -#endif - } - delete keys; - delete values; -#if STORE_HASHES - delete hashes; -#endif +template +void Hashtable2::free_rows(){ + for(uint32 i=0; i< height; i++) + delete rows[i]; + delete[] rows; } - template -void Hashtable2::expand(){ - if(hein>=_HT_HEIN_MAX) - throw_id(ERR_MAXLENGTH); - uint32 newHeight=HT_HEIGHTS[++hein]; - Autoarr2** newKeys=new Autoarr2*[newHeight]; - Autoarr2** newValues=new Autoarr2*[newHeight]; -#if STORE_HASHES - Autoarr2** newHashes=new Autoarr2*[newHeight]; -#endif - - for(HT_HEIGHT_T i=0; i(_HT_ARR_BL); - newValues[i]=new Autoarr2(_HT_ARR_BL); -#if STORE_HASHES - newHashes[i]=new Autoarr2(_HT_ARR_BL); -#endif - } - - for(HT_HEIGHT_T rowN=0; rowN<_height; rowN++){ - Autoarr2* oldKeysRow=keys[rowN]; - Autoarr2* oldValuesRow=values[rowN]; -#if STORE_HASHES - Autoarr2* oldHashesRow=hashes[rowN]; -#endif - - for(uint32 k=0; k < oldKeysRow->length; k++){ - TKey currentKey=oldKeysRow->get(k); -#if STORE_HASHES - HT_HASH_T currentHash=oldHashesRow->get(k); -#else - HT_HASH_T currentHash=HT_HASH(currentKey); -#endif - HT_HEIGHT_T newRowN=currentHash%newHeight; -#if STORE_HASHES - newHashes[newRowN]->add(currentHash); -#endif - newKeys[newRowN]->add(currentKey); - newValues[newRowN]->add(values[rowN]->get(k)); - } - } - - ~Hashtable2(); - _height=newHeight; - keys=newKeys; - values=newValues; -#if STORE_HASHES - hashes=newHashes; -#endif -} +Hashtable2::~Hashtable2() { free_rows(); } template -TVal* Hashtable2::getptr(TKey key){ - HT_HASH_T keyHash=HT_HASH(key); - HT_HEIGHT_T rowN=keyHash%_height; +TVal* Hashtable2::getptr(TKey key, HT_HASH_T& keyHash, HT_HEIGHT_T& rowN){ + keyHash=hashKeyFunc(key); + rowN=keyHash%height; + KeyValue kv; #if STORE_HASHES - uint32 index=hashes[rowN]->search(keyHash, uint32_compare); + kv.hash=keyHash; + uint32 index=rows[rowN]->search(kv, [](KeyValue kv0, KeyValue kv1) { return kv0.hash==kv1.hash; }); #else - uint32 index=keys[rowN]->search(key, keyComparFunc); + kv.key=key; + uint32 index=rows[rowN]->search(kv, [this](KeyValue kv0, KeyValue kv1) { return this->keyComparFunc(kv0.key, kv1.key); }); #endif if(index==Autoarr2_NO_REZULT) return NULL; - return values[rowN]->getptr(index); + return &(rows[rowN]->getptr(index))->value; } +template +TVal* Hashtable2::getptr(TKey key){ + HT_HASH_T keyHash; + HT_HEIGHT_T rowN; + return getptr(key, keyHash, rowN); +} template TVal Hashtable2::get(TKey key){ - + TVal* ptr=getptr(key); + if(!ptr) + throw_id(ERR_KEYNOTFOUND); + return *ptr; +} + +template +bool Hashtable2::tryGet(TKey key, TVal* output){ + TVal* ptr=getptr(key); + if(!ptr) + return false; + *output=*ptr; + return true; +} + +template +void Hashtable2::expand(){ printf("expand\n"); fflush(stdout); + if(hein>=_HT_HEIN_MAX) + throw_id(ERR_MAXLENGTH); + + uint32 newHeight=HT_HEIGHTS[++hein]; + Autoarr2** newRows=new Autoarr2*[newHeight]; + for(HT_HEIGHT_T i=0; i(_HT_ARR_BL); + + for(HT_HEIGHT_T oldRowN=0; oldRowNlength; k++){ + KeyValue kv=rows[oldRowN]->get(k); +#if STORE_HASHES + HT_HEIGHT_T newRowN=kv.hash%newHeight; +#else + HT_HEIGHT_T newRowN=hashKeyFunc(kv.key)%newHeight; +#endif + newRows[newRowN]->add(kv); + } + + free_rows(); + height=newHeight; + rows=newRows; +} + +template +void Hashtable2::add(TKey& key, TVal& value, HT_HASH_T keyHash, HT_HEIGHT_T rowN){ printf("add\n"); fflush(stdout); + Autoarr2* row=rows[rowN]; + if(row->length == _HT_ARR_BC*_HT_ARR_BL) + expand(); + KeyValue kv; + kv.key=key; + kv.value=value; +#if STORE_HASHES + kv.hash=keyHash; +#endif + row->add(kv); +} + +template +void Hashtable2::add(TKey key, TVal value){ + HT_HASH_T keyHash=hashKeyFunc(key); + HT_HEIGHT_T rowN=keyHash%height; + add(key, value, keyHash, rowN); +} + +template +void Hashtable2::addOrSet(TKey key, TVal value){ + HT_HASH_T keyHash; + HT_HEIGHT_T rowN; + TVal* valptr=getptr(key, keyHash, rowN); + if(valptr) *valptr=value; + else add(key, value, keyHash, rowN); } template -bool Hashtable2::addOrSet(TKey key, TVal){ - //expand -} - - -template -bool Hashtable2::remove(TKey){ - +void Hashtable2::remove(TKey key){ + throw_id(ERR_NOTIMPLEMENTED); } diff --git a/src/base/errors.c b/src/base/errors.c index 1df7552..e3f61a2 100644 --- a/src/base/errors.c +++ b/src/base/errors.c @@ -11,7 +11,7 @@ char* errname(ErrorId err){ case ERR_NOTIMPLEMENTED: return "ERR_NOTIMPLEMENTED"; case ERR_NULLPTR: return "ERR_NULLPTR"; case ERR_ENDOFSTR: return "ERR_ENDOFSTR"; - case ERR_DESYNC: return "ERR_DESYNC"; + case ERR_KEYNOTFOUND: return "ERR_KEYNOTFOUND"; default: return "UNKNOWN_ERROR"; } } diff --git a/src/base/errors.h b/src/base/errors.h index c4c59b5..eb347dc 100644 --- a/src/base/errors.h +++ b/src/base/errors.h @@ -11,7 +11,7 @@ typedef enum ErrorId { SUCCESS, // not an error ERR_MAXLENGTH, ERR_WRONGTYPE, ERR_WRONGINDEX, ERR_NOTIMPLEMENTED, ERR_NULLPTR, ERR_ENDOFSTR, - ERR_DESYNC + ERR_KEYNOTFOUND } ErrorId; char* errname(ErrorId err); @@ -51,10 +51,10 @@ char* __unknownErr( ); #if __cplusplus #define throw_id(E) __EXIT(((char*)__genErrMsg(errname(E), __FILE__,__LINE__,__func__))) #define throw_msg(E) __EXIT(((char*)__genErrMsg(E, __FILE__,__LINE__,__func__))) +#else + #define throw(E) __EXIT(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))) + #define safethrow(E, FREEMEM) { FREEMEM; __RETURN_EXCEPTION(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))); } #endif -#define throw(E) __EXIT(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))) -#define safethrow(E, FREEMEM) { FREEMEM; __RETURN_EXCEPTION(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))); } - #define try(_funcCall, _rezult, freeMem) Maybe _rezult=_funcCall; if(_rezult.errmsg){\ freeMem;\ diff --git a/tests/main.cpp b/tests/main.cpp index ab78183..3f7da09 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -4,12 +4,12 @@ void test_all(){ // test_string(); // test_safethrow(); // test_searchtree(); - test_autoarr(); - test_autoarr2(); + // test_autoarr(); + // test_autoarr2(); // test_hash_functions(); - test_hashtable(); + // test_hashtable(); + // test_dtsod(); test_hashtable2(); - //test_dtsod(); printf("\e[96m--------------------------------------\e[0m\n"); } diff --git a/tests/test_hashtable2.cpp b/tests/test_hashtable2.cpp index b06d8ec..558d6ed 100644 --- a/tests/test_hashtable2.cpp +++ b/tests/test_hashtable2.cpp @@ -1,58 +1,65 @@ #include "tests.h" #include "../src/Hashtable2/Hashtable2.hpp" +#include -#define TKey char* +#define TKey std::shared_ptr #define TVal uint64 #define HT_TYPE Hashtable2 -#define HT_TYPE_NAME "Hashtable2" +#define HT_TYPE_NAME "Hashtable2, uint64>" void print_hashtable(HT_TYPE* ht){ printf("\e[94m" HT_TYPE_NAME ": " IFWIN("%llu", "%lu") "\n height: %u\n", sizeof(HT_TYPE), - ht->height()); + ht->height); } -char* genkey(uint32 i){ - char* key=new char[16]; +std::shared_ptr genkey(uint32 i){ + char* key=new char[24]; IFMSC( - sprintf_s(key,16,"key_%u",i), + sprintf_s(key,24,"key_%u",i), sprintf(key,"key_%u",i) ); - return key; + dbg(i); + return std::shared_ptr(key, [](char* s){ delete[] s;}); } void fill(HT_TYPE* ht){ - //for(uint32 i=0;i<100000;i++) - // ht->add(genkey(i),Uni(UInt64,i)); + for(uint32 i=0;i<251;i++) + ht->add(genkey(i), 555666); + print_hashtable(ht); } TVal gett(HT_TYPE* ht){ TVal u; - for(uint32 i=0;i<100000;i++){ + for(uint32 i=0;i<1000;i++){ TKey key=genkey(i); - //u=ht->get(key); - delete[] key; + u=ht->get(key); } return u; } void test_hashtable2(){ - optime("test_hashtable2",1,({ + //optime("test_hashtable2",1,({ printf("\e[96m-----------[test_hashtable2]-----------\n"); #if STORE_HASHES - HT_TYPE* ht=new HT_TYPE(); + HT_TYPE* ht=new HT_TYPE( + [](TKey k) { return hashs(hash_sdbm32,k.get()); }); #else - HT_TYPE* ht=new HT_TYPE(cptr_compare); + HT_TYPE* ht=new HT_TYPE( + [](TKey k) { return hashs(hash_sdbm32,k.get()); }, + [](TKey k0, TKey k1) { return cptr_compare(k0.get(), k1.get()); }); #endif - printf("\e[92m" HT_TYPE_NAME " created\n"); + printf("\e[92mhashtable created\n"); print_hashtable(ht); optime("fill",1,fill(ht)); - optime("get",1,gett(ht)); - print_hashtable(ht); + // TVal r; + // optime("get",1,r=gett(ht)); + // dbg((uint32)r); + // print_hashtable(ht); delete ht; - printf("\e[92m" HT_TYPE_NAME " deleted\n"); - })); + printf("\e[92mhashtable deleted\n"); + //})); }