SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
coordinate_matrix.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <concepts>
16 #include <ranges>
17 
26 
27 namespace seqan3::detail
28 {
29 
30 //------------------------------------------------------------------------------
31 // coordinate_matrix
32 //------------------------------------------------------------------------------
33 
62 template <typename index_t>
63  requires (std::integral<index_t> || simd_index<index_t>)
64 class coordinate_matrix
65 {
66 private:
74  struct convert_to_matrix_coordinate
75  {
77  index_t column_index{};
78 
85  auto operator()(index_t const row_index) noexcept
86  {
87  return matrix_index<index_t>{row_index_type{row_index}, column_index_type{column_index}};
88  }
89  };
90 
92  template <typename simd_index_t>
93  using lazy_scalar_type_t = typename simd_traits<simd_index_t>::scalar_type;
94 
96  using size_type = lazy_conditional_t<simd_concept<index_t>, lazy<lazy_scalar_type_t, index_t>, index_t>;
97 
98  // The coordinate matrix iterator.
99  class iterator;
100 
102  size_type column_count{};
104  size_type row_count{};
105 
106 public:
110  coordinate_matrix() = default;
111  coordinate_matrix(coordinate_matrix const &) = default;
112  coordinate_matrix(coordinate_matrix &&) = default;
113  coordinate_matrix & operator=(coordinate_matrix const &) = default;
114  coordinate_matrix & operator=(coordinate_matrix &&) = default;
115  ~coordinate_matrix() = default;
116 
135  template <std::integral column_index_t, std::integral row_index_t>
136  void resize(column_index_type<column_index_t> const column_count,
137  row_index_type<row_index_t> const row_count) noexcept
138  {
139  this->column_count = column_count.get();
140  this->row_count = row_count.get();
141  }
143 
148  iterator begin() const noexcept
149  {
150  return iterator{size_type{}, row_count};
151  }
152 
154  iterator end() const noexcept
155  {
156  return iterator{column_count, row_count};
157  }
159 };
160 
161 //------------------------------------------------------------------------------
162 // iterator
163 //------------------------------------------------------------------------------
164 
174 template <typename index_t>
175  requires (std::integral<index_t> || simd_index<index_t>)
176 class coordinate_matrix<index_t>::iterator
177 {
178 private:
180  using iota_view_t = lazy_conditional_t<simd_index<index_t>,
181  lazy<iota_simd_view, index_t>,
182  decltype(std::views::iota(size_type{}, size_type{}))>;
184  index_t column_id{0};
186  size_type row_count{0};
187 
188 public:
193  using value_type = decltype(std::declval<iota_view_t>()
194  | std::views::transform(convert_to_matrix_coordinate{index_t{} /*column_id*/}));
196  using reference = value_type;
198  using pointer = void;
200  using difference_type = std::ptrdiff_t;
202  using iterator_category = std::forward_iterator_tag;
204 
208  iterator() = default;
209  iterator(iterator const &) = default;
210  iterator(iterator &&) = default;
211  iterator & operator=(iterator const &) = default;
212  iterator & operator=(iterator &&) = default;
213  ~iterator() = default;
214 
221  explicit iterator(size_type column_id, size_type row_count) noexcept : row_count{std::move(row_count)}
222  {
223  if constexpr (simd_index<index_t>)
224  this->column_id = simd::fill<index_t>(std::move(column_id));
225  else
226  this->column_id = std::move(column_id);
227  }
229 
235  auto operator*() const
236  {
237  if constexpr (simd_index<index_t>)
238  {
239  return views::iota_simd<index_t>(size_type{}, row_count)
240  | std::views::transform(convert_to_matrix_coordinate{column_id});
241  }
242  else
243  {
244  return std::views::iota(size_type{}, row_count)
245  | std::views::transform(convert_to_matrix_coordinate{column_id});
246  }
247  }
249 
255  iterator & operator++()
256  {
257  // clang: pre-increment of a SIMD vector does not work
258  if constexpr (simd_index<index_t>)
259  column_id = column_id + simd::fill<index_t>(1);
260  else
261  ++column_id;
262 
263  return *this;
264  }
265 
267  iterator operator++(int)
268  {
269  iterator tmp{*this};
270  ++(*this);
271  return tmp;
272  }
274 
280  friend bool operator==(iterator const & lhs, iterator const & rhs)
281  {
282  if constexpr (simd_index<index_t>)
283  return lhs.column_id[0] == rhs.column_id[0];
284  else
285  return lhs.column_id == rhs.column_id;
286  }
287 
289  friend bool operator!=(iterator const & lhs, iterator const & rhs)
290  {
291  return !(lhs == rhs);
292  }
294 };
295 } // namespace seqan3::detail
Provides algorithms to modify seqan3::simd::simd_type.
Provides seqan3::aligned_allocator.
T begin(T... args)
The <concepts> header from C++20's standard library.
T end(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
decltype(detail::transform< trait_t >(list_t{})) transform
Apply a transformation trait to every type in the list and return a seqan3::type_list of the results.
Definition: type_list/traits.hpp:469
Provides seqan3::detail::counted_simd_iterator and seqan3::views::iota_simd.
Provides lazy template instantiation traits.
Provides seqan3::detail::matrix_index, seqan3::detail::matrix_coordinate and associated strong types.
T operator!=(T... args)
The <ranges> header from C++20's standard library.
Provides seqan3::simd::simd_traits.
Provides type traits for working with templates.
Provides seqan3::simd::simd_concept.