diff --git a/.idea/misc.xml b/.idea/misc.xml index 79b3c94..0b76fe5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..887d4ca --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/cmake-build-debug/BLT_TESTS", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d3f548b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,75 @@ +{ + "files.associations": { + "iostream": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "strstream": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "cinttypes": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "scoped_allocator": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cfenv": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index df2a4bf..e3365ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 1.0.3) +set(BLT_VERSION 1.0.4) set(BLT_TARGET BLT) diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h index 21bea96..aa6cf47 100644 --- a/include/blt/iterator/zip.h +++ b/include/blt/iterator/zip.h @@ -20,28 +20,23 @@ #define BLT_ITERATOR_ZIP #include +#include +#include #include namespace blt { - namespace iterator { template class zip_wrapper; - template - class zip_iterator_storage; - - template - class zip_iterator_storage_rev; - template - class zip_wrapper + class zip_wrapper { public: - using iterator_category = std::forward_iterator_tag; - using value_type = std::tuple...>; + using iterator_category = std::input_iterator_tag; + using value_type = std::tuple...>; using difference_type = blt::ptrdiff_t; using pointer = value_type; using reference = value_type; @@ -49,9 +44,9 @@ namespace blt explicit zip_wrapper(Iter... iter): iter(std::make_tuple(iter...)) {} - std::tuple...> operator*() const + std::tuple...> operator*() const { - return std::apply([](auto& ... i) { return std::make_tuple(*i...); }, iter); + return std::apply([](auto& ... i) { return std::tuple...>{*i...}; }, iter); } friend bool operator==(const zip_wrapper& a, const zip_wrapper& b) @@ -87,17 +82,30 @@ namespace blt }; template - class zip_wrapper : public zip_wrapper + class zip_wrapper : public zip_wrapper { public: - using zip_wrapper::zip_wrapper; - - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::tuple...>; + using iterator_category = std::forward_iterator_tag; + using value_type = std::tuple...>; using difference_type = blt::ptrdiff_t; using pointer = value_type; using reference = value_type; + using zip_wrapper::zip_wrapper; + }; + + template + class zip_wrapper : public zip_wrapper + { + public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = std::tuple...>; + using difference_type = blt::ptrdiff_t; + using pointer = value_type; + using reference = value_type; + public: + using zip_wrapper::zip_wrapper; + zip_wrapper& operator--() { std::apply([](auto& ... i) { ((--i), ...); }, this->iter); @@ -115,25 +123,25 @@ namespace blt template class zip_wrapper : public zip_wrapper { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = std::tuple...>; + using difference_type = blt::ptrdiff_t; + using pointer = value_type; + using reference = value_type; private: template static blt::ptrdiff_t sub(const zip_wrapper& a, const zip_wrapper& b, std::integer_sequence) { - auto min = std::min(std::get(a.iter) - std::get(b.iter)...); + blt::ptrdiff_t min = std::numeric_limits::max(); + ((min = std::min(min, std::get(a.iter) - std::get(b.iter))), ...); return min; } + public: using zip_wrapper::zip_wrapper; - using iterator_category = std::random_access_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - - using zip_bidirectional_iterator::zip_bidirectional_iterator; - zip_wrapper& operator+=(blt::ptrdiff_t n) { std::apply([n](auto& ... i) { ((i += n), ...); }, this->iter); @@ -148,22 +156,22 @@ namespace blt friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n) { - return std::apply([n](auto& ... i) { return zip_random_access_iterator{(i + n)...}; }, a.iter); + return std::apply([n](auto& ... i) { return zip_wrapper{(i + n)...}; }, a.iter); } friend zip_wrapper operator+(blt::ptrdiff_t n, const zip_wrapper& a) { - return std::apply([n](auto& ... i) { return zip_random_access_iterator{(i + n)...}; }, a.iter); + return std::apply([n](auto& ... i) { return zip_wrapper{(i + n)...}; }, a.iter); } friend zip_wrapper operator-(const zip_wrapper& a, blt::ptrdiff_t n) { - return std::apply([n](auto& ... i) { return zip_random_access_iterator{(i - n)...}; }, a.iter); + return std::apply([n](auto& ... i) { return zip_wrapper{(i - n)...}; }, a.iter); } friend zip_wrapper operator-(blt::ptrdiff_t n, const zip_wrapper& a) { - return std::apply([n](auto& ... i) { return zip_random_access_iterator{(i - n)...}; }, a.iter); + return std::apply([n](auto& ... i) { return zip_wrapper{(i - n)...}; }, a.iter); } friend blt::ptrdiff_t operator-(const zip_wrapper& a, const zip_wrapper& b) @@ -197,43 +205,199 @@ namespace blt } }; - template - class zip_iterator_storage + template + auto get_base(Iter iter) { + if constexpr (meta::is_reverse_iterator_v) + { + return std::move(iter).base(); + } else + { + return std::move(iter); + } + } - }; - - template - class zip_iterator_storage + template + class take_impl { - - }; - - template - class zip_iterator_storage - { - - }; - - template - class zip_iterator_storage_rev - { - - }; - - template - class zip_iterator_storage_rev - { - - }; - - template - class zip_iterator_storage_rev - { - + private: + template + auto take_base(blt::size_t n) + { + static_assert(!std::is_same_v, + "Cannot .take() on an input iterator!"); + auto* d = static_cast(this); + auto begin = d->begin(); + auto end = d->end(); + + // take variant for forward and bidirectional iterators + if constexpr (std::is_same_v || + std::is_same_v) + { + // with these guys we have to loop forward to move the iterators. an unfortunate inefficiency + auto new_end = begin; + for (blt::size_t i = 0; i < n; i++) + { + if constexpr (check) + { + if (new_end == end) + break; + } + ++new_end; + } + return Derived{get_base(std::move(begin)), get_base(std::move(new_end))}; + } else if constexpr (std::is_same_v) + { + // random access iterators can have math directly applied to them. + if constexpr (check) + { + return Derived{get_base(begin), + get_base(begin + std::min(n, static_cast(std::distance(begin, end))))}; + } else + { + return Derived{get_base(begin), get_base(begin + n)}; + } + } + } + + public: + auto take(blt::size_t n) + { return take_base(n); } + + auto take_or(blt::size_t n) + { return take_base(n); } }; } + template + struct iterator_pair + { + using type = Iter; + + iterator_pair(Iter begin, Iter end): begin(std::move(begin)), end(std::move(end)) + {} + + Iter begin; + Iter end; + }; + + template + class zip_iterator_storage; + + template + class zip_iterator_storage_rev; + + template + class zip_iterator_storage : public iterator::take_impl> + { + public: + using iterator_category = meta::lowest_iterator_category_t; + public: + zip_iterator_storage(iterator_pair... iterator_pairs): + m_begins(std::move(iterator_pairs.begin)...), m_ends(std::move(iterator_pairs.end)...) + {} + + zip_iterator_storage(iterator::zip_wrapper begins, iterator::zip_wrapper ends): + m_begins(std::move(begins)), m_ends(std::move(ends)) + {} + + auto rev() + { + static_assert((std::is_same_v || + std::is_same_v), + ".rev() must be used with bidirectional (or better) iterators!"); + return zip_iterator_storage_rev{m_ends, m_begins}; + } + + auto skip(blt::size_t n) + { + if constexpr (std::is_same_v) + { + + } + } + + auto begin() const + { + return m_begins; + } + + auto end() const + { + return m_ends; + } + + private: + iterator::zip_wrapper m_begins; + iterator::zip_wrapper m_ends; + }; + + template + class zip_iterator_storage_rev : public iterator::take_impl> + { + public: + using iterator_category = meta::lowest_iterator_category_t; + public: + zip_iterator_storage_rev(iterator_pair... iterator_pairs): m_begins(iterator_pairs.begin...), m_ends(iterator_pairs.end...) + { + static_assert((std::is_same_v || + std::is_same_v), + "reverse iteration is only supported on bidirectional or better iterators!"); + } + + zip_iterator_storage_rev(iterator::zip_wrapper begins, + iterator::zip_wrapper ends): m_begins(std::move(begins)), m_ends(std::move(ends)) + { + static_assert((std::is_same_v || + std::is_same_v), + "reverse iteration is only supported on bidirectional or better iterators!"); + } + + auto rev() + { + return zip_iterator_storage{m_ends.base(), m_begins.base()}; + } + + auto begin() const + { + return m_begins; + } + + auto end() const + { + return m_ends; + } + + private: + std::reverse_iterator> m_begins; + std::reverse_iterator> m_ends; + }; + + /* + * CTAD for the zip containers + */ + + template + zip_iterator_storage(iterator_pair...) -> zip_iterator_storage; + + template + zip_iterator_storage(std::initializer_list...) -> zip_iterator_storage; + + template + zip_iterator_storage_rev(iterator_pair...) -> zip_iterator_storage_rev; + + template + zip_iterator_storage_rev(std::initializer_list...) -> zip_iterator_storage_rev; + + /* + * Helper functions for creating zip containers + */ + + template + auto zip(Container& ... container) + { + return blt::zip_iterator_storage{iterator_pair{container.begin(), container.end()}...}; + } } #endif //BLT_ITERATOR_ZIP diff --git a/include/blt/meta/iterator.h b/include/blt/meta/iterator.h index 77084d0..e7df5a7 100644 --- a/include/blt/meta/iterator.h +++ b/include/blt/meta/iterator.h @@ -114,6 +114,18 @@ namespace blt::meta template using lowest_iterator_category_t = typename lowest_iterator_category::type; + + template + struct is_reverse_iterator : std::false_type + { + }; + + template + struct is_reverse_iterator> : std::true_type + {}; + + template + inline constexpr bool is_reverse_iterator_v = is_reverse_iterator::value; } #endif //BLT_META_ITERATOR_H diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 7ef2e73..93201da 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5 +Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3 diff --git a/tests/iterator_tests.cpp b/tests/iterator_tests.cpp index 5922a7a..e5a4a35 100644 --- a/tests/iterator_tests.cpp +++ b/tests/iterator_tests.cpp @@ -24,13 +24,17 @@ #include #include #include +#include -constexpr auto increasing_reverse_pairs = [](blt::size_t i, blt::size_t index, blt::size_t size) { return i == 0 ? index : (size - 1) - index; }; -constexpr auto increasing_pairs = [](blt::size_t, blt::size_t index, blt::size_t) { return index; }; -constexpr auto decreasing_pairs = [](blt::size_t, blt::size_t index, blt::size_t size) { return size - index; }; +constexpr auto increasing_reverse_pairs = + [](blt::size_t i, blt::size_t index, blt::size_t size) { return i == 0 ? index : (size - 1) - index; }; +constexpr auto increasing_pairs = + [](blt::size_t, blt::size_t index, blt::size_t) { return index; }; +constexpr auto decreasing_pairs = + [](blt::size_t, blt::size_t index, blt::size_t size) { return size - index; }; template -std::array make_array(Func&& func) +std::array make_array(Func func) { std::array array; for (auto&& [index, value] : blt::enumerate(array)) @@ -38,11 +42,22 @@ std::array make_array(Func&& func) return array; } +template +std::forward_list make_list(Func func) +{ + std::forward_list array; + for (auto index : blt::range(0ul, n)) + array.push_front(blt::vec2(func(0, index, n), func(1, index, n))); + return array; +} + constexpr blt::size_t array_size = 10; auto array_1 = make_array(increasing_reverse_pairs); auto array_2 = make_array(increasing_pairs); auto array_3 = make_array(decreasing_pairs); +auto list_1 = make_list(increasing_reverse_pairs); + void test_enumerate() { blt::log_box_t box(std::cout, "Enumerate Tests", 25); @@ -111,6 +126,30 @@ void test_pairs() void test_zip() { blt::log_box_t box(std::cout, "Zip Tests", 25); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3).rev()) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take_or(13)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).rev().take(3)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } } int main()