SeqAn3
utility.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <meta/meta.hpp>
43 
46 
47 #include <seqan3/alignment/configuration/utility.hpp> // TODO: move common code into core module and remove this include
48 
49 namespace seqan3::search_cfg
50 {
51 
68 enum struct id : uint8_t
69 {
71  max_error,
73  output,
74  mode,
76  // ATTENTION: Must always be the last item; will be used to determine the number of ids.
77  SIZE
79 };
80 
81 } // namespace seqan3::search_cfg
82 
83 namespace seqan3::detail
84 {
85 
86 // ----------------------------------------------------------------------------
87 // on_search_config
88 // ----------------------------------------------------------------------------
89 
116 template <search_cfg::id e>
117 struct on_search_config
118 {
122  template <config_element_concept t>
123  using invoke = std::false_type;
124 };
125 
126 // ----------------------------------------------------------------------------
127 // search_config_type_to_id
128 // ----------------------------------------------------------------------------
129 
135 template <config_element_concept config_element_t>
136 struct search_config_type_to_id
137 {
139  static constexpr search_cfg::id value = search_cfg::id::SIZE;
140 };
141 
144 template <config_element_concept config_element_t>
145 inline constexpr search_cfg::id search_config_type_to_id_v = search_config_type_to_id<config_element_t>::value;
146 
147 // ----------------------------------------------------------------------------
148 // search_config_validation_matrix
149 // ----------------------------------------------------------------------------
150 
161 inline constexpr std::array<std::array<bool, static_cast<uint8_t>(search_cfg::id::SIZE)>,
162  static_cast<uint8_t>(search_cfg::id::SIZE)> search_config_validation_matrix =
163 {
164  {
165  // max_error, max_error_rate, output, mode
166  { 0, 0, 1, 1 },
167  { 0, 0, 1, 1 },
168  { 1, 1, 0, 1 },
169  { 1, 1, 1, 0 }
170  }
171 };
172 
183 template <search_cfg::id query, typename configuration_t>
185  requires is_algorithm_configuration_v<remove_cvref_t<configuration_t>>
187 struct invalid_search_configuration
188 {
189 protected:
190 
194  template <typename target_t>
195  struct invoke
196  {
198  static constexpr uint8_t pos1 = static_cast<uint8_t>(query);
200  static constexpr uint8_t pos2 = static_cast<uint8_t>(search_config_type_to_id_v<remove_cvref_t<target_t>>);
201 
202  static_assert(pos1 != static_cast<uint8_t>(search_cfg::id::SIZE),
203  "Unknown search_cfg::id! "
204  "Did you use an unknown config or did you forget to specialize search_config_type_to_id?");
205  static_assert(pos2 != static_cast<uint8_t>(search_cfg::id::SIZE),
206  "Unknown search_cfg::id! "
207  "Did you use an unknown config or did you forget to specialize search_config_type_to_id?");
208 
210  using type = std::conditional_t<search_config_validation_matrix[pos1][pos2], std::false_type, std::true_type>;
211  };
212 
214  using target_list_t = tuple_type_list_t<typename remove_cvref_t<configuration_t>::base_type>;
216  using tail_list_t = meta::find_if<meta::reverse<target_list_t>, meta::quote_trait<invoke>>;
218  using final_list_t = std::conditional_t<meta::empty<tail_list_t>::value, type_list<void>, tail_list_t>;
219 
220 public:
221 
223  using type = meta::front<final_list_t>;
224 };
225 
228 template <search_cfg::id query, typename configuration_t>
230  requires is_algorithm_configuration_v<remove_cvref_t<configuration_t>>
232 using invalid_search_configuration_t = typename invalid_search_configuration<query, configuration_t>::type;
233 
243 template <search_cfg::id query, typename configuration_t>
245  requires is_algorithm_configuration_v<remove_cvref_t<configuration_t>>
247 struct is_valid_search_configuration :
248  public std::is_same<invalid_search_configuration_t<query, configuration_t>, void>
249 {};
250 
253 template <search_cfg::id query, typename configuration_t>
255  requires is_algorithm_configuration_v<remove_cvref_t<configuration_t>>
257 inline constexpr bool is_valid_search_configuration_v =
258  is_valid_search_configuration<query, configuration_t>::value;
259 
260 } // namespace seqan3::detail
261 
262 namespace seqan3
263 {
264 
265 // TODO: my own implementation to check whether a cfg element is in the configuration. This will be replaced by rrahns implementation
266 
268 template <search_cfg::id e, typename ... cfg_elements_t>
269 constexpr bool contains(detail::configuration<cfg_elements_t...> & cfg) noexcept
270 {
271  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
272 
273  constexpr size_t pos = meta::size<type_list_t>::value -
274  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
275 
276  return pos < meta::size<type_list_t>::value;
277 }
278 
279 template <search_cfg::id e, typename ... cfg_elements_t>
280 constexpr bool contains(detail::configuration<cfg_elements_t...> const &) noexcept
281 {
282  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
283 
284  constexpr size_t pos = meta::size<type_list_t>::value -
285  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
286 
287  return pos < meta::size<type_list_t>::value;
288 }
289 
290 template <search_cfg::id e, typename ... cfg_elements_t>
291 constexpr bool contains(detail::configuration<cfg_elements_t...> && cfg) noexcept
292 {
293  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
294 
295  constexpr size_t pos = meta::size<type_list_t>::value -
296  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
297 
298  return pos < meta::size<type_list_t>::value;
299 }
300 
301 template <search_cfg::id e, typename ... cfg_elements_t>
302 constexpr bool contains(detail::configuration<cfg_elements_t...> const && cfg) noexcept
303 {
304  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
305 
306  constexpr size_t pos = meta::size<type_list_t>::value -
307  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
308 
309  return pos < meta::size<type_list_t>::value;
310 }
312 
328 template <search_cfg::id e, typename ... cfg_elements_t>
329 constexpr auto & get(detail::configuration<cfg_elements_t...> & cfg) noexcept
330 {
331  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
332 
333  constexpr size_t pos = meta::size<type_list_t>::value -
334  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
335 
336  static_assert(static_cast<int8_t>(e) < static_cast<int8_t>(search_cfg::id::SIZE),
337  "Did you forget to update search_cfg::id::SIZE value?");
338  static_assert(pos < meta::size<type_list_t>::value,
339  "The specified config element is not contained in the configuration.");
340 
341  return get<pos>(cfg).value;
342 }
343 
353 template <search_cfg::id e, typename ... cfg_elements_t>
354 constexpr auto const & get(detail::configuration<cfg_elements_t...> const & cfg) noexcept
355 {
356  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
357  constexpr size_t pos = meta::size<type_list_t>::value -
358  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
359 
360  static_assert(static_cast<int8_t>(e) < static_cast<int8_t>(search_cfg::id::SIZE),
361  "Did you forget to update search_cfg::id::SIZE value?");
362  static_assert(pos < meta::size<type_list_t>::value,
363  "The specified config element is not contained in the configuration.");
364 
365  return get<pos>(cfg).value;
366 }
367 
377 template <search_cfg::id e, typename ... cfg_elements_t>
378 constexpr auto && get(detail::configuration<cfg_elements_t...> && cfg) noexcept
379 {
380  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
381  constexpr size_t pos = meta::size<type_list_t>::value -
382  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
383 
384  static_assert(static_cast<int8_t>(e) < static_cast<int8_t>(search_cfg::id::SIZE),
385  "Did you forget to update search_cfg::id::SIZE value?");
386  static_assert(pos < meta::size<type_list_t>::value,
387  "The specified config element is not contained in the configuration.");
388 
389  return get<pos>(std::move(cfg)).value;
390 }
391 
401 template <search_cfg::id e, typename ... cfg_elements_t>
402 constexpr auto const && get(detail::configuration<cfg_elements_t...> const && cfg) noexcept
403 {
404  using type_list_t = detail::tuple_type_list_t<typename detail::configuration<cfg_elements_t...>::base_type>;
405  constexpr size_t pos = meta::size<type_list_t>::value -
406  meta::size<meta::find_if<type_list_t, detail::on_search_config<e>>>::value;
407 
408  static_assert(static_cast<int8_t>(e) < static_cast<int8_t>(search_cfg::id::SIZE),
409  "Did you forget to update search_cfg::id::SIZE value?");
410  static_assert(pos < meta::size<type_list_t>::value,
411  "The specified config element is not contained in the configuration.");
412 
413  // TODO: Remove outer move once std::get is fixed for gcc 7.
414  return std::move(get<pos>(std::move(cfg)).value);
415 }
417 } // namespace seqan3
constexpr detail::search_config_max_error_rate_adaptor max_error_rate
A configuration element for the maximum number of errors in percent of the query length across all er...
Definition: max_error_rate.hpp:176
A special sub namespace for the search configurations.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
Provides functionality to access get function by enum values.
id
Specifies an id for every configuration element.
Definition: utility.hpp:68
Definition: aligned_sequence_concept.hpp:288
detail::search_config_mode_adaptor< seqan3::detail::search_config_mode > constexpr mode
Configuration element to determine the search mode.
Definition: mode.hpp:150
meta::list< types... > type_list
Type that contains multiple types, an alias for meta::list.
Definition: type_list.hpp:54
Provides seqan3::detail::configuration and utility functions.
Static reflection for arbitrary types.
Identifier for max_errors configuration.