SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
simd_match_mismatch_scoring_scheme.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 
24 
25 namespace seqan3::detail
26 {
27 
65 template <simd_concept simd_score_t, semialphabet alphabet_t, typename alignment_t>
66  requires (seqan3::alphabet_size<alphabet_t> > 1)
67  && (std::same_as<alignment_t, align_cfg::method_local> || std::same_as<alignment_t, align_cfg::method_global>)
68 class simd_match_mismatch_scoring_scheme
69 {
70 private:
72  using scalar_type = typename simd_traits<simd_score_t>::scalar_type;
74  using alphabet_ranks_type = simd_score_t;
75 
76 public:
78  static constexpr scalar_type padding_symbol = static_cast<scalar_type>(1u << (bits_of<scalar_type> - 1));
79 
84  constexpr simd_match_mismatch_scoring_scheme() = default;
86  constexpr simd_match_mismatch_scoring_scheme(simd_match_mismatch_scoring_scheme const &) = default;
88  constexpr simd_match_mismatch_scoring_scheme(simd_match_mismatch_scoring_scheme &&) = default;
90  constexpr simd_match_mismatch_scoring_scheme & operator=(simd_match_mismatch_scoring_scheme const &) = default;
92  constexpr simd_match_mismatch_scoring_scheme & operator=(simd_match_mismatch_scoring_scheme &&) = default;
94  ~simd_match_mismatch_scoring_scheme() = default;
95 
97  template <typename scoring_scheme_t>
99  constexpr explicit simd_match_mismatch_scoring_scheme(scoring_scheme_t const & scoring_scheme)
100  {
101  initialise_from_scalar_scoring_scheme(scoring_scheme);
102  }
103 
105  template <typename scoring_scheme_t>
107  constexpr simd_match_mismatch_scoring_scheme & operator=(scoring_scheme_t const & scoring_scheme)
108  {
109  initialise_from_scalar_scoring_scheme(scoring_scheme);
110  return *this;
111  }
113 
143  constexpr simd_score_t score(alphabet_ranks_type const & ranks1, alphabet_ranks_type const & ranks2) const noexcept
144  {
145  typename simd_traits<simd_score_t>::mask_type mask;
146  // For global and local alignment there are slightly different formulas because
147  // in global alignment padded characters always match
148  if constexpr (std::same_as<alignment_t, align_cfg::method_global>)
149  mask = (ranks1 ^ ranks2) <= simd::fill<simd_score_t>(0);
150  else // and in local alignment type padded characters always mismatch.
151  mask = (ranks1 ^ ranks2) == simd::fill<simd_score_t>(0);
152 
153  return mask ? match_score : mismatch_score;
154  }
156 
158  constexpr auto padding_match_score() noexcept
159  {
160  return match_score[0];
161  }
162 
164  template <typename alphabet_ranks_t>
165  requires std::same_as<std::remove_cvref_t<alphabet_ranks_t>, alphabet_ranks_type>
166  constexpr alphabet_ranks_t make_score_profile(alphabet_ranks_t && ranks) const noexcept
167  {
168  return std::forward<alphabet_ranks_t>(ranks);
169  }
170 
171 private:
187  template <typename scoring_scheme_t>
188  constexpr void initialise_from_scalar_scoring_scheme(scoring_scheme_t const & scoring_scheme)
189  {
190  using score_t = decltype(std::declval<scoring_scheme_t const &>().score(alphabet_t{}, alphabet_t{}));
191  using simd_scalar_t = typename simd_traits<simd_score_t>::scalar_type;
192 
193  score_t scalar_match_score =
194  scoring_scheme.score(seqan3::assign_rank_to(0, alphabet_t{}), seqan3::assign_rank_to(0, alphabet_t{}));
195  score_t scalar_mismatch_score =
196  scoring_scheme.score(seqan3::assign_rank_to(0, alphabet_t{}), seqan3::assign_rank_to(1, alphabet_t{}));
197 
198  // Check if the scoring scheme match and mismatch scores do not overflow with the respective scalar type.
199  if constexpr (sizeof(simd_scalar_t) < sizeof(score_t))
200  {
201  if (scalar_match_score > static_cast<score_t>(std::numeric_limits<simd_scalar_t>::max())
202  || scalar_mismatch_score < static_cast<score_t>(std::numeric_limits<simd_scalar_t>::lowest()))
203  {
204  throw std::invalid_argument{"The selected scoring scheme score overflows "
205  "for the selected scalar type of the simd type."};
206  }
207  }
208 
209  match_score = simd::fill<simd_score_t>(static_cast<simd_scalar_t>(scalar_match_score));
210  mismatch_score = simd::fill<simd_score_t>(static_cast<simd_scalar_t>(scalar_mismatch_score));
211  }
212 
213  simd_score_t match_score;
214  simd_score_t mismatch_score;
215 };
216 
217 } // namespace seqan3::detail
Provides algorithms to modify seqan3::simd::simd_type.
Provides global and local alignment configurations.
Core alphabet concept and free function/type trait wrappers.
Provides utility functions for bit twiddling.
Adaptions of concepts from the Cereal library.
The <concepts> header from C++20's standard library.
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: alphabet/concept.hpp:293
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
A concept that requires that type be able to score two letters.
Provides seqan3::scoring_scheme_for.
Provides seqan3::simd::simd_concept.