SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
simd_affine_gap_policy.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 <limits>
16 #include <tuple>
17 
27 
28 namespace seqan3::detail
29 {
30 
31 // ----------------------------------------------------------------------------
32 // simd_affine_gap_policy
33 // ----------------------------------------------------------------------------
34 
52 template <typename alignment_algorithm_t, simd_concept score_t, typename align_local_t = std::false_type>
53 class simd_affine_gap_policy
54 {
55 private:
57  friend alignment_algorithm_t;
58 
60  using alignment_state_t = alignment_algorithm_state<score_t>;
61 
65  constexpr simd_affine_gap_policy() noexcept = default;
66  constexpr simd_affine_gap_policy(simd_affine_gap_policy const &) noexcept = default;
67  constexpr simd_affine_gap_policy(simd_affine_gap_policy &&) noexcept = default;
68  constexpr simd_affine_gap_policy & operator=(simd_affine_gap_policy const &) noexcept = default;
69  constexpr simd_affine_gap_policy & operator=(simd_affine_gap_policy &&) noexcept = default;
70  ~simd_affine_gap_policy() noexcept = default;
71 
73  template <typename configuration_t>
74  simd_affine_gap_policy(configuration_t const & /*config*/)
75  {}
77 
95  template <typename cell_t>
96  constexpr void compute_cell(cell_t && current_cell,
97  alignment_algorithm_state<score_t> & state,
98  score_t const score) const noexcept
99  {
100  // score_cell = seqan3::detail::alignment_score_matrix_proxy
101  // trace_cell = seqan3::detail::alignment_trace_matrix_proxy
102  auto & [score_cell, trace_cell] = current_cell;
103  constexpr bool with_trace = !decays_to_ignore_v<std::remove_reference_t<decltype(trace_cell.current)>>;
104  // Precompute the diagonal score.
105  score_t tmp = score_cell.diagonal + score;
106 
107  if constexpr (with_trace)
108  {
109  auto mask = tmp < score_cell.up;
110  tmp = (mask) ? score_cell.up : tmp;
111  trace_cell.current = (mask) ? trace_cell.up : convert_to_simd(trace_directions::diagonal) | trace_cell.up;
112 
113  mask = tmp < score_cell.r_left;
114  tmp = (mask) ? score_cell.r_left : tmp;
115  trace_cell.current = (mask) ? trace_cell.r_left : trace_cell.current | trace_cell.r_left;
116  }
117  else
118  {
119  tmp = (tmp < score_cell.up) ? score_cell.up : tmp;
120  tmp = (tmp < score_cell.r_left) ? score_cell.r_left : tmp;
121  }
122 
123  if constexpr (align_local_t::value)
124  {
125  tmp = (tmp < simd::fill<score_t>(0))
126  /*then*/ ? (trace_cell.current = convert_to_simd(trace_directions::none), simd::fill<score_t>(0))
127  /*else*/ : tmp;
128  }
129 
130  // Store the current max score.
131  score_cell.current = tmp;
132  // Check if this was the optimum. Possibly a noop.
133  static_cast<alignment_algorithm_t const &>(*this).check_score_of_cell(current_cell, state);
134 
135  // Prepare horizontal and vertical score for next column.
136  tmp += state.gap_open_score;
137  score_cell.up += state.gap_extension_score;
138  score_cell.w_left = score_cell.r_left + state.gap_extension_score;
139 
140  auto mask = score_cell.up < tmp;
141  score_cell.up = (mask) ? tmp : score_cell.up;
142  trace_cell.up = (mask) ? convert_to_simd(trace_directions::up_open) : convert_to_simd(trace_directions::up);
143  mask = score_cell.w_left < tmp;
144  score_cell.w_left = (mask) ? tmp : score_cell.w_left;
145  trace_cell.w_left = (mask) ? convert_to_simd(trace_directions::left_open)
146  : convert_to_simd(trace_directions::left);
147  }
148 
162  template <typename alignment_configuration_t>
163  constexpr void initialise_alignment_state(alignment_configuration_t const & config) noexcept
164  {
165  using scalar_t = typename simd_traits<score_t>::scalar_type;
166  auto scheme = config.get_or(align_cfg::gap_cost_affine{align_cfg::open_score{-10},
167  align_cfg::extension_score{-1}});
168 
169  alignment_state.gap_extension_score = simd::fill<score_t>(static_cast<scalar_t>(scheme.extension_score));
170  alignment_state.gap_open_score = simd::fill<score_t>(static_cast<scalar_t>(scheme.extension_score +
171  scheme.open_score));
172  }
173 
177  constexpr score_t convert_to_simd(trace_directions const direction) const noexcept
178  {
179  using scalar_t = typename simd_traits<score_t>::scalar_type;
180 
181  return simd::fill<score_t>(static_cast<scalar_t>(direction));
182  }
183 
184  alignment_state_t alignment_state{};
185 };
186 
187 } // namespace seqan3::detail
align_config_gap_cost_affine.hpp
Provides seqan3::align_config::gap_cost_affine.
configuration.hpp
Provides seqan3::detail::configuration and utility functions.
tuple
concept.hpp
Provides seqan3::simd::simd_concept.
trace_directions.hpp
Provides the declaration of seqan3::detail::trace_directions.
simd_algorithm.hpp
Provides algorithms to modify seqan3::simd::simd_type.
simd_traits.hpp
Provides seqan3::simd::simd_traits.
core_language.hpp
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
alignment_optimum.hpp
Provides seqan3::detail::alignment_optimum.
std::remove_reference_t
std::left
T left(T... args)
limits
alignment_algorithm_state.hpp
Provides seqan3::detail::alignment_algorithm_state.