diff --git a/.vscode/launch.json b/.vscode/launch.json index d56a9f9..039c682 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "type": "gdb", "request": "launch", "name": "Launch Program", - "target": "./bin/tests", + "target": "${workspaceRoot}/bin/tests", "cwd": "${workspaceRoot}", "valuesFormatting": "parseText", "env": {"LLVM_PROFILE_FILE":"./bin/tests.profraw"} diff --git a/Makefile b/Makefile index b8c758b..4b276dc 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ EVERY_TEST_FILE= $(shell find tests/ -name "*.cpp" -type "f") TEST_OBJECTS := $(EVERY_TEST_FILE:%.cpp=bin/obj/%.test.o) all: tests -bin/obj/%.test.o: %.cpp +bin/obj/%.test.o: %.cpp $(EVERY_USEFUL_FILE) @mkdir -p $(@D) $(CXX) $(CXXFLAGS) -DUSE_CATCH -Itests -Iinclude -o $@ -c $< diff --git a/include/gp/algorithms/partition.hpp b/include/gp/algorithms/partition.hpp new file mode 100644 index 0000000..898caa8 --- /dev/null +++ b/include/gp/algorithms/partition.hpp @@ -0,0 +1,44 @@ +#pragma once +#include + +namespace gp { + template + it_t lomuto_partition(it_t first, it_t last, pred predicate = pred{}) { + auto pivot = *--it_t(last); + + auto i = --it_t(first); + + for(auto j = first; j != last; ++j) { + if(!predicate(*j, pivot)){ + ++i; + gp::swap(*i, *j); + } + } + + return i; + } + + template + it_t hoare_partition(it_t first, it_t last, pred predicate = pred{}) { + while(first != last) { + while(predicate(*first)) { + ++first; + if(first == last) return first; + } + do { + --last; + if(first == last) return first; + } while(!predicate(*last)); + + swap(*first, *last); + ++first; + } + return first; + } + + + template + it_t partition(it_t first, it_t last, pred predicate = pred{}) { + return gp::hoare_partition(first, last, predicate); + } +} \ No newline at end of file diff --git a/include/gp/algorithms/sort.hpp b/include/gp/algorithms/sort.hpp index 9181ed7..0ee73d1 100644 --- a/include/gp/algorithms/sort.hpp +++ b/include/gp/algorithms/sort.hpp @@ -1,25 +1,75 @@ #pragma once #include +#include +#include namespace gp { - template - void selection_sort(it_t first, it_t last, pred predicate = pred{}) { - - while(first != last) { - auto traveler = first; - auto it = first; - it++; - for(;it!=last;it++) { - if(predicate(*it, *traveler)) traveler = it; + + namespace __details { + template + void selection_sort(it_t first, it_t last, pred predicate = pred{}) { + + while(first != last) { + it_t traveler = first; + it_t it = first; + it++; + for(;it!=last;it++) { + if(predicate(*it, *traveler)) traveler = it; + } + gp::swap(*first, *traveler); + first++; + } + } + + template + bool sort2(auto it0, auto it1, pred predicate = pred{}){ + if(it0 != it1 && predicate(*it1, *it0)) { + gp::swap(*it0, *it1); + return true; + } + return false; + }; + + template + void quick_sort(it_t first, it_t last, pred predicate = pred{}) { + using __details::sort2; + if(last - first <= 2) { + auto nit = first + (size_t)(last == first + 1); + __details::sort2(first, nit, predicate); + return; + } + auto pivot_v = *(first + (last - first)/2); + auto pivot = gp::partition(first, last, [&](auto& a) -> bool{ + return predicate(a, pivot_v); + }); + gp::__details::quick_sort(first, pivot, predicate); + gp::__details::quick_sort(pivot, last, predicate); + } + + template + void bubble_sort(it_t first, it_t last, pred predicate = pred{}) { + if(last - first <= 2) { + auto nit = first + (size_t)(last == first + 1); + __details::sort2(first, nit, predicate); + return; } - gp::swap(*first, *traveler); - first++; + size_t swaps; + do { + swaps = 0; + auto it = first; + auto nit = it + 1; + for(;;) { + swaps += __details::sort2(it, nit, predicate); + ++it; ++nit; + if(nit == last) break; + } + } while(swaps); } } template void sort(it_t first, it_t last, pred predicate = pred{}) { - return selection_sort(first, last, predicate); + return gp::__details::bubble_sort(first, last, predicate); } } \ No newline at end of file diff --git a/include/gp/containers/dynarray.hpp b/include/gp/containers/dynarray.hpp index 9895f85..d3a6ee2 100644 --- a/include/gp/containers/dynarray.hpp +++ b/include/gp/containers/dynarray.hpp @@ -70,12 +70,36 @@ namespace gp { } } - /*dynarray(dynarray&& oth) + dynarray(dynarray&& oth) { + for(auto& ref : oth) { + emplace_back(gp::move(ref)); + } + oth.sz = 0; + } + + dynarray& operator=(const dynarray& oth) { + for(auto& self : data) { + self.clear(); + } + sz = 0; + for(auto& ref : oth) { + push_back(ref); + } + return *this; + } + + dynarray& operator=(dynarray&& oth) { + for(auto& self : data) { + self.clear(); + } + sz = 0; for(auto& ref : oth) { emplace_back(gp::forward(ref)); } - }*/ + oth.sz = 0; + return *this; + } constexpr associated_iterator begin() { @@ -87,6 +111,16 @@ namespace gp { return associated_iterator((T*)&data[sz]); } + constexpr const associated_iterator begin() const + { + return associated_iterator((T*)&data[0]); + } + + constexpr const associated_iterator end() const + { + return associated_iterator((T*)&data[sz]); + } + constexpr associated_const_iterator cbegin() const { return associated_const_iterator((T*)&data[0]); diff --git a/include/gp/containers/vector.hpp b/include/gp/containers/vector.hpp index 1db8cf9..b3b879d 100644 --- a/include/gp/containers/vector.hpp +++ b/include/gp/containers/vector.hpp @@ -293,50 +293,50 @@ namespace gp{ return gp::move(ret_val); } - void remove(pointer_iterator it) { - for(auto step = it + 1; step it) { + for(auto step = it + 1; step!=end(); step++) { (*it++) = gp::move(*step); } - *rbegin().~T(); + (*rbegin()).~T(); sz -= 1; } - constexpr pointer_iterator begin() + constexpr gp::pointer_iterator begin() { return associated_iterator(&ary[0]); } - constexpr pointer_iterator end() + constexpr gp::pointer_iterator end() { return associated_iterator(&ary[sz]); } - constexpr const_pointer_iterator cbegin() const + constexpr gp::const_pointer_iterator cbegin() const { return associated_const_iterator(&ary[0]); } - constexpr const_pointer_iterator cend() const + constexpr gp::const_pointer_iterator cend() const { return associated_const_iterator(&ary[sz]); } - constexpr pointer_iterator rbegin() + constexpr gp::pointer_iterator rbegin() { return associated_riterator(&ary[sz-1]); } - constexpr pointer_iterator rend() + constexpr gp::pointer_iterator rend() { return associated_riterator(ary-1); } - constexpr const_pointer_iterator crbegin() const + constexpr gp::const_pointer_iterator crbegin() const { return associated_const_riterator(&ary[sz-1]); } - constexpr const_pointer_iterator crend() const + constexpr gp::const_pointer_iterator crend() const { return associated_const_riterator(ary-1); } diff --git a/include/gp/functional/function.hpp b/include/gp/functional/function.hpp index 389428d..9018627 100644 --- a/include/gp/functional/function.hpp +++ b/include/gp/functional/function.hpp @@ -157,11 +157,11 @@ namespace gp{ } function& operator=(function&& rhs) { - gp::swap(alloc, rhs.alloc); - gp::swap(invokator, rhs.invokator); - gp::swap(condestructor, rhs.condestructor); - gp::swap(data_ptr,rhs.data_ptr); - gp::swap(data_size,rhs.data_size); + swap(alloc, rhs.alloc); + swap(invokator, rhs.invokator); + swap(condestructor, rhs.condestructor); + swap(data_ptr,rhs.data_ptr); + swap(data_size,rhs.data_size); return *this; } diff --git a/include/gp/utils/iterators/pointer_iterator.hpp b/include/gp/utils/iterators/pointer_iterator.hpp index b470942..be17c89 100644 --- a/include/gp/utils/iterators/pointer_iterator.hpp +++ b/include/gp/utils/iterators/pointer_iterator.hpp @@ -19,7 +19,7 @@ namespace gp { { T* data; /**< the only data field of the class */ typedef T value_type; /**< The type of which a reference will be returned on dereferencing */ - typedef std::size_t difference_type; /**< The type of the substraction of two pointers */ + typedef std::intptr_t difference_type; /**< The type of the substraction of two pointers */ static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; /**< @see iterator_type_t */ /** @@ -81,6 +81,11 @@ namespace gp { return pointer_iterator{data+sign*offset}; } + constexpr pointer_iterator operator+(const difference_type offset) const + { + return pointer_iterator{data+sign*offset}; + } + constexpr pointer_iterator operator+(const int offset) const { return pointer_iterator{data+sign*offset}; @@ -91,6 +96,11 @@ namespace gp { return pointer_iterator{data-sign*offset}; } + constexpr pointer_iterator operator-(const difference_type offset) const + { + return pointer_iterator{data-sign*offset}; + } + constexpr pointer_iterator operator-(const int offset) const { return pointer_iterator{data-sign*offset}; @@ -98,7 +108,7 @@ namespace gp { constexpr difference_type operator-(const pointer_iterator& oth) const { - return ((T*)data-(T*)oth.data)*sign; + return (data-oth.data)*sign; } constexpr bool operator==(const pointer_iterator oth) const @@ -116,10 +126,20 @@ namespace gp { return reinterpret_cast(data) <= reinterpret_cast(oth.data); } + constexpr bool after_or_equal(const pointer_iterator oth) const + { + return reinterpret_cast(data) >= reinterpret_cast(oth.data); + } + constexpr bool operator<=(const pointer_iterator oth) const { return before_or_equal(oth); } + + constexpr bool operator>=(const pointer_iterator oth) const + { + return after_or_equal(oth); + } }; /** @@ -134,7 +154,7 @@ namespace gp { { const T* data; /**< @see pointer_iterator */ typedef T value_type; /**< @see pointer_iterator */ - typedef std::size_t difference_type; /**< @see pointer_iterator */ + typedef std::intptr_t difference_type; /**< @see pointer_iterator */ static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; /**< @see pointer_iterator */ constexpr const_pointer_iterator(const const_pointer_iterator& oth) @@ -187,11 +207,21 @@ namespace gp { return const_pointer_iterator{data+sign*offset}; } + constexpr const_pointer_iterator operator+(const difference_type offset) const + { + return const_pointer_iterator{data+sign*offset}; + } + constexpr const_pointer_iterator operator+(const int offset) const { return const_pointer_iterator{data+sign*offset}; } + constexpr const_pointer_iterator operator-(const difference_type offset) const + { + return const_pointer_iterator{data-sign*offset}; + } + constexpr const_pointer_iterator operator-(const std::size_t offset) const { return const_pointer_iterator{data-sign*offset}; @@ -222,9 +252,19 @@ namespace gp { return reinterpret_cast(data) <= reinterpret_cast(oth.data); } + constexpr bool after_or_equal(const const_pointer_iterator oth) const + { + return reinterpret_cast(data) >= reinterpret_cast(oth.data); + } + constexpr bool operator<=(const const_pointer_iterator oth) const { return before_or_equal(oth); } + + constexpr bool operator>=(const const_pointer_iterator oth) const + { + return after_or_equal(oth); + } }; } \ No newline at end of file diff --git a/tests/arena_test.cpp b/tests/arena_test.cpp new file mode 100644 index 0000000..af4bdd5 --- /dev/null +++ b/tests/arena_test.cpp @@ -0,0 +1,37 @@ +#include "gp/utils/pointers.hpp" +#include "gp/utils/allocators/arena.hpp" +#include "test_scaffold.h" +#include "allocator.hpp" +#include + + +struct arena_test : public test_scaffold { + uint32_t seed; + + arena_test() { + name = __FILE__ ":1"; + } + + virtual int run() { + int return_val = 0; + std::unique_ptr> store = std::make_unique>(); + gp::arena alloc{&*store->begin(), store->size()}; + auto v = gp::unique_ptr::make(alloc, 1024); + gp::arena alloc2{alloc, 1024}; + gp::arena alloc3{}; + { + auto v2 = gp::unique_ptr::make(alloc2, 1024); + void* some_memory = alloc2.allocate(128); + if(!some_memory) return_val++; + if(alloc2.deallocate(nullptr)) return_val++; + } + { + if(alloc3.allocate(4)) return_val++; + if(alloc3.deallocate(nullptr)) return_val++; + } + alloc2.reset(); + return return_val; + } +}; + +append_test dummy_8djbvs543(new arena_test{}); \ No newline at end of file diff --git a/tests/dynarray_test.cpp b/tests/dynarray_test.cpp new file mode 100644 index 0000000..498ed8f --- /dev/null +++ b/tests/dynarray_test.cpp @@ -0,0 +1,63 @@ +#include "gp/containers/dynarray.hpp" +#include "gp/containers/vector.hpp" +#include "gp/algorithms/sort.hpp" +#include "test_scaffold.h" +#include "allocator.hpp" +#include + +#include +#include +#include +#include + +typedef std::mt19937_64 cheap_rand; + + + +struct dynarray_test : public test_scaffold { + uint32_t seed; + + dynarray_test() { + name = __FILE__ ":1_seed"; + seed = std::random_device{}(); + name += std::to_string(seed); + } + + virtual int run() { + using val = gp::dynarray; + cheap_rand setter(seed); + + std::unique_ptr> store = std::make_unique>(); + gp::buddy alloc{&*store->begin(), store->size()}; + + gp::vector vals{alloc}; + std::uniform_int_distribution dist(0,99); + for(int i = 0; i < 1000; i++) { + val insert{}; + int max = dist(setter); + for(int b = 0; b < max; b++) { + insert.emplace_back(b); + } + vals.emplace_back(insert); + } + + for(int i = 0; i < vals.size(); i++) { + for(int j = i+1; j < vals.size(); j++) { + if(!(vals[i] != vals[j])) { + if(vals[i] == vals[j]) { + vals.remove(vals.begin()+j); + j--; + } + } + } + } + + gp::sort(vals.begin(), vals.end(), [](const val& a, const val& b){ + return a.size() < b.size(); + }); + + return vals.size() > 100; + } +}; + +append_test dummy_afdglys543(new dynarray_test{}); \ No newline at end of file diff --git a/tests/flat_tree_test.cpp b/tests/flat_tree_test.cpp index cdcf895..7ce2ac4 100644 --- a/tests/flat_tree_test.cpp +++ b/tests/flat_tree_test.cpp @@ -12,9 +12,9 @@ struct flat_tree_test : public test_scaffold { gp::flat_tree hello(v); for(auto elem : hello) { - std::cout << elem << std::endl; + //std::cout << elem << std::endl; } - + // TODO: implement a proper test, not this sad placeholder return 0; } }; diff --git a/tests/math.cpp b/tests/math.cpp index 7edff01..0ca043a 100644 --- a/tests/math.cpp +++ b/tests/math.cpp @@ -193,7 +193,7 @@ struct math_funcs_test : public test_scaffold { this->low = low; this->high = high; seed = std::random_device{}(); - name = __FILE__ ":4_sort_pair"; + name = __FILE__ ":4_math_funcs"; name += std::to_string(seed); }