From 179d26bda3d30fe29bf1e32b4fb4aaf898037552 Mon Sep 17 00:00:00 2001 From: Enrico Seiler Date: Wed, 21 Aug 2019 11:20:21 +0200 Subject: [PATCH] [MISC] Add alphabet type template to fm_index --- CHANGELOG.md | 13 + .../read_mapper/read_mapper_step2.cpp | 2 +- .../read_mapper/read_mapper_step3.cpp | 2 +- .../read_mapper/read_mapper_step4.cpp | 2 +- doc/tutorial/search/search_small_snippets.cpp | 3 +- doc/tutorial/search/search_solution1.cpp | 3 +- .../seqan3/search/algorithm/detail/search.hpp | 4 +- .../algorithm/detail/search_trivial.hpp | 1 + include/seqan3/search/algorithm/search.hpp | 2 - .../seqan3/search/fm_index/bi_fm_index.hpp | 156 ++++++------ .../search/fm_index/bi_fm_index_cursor.hpp | 59 +++-- include/seqan3/search/fm_index/concept.hpp | 33 ++- include/seqan3/search/fm_index/fm_index.hpp | 236 +++++++++--------- .../search/fm_index/fm_index_cursor.hpp | 55 ++-- .../search/fm_index/bi_fm_index_aa27_test.cpp | 6 +- .../search/fm_index/bi_fm_index_char_test.cpp | 10 +- .../search/fm_index/bi_fm_index_dna4_test.cpp | 10 +- .../fm_index_collection_test_template.hpp | 2 +- .../search/fm_index/fm_index_dna4_test.cpp | 41 ++- .../fm_index/fm_index_test_template.hpp | 2 +- .../bi_fm_index_cursor_collection_test.cpp | 2 +- .../bi_fm_index_cursor_test.cpp | 2 +- .../fm_index_cursor_collection_test.cpp | 8 +- .../fm_index_cursor/fm_index_cursor_test.cpp | 8 +- test/unit/search/search_collection_test.cpp | 10 +- test/unit/search/search_test.cpp | 10 +- 26 files changed, 365 insertions(+), 317 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdf53517ed..de91cba829 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,19 @@ If possible, provide tooling that performs the changes, e.g. a shell-script. * **The `seqan3::concatenated_sequences::data()` function has been deprecated:** Use `seqan3::concatenated_sequences::raw_data()` instead. +#### Search + +* **Changed class signature of (bi_)fm_index:** + All code that relies on automatic template deduction will be unaffected. In case you specified the template parameters + of a `seqan3::fm_index` or `seqan3::bi_fm_index` you will need to add the alphabet type as first parameter and pass a + `seqan3::text_layout` instead of a `bool` to indicate the text layout (single, collection). + For example, `fm_index index{text}` where `text` is of type `dna4_vector` needs to be changed to + `fm_index index{text}`. + +* **The `construct()` method of the (bi_)fm_index is now private:** + Use the constructor `seqan3::fm_index::fm_index(text_t && text)` or `seqan3::bi_fm_index::bi_fm_index(text_t && text)` + instead. + ## Notable Bug-fixes # 3.0.0 ("Escala") diff --git a/doc/tutorial/read_mapper/read_mapper_step2.cpp b/doc/tutorial/read_mapper/read_mapper_step2.cpp index 72d1ea93da..9cf102acdc 100644 --- a/doc/tutorial/read_mapper/read_mapper_step2.cpp +++ b/doc/tutorial/read_mapper/read_mapper_step2.cpp @@ -38,7 +38,7 @@ void map_reads(std::filesystem::path const & query_path, uint8_t const errors) //! [map_reads] { - bi_fm_index index; // we need to know if we work on a text collection before loading + bi_fm_index index; // we need the alphabet and text layout before loading { std::ifstream is{index_path, std::ios::binary}; cereal::BinaryInputArchive iarchive{is}; diff --git a/doc/tutorial/read_mapper/read_mapper_step3.cpp b/doc/tutorial/read_mapper/read_mapper_step3.cpp index 8c5bb0e78a..11a6ee6f61 100644 --- a/doc/tutorial/read_mapper/read_mapper_step3.cpp +++ b/doc/tutorial/read_mapper/read_mapper_step3.cpp @@ -39,7 +39,7 @@ void map_reads(std::filesystem::path const & query_path, reference_storage_t & storage, uint8_t const errors) { - bi_fm_index index; // we need to know if we work on a text collection before loading + bi_fm_index index; // we need the alphabet and text layout before loading { std::ifstream is{index_path, std::ios::binary}; cereal::BinaryInputArchive iarchive{is}; diff --git a/doc/tutorial/read_mapper/read_mapper_step4.cpp b/doc/tutorial/read_mapper/read_mapper_step4.cpp index 9fb6b7c856..fcfb46cd3e 100644 --- a/doc/tutorial/read_mapper/read_mapper_step4.cpp +++ b/doc/tutorial/read_mapper/read_mapper_step4.cpp @@ -40,7 +40,7 @@ void map_reads(std::filesystem::path const & query_path, reference_storage_t & storage, uint8_t const errors) { - bi_fm_index index; // we need to know if we work on a text collection before loading + bi_fm_index index; // we need the alphabet and text layout before loading { std::ifstream is{index_path, std::ios::binary}; cereal::BinaryInputArchive iarchive{is}; diff --git a/doc/tutorial/search/search_small_snippets.cpp b/doc/tutorial/search/search_small_snippets.cpp index 85b006ac1a..350bcbd9f5 100644 --- a/doc/tutorial/search/search_small_snippets.cpp +++ b/doc/tutorial/search/search_small_snippets.cpp @@ -48,7 +48,8 @@ fm_index index{text}; { //![load] -fm_index index; // we need to tell the index that we work on a single text before loading +// we need to tell the index that we work on a single text and a `char` alphabet before loading +fm_index index; { std::ifstream is{"index.file", std::ios::binary}; cereal::BinaryInputArchive iarchive{is}; diff --git a/doc/tutorial/search/search_solution1.cpp b/doc/tutorial/search/search_solution1.cpp index cf8ed94ecb..8ed4d46110 100644 --- a/doc/tutorial/search/search_solution1.cpp +++ b/doc/tutorial/search/search_solution1.cpp @@ -23,7 +23,8 @@ int main() oarchive(index); } - fm_index index2; // we need to tell the index that we work on a single text before loading + // we need to tell the index that we work on a single text and a `dna4` alphabet before loading + fm_index index2; { std::ifstream is{"index.file", std::ios::binary}; cereal::BinaryInputArchive iarchive{is}; diff --git a/include/seqan3/search/algorithm/detail/search.hpp b/include/seqan3/search/algorithm/detail/search.hpp index 52c9c5c4ef..37a3d33a7c 100644 --- a/include/seqan3/search/algorithm/detail/search.hpp +++ b/include/seqan3/search/algorithm/detail/search.hpp @@ -130,7 +130,7 @@ inline auto search_single(index_t const & index, query_t & query, configuration_ } else { - using hit_t = std::conditional_t, typename index_t::size_type>; std::vector hits; @@ -184,7 +184,7 @@ inline auto search_all(index_t const & index, queries_t & queries, configuration // delegate params: text_position (or cursor). we will withhold all hits of one query anyway to filter // duplicates. more efficient to call delegate once with one vector instead of calling // delegate for each hit separately at once. - using text_pos_t = std::conditional_t, typename index_t::size_type>; using hit_t = std::conditional_t>(), diff --git a/include/seqan3/search/algorithm/detail/search_trivial.hpp b/include/seqan3/search/algorithm/detail/search_trivial.hpp index b74ef03827..406c5e60d2 100644 --- a/include/seqan3/search/algorithm/detail/search_trivial.hpp +++ b/include/seqan3/search/algorithm/detail/search_trivial.hpp @@ -15,6 +15,7 @@ #include +#include #include #include #include diff --git a/include/seqan3/search/algorithm/search.hpp b/include/seqan3/search/algorithm/search.hpp index b8964a1c39..377222d876 100644 --- a/include/seqan3/search/algorithm/search.hpp +++ b/include/seqan3/search/algorithm/search.hpp @@ -108,8 +108,6 @@ inline auto search(queries_t && queries, static_assert(detail::is_type_specialisation_of_v, configuration>, "cfg must be a specialisation of seqan3::configuration."); - assert(alphabet_size> == index.sigma); - using cfg_t = remove_cvref_t; if constexpr (cfg_t::template exists()) diff --git a/include/seqan3/search/fm_index/bi_fm_index.hpp b/include/seqan3/search/fm_index/bi_fm_index.hpp index c0132deb88..1b3f950309 100644 --- a/include/seqan3/search/fm_index/bi_fm_index.hpp +++ b/include/seqan3/search/fm_index/bi_fm_index.hpp @@ -24,23 +24,16 @@ namespace seqan3 { -//!\cond -SEQAN3_DEPRECATED_310 -void bi_fm_index_deprecation(bool); - -template -void bi_fm_index_deprecation(t); -//!\endcond - /*!\addtogroup submodule_fm_index * \{ */ /*!\brief The SeqAn Bidirectional FM Index * \implements seqan3::BiFmIndex - * \tparam is_collection Indicates whether this index works on a text collection or a single text. - * See seqan3::text_layout. - * \tparam sdsl_index_type_ The type of the underlying SDSL index, must model seqan3::SdslIndex. + * \tparam alphabet_t The alphabet type; must model seqan3::Semialphabet. + * \tparam text_layout_mode_ Indicates whether this index works on a text collection or a single text. + * See seqan3::text_layout. + * \tparam sdsl_index_type_ The type of the underlying SDSL index, must model seqan3::SdslIndex. * \details * * The seqan3::bi_fm_index is a fast and space-efficient bidirectional string index to search strings and @@ -64,18 +57,13 @@ void bi_fm_index_deprecation(t); * * \attention When building an index for a **text collection** over any alphabet, the symbols with rank 254 and 255 * are reserved and may not be used in the text. - * - * \deprecated Use seqan3::text_layout to indicate single texts and text collections. The use of bool is deprecated. */ -template +template class bi_fm_index { -protected: - //!\brief The alphabet size of the text. - size_t sigma{0}; - //!\brief Indicates whether index is built over a collection. - static constexpr bool is_collection_{is_collection}; - +private: /*!\name Index types * \{ */ @@ -94,10 +82,10 @@ class bi_fm_index using sdsl_sigma_type = typename sdsl_index_type::alphabet_type::sigma_type; //!\brief The type of the underlying FM index for the original text. - using fm_index_type = fm_index; + using fm_index_type = fm_index; //!\brief The type of the underlying FM index for the reversed text.\if DEV \todo Change sampling behaviour. \endif - using rev_fm_index_type = fm_index; + using rev_fm_index_type = fm_index; //!\} //!\brief Underlying FM index for the original text. @@ -106,57 +94,6 @@ class bi_fm_index //!\brief Underlying FM index for the reversed text. rev_fm_index_type rev_fm; - //!\cond - using unused_t [[maybe_unused]] = decltype(bi_fm_index_deprecation(is_collection)); - //!\endcond - -public: - /*!\name Text types - * \{ - */ - //!\brief Type for representing positions in the indexed text. - using size_type = typename sdsl_index_type::size_type; - //!\} - - /*!\name Cursor types - * \{ - */ - //!\brief The type of the bidirectional cursor. - using cursor_type = bi_fm_index_cursor>; - //!\brief The type of the unidirectional cursor on the original text. - using fwd_cursor_type = fm_index_cursor; - //!\brief The type of the unidirectional cursor on the reversed text. - using rev_cursor_type = fm_index_cursor; - //!\} - - template - friend class fm_index_cursor; - - /*!\name Constructors, destructor and assignment - * \{ - */ - bi_fm_index() = default; //!< Defaulted. - bi_fm_index(bi_fm_index const &) = default; //!< Defaulted. - bi_fm_index & operator=(bi_fm_index const &) = default; //!< Defaulted. - bi_fm_index(bi_fm_index &&) = default; //!< Defaulted. - bi_fm_index & operator=(bi_fm_index &&) = default; //!< Defaulted. - ~bi_fm_index() = default; //!< Defaulted. - - /*!\brief Constructor that immediately constructs the index given a range. The range cannot be empty. - * \tparam text_t The type of range to construct from; must model std::ranges::BidirectionalRange. - * \param[in] text The text to construct from. - * - * ### Complexity - * - * \if DEV \todo \endif At least linear. - */ - template - bi_fm_index(text_t && text) - { - construct(std::forward(text)); - } - //!\} - /*!\brief Constructs the index given a range. * The range cannot be an rvalue (i.e. a temporary object) and has to be non-empty. * \tparam text_t The type of range to construct from; must model std::ranges::BidirectionalRange. @@ -177,13 +114,15 @@ class bi_fm_index * No guarantee. \if DEV \todo Ensure strong exception guarantee. \endif */ template - //!\cond - requires !is_collection_ - //!\endcond + //!\cond + requires text_layout_mode_ == text_layout::single + //!\endcond void construct(text_t && text) { static_assert(std::ranges::BidirectionalRange, "The text must model BidirectionalRange."); static_assert(alphabet_size> <= 256, "The alphabet is too big."); + static_assert(std::ConvertibleTo, alphabet_t>, + "The alphabet of the text collection must be convertible to the alphabet of the index."); static_assert(dimension_v == 1, "The input cannot be a text collection."); // text must not be empty @@ -193,21 +132,21 @@ class bi_fm_index auto rev_text = std::view::reverse(text); fwd_fm.construct(text); rev_fm.construct(rev_text); - - sigma = fwd_fm.sigma; } //!\overload template - //!\cond - requires is_collection_ - //!\endcond + //!\cond + requires text_layout_mode_ == text_layout::collection + //!\endcond void construct(text_t && text) { static_assert(std::ranges::BidirectionalRange, "The text must model BidirectionalRange."); static_assert(std::ranges::BidirectionalRange>, "The elements of the text collection must model BidirectionalRange."); static_assert(alphabet_size> <= 256, "The alphabet is too big."); + static_assert(std::ConvertibleTo, alphabet_t>, + "The alphabet of the text collection must be convertible to the alphabet of the index."); static_assert(dimension_v == 2, "The input must be a text collection."); // text must not be empty @@ -217,9 +156,60 @@ class bi_fm_index auto rev_text = text | view::deep{std::view::reverse} | std::view::reverse; fwd_fm.construct(text); rev_fm.construct(rev_text); + } + +public: + //!\brief Indicates whether index is built over a collection. + static constexpr text_layout text_layout_mode = text_layout_mode_; + + /*!\name Text types + * \{ + */ + //!\brief The type of the underlying character of the indexed text. + using char_type = typename fm_index_type::char_type; + //!\brief Type for representing positions in the indexed text. + using size_type = typename sdsl_index_type::size_type; + //!\} + + /*!\name Cursor types + * \{ + */ + //!\brief The type of the bidirectional cursor. + using cursor_type = bi_fm_index_cursor>; + //!\brief The type of the unidirectional cursor on the original text. + using fwd_cursor_type = fm_index_cursor; + //!\brief The type of the unidirectional cursor on the reversed text. + using rev_cursor_type = fm_index_cursor; + + //!\} + + template + friend class fm_index_cursor; + + /*!\name Constructors, destructor and assignment + * \{ + */ + bi_fm_index() = default; //!< Defaulted. + bi_fm_index(bi_fm_index const &) = default; //!< Defaulted. + bi_fm_index & operator=(bi_fm_index const &) = default; //!< Defaulted. + bi_fm_index(bi_fm_index &&) = default; //!< Defaulted. + bi_fm_index & operator=(bi_fm_index &&) = default; //!< Defaulted. + ~bi_fm_index() = default; //!< Defaulted. - sigma = fwd_fm.sigma; + /*!\brief Constructor that immediately constructs the index given a range. The range cannot be empty. + * \tparam text_t The type of range to construct from; must model std::ranges::BidirectionalRange. + * \param[in] text The text to construct from. + * + * ### Complexity + * + * \if DEV \todo \endif At least linear. + */ + template + bi_fm_index(text_t && text) + { + construct(std::forward(text)); } + //!\} /*!\brief Returns the length of the indexed text including sentinel characters. * \returns Returns the length of the indexed text including sentinel characters. @@ -361,7 +351,7 @@ class bi_fm_index */ //! \brief Deduces the dimensions of the text. template -bi_fm_index(text_t &&) -> bi_fm_index != 1}>; +bi_fm_index(text_t &&) -> bi_fm_index, text_layout{dimension_v != 1}>; //!\} //!\} diff --git a/include/seqan3/search/fm_index/bi_fm_index_cursor.hpp b/include/seqan3/search/fm_index/bi_fm_index_cursor.hpp index ce9e83136e..1af55391aa 100644 --- a/include/seqan3/search/fm_index/bi_fm_index_cursor.hpp +++ b/include/seqan3/search/fm_index/bi_fm_index_cursor.hpp @@ -68,14 +68,16 @@ class bi_fm_index_cursor * \{ */ //!\brief Type for the unidirectional cursor on the original text. - using fwd_cursor = fm_index_cursor>; //!\brief Type for the unidirectional cursor on the reversed text. - using rev_cursor = fm_index_cursor>; //!\} -protected: +private: //!\brief Type of the representation of characters in the underlying SDSL index. using sdsl_char_type = typename index_type::sdsl_char_type; //!\brief Type of the alphabet size in the underlying SDSL index. @@ -237,18 +239,18 @@ class bi_fm_index_cursor //!\brief Default constructor. Accessing member functions on a default constructed object is undefined behavior. // Default construction is necessary to make this class semi-regular and e.g., to allow construction of // std::array of cursors. - bi_fm_index_cursor() noexcept = default; //!< Default constructor. - bi_fm_index_cursor(bi_fm_index_cursor const &) noexcept = default; //!< Copy constructor. - bi_fm_index_cursor & operator=(bi_fm_index_cursor const &) noexcept = default; //!< Copy assignment. - bi_fm_index_cursor(bi_fm_index_cursor &&) noexcept = default; //!< Move constructor. - bi_fm_index_cursor & operator=(bi_fm_index_cursor &&) noexcept = default; //!< Move assignment. - ~bi_fm_index_cursor() = default; //!< Destructor. + bi_fm_index_cursor() noexcept = default; //!< Defaulted. + bi_fm_index_cursor(bi_fm_index_cursor const &) noexcept = default; //!< Defaulted. + bi_fm_index_cursor & operator=(bi_fm_index_cursor const &) noexcept = default; //!< Defaulted. + bi_fm_index_cursor(bi_fm_index_cursor &&) noexcept = default; //!< Defaulted. + bi_fm_index_cursor & operator=(bi_fm_index_cursor &&) noexcept = default; //!< Defaulted. + ~bi_fm_index_cursor() = default; //!< Defaulted. //! \brief Construct from given index. bi_fm_index_cursor(index_t const & _index) noexcept : index(&_index), fwd_lb(0), fwd_rb(_index.size() - 1), rev_lb(0), rev_rb(_index.size() - 1), - sigma(_index.fwd_fm.index.sigma - index_t::is_collection_), + sigma(_index.fwd_fm.index.sigma - index_t::text_layout_mode), depth(0) {} //\} @@ -405,15 +407,17 @@ class bi_fm_index_cursor * * No-throw guarantee. */ - template + template bool extend_right(char_t const c) noexcept { #ifndef NDEBUG fwd_cursor_last_used = true; #endif + static_assert(std::ConvertibleTo, + "The character must be convertible to the alphabet of the index."); + assert(index != nullptr); - assert(index->fwd_fm.sigma == alphabet_size); size_type new_parent_lb = fwd_lb, new_parent_rb = fwd_rb; @@ -445,15 +449,17 @@ class bi_fm_index_cursor * * No-throw guarantee. */ - template + template bool extend_left(char_t const c) noexcept { #ifndef NDEBUG fwd_cursor_last_used = false; #endif + static_assert(std::ConvertibleTo, + "The character must be convertible to the alphabet of the index."); + assert(index != nullptr); - assert(index->fwd_fm.sigma == alphabet_size); size_type new_parent_lb = rev_lb, new_parent_rb = rev_rb; @@ -491,8 +497,10 @@ class bi_fm_index_cursor bool extend_right(seq_t && seq) noexcept { static_assert(std::ranges::ForwardRange, "The query must model ForwardRange."); + static_assert(std::ConvertibleTo, typename index_t::char_type>, + "The alphabet of the sequence must be convertible to the alphabet of the index."); + assert(index != nullptr); - assert(index->fwd_fm.sigma == alphabet_size>); auto first = std::ranges::begin(seq); auto last = std::ranges::end(seq); @@ -554,8 +562,9 @@ class bi_fm_index_cursor bool extend_left(seq_t && seq) noexcept { static_assert(std::ranges::BidirectionalRange, "The query must model BidirectionalRange."); + static_assert(std::ConvertibleTo, typename index_t::char_type>, + "The alphabet of the sequence must be convertible to the alphabet of the index."); assert(index != nullptr); - assert(index->fwd_fm.sigma == alphabet_size>); auto rev_seq = std::view::reverse(seq); auto first = std::ranges::begin(rev_seq); @@ -853,13 +862,14 @@ class bi_fm_index_cursor template auto path_label(text_t && text) const noexcept //!\cond - requires !index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::single //!\endcond { static_assert(std::ranges::InputRange, "The text must model InputRange."); static_assert(dimension_v == 1, "The input cannot be a text collection."); + static_assert(std::Same, typename index_t::char_type>, + "The alphabet types of the given text and index differ."); assert(index != nullptr); - assert(index->fwd_fm.sigma == alphabet_size>); size_type const query_begin = offset() - index->fwd_fm.index[fwd_lb]; return text | view::slice(query_begin, query_begin + query_length()); @@ -869,13 +879,14 @@ class bi_fm_index_cursor template auto path_label(text_t && text) const noexcept //!\cond - requires index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::collection //!\endcond { static_assert(std::ranges::InputRange, "The text collection must model InputRange."); static_assert(dimension_v == 2, "The input must be a text collection."); + static_assert(std::Same, typename index_t::char_type>, + "The alphabet types of the given text and index differ."); assert(index != nullptr); - assert(index->fwd_fm.sigma == alphabet_size>); size_type const loc = offset() - index->fwd_fm.index[fwd_lb]; size_type const query_begin = loc - index->fwd_fm.text_begin_rs.rank(loc + 1) + 1; // Substract delimiters @@ -913,7 +924,7 @@ class bi_fm_index_cursor */ std::vector locate() const //!\cond - requires !index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::single //!\endcond { assert(index != nullptr); @@ -929,7 +940,7 @@ class bi_fm_index_cursor //!\overload std::vector> locate() const //!\cond - requires index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::collection //!\endcond { assert(index != nullptr); @@ -960,7 +971,7 @@ class bi_fm_index_cursor */ auto lazy_locate() const //!\cond - requires !index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::single //!\endcond { assert(index != nullptr); @@ -975,7 +986,7 @@ class bi_fm_index_cursor //!\overload auto lazy_locate() const //!\cond - requires index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::collection //!\endcond { assert(index != nullptr); diff --git a/include/seqan3/search/fm_index/concept.hpp b/include/seqan3/search/fm_index/concept.hpp index cbc4970347..e0cc411a47 100644 --- a/include/seqan3/search/fm_index/concept.hpp +++ b/include/seqan3/search/fm_index/concept.hpp @@ -16,7 +16,6 @@ #include -#include #include #include #include @@ -78,6 +77,15 @@ namespace seqan3 * \{ */ +//!\brief The possible text layouts (single, collection) the seqan3::fm_index and seqan3::bi_fm_index can support. +enum text_layout : bool +{ + //!\brief The text is a single range. + single, + //!\brief The text is a range of ranges. + collection +}; + // ============================================================================ // FmIndex // ============================================================================ @@ -91,14 +99,15 @@ namespace seqan3 template SEQAN3_CONCEPT FmIndex = std::Semiregular && requires (t index) { + typename t::char_type; typename t::size_type; typename t::cursor_type; // NOTE: circular dependency // requires FmIndexCursor; - requires requires (t index, std::conditional_t>, - std::vector> const text) + requires requires (t index, std::conditional_t>, + std::vector> const text) { { t(text) }; { index.construct(text) } -> void; @@ -149,10 +158,12 @@ SEQAN3_CONCEPT FmIndexCursor = std::Semiregular && requires (t cur) requires requires (typename t::index_type const index) { { t(index) } }; - requires requires (t cur, dna4 const c, std::vector const seq, - std::conditional_t>, - std::vector> const text) + requires requires (t cur, + typename t::index_type::char_type const c, + std::vector const seq, + std::conditional_t>, + std::vector> const text) { { cur.extend_right() } -> bool; { cur.extend_right(c) } -> bool; @@ -164,7 +175,7 @@ SEQAN3_CONCEPT FmIndexCursor = std::Semiregular && requires (t cur) { cur.last_rank() } -> typename t::size_type; { cur.query_length() } -> typename t::size_type; { cur.count() } -> typename t::size_type; - { cur.locate() } -> std::conditional_t std::conditional_t>, std::vector>; { cur.lazy_locate() } -> auto; @@ -240,7 +251,9 @@ SEQAN3_CONCEPT BiFmIndexCursor = FmIndexCursor && requires (t cur) requires requires (typename t::index_type const index) { { t(index) } }; - requires requires (t cur, dna4 const c, std::vector const seq) + requires requires (t cur, + typename t::index_type::char_type const c, + std::vector const seq) { { cur.extend_left() } -> bool; { cur.extend_left(c) } -> bool; diff --git a/include/seqan3/search/fm_index/fm_index.hpp b/include/seqan3/search/fm_index/fm_index.hpp index baba0af2a7..9e005f90aa 100644 --- a/include/seqan3/search/fm_index/fm_index.hpp +++ b/include/seqan3/search/fm_index/fm_index.hpp @@ -89,28 +89,14 @@ using sdsl_wt_index_type = */ using default_sdsl_index_type = sdsl_wt_index_type; -//!\brief The possible text layouts (single, collection) the seqan3::fm_index and seqan3::bi_fm_index can support. -enum text_layout : bool -{ - //!\brief The text is a single range. - single, - //!\brief The text is a range of ranges. - collection -}; -//!\cond -SEQAN3_DEPRECATED_310 -void fm_index_deprecation(bool); - -template -void fm_index_deprecation(t); -//!\endcond /*!\brief The SeqAn FM Index. * \implements seqan3::FmIndex - * \tparam is_collection Indicates whether this index works on a text collection or a single text. - * See seqan3::text_layout. - * \tparam sdsl_index_type_ The type of the underlying SDSL index, must model seqan3::SdslIndex. + * \tparam alphabet_t The alphabet type; must model seqan3::Semialphabet. + * \tparam text_layout_mode_ Indicates whether this index works on a text collection or a single text. + * See seqan3::text_layout. + * \tparam sdsl_index_type_ The type of the underlying SDSL index, must model seqan3::SdslIndex. * \details * * The seqan3::fm_index is a fast and space-efficient string index to search strings and collections of strings. @@ -141,18 +127,13 @@ void fm_index_deprecation(t); * \todo Link to SDSL documentation or write our own once SDSL3 documentation is available somewhere.... * * \endif - * - * \deprecated Use seqan3::text_layout to indicate single texts and text collections. The use of bool is deprecated. */ -template +template class fm_index { -protected: - //!\brief The alphabet size of the text. - size_t sigma{0}; - //!\brief Indicates whether index is built over a collection. - static constexpr bool is_collection_{is_collection}; - +private: /*!\name Member types * \{ */ @@ -176,81 +157,6 @@ class fm_index //!\brief Rank support for text_begin. sdsl::rank_support_sd<1> text_begin_rs; - //!\cond - using unused_t [[maybe_unused]] = decltype(fm_index_deprecation(is_collection)); - //!\endcond - -public: - /*!\name Member types - * \{ - */ - //!\brief Type for representing positions in the indexed text. - using size_type = typename sdsl_index_type::size_type; - //!\brief The type of the (unidirectional) cursor. - using cursor_type = fm_index_cursor>; - //!\} - - template - friend class bi_fm_index_cursor; - - template - friend class fm_index_cursor; - - template - friend class detail::fm_index_cursor_node; - - /*!\name Constructors, destructor and assignment - * \{ - */ - fm_index() = default; //!< Defaulted. - - fm_index(fm_index const & rhs) : //!< When copy constructing, also update internal data structures. - sigma{rhs.sigma}, index{rhs.index}, text_begin{rhs.text_begin}, text_begin_ss{rhs.text_begin_ss}, - text_begin_rs{rhs.text_begin_rs} - { - text_begin_ss.set_vector(&text_begin); - text_begin_rs.set_vector(&text_begin); - } - - fm_index(fm_index && rhs) : //!< When move constructing, also update internal data structures. - sigma{std::move(rhs.sigma)}, index{std::move(rhs.index)}, text_begin{std::move(rhs.text_begin)}, - text_begin_ss{std::move(rhs.text_begin_ss)}, text_begin_rs{std::move(rhs.text_begin_rs)} - { - text_begin_ss.set_vector(&text_begin); - text_begin_rs.set_vector(&text_begin); - } - - fm_index & operator=(fm_index rhs) //!< When copy/move assigning, also update internal data structures. - { - index = std::move(rhs.index); - sigma = std::move(rhs.sigma); - text_begin = std::move(rhs.text_begin); - text_begin_ss = std::move(rhs.text_begin_ss); - text_begin_rs = std::move(rhs.text_begin_rs); - - text_begin_ss.set_vector(&text_begin); - text_begin_rs.set_vector(&text_begin); - - return *this; - } - - ~fm_index() = default; //!< Defaulted. - - /*!\brief Constructor that immediately constructs the index given a range. The range cannot be empty. - * \tparam text_t The type of range to construct from; must model std::ranges::BidirectionalRange. - * \param[in] text The text to construct from. - * - * ### Complexity - * - * \if DEV \todo \endif At least linear. - */ - template - fm_index(text_t && text) - { - construct(std::forward(text)); - } - //!\} - /*!\brief Constructs the index given a range. The range cannot be an rvalue (i.e. a temporary object) and has to be non-empty. * \tparam text_t The type of range to construct from; must model std::ranges::BidirectionalRange. @@ -271,21 +177,23 @@ class fm_index * No guarantee. \if DEV \todo Ensure strong exception guarantee. \endif */ template + //!\cond + requires text_layout_mode_ == text_layout::single + //!\endcond void construct(text_t && text) - //!\cond - requires !is_collection_ - //!\endcond { static_assert(std::ranges::BidirectionalRange, "The text must model BidirectionalRange."); static_assert(alphabet_size> <= 256, "The alphabet is too big."); + static_assert(std::ConvertibleTo, alphabet_t>, + "The alphabet of the text collection must be convertible to the alphabet of the index."); static_assert(dimension_v == 1, "The input cannot be a text collection."); // text must not be empty if (std::ranges::begin(text) == std::ranges::end(text)) throw std::invalid_argument("The text that is indexed cannot be empty."); - constexpr auto cexpr_sigma = alphabet_size>; - sigma = cexpr_sigma; + constexpr auto sigma = alphabet_size; + // TODO: // * check what happens in sdsl when constructed twice! // * choose between in-memory/external and construction algorithms @@ -297,7 +205,7 @@ class fm_index | view::to_rank | std::view::transform([] (uint8_t const r) { - if constexpr (cexpr_sigma == 256) + if constexpr (sigma == 256) { if (r == 255) throw std::out_of_range("The input text cannot be indexed, because for full" @@ -319,15 +227,17 @@ class fm_index //!\overload template + //!\cond + requires text_layout_mode_ == text_layout::collection + //!\endcond void construct(text_t && text) - //!\cond - requires is_collection_ - //!\endcond { static_assert(std::ranges::BidirectionalRange, "The text collection must model BidirectionalRange."); static_assert(std::ranges::BidirectionalRange>, "The elements of the text collection must model BidirectionalRange."); static_assert(alphabet_size> <= 256, "The alphabet is too big."); + static_assert(std::ConvertibleTo, alphabet_t>, + "The alphabet of the text collection must be convertible to the alphabet of the index."); static_assert(dimension_v == 2, "The input must be a text collection."); // text collection must not be empty @@ -351,8 +261,7 @@ class fm_index if (all_empty) throw std::invalid_argument("A text collection that only contains empty texts cannot be indexed."); - constexpr auto cexpr_sigma = alphabet_size>; - sigma = cexpr_sigma; + constexpr auto sigma = alphabet_size; // bitvector where 1 marks the begin position of a single text from the collection in the concatenated text sdsl::bit_vector pos(text_size, 0); @@ -370,7 +279,7 @@ class fm_index sdsl::int_vector<8> tmp_text(text_size - 1); // last text in collection needs no delimiter - constexpr uint8_t delimiter = cexpr_sigma >= 255 ? 255 : cexpr_sigma + 1; + constexpr uint8_t delimiter = sigma >= 255 ? 255 : sigma + 1; std::vector tmp = text | view::deep{view::to_rank} @@ -378,7 +287,7 @@ class fm_index { std::view::transform([] (uint8_t const r) { - if constexpr (cexpr_sigma >= 255) + if constexpr (sigma >= 255) { if (r >= 254) throw std::out_of_range("The input text cannot be indexed, because" @@ -405,6 +314,80 @@ class fm_index sdsl::construct_im(index, tmp_text, 0); } +public: + //!\brief Indicates whether index is built over a collection. + static constexpr text_layout text_layout_mode = text_layout_mode_; + + /*!\name Member types + * \{ + */ + //!\brief The type of the underlying character of the indexed text. + using char_type = alphabet_t; + //!\brief Type for representing positions in the indexed text. + using size_type = typename sdsl_index_type::size_type; + //!\brief The type of the (unidirectional) cursor. + using cursor_type = fm_index_cursor>; + //!\} + + template + friend class bi_fm_index_cursor; + + template + friend class fm_index_cursor; + + template + friend class detail::fm_index_cursor_node; + + /*!\name Constructors, destructor and assignment + * \{ + */ + fm_index() = default; //!< Defaulted. + + fm_index(fm_index const & rhs) : //!< When copy constructing, also update internal data structures. + index{rhs.index}, text_begin{rhs.text_begin}, text_begin_ss{rhs.text_begin_ss}, text_begin_rs{rhs.text_begin_rs} + { + text_begin_ss.set_vector(&text_begin); + text_begin_rs.set_vector(&text_begin); + } + + fm_index(fm_index && rhs) : //!< When move constructing, also update internal data structures. + index{std::move(rhs.index)}, text_begin{std::move(rhs.text_begin)},text_begin_ss{std::move(rhs.text_begin_ss)}, + text_begin_rs{std::move(rhs.text_begin_rs)} + { + text_begin_ss.set_vector(&text_begin); + text_begin_rs.set_vector(&text_begin); + } + + fm_index & operator=(fm_index rhs) //!< When copy/move assigning, also update internal data structures. + { + index = std::move(rhs.index); + text_begin = std::move(rhs.text_begin); + text_begin_ss = std::move(rhs.text_begin_ss); + text_begin_rs = std::move(rhs.text_begin_rs); + + text_begin_ss.set_vector(&text_begin); + text_begin_rs.set_vector(&text_begin); + + return *this; + } + + ~fm_index() = default; //!< Defaulted. + + /*!\brief Constructor that immediately constructs the index given a range. The range cannot be empty. + * \tparam text_t The type of range to construct from; must model std::ranges::BidirectionalRange. + * \param[in] text The text to construct from. + * + * ### Complexity + * + * \if DEV \todo \endif At least linear. + */ + template + fm_index(text_t && text) + { + construct(std::forward(text)); + } + //!\} + /*!\brief Returns the length of the indexed text including sentinel characters. * \returns Returns the length of the indexed text including sentinel characters. * @@ -505,10 +488,25 @@ class fm_index text_begin_ss.set_vector(&text_begin); archive(text_begin_rs); text_begin_rs.set_vector(&text_begin); + + auto sigma = alphabet_size; archive(sigma); - bool tmp = is_collection_; + if (sigma != alphabet_size) + { + throw std::logic_error{"The fm_index was built over an alphabet of size " + std::to_string(sigma) + + " but it is being read into an fm_index with an alphabet of size " + + std::to_string(alphabet_size) + "."}; + } + + bool tmp = text_layout_mode; archive(tmp); - assert(tmp == is_collection_); + if (tmp != text_layout_mode) + { + throw std::logic_error{std::string{"The fm_index was built over a "} + + (tmp ? "text collection" : "single text") + + " but it is being read into an fm_index expecting a " + + (text_layout_mode ? "text collection." : "single text.")}; + } } //!\endcond @@ -517,9 +515,9 @@ class fm_index /*!\name Template argument type deduction guides * \{ */ -//! \brief Deduces the dimensions of the text. +//! \brief Deduces the alphabet and dimensions of the text. template -fm_index(text_t &&) -> fm_index != 1}>; +fm_index(text_t &&) -> fm_index, text_layout{dimension_v != 1}>; //!\} //!\} diff --git a/include/seqan3/search/fm_index/fm_index_cursor.hpp b/include/seqan3/search/fm_index/fm_index_cursor.hpp index eb5d076766..5b5be992d9 100644 --- a/include/seqan3/search/fm_index/fm_index_cursor.hpp +++ b/include/seqan3/search/fm_index/fm_index_cursor.hpp @@ -27,12 +27,6 @@ #include #include -// namespace seqan3::detail -// { -// // forward declaration -// auto get_suffix_array_range(fm_index_cursor const & it); -// } // namespace seqan3::detail - namespace seqan3 { @@ -63,7 +57,6 @@ namespace seqan3 template class fm_index_cursor { - public: /*!\name Member types @@ -75,7 +68,7 @@ class fm_index_cursor using size_type = typename index_type::size_type; //!\} -protected: +private: //!\privatesection /*!\name Member types @@ -159,16 +152,16 @@ class fm_index_cursor //!\brief Default constructor. Accessing member functions on a default constructed object is undefined behavior. // Default construction is necessary to make this class semi-regular and e.g., to allow construction of // std::array of iterators. - fm_index_cursor() noexcept = default; //!< Default constructor. - fm_index_cursor(fm_index_cursor const &) noexcept = default; //!< Copy constructor. - fm_index_cursor & operator=(fm_index_cursor const &) noexcept = default; //!< Copy assignment. - fm_index_cursor(fm_index_cursor &&) noexcept = default; //!< Move constructor. - fm_index_cursor & operator=(fm_index_cursor &&) noexcept = default; //!< Move assignment. - ~fm_index_cursor() = default; //!< Destructor. + fm_index_cursor() noexcept = default; //!< Defaulted. + fm_index_cursor(fm_index_cursor const &) noexcept = default; //!< Defaulted. + fm_index_cursor & operator=(fm_index_cursor const &) noexcept = default; //!< Defaulted. + fm_index_cursor(fm_index_cursor &&) noexcept = default; //!< Defaulted. + fm_index_cursor & operator=(fm_index_cursor &&) noexcept = default; //!< Defaulted. + ~fm_index_cursor() = default; //!< Defaulted. //! \brief Construct from given index. fm_index_cursor(index_t const & _index) noexcept : index(&_index), node({0, _index.index.size() - 1, 0, 0}), - sigma(_index.index.sigma - index_t::is_collection_) + sigma(_index.index.sigma - index_t::text_layout_mode) {} //\} @@ -267,11 +260,13 @@ class fm_index_cursor * * No-throw guarantee. */ - template + template bool extend_right(char_t const c) noexcept { + static_assert(std::ConvertibleTo, + "The character must be convertible to the alphabet of the index."); + assert(index != nullptr); - assert(index->sigma == alphabet_size); size_type _lb = node.lb, _rb = node.rb; @@ -307,8 +302,10 @@ class fm_index_cursor bool extend_right(seq_t && seq) noexcept { static_assert(std::ranges::ForwardRange, "The query must model ForwardRange."); + static_assert(std::ConvertibleTo, typename index_t::char_type>, + "The alphabet of the sequence must be convertible to the alphabet of the index."); + assert(index != nullptr); // range must not be empty! - assert(index->sigma == alphabet_size>); size_type _lb = node.lb, _rb = node.rb; size_type new_parent_lb = parent_lb, new_parent_rb = parent_rb; @@ -445,13 +442,14 @@ class fm_index_cursor template auto path_label(text_t && text) const noexcept //!\cond - requires !index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::single //!\endcond { static_assert(std::ranges::InputRange, "The text must model InputRange."); - static_assert(!(dimension_v != 1), "The input cannot be a text collection."); + static_assert(dimension_v == 1, "The input cannot be a text collection."); + static_assert(std::Same, typename index_t::char_type>, + "The alphabet types of the given text and index differ."); assert(index != nullptr); - assert(index->sigma == alphabet_size>); size_type const query_begin = offset() - index->index[node.lb]; return text | view::slice(query_begin, query_begin + query_length()); @@ -461,13 +459,14 @@ class fm_index_cursor template auto path_label(text_t && text) const noexcept //!\cond - requires index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::collection //!\endcond { static_assert(std::ranges::InputRange, "The text collection must model InputRange."); - static_assert(!(dimension_v != 2), "The input must be a text collection."); + static_assert(dimension_v == 2, "The input must be a text collection."); + static_assert(std::Same, typename index_t::char_type>, + "The alphabet types of the given text and index differ."); assert(index != nullptr); - assert(index->sigma == alphabet_size>); size_type const loc = offset() - index->index[node.lb]; size_type const query_begin = loc - index->text_begin_rs.rank(loc + 1) + 1; // Substract delimiters @@ -505,7 +504,7 @@ class fm_index_cursor */ std::vector locate() const //!\cond - requires !index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::single //!\endcond { assert(index != nullptr); @@ -521,7 +520,7 @@ class fm_index_cursor //!\overload std::vector> locate() const //!\cond - requires index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::collection //!\endcond { assert(index != nullptr); @@ -552,7 +551,7 @@ class fm_index_cursor */ auto lazy_locate() const //!\cond - requires !index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::single //!\endcond { assert(index != nullptr); @@ -564,7 +563,7 @@ class fm_index_cursor //!\overload auto lazy_locate() const //!\cond - requires index_t::is_collection_ + requires index_t::text_layout_mode == text_layout::collection //!\endcond { assert(index != nullptr); diff --git a/test/unit/search/fm_index/bi_fm_index_aa27_test.cpp b/test/unit/search/fm_index/bi_fm_index_aa27_test.cpp index 874335d706..59af668442 100644 --- a/test/unit/search/fm_index/bi_fm_index_aa27_test.cpp +++ b/test/unit/search/fm_index/bi_fm_index_aa27_test.cpp @@ -5,10 +5,10 @@ // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md // ----------------------------------------------------------------------------------------------------- -#include "fm_index_test_template.hpp" #include "fm_index_collection_test_template.hpp" +#include "fm_index_test_template.hpp" -using t1 = std::pair, std::vector>; +using t1 = std::pair, std::vector>; INSTANTIATE_TYPED_TEST_CASE_P(aa27, fm_index_test, t1); -using t2 = std::pair, std::vector>>; +using t2 = std::pair, std::vector>>; INSTANTIATE_TYPED_TEST_CASE_P(aa27_collection, fm_index_collection_test, t2); diff --git a/test/unit/search/fm_index/bi_fm_index_char_test.cpp b/test/unit/search/fm_index/bi_fm_index_char_test.cpp index 00aacd0554..b76114a0c3 100644 --- a/test/unit/search/fm_index/bi_fm_index_char_test.cpp +++ b/test/unit/search/fm_index/bi_fm_index_char_test.cpp @@ -5,17 +5,17 @@ // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md // ----------------------------------------------------------------------------------------------------- -#include "fm_index_test_template.hpp" #include "fm_index_collection_test_template.hpp" +#include "fm_index_test_template.hpp" -using t1 = std::pair, std::vector>; +using t1 = std::pair, std::vector>; INSTANTIATE_TYPED_TEST_CASE_P(char, fm_index_test, t1); -using t2 = std::pair, std::vector>>; +using t2 = std::pair, std::vector>>; INSTANTIATE_TYPED_TEST_CASE_P(char_collection, fm_index_collection_test, t2); TEST(char, throw_on_reserved_char) { - using bi_fm_index_t = bi_fm_index; + using bi_fm_index_t = bi_fm_index; unsigned char c = 255; std::vector text{'a', 'u', ',', c, '0'}; @@ -25,7 +25,7 @@ TEST(char, throw_on_reserved_char) TEST(char_collection, throw_on_reserved_char) { - using bi_fm_index_t = bi_fm_index; + using bi_fm_index_t = bi_fm_index; { unsigned char c = 255; diff --git a/test/unit/search/fm_index/bi_fm_index_dna4_test.cpp b/test/unit/search/fm_index/bi_fm_index_dna4_test.cpp index aa0a93ac2b..54df0bfa4f 100644 --- a/test/unit/search/fm_index/bi_fm_index_dna4_test.cpp +++ b/test/unit/search/fm_index/bi_fm_index_dna4_test.cpp @@ -5,16 +5,10 @@ // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md // ----------------------------------------------------------------------------------------------------- -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -#include #include "fm_index_collection_test_template.hpp" #include "fm_index_test_template.hpp" -using t1 = std::pair, std::vector>; +using t1 = std::pair, std::vector>; INSTANTIATE_TYPED_TEST_CASE_P(dna4, fm_index_test, t1); -using t2 = std::pair, std::vector>>; +using t2 = std::pair, std::vector>>; INSTANTIATE_TYPED_TEST_CASE_P(dna4_collection, fm_index_collection_test, t2); - -using t3 = std::pair, std::vector>; -INSTANTIATE_TYPED_TEST_CASE_P(dna4_deprecation, fm_index_test, t3); diff --git a/test/unit/search/fm_index/fm_index_collection_test_template.hpp b/test/unit/search/fm_index/fm_index_collection_test_template.hpp index 42e84cb7c6..d68faeefbf 100644 --- a/test/unit/search/fm_index/fm_index_collection_test_template.hpp +++ b/test/unit/search/fm_index/fm_index_collection_test_template.hpp @@ -123,7 +123,7 @@ TYPED_TEST_P(fm_index_collection_test, concept_check) using index_t = typename TypeParam::first_type; EXPECT_TRUE((FmIndex)); - if constexpr (std::Same>) + if constexpr (std::Same>) { EXPECT_TRUE(BiFmIndex); } diff --git a/test/unit/search/fm_index/fm_index_dna4_test.cpp b/test/unit/search/fm_index/fm_index_dna4_test.cpp index b1c2b093a2..9cd8734e60 100644 --- a/test/unit/search/fm_index/fm_index_dna4_test.cpp +++ b/test/unit/search/fm_index/fm_index_dna4_test.cpp @@ -5,21 +5,46 @@ // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md // ----------------------------------------------------------------------------------------------------- -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -#include #include "fm_index_collection_test_template.hpp" #include "fm_index_test_template.hpp" -using t1 = std::pair, std::vector>; +using t1 = std::pair, std::vector>; INSTANTIATE_TYPED_TEST_CASE_P(dna4, fm_index_test, t1); -using t2 = std::pair, std::vector>>; +using t2 = std::pair, std::vector>>; INSTANTIATE_TYPED_TEST_CASE_P(dna4_collection, fm_index_collection_test, t2); -using t3 = std::pair, std::vector>; -INSTANTIATE_TYPED_TEST_CASE_P(dna4_deprecation, fm_index_test, t3); - TEST(fm_index_test, additional_concepts) { EXPECT_TRUE(detail::SdslIndex); } + +TEST(fm_index_test, cerealisation_errors) +{ +#if SEQAN3_WITH_CEREAL + using namespace seqan3; + + fm_index index{"AGTCTGATGCTGCTAC"_dna4}; + + test::tmp_filename filename{"cereal_test"}; + + { + std::ofstream os{filename.get_path(), std::ios::binary}; + cereal::BinaryOutputArchive oarchive{os}; + oarchive(index); + } + + { + fm_index in; + std::ifstream is{filename.get_path(), std::ios::binary}; + cereal::BinaryInputArchive iarchive{is}; + EXPECT_THROW(iarchive(in), std::logic_error); + } + + { + fm_index in; + std::ifstream is{filename.get_path(), std::ios::binary}; + cereal::BinaryInputArchive iarchive{is}; + EXPECT_THROW(iarchive(in), std::logic_error); + } +#endif +} diff --git a/test/unit/search/fm_index/fm_index_test_template.hpp b/test/unit/search/fm_index/fm_index_test_template.hpp index 1c3998438c..420fe937b9 100644 --- a/test/unit/search/fm_index/fm_index_test_template.hpp +++ b/test/unit/search/fm_index/fm_index_test_template.hpp @@ -93,7 +93,7 @@ TYPED_TEST_P(fm_index_test, concept_check) { using index_t = typename TypeParam::first_type; EXPECT_TRUE(FmIndex); - if constexpr (std::Same>) + if constexpr (std::Same>) { EXPECT_TRUE(BiFmIndex); } diff --git a/test/unit/search/fm_index_cursor/bi_fm_index_cursor_collection_test.cpp b/test/unit/search/fm_index_cursor/bi_fm_index_cursor_collection_test.cpp index a46ca72df1..855b0e3058 100644 --- a/test/unit/search/fm_index_cursor/bi_fm_index_cursor_collection_test.cpp +++ b/test/unit/search/fm_index_cursor/bi_fm_index_cursor_collection_test.cpp @@ -7,5 +7,5 @@ #include "bi_fm_index_cursor_collection_test_template.hpp" -using it_t1 = bi_fm_index_cursor>; +using it_t1 = bi_fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(dna4, bi_fm_index_cursor_collection_test, it_t1); diff --git a/test/unit/search/fm_index_cursor/bi_fm_index_cursor_test.cpp b/test/unit/search/fm_index_cursor/bi_fm_index_cursor_test.cpp index ad74313a9d..b3fa3b3c3f 100644 --- a/test/unit/search/fm_index_cursor/bi_fm_index_cursor_test.cpp +++ b/test/unit/search/fm_index_cursor/bi_fm_index_cursor_test.cpp @@ -7,5 +7,5 @@ #include "bi_fm_index_cursor_test_template.hpp" -using it_t1 = bi_fm_index_cursor>; +using it_t1 = bi_fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(dna4, bi_fm_index_cursor_test, it_t1); diff --git a/test/unit/search/fm_index_cursor/fm_index_cursor_collection_test.cpp b/test/unit/search/fm_index_cursor/fm_index_cursor_collection_test.cpp index 194aa163b2..4e102c8ee7 100644 --- a/test/unit/search/fm_index_cursor/fm_index_cursor_collection_test.cpp +++ b/test/unit/search/fm_index_cursor/fm_index_cursor_collection_test.cpp @@ -7,14 +7,14 @@ #include "fm_index_cursor_collection_test_template.hpp" -using it_t1 = fm_index_cursor>; +using it_t1 = fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(default_traits, fm_index_cursor_collection_test, it_t1); -using it_t2 = fm_index_cursor>; +using it_t2 = fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(byte_alphabet_traits, fm_index_cursor_collection_test, it_t2); -using it_t3 = bi_fm_index_cursor>; +using it_t3 = bi_fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(bi_default_traits, fm_index_cursor_collection_test, it_t3); -using it_t4 = bi_fm_index_cursor>; +using it_t4 = bi_fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(bi_byte_alphabet_traits, fm_index_cursor_collection_test, it_t4); diff --git a/test/unit/search/fm_index_cursor/fm_index_cursor_test.cpp b/test/unit/search/fm_index_cursor/fm_index_cursor_test.cpp index c566dcd004..1a399d2f35 100644 --- a/test/unit/search/fm_index_cursor/fm_index_cursor_test.cpp +++ b/test/unit/search/fm_index_cursor/fm_index_cursor_test.cpp @@ -7,14 +7,14 @@ #include "fm_index_cursor_test_template.hpp" -using it_t1 = fm_index_cursor>; +using it_t1 = fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(default_traits, fm_index_cursor_test, it_t1); -using it_t2 = fm_index_cursor>; +using it_t2 = fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(byte_alphabet_traits, fm_index_cursor_test, it_t2); -using it_t3 = bi_fm_index_cursor>; +using it_t3 = bi_fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(bi_default_traits, fm_index_cursor_test, it_t3); -using it_t4 = bi_fm_index_cursor>; +using it_t4 = bi_fm_index_cursor>; INSTANTIATE_TYPED_TEST_CASE_P(bi_byte_alphabet_traits, fm_index_cursor_test, it_t4); diff --git a/test/unit/search/search_collection_test.cpp b/test/unit/search/search_collection_test.cpp index c7455c089a..e3413b451b 100644 --- a/test/unit/search/search_collection_test.cpp +++ b/test/unit/search/search_collection_test.cpp @@ -8,12 +8,12 @@ #include #include -#include "helper.hpp" - #include #include +#include "helper.hpp" + using namespace seqan3; using namespace seqan3::search_cfg; using namespace std::string_literals; @@ -34,8 +34,10 @@ class search_string_test : public ::testing::Test T index{text}; }; -using fm_index_types = ::testing::Types, bi_fm_index>; -using fm_index_string_types = ::testing::Types, bi_fm_index>; +using fm_index_types = ::testing::Types, + bi_fm_index>; +using fm_index_string_types = ::testing::Types, + bi_fm_index>; TYPED_TEST_CASE(search_test, fm_index_types); TYPED_TEST_CASE(search_string_test, fm_index_string_types); diff --git a/test/unit/search/search_test.cpp b/test/unit/search/search_test.cpp index 00bb5ec6de..a3c4594701 100644 --- a/test/unit/search/search_test.cpp +++ b/test/unit/search/search_test.cpp @@ -8,12 +8,12 @@ #include #include -#include "helper.hpp" - #include #include +#include "helper.hpp" + using namespace seqan3; using namespace seqan3::search_cfg; using namespace std::string_literals; @@ -34,8 +34,10 @@ class search_string_test : public ::testing::Test T index{text}; }; -using fm_index_types = ::testing::Types, bi_fm_index>; -using fm_index_string_types = ::testing::Types, bi_fm_index>; +using fm_index_types = ::testing::Types, + bi_fm_index>; +using fm_index_string_types = ::testing::Types, + bi_fm_index>; TYPED_TEST_CASE(search_test, fm_index_types); TYPED_TEST_CASE(search_string_test, fm_index_string_types);