Brett 2024-09-30 02:38:36 -04:00
parent 1830a3936b
commit 0e5d8b6043
6 changed files with 158 additions and 169 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
include(cmake/color.cmake) include(cmake/color.cmake)
set(BLT_VERSION 1.0.6) set(BLT_VERSION 1.1.1)
set(BLT_TARGET BLT) set(BLT_TARGET BLT)

View File

@ -0,0 +1,130 @@
#pragma once
/*
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef BLT_ITERATOR_ITER_COMMON
#define BLT_ITERATOR_ITER_COMMON
#include <type_traits>
#include <iterator>
namespace blt::iterator
{
template<typename Derived>
struct wrapper_base
{
wrapper_base operator++(int)
{
auto tmp = *this;
++*this;
return tmp;
}
wrapper_base operator--(int)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::bidirectional_iterator_tag> ||
std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
auto tmp = *this;
--*this;
return tmp;
}
auto operator[](blt::ptrdiff_t n) const
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
return *(*this + n);
}
friend wrapper_base operator+(const wrapper_base& a, blt::ptrdiff_t n)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
auto copy = a;
copy += n;
return copy;
}
friend wrapper_base operator+(blt::ptrdiff_t n, const wrapper_base& a)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
auto copy = a;
copy += n;
return copy;
}
friend wrapper_base operator-(const wrapper_base& a, blt::ptrdiff_t n)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
auto copy = a;
copy -= n;
return copy;
}
friend wrapper_base operator-(blt::ptrdiff_t n, const wrapper_base& a)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
auto copy = a;
copy -= n;
return copy;
}
friend bool operator<(const wrapper_base& a, const wrapper_base& b)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
return b - a > 0;
}
friend bool operator>(const wrapper_base& a, const wrapper_base& b)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
return b < a;
}
friend bool operator>=(const wrapper_base& a, wrapper_base& b)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
return !(a < b); // NOLINT
}
friend bool operator<=(const wrapper_base& a, const wrapper_base& b)
{
static_assert(std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
"Iterator must allow random access");
return !(a > b); // NOLINT
}
friend bool operator==(const wrapper_base& a, const wrapper_base& b)
{
return a.base() == b.base();
}
friend bool operator!=(const wrapper_base& a, const wrapper_base& b)
{
return !(a.base() == b.base()); // NOLINT
}
};
}
#endif //BLT_ITERATOR_ITER_COMMON

View File

@ -1,30 +0,0 @@
#pragma once
/*
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef BLT_ITERATOR_ITER_COMMON
#define BLT_ITERATOR_ITER_COMMON
#include <type_traits>
#include <iterator>
namespace blt
{
}
#endif //BLT_ITERATOR_ITER_COMMON

View File

@ -21,7 +21,7 @@
#include <blt/std/types.h> #include <blt/std/types.h>
#include <blt/std/logging.h> #include <blt/std/logging.h>
#include <blt/iterator/iter_common.h> #include <blt/iterator/common.h>
#include <blt/iterator/zip.h> #include <blt/iterator/zip.h>
#include <blt/meta/meta.h> #include <blt/meta/meta.h>
#include <blt/meta/iterator.h> #include <blt/meta/iterator.h>

View File

@ -19,7 +19,7 @@
#ifndef BLT_ITERATOR_ZIP #ifndef BLT_ITERATOR_ZIP
#define BLT_ITERATOR_ZIP #define BLT_ITERATOR_ZIP
#include <blt/iterator/iter_common.h> #include <blt/iterator/common.h>
#include <blt/meta/meta.h> #include <blt/meta/meta.h>
#include <blt/meta/iterator.h> #include <blt/meta/iterator.h>
#include <tuple> #include <tuple>
@ -28,14 +28,11 @@ namespace blt
{ {
namespace iterator namespace iterator
{ {
template<typename Tag, typename... Iter>
class zip_wrapper;
template<typename... Iter> template<typename... Iter>
class zip_wrapper<std::input_iterator_tag, Iter...> class zip_wrapper : public wrapper_base<zip_wrapper<Iter...>>
{ {
public: public:
using iterator_category = std::input_iterator_tag; using iterator_category = meta::lowest_iterator_category_t<Iter...>;
using value_type = std::tuple<meta::deref_return_t<Iter>...>; using value_type = std::tuple<meta::deref_return_t<Iter>...>;
using difference_type = blt::ptrdiff_t; using difference_type = blt::ptrdiff_t;
using pointer = value_type; using pointer = value_type;
@ -49,99 +46,18 @@ namespace blt
return std::apply([](auto& ... i) { return std::tuple<meta::deref_return_t<Iter>...>{*i...}; }, iter); return std::apply([](auto& ... i) { return std::tuple<meta::deref_return_t<Iter>...>{*i...}; }, iter);
} }
friend bool operator==(const zip_wrapper& a, const zip_wrapper& b)
{
return a.iter == b.iter;
}
friend bool operator!=(const zip_wrapper& a, const zip_wrapper& b)
{
return !(a.iter == b.iter);
}
zip_wrapper& operator++() zip_wrapper& operator++()
{ {
std::apply([](auto& ... i) { ((++i), ...); }, iter); std::apply([](auto& ... i) { ((++i), ...); }, iter);
return *this; return *this;
} }
zip_wrapper operator++(int)
{
auto tmp = *this;
++*this;
return tmp;
}
auto raw_tuple()
{
return iter;
}
protected:
std::tuple<Iter...> iter;
};
template<typename... Iter>
class zip_wrapper<std::forward_iterator_tag, Iter...> : public zip_wrapper<std::input_iterator_tag, Iter...>
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = std::tuple<meta::deref_return_t<Iter>...>;
using difference_type = blt::ptrdiff_t;
using pointer = value_type;
using reference = value_type;
using zip_wrapper<std::input_iterator_tag, Iter...>::zip_wrapper;
};
template<typename... Iter>
class zip_wrapper<std::bidirectional_iterator_tag, Iter...> : public zip_wrapper<std::forward_iterator_tag, Iter...>
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = std::tuple<meta::deref_return_t<Iter>...>;
using difference_type = blt::ptrdiff_t;
using pointer = value_type;
using reference = value_type;
public:
using zip_wrapper<std::forward_iterator_tag, Iter...>::zip_wrapper;
zip_wrapper& operator--() zip_wrapper& operator--()
{ {
std::apply([](auto& ... i) { ((--i), ...); }, this->iter); std::apply([](auto& ... i) { ((--i), ...); }, this->iter);
return *this; return *this;
} }
zip_wrapper operator--(int)
{
auto tmp = *this;
--*this;
return tmp;
}
};
template<typename... Iter>
class zip_wrapper<std::random_access_iterator_tag, Iter...> : public zip_wrapper<std::bidirectional_iterator_tag, Iter...>
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = std::tuple<meta::deref_return_t<Iter>...>;
using difference_type = blt::ptrdiff_t;
using pointer = value_type;
using reference = value_type;
private:
template<typename T, T... n>
static blt::ptrdiff_t sub(const zip_wrapper& a, const zip_wrapper& b,
std::integer_sequence<T, n...>)
{
blt::ptrdiff_t min = std::numeric_limits<blt::ptrdiff_t>::max();
((min = std::min(min, std::get<n>(a.iter) - std::get<n>(b.iter))), ...);
return min;
}
public:
using zip_wrapper<std::bidirectional_iterator_tag, Iter...>::zip_wrapper;
zip_wrapper& operator+=(blt::ptrdiff_t n) zip_wrapper& operator+=(blt::ptrdiff_t n)
{ {
std::apply([n](auto& ... i) { ((i += n), ...); }, this->iter); std::apply([n](auto& ... i) { ((i += n), ...); }, this->iter);
@ -154,54 +70,26 @@ namespace blt
return *this; return *this;
} }
friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n)
{
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_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_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_wrapper{(i - n)...}; }, a.iter);
}
friend blt::ptrdiff_t operator-(const zip_wrapper& a, const zip_wrapper& b) friend blt::ptrdiff_t operator-(const zip_wrapper& a, const zip_wrapper& b)
{ {
return sub(a, b, std::index_sequence_for<Iter...>()); return sub(a, b, std::index_sequence_for<Iter...>());
} }
auto operator[](blt::ptrdiff_t n) const auto base()
{ {
return *(*this + n); return iter;
} }
protected:
std::tuple<Iter...> iter;
friend bool operator<(const zip_wrapper& a, const zip_wrapper& b) template<typename T, T... n>
static blt::ptrdiff_t sub(const zip_wrapper& a, const zip_wrapper& b,
std::integer_sequence<T, n...>)
{ {
return b - a > 0; blt::ptrdiff_t min = std::numeric_limits<blt::ptrdiff_t>::max();
} ((min = std::min(min, std::get<n>(a.iter) - std::get<n>(b.iter))), ...);
return min;
friend bool operator>(const zip_wrapper& a, const zip_wrapper& b)
{
return b < a;
}
friend bool operator>=(const zip_wrapper& a, const zip_wrapper& b)
{
return !(a < b); // NOLINT
}
friend bool operator<=(const zip_wrapper& a, const zip_wrapper& b)
{
return !(a > b); // NOLINT
} }
}; };
@ -294,7 +182,8 @@ namespace blt
{ {
for (blt::size_t i = 0; i < n; i++) for (blt::size_t i = 0; i < n; i++)
{ {
if constexpr (check){ if constexpr (check)
{
if (begin == end) if (begin == end)
break; break;
} }
@ -341,7 +230,7 @@ namespace blt
m_begins(std::move(iterator_pairs.begin)...), m_ends(std::move(iterator_pairs.end)...) m_begins(std::move(iterator_pairs.begin)...), m_ends(std::move(iterator_pairs.end)...)
{} {}
zip_iterator_storage(iterator::zip_wrapper<iterator_category, Iter...> begins, iterator::zip_wrapper<iterator_category, Iter...> ends): zip_iterator_storage(iterator::zip_wrapper<Iter...> begins, iterator::zip_wrapper<Iter...> ends):
m_begins(std::move(begins)), m_ends(std::move(ends)) m_begins(std::move(begins)), m_ends(std::move(ends))
{} {}
@ -372,8 +261,8 @@ namespace blt
} }
private: private:
iterator::zip_wrapper<iterator_category, Iter...> m_begins; iterator::zip_wrapper<Iter...> m_begins;
iterator::zip_wrapper<iterator_category, Iter...> m_ends; iterator::zip_wrapper<Iter...> m_ends;
}; };
template<typename... Iter> template<typename... Iter>
@ -389,8 +278,8 @@ namespace blt
"reverse iteration is only supported on bidirectional or better iterators!"); "reverse iteration is only supported on bidirectional or better iterators!");
} }
zip_iterator_storage_rev(iterator::zip_wrapper<iterator_category, Iter...> begins, zip_iterator_storage_rev(iterator::zip_wrapper<Iter...> begins,
iterator::zip_wrapper<iterator_category, Iter...> ends): m_begins(std::move(begins)), m_ends(std::move(ends)) iterator::zip_wrapper<Iter...> ends): m_begins(std::move(begins)), m_ends(std::move(ends))
{ {
static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> || static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> ||
std::is_same_v<iterator_category, std::random_access_iterator_tag>), std::is_same_v<iterator_category, std::random_access_iterator_tag>),
@ -413,8 +302,8 @@ namespace blt
} }
private: private:
std::reverse_iterator<iterator::zip_wrapper<iterator_category, Iter...>> m_begins; std::reverse_iterator<iterator::zip_wrapper<Iter...>> m_begins;
std::reverse_iterator<iterator::zip_wrapper<iterator_category, Iter...>> m_ends; std::reverse_iterator<iterator::zip_wrapper<Iter...>> m_ends;
}; };
/* /*

View File

@ -126,17 +126,17 @@ void test_pairs()
void test_zip() void test_zip()
{ {
blt::log_box_t box(std::cout, "Zip Tests", 25); blt::log_box_t box(std::cout, "Zip Tests", 25);
for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3)) for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1))
{ {
BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
} }
BLT_TRACE("================================"); BLT_TRACE("================================");
for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3)) for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3))
{ {
BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
} }
BLT_TRACE("================================"); BLT_TRACE("================================");
for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3).rev()) for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3).rev())
{ {
BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
} }