Loading...
Searching...
No Matches
trace_iterator_base.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <concepts>
#include <ranges>
#include <seqan3/alignment/matrix/detail/trace_directions.hpp>
#include <seqan3/alignment/matrix/detail/two_dimensional_matrix_iterator_base.hpp>
#include <seqan3/alignment/matrix/detail/two_dimensional_matrix_iterator_concept.hpp>
namespace seqan3::detail
{
template <typename derived_t, two_dimensional_matrix_iterator matrix_iter_t>
class trace_iterator_base
{
private:
static_assert(std::same_as<std::iter_value_t<matrix_iter_t>, trace_directions>,
"Value type of the underlying iterator must be seqan3::detail::trace_directions.");
template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
friend class trace_iterator_base;
friend derived_t;
constexpr trace_iterator_base() = default;
constexpr trace_iterator_base(trace_iterator_base const &) = default;
constexpr trace_iterator_base(trace_iterator_base &&) = default;
constexpr trace_iterator_base & operator=(trace_iterator_base const &) = default;
constexpr trace_iterator_base & operator=(trace_iterator_base &&) = default;
~trace_iterator_base() = default;
constexpr trace_iterator_base(matrix_iter_t const matrix_iter) noexcept : matrix_iter{matrix_iter}
{
set_trace_direction(*matrix_iter);
}
template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
requires std::constructible_from<matrix_iter_t, other_matrix_iter_t>
constexpr trace_iterator_base(trace_iterator_base<other_derived_t, other_matrix_iter_t> const & other) noexcept :
trace_iterator_base{other.matrix_iter}
{}
public:
// Doxygen: https://github.com/seqan/product_backlog/issues/424
using value_type = trace_directions;
using reference = trace_directions const &;
using pointer = value_type const *;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
reference operator*() const noexcept
{
return current_direction;
}
pointer operator->() const noexcept
{
return &current_direction;
}
[[nodiscard]] constexpr matrix_coordinate coordinate() const noexcept
{
return matrix_iter.coordinate();
}
constexpr derived_t & operator++() noexcept
{
trace_directions old_dir = *matrix_iter;
assert(old_dir != trace_directions::none);
if (current_direction == trace_directions::up)
{
derived().go_up(matrix_iter);
// Set new trace direction if last position was up_open.
if (static_cast<bool>(old_dir & trace_directions::carry_up_open))
set_trace_direction(*matrix_iter);
}
else if (current_direction == trace_directions::left)
{
derived().go_left(matrix_iter);
// Set new trace direction if last position was left_open.
if (static_cast<bool>(old_dir & trace_directions::carry_left_open))
set_trace_direction(*matrix_iter);
}
else
{
assert(current_direction == trace_directions::diagonal);
derived().go_diagonal(matrix_iter);
set_trace_direction(*matrix_iter);
}
return derived();
}
constexpr derived_t operator++(int) noexcept
{
derived_t tmp{derived()};
++(*this);
return tmp;
}
constexpr friend bool operator==(derived_t const & lhs, derived_t const & rhs) noexcept
{
return lhs.matrix_iter == rhs.matrix_iter;
}
constexpr friend bool operator==(derived_t const & lhs, std::default_sentinel_t const &) noexcept
{
return *lhs.matrix_iter == trace_directions::none;
}
constexpr friend bool operator==(std::default_sentinel_t const &, derived_t const & rhs) noexcept
{
return rhs == std::default_sentinel;
}
constexpr friend bool operator!=(derived_t const & lhs, derived_t const & rhs) noexcept
{
return !(lhs == rhs);
}
constexpr friend bool operator!=(derived_t const & lhs, std::default_sentinel_t const &) noexcept
{
return !(lhs == std::default_sentinel);
}
constexpr friend bool operator!=(std::default_sentinel_t const &, derived_t const & rhs) noexcept
{
return !(rhs == std::default_sentinel);
}
private:
constexpr void go_left(matrix_iter_t & iter) const noexcept
{
iter -= matrix_offset{row_index_type{0}, column_index_type{1}};
}
constexpr void go_up(matrix_iter_t & iter) const noexcept
{
iter -= matrix_offset{row_index_type{1}, column_index_type{0}};
}
constexpr void go_diagonal(matrix_iter_t & iter) const noexcept
{
iter -= matrix_offset{row_index_type{1}, column_index_type{1}};
}
void set_trace_direction(trace_directions const dir) noexcept
{
if (static_cast<bool>(dir & trace_directions::diagonal))
{
current_direction = trace_directions::diagonal;
}
else if (static_cast<bool>(dir & trace_directions::up))
{
current_direction = trace_directions::up;
}
else if (static_cast<bool>(dir & trace_directions::left))
{
current_direction = trace_directions::left;
}
else
{
current_direction = trace_directions::none;
}
}
constexpr derived_t & derived() noexcept
{
return static_cast<derived_t &>(*this);
}
constexpr derived_t const & derived() const noexcept
{
return static_cast<derived_t const &>(*this);
}
matrix_iter_t matrix_iter{};
trace_directions current_direction{};
};
} // namespace seqan3::detail
trace_directions.hpp
Provides the declaration of seqan3::detail::trace_directions.
two_dimensional_matrix_iterator_base.hpp
Provides seqan3::detail::two_dimensional_matrix_iterator_base.
two_dimensional_matrix_iterator_concept.hpp
Provides seqan3::detail::two_dimensional_matrix_iterator.
Hide me