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()