diff --git a/doc/cookbook/custom_dna4.cpp b/doc/cookbook/custom_dna4.cpp index ceb5835f2b..c368935307 100644 --- a/doc/cookbook/custom_dna4.cpp +++ b/doc/cookbook/custom_dna4.cpp @@ -9,15 +9,32 @@ class my_dna4 : public seqan3::nucleotide_base using nucleotide_base::nucleotide_base; // Use constructors of the base class. private: + // Returns the character representation of rank. This is where rank conversion for to_char() is handled! + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + // Returns the rank representation of character. This is where char conversion for assign_char() is handled! + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } + +private: + // === lookup-table implementation detail === + // Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] {'A', 'C', 'G', 'T'}; // rank 0,1,2,3 + static constexpr char_type rank_to_char_table[alphabet_size] {'A', 'C', 'G', 'T'}; // rank 0,1,2,3 - // Char-to-value conversion table. This is where char conversion for assign_char() is handled! - static constexpr std::array char_to_rank + // Char-to-value conversion table. + static constexpr std::array char_to_rank_table { [] () constexpr { - std::array conversion_table{}; // By default now, everything has rank 0 which equals `A`. + // By default, everything has rank 0 which equals `A`. + std::array conversion_table{}; conversion_table['C'] = conversion_table['c'] = 1; conversion_table['G'] = conversion_table['g'] = 2; diff --git a/doc/howto/write_an_alphabet/dna2_derive_from_base.cpp b/doc/howto/write_an_alphabet/dna2_derive_from_base.cpp index 00b0f2173a..38dcbd8e68 100644 --- a/doc/howto/write_an_alphabet/dna2_derive_from_base.cpp +++ b/doc/howto/write_an_alphabet/dna2_derive_from_base.cpp @@ -9,15 +9,40 @@ #include // std::array #include // alphabet_base #include // alphabet concept checks +#include // seqan3::to_lower // derive from alphabet_base struct dna2 : public seqan3::alphabet_base { private: + // make the base class a friend so it can access the tables: + friend seqan3::alphabet_base; + // map 0 => 'S' and 1 => 'W' - static constexpr char_type rank_to_char[alphabet_size] {'S', 'W'}; + static constexpr char_type rank_to_char(rank_type const rank) + { + // via a lookup table + return rank_to_char_table[rank]; + // or via an arithmetic expression + return rank == 1 ? 'W' : 'S'; + } - static constexpr std::array char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + // via a lookup table + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + // or via an arithmetic expression + return seqan3::to_lower(chr) == 'w' ? 1 : 0; + } + +private: + // === lookup-table implementation detail === + + // map 0 => 'S' and 1 => 'W' + static constexpr char_type rank_to_char_table[alphabet_size] {'S', 'W'}; + + static constexpr std::array char_to_rank_table { // initialise with an immediately evaluated lambda expression: [] () constexpr @@ -28,9 +53,6 @@ struct dna2 : public seqan3::alphabet_base return ret; } () }; - - // make the base class a friend so it can access the tables: - friend seqan3::alphabet_base; }; // check the concepts diff --git a/include/seqan3/alphabet/alphabet_base.hpp b/include/seqan3/alphabet/alphabet_base.hpp index 5401d758cf..8426ecdc11 100644 --- a/include/seqan3/alphabet/alphabet_base.hpp +++ b/include/seqan3/alphabet/alphabet_base.hpp @@ -19,6 +19,30 @@ #include #include +#ifdef SEQAN3_DEPRECATED_310 +namespace seqan3::detail +{ +//!\cond +// helper concept to deprecate old rank_to_char lookup tables +template +SEQAN3_CONCEPT has_rank_to_char_table = requires() +{ + { alphabet_t::rank_to_char[0] }; +}; +//!\endcond + +//!\cond +// helper concept to deprecate old char_to_rank lookup tables +template +SEQAN3_CONCEPT has_char_to_rank_table = requires() +{ + { alphabet_t::char_to_rank[0] }; +}; +//!\endcond + +} // namespace seqan3::detail +#endif // SEQAN3_DEPRECATED_310 + namespace seqan3 { @@ -35,18 +59,20 @@ namespace seqan3 * seqan3::alphabet, it is purely a way to avoid code duplication. * * The base class represents the alphabet value as the rank and automatically deduces the rank type from the size and - * defines all required member functions. The derived type needs to define only the following two tables as static - * member variables (can be private if the base class is befriended): + * defines all required member functions. The derived type needs to define only the following two static + * member functions (can be private if the base class is befriended): * - * * `static std::array constexpr rank_to_char` that defines for every possible rank value - * the corresponding char value. - * * `static std::array constexpr char_to_rank` that defines for every possible character value the - * corresponding rank value (adapt size if char_type isn't `char`). + * * `static constexpr char_type rank_to_char(rank_type const rank);` that defines for every possible rank value the + * corresponding char value. + * (The implementation can be a lookup-table or an arithmetic expression.) + * * `static constexpr rank_type char_to_rank(char_type const chr);` that defines for every possible character value + * the corresponding rank value (adapt size if char_type isn't `char`). + * (The implementation can be a lookup-table or an arithmetic expression.) * * ### Example * * This creates an alphabet called `ab` which has size two and the two letters 'A' and 'B': - * \include test/snippet/alphabet/detail/alphabet_base.cpp + * \include test/snippet/alphabet/alphabet_base.cpp * * \stableapi{Since version 3.1.} */ @@ -110,10 +136,32 @@ class alphabet_base //!\cond requires (!std::same_as) //!\endcond + { +#ifdef SEQAN3_DEPRECATED_310 + if constexpr (detail::has_rank_to_char_table) + return rank_to_char_table(rank); + else + return derived_type::rank_to_char(rank); +#else // ^^^ before 3.1.0 release / after 3.1.0 release vvv + return derived_type::rank_to_char(rank); +#endif // SEQAN3_DEPRECATED_310 + } + +#ifdef SEQAN3_DEPRECATED_310 +private: + + /*!\brief Before SeqAn 3.0.3, we defined derived_type::rank_to_char_table as a lookup table. We relaxed this to be a + * function to give the implementer more freedom. + * \deprecated Define derived_type::rank_to_char_table as a function. + */ + SEQAN3_DEPRECATED_310 static constexpr char_type rank_to_char_table(rank_type const rank) noexcept { return derived_type::rank_to_char[rank]; } +public: +#endif // SEQAN3_DEPRECATED_310 + /*!\brief Return the letter's numeric value (rank in the alphabet). * * \details @@ -140,7 +188,7 @@ class alphabet_base * \{ */ /*!\brief Assign from a character, implicitly converts invalid characters. - * \param c The character to be assigned. + * \param chr The character to be assigned. * * \details * @@ -156,16 +204,42 @@ class alphabet_base * * \stableapi{Since version 3.1.} */ - constexpr derived_type & assign_char(char_type const c) noexcept + constexpr derived_type & assign_char(char_type const chr) noexcept //!\cond requires (!std::same_as) //!\endcond { - using index_t = std::make_unsigned_t; - rank = derived_type::char_to_rank[static_cast(c)]; +#ifdef SEQAN3_DEPRECATED_310 + if constexpr (detail::has_char_to_rank_table) + rank = char_to_rank_table(chr); + else + rank = derived_type::char_to_rank(chr); +#else // ^^^ before 3.1.0 release / after 3.1.0 release vvv + rank = derived_type::char_to_rank(chr); +#endif // SEQAN3_DEPRECATED_310 + return static_cast(*this); } +#ifdef SEQAN3_DEPRECATED_310 +private: + + /*!\brief Before SeqAn 3.0.3, we defined derived_type::char_to_rank as a lookup table. We relaxed this to be a + * function to give the implementer more freedom. + * \deprecated Define derived_type::char_to_rank as a function. + */ + SEQAN3_DEPRECATED_310 static constexpr rank_type char_to_rank_table(char_type const chr) noexcept + { + using index_t = std::make_unsigned_t; +#if SEQAN3_WORKAROUND_GCC_99318 +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif // SEQAN3_WORKAROUND_GCC_99318 + return derived_type::char_to_rank[static_cast(chr)]; + } + +public: +#endif // SEQAN3_DEPRECATED_310 + /*!\brief Assign from a numeric value. * \param c The rank to be assigned. * diff --git a/include/seqan3/alphabet/aminoacid/aa10li.hpp b/include/seqan3/alphabet/aminoacid/aa10li.hpp index a54475f53e..2a49b428d4 100644 --- a/include/seqan3/alphabet/aminoacid/aa10li.hpp +++ b/include/seqan3/alphabet/aminoacid/aa10li.hpp @@ -106,9 +106,9 @@ class aa10li : public aminoacid_base using base_t::base_t; //!\} -protected: - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::aa27::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'B', @@ -119,11 +119,11 @@ class aa10li : public aminoacid_base 'I', 'J', 'K', - 'P', + 'P' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::aa27::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -136,8 +136,8 @@ class aa10li : public aminoacid_base // reverse mapping for characters and their lowercase for (rank_type rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[static_cast( rank_to_char[rnk]) ] = rnk; - ret[static_cast(to_lower(rank_to_char[rnk]))] = rnk; + ret[static_cast(rank_to_char_table[rnk])] = rnk; + ret[static_cast(to_lower(rank_to_char_table[rnk]))] = rnk; } ret['D'] = ret['B']; ret['d'] = ret['B']; // Convert D to B (either D/N). @@ -160,6 +160,19 @@ class aa10li : public aminoacid_base return ret; }() }; + + //!\copydoc seqan3::aa27::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } + + //!\copydoc seqan3::aa27::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/aminoacid/aa10murphy.hpp b/include/seqan3/alphabet/aminoacid/aa10murphy.hpp index 90ae23fa33..1dd19a7660 100644 --- a/include/seqan3/alphabet/aminoacid/aa10murphy.hpp +++ b/include/seqan3/alphabet/aminoacid/aa10murphy.hpp @@ -105,9 +105,9 @@ class aa10murphy : public aminoacid_base using base_t::base_t; //!\} -protected: - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::aa27::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'B', @@ -118,11 +118,11 @@ class aa10murphy : public aminoacid_base 'I', 'K', 'P', - 'S', + 'S' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::aa27::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -135,8 +135,8 @@ class aa10murphy : public aminoacid_base // reverse mapping for characters and their lowercase for (rank_type rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[static_cast( rank_to_char[rnk]) ] = rnk; - ret[static_cast(to_lower(rank_to_char[rnk]))] = rnk; + ret[static_cast(rank_to_char_table[rnk])] = rnk; + ret[static_cast(to_lower(rank_to_char_table[rnk]))] = rnk; } ret['D'] = ret['B']; ret['d'] = ret['B']; // Convert D to B (either D/N). @@ -159,6 +159,19 @@ class aa10murphy : public aminoacid_base return ret; }() }; + + //!\copydoc seqan3::aa27::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::aa27::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/aminoacid/aa20.hpp b/include/seqan3/alphabet/aminoacid/aa20.hpp index 493d5e0f22..965468b12b 100644 --- a/include/seqan3/alphabet/aminoacid/aa20.hpp +++ b/include/seqan3/alphabet/aminoacid/aa20.hpp @@ -86,9 +86,9 @@ class aa20 : public aminoacid_base using base_t::base_t; //!\} -protected: - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::aa27::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'C', @@ -109,11 +109,11 @@ class aa20 : public aminoacid_base 'T', 'V', 'W', - 'Y', + 'Y' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::aa27::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -126,8 +126,8 @@ class aa20 : public aminoacid_base // reverse mapping for characters and their lowercase for (rank_type rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[static_cast( rank_to_char[rnk]) ] = rnk; - ret[static_cast(to_lower(rank_to_char[rnk]))] = rnk; + ret[static_cast(rank_to_char_table[rnk])] = rnk; + ret[static_cast(to_lower(rank_to_char_table[rnk]))] = rnk; } ret['B'] = ret['D']; ret['b'] = ret['D']; // Convert b (either D/N) to D, since D occurs more frequently. @@ -140,6 +140,19 @@ class aa20 : public aminoacid_base return ret; }() }; + + //!\copydoc seqan3::aa27::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::aa27::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; } // namespace seqan3 diff --git a/include/seqan3/alphabet/aminoacid/aa27.hpp b/include/seqan3/alphabet/aminoacid/aa27.hpp index 1eb312c170..da79c3bc1f 100644 --- a/include/seqan3/alphabet/aminoacid/aa27.hpp +++ b/include/seqan3/alphabet/aminoacid/aa27.hpp @@ -68,9 +68,9 @@ class aa27 : public aminoacid_base using base_t::base_t; //!\} -protected: - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'B', @@ -101,8 +101,8 @@ class aa27 : public aminoacid_base '*' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -115,13 +115,26 @@ class aa27 : public aminoacid_base // reverse mapping for characters and their lowercase for (rank_type rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[static_cast( rank_to_char[rnk]) ] = rnk; - ret[static_cast(to_lower(rank_to_char[rnk]))] = rnk; + ret[static_cast(rank_to_char_table[rnk])] = rnk; + ret[static_cast(to_lower(rank_to_char_table[rnk]))] = rnk; } return ret; }() }; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; } // namespace seqan3 diff --git a/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp b/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp index 21e5245cea..0a53004b9c 100644 --- a/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp +++ b/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp @@ -129,9 +129,18 @@ class aminoacid_base : public alphabet_base, public am std::array ret{}; // the original valid chars and their lower cases - for (uint8_t c : derived_type::rank_to_char) + for (size_t rank = 0u; rank < derived_type::alphabet_size; ++rank) { - ret[ c ] = true; + uint8_t c{}; +#ifdef SEQAN3_DEPRECATED_310 + if constexpr (detail::has_rank_to_char_table) + c = derived_type::rank_to_char[rank]; + else + c = derived_type::rank_to_char(rank); +#else // ^^^ before 3.1.0 release / after 3.1.0 release vvv + c = derived_type::rank_to_char(rank); +#endif // SEQAN3_DEPRECATED_310 + ret[c] = true; ret[to_lower(c)] = true; } diff --git a/include/seqan3/alphabet/cigar/exposition_only/cigar_operation.hpp b/include/seqan3/alphabet/cigar/exposition_only/cigar_operation.hpp index c03c3638ec..609a26b771 100644 --- a/include/seqan3/alphabet/cigar/exposition_only/cigar_operation.hpp +++ b/include/seqan3/alphabet/cigar/exposition_only/cigar_operation.hpp @@ -66,11 +66,9 @@ class cigar_operation : public alphabet_base //!\} -protected: - //!\privatesection - - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'M', 'D', @@ -83,8 +81,8 @@ class cigar_operation : public alphabet_base '=' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -93,12 +91,25 @@ class cigar_operation : public alphabet_base // reverse mapping for characters for (size_t rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[rank_to_char[rnk] ] = rnk; + ret[rank_to_char_table[rnk]] = rnk; } return ret; }() }; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; } // namespace seqan3::exposition_only diff --git a/include/seqan3/alphabet/composite/alphabet_variant.hpp b/include/seqan3/alphabet/composite/alphabet_variant.hpp index 07adc971d4..ccb11aa71c 100644 --- a/include/seqan3/alphabet/composite/alphabet_variant.hpp +++ b/include/seqan3/alphabet/composite/alphabet_variant.hpp @@ -481,14 +481,8 @@ class alphabet_variant : public alphabet_base rank_to_char = []() constexpr + //!\copydoc seqan3::alphabet_variant::rank_to_char + static constexpr std::array rank_to_char_table = []() constexpr { // Explicitly writing assign_rank_to_char within assign_rank_to_char // causes this bug (g++-7 and g++-8): @@ -578,14 +572,8 @@ class alphabet_variant : public alphabet_base> char_to_rank = []() constexpr + //!\copydoc seqan3::alphabet_variant::char_to_rank + static constexpr std::array> char_to_rank_table = []() constexpr { constexpr size_t alternative_size = sizeof...(alternative_types); constexpr size_t table_size = detail::size_in_values_v; @@ -604,6 +592,29 @@ class alphabet_variant : public alphabet_base; + return char_to_rank_table[static_cast(chr)]; + } }; } // namespace seqan3 diff --git a/include/seqan3/alphabet/gap/gap.hpp b/include/seqan3/alphabet/gap/gap.hpp index 2e5b9a1ca7..753967f797 100644 --- a/include/seqan3/alphabet/gap/gap.hpp +++ b/include/seqan3/alphabet/gap/gap.hpp @@ -42,11 +42,17 @@ class gap : public alphabet_base //!\brief Befriend seqan3::alphabet_base. friend base_t; - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[1]{'-'}; + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const) + { + return '-'; + } - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank{}; + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const) + { + return 0; + } public: /*!\name Constructors, destructor and assignment diff --git a/include/seqan3/alphabet/nucleotide/dna15.hpp b/include/seqan3/alphabet/nucleotide/dna15.hpp index dbb76d90e1..ca6ff388d7 100644 --- a/include/seqan3/alphabet/nucleotide/dna15.hpp +++ b/include/seqan3/alphabet/nucleotide/dna15.hpp @@ -80,11 +80,9 @@ class dna15 : public nucleotide_base } //!\} -protected: - //!\privatesection - - //!\copydoc seqan3::dna4::rank_to_char - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'B', @@ -104,7 +102,7 @@ class dna15 : public nucleotide_base }; //!\copydoc seqan3::dna4::char_to_rank - static constexpr std::array char_to_rank + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -117,8 +115,8 @@ class dna15 : public nucleotide_base // reverse mapping for characters and their lowercase for (size_t rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[ rank_to_char[rnk] ] = rnk; - ret[to_lower(rank_to_char[rnk])] = rnk; + ret[rank_to_char_table[rnk]] = rnk; + ret[to_lower(rank_to_char_table[rnk])] = rnk; } // set U equal to T @@ -128,6 +126,19 @@ class dna15 : public nucleotide_base }() }; + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } + //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; }; diff --git a/include/seqan3/alphabet/nucleotide/dna3bs.hpp b/include/seqan3/alphabet/nucleotide/dna3bs.hpp index 762bc581db..30217c6005 100644 --- a/include/seqan3/alphabet/nucleotide/dna3bs.hpp +++ b/include/seqan3/alphabet/nucleotide/dna3bs.hpp @@ -78,19 +78,17 @@ class dna3bs : public nucleotide_base using base_t::base_t; //!\} -protected: - //!\privatesection - - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'G', 'T' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -99,8 +97,8 @@ class dna3bs : public nucleotide_base // reverse mapping for characters and their lowercase for (size_t rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[ rank_to_char[rnk] ] = rnk; - ret[to_lower(rank_to_char[rnk])] = rnk; + ret[rank_to_char_table[rnk]] = rnk; + ret[to_lower(rank_to_char_table[rnk])] = rnk; } // set C and U equal to T @@ -123,8 +121,21 @@ class dna3bs : public nucleotide_base }() }; - //!\brief The complement table. + //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/nucleotide/dna4.hpp b/include/seqan3/alphabet/nucleotide/dna4.hpp index 2547b8a490..8e0b93ce67 100644 --- a/include/seqan3/alphabet/nucleotide/dna4.hpp +++ b/include/seqan3/alphabet/nucleotide/dna4.hpp @@ -82,11 +82,31 @@ class dna4 : public nucleotide_base } //!\} -protected: - //!\privatesection - - //!\brief Value to char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + /*!\brief The lookup table used in #rank_to_char. + * \details + * We would have defined these lookup tables directly within their respective constexpr functions, but at the time + * of writing this, gcc did not (clang >= 4 did!) auto-generate lookup tables. + * + * ```cpp + * static constexpr char_type rank_to_char(rank_type const rank) + * { + * // not possible because of static not being allowed within a constexpr function + * static constexpr lookup_table = ...; + * return lookup_table[rank]; + * } + * + * static constexpr char_type rank_to_char(rank_type const rank) + * { + * // up-to the compiler to optimise, no guarantee that a lookup table is used. + * constexpr lookup_table = ...; + * return lookup_table[rank]; + * } + * ``` + * + * \sa https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99320 for the progress on gcc + */ + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'C', @@ -94,8 +114,10 @@ class dna4 : public nucleotide_base 'T' }; - //!\brief Char to value conversion table. - static constexpr std::array char_to_rank + /*!\brief The lookup table used in #char_to_rank. + * \copydetails seqan3::dna4::rank_to_char_table + */ + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -104,8 +126,8 @@ class dna4 : public nucleotide_base // reverse mapping for characters and their lowercase for (size_t rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[ rank_to_char[rnk] ] = rnk; - ret[to_lower(rank_to_char[rnk])] = rnk; + ret[rank_to_char_table[rnk]] = rnk; + ret[to_lower(rank_to_char_table[rnk])] = rnk; } // set U equal to T @@ -129,6 +151,25 @@ class dna4 : public nucleotide_base //!\brief The complement table. static const std::array complement_table; + + /*!\brief Returns the character representation of rank. + * \details + * This function is required by seqan3::alphabet_base. + */ + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + /*!\brief Returns the rank representation of character. + * \details + * This function is required by seqan3::alphabet_base. + */ + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/nucleotide/dna5.hpp b/include/seqan3/alphabet/nucleotide/dna5.hpp index 54281d3f50..43c84beabd 100644 --- a/include/seqan3/alphabet/nucleotide/dna5.hpp +++ b/include/seqan3/alphabet/nucleotide/dna5.hpp @@ -80,11 +80,9 @@ class dna5 : public nucleotide_base } //!\} -protected: - //!\privatesection - - //!\copydoc seqan3::dna4::rank_to_char - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'C', @@ -93,8 +91,8 @@ class dna5 : public nucleotide_base 'T' }; - //!\copydoc seqan3::dna4::char_to_rank - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -107,8 +105,8 @@ class dna5 : public nucleotide_base // reverse mapping for characters and their lowercase for (size_t rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[ rank_to_char[rnk] ] = rnk; - ret[to_lower(rank_to_char[rnk])] = rnk; + ret[rank_to_char_table[rnk]] = rnk; + ret[to_lower(rank_to_char_table[rnk])] = rnk; } // set U equal to T @@ -121,6 +119,19 @@ class dna5 : public nucleotide_base //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp b/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp index 3987376bfc..356a7a7edd 100644 --- a/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp +++ b/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp @@ -145,9 +145,18 @@ class nucleotide_base : public alphabet_base std::array ret{}; // the original valid chars and their lower cases - for (uint8_t c : derived_type::rank_to_char) + for (size_t rank = 0u; rank < derived_type::alphabet_size; ++rank) { - ret[ c ] = true; + uint8_t c{}; +#ifdef SEQAN3_DEPRECATED_310 + if constexpr (detail::has_rank_to_char_table) + c = derived_type::rank_to_char[rank]; + else + c = derived_type::rank_to_char(rank); +#else // ^^^ before 3.1.0 release / after 3.1.0 release vvv + c = derived_type::rank_to_char(rank); +#endif // SEQAN3_DEPRECATED_310 + ret[c] = true; ret[to_lower(c)] = true; } diff --git a/include/seqan3/alphabet/nucleotide/rna15.hpp b/include/seqan3/alphabet/nucleotide/rna15.hpp index a848e0a7b0..0f6587c630 100644 --- a/include/seqan3/alphabet/nucleotide/rna15.hpp +++ b/include/seqan3/alphabet/nucleotide/rna15.hpp @@ -80,11 +80,9 @@ class rna15 : public nucleotide_base } //!\} -protected: - //!\privatesection - - //!\copydoc seqan3::dna4::rank_to_char - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'B', @@ -103,11 +101,20 @@ class rna15 : public nucleotide_base 'Y' }; - //!\copydoc seqan3::dna4::char_to_rank - static constexpr std::array char_to_rank = dna15::char_to_rank; - //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + return dna15::char_to_rank(chr); + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/nucleotide/rna4.hpp b/include/seqan3/alphabet/nucleotide/rna4.hpp index a0cfd086b4..18c2ef2c32 100644 --- a/include/seqan3/alphabet/nucleotide/rna4.hpp +++ b/include/seqan3/alphabet/nucleotide/rna4.hpp @@ -78,11 +78,10 @@ class rna4 : public nucleotide_base } //!\} -protected: - //!\privatesection +private: - //!\copydoc seqan3::dna4::rank_to_char - static constexpr char_type rank_to_char[alphabet_size] + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'C', @@ -90,11 +89,20 @@ class rna4 : public nucleotide_base 'U' }; - //!\copydoc seqan3::dna4::char_to_rank - static constexpr std::array char_to_rank = dna4::char_to_rank; - //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + return dna4::char_to_rank(chr); + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/nucleotide/rna5.hpp b/include/seqan3/alphabet/nucleotide/rna5.hpp index bcee0301b7..5aa3c3d9d4 100644 --- a/include/seqan3/alphabet/nucleotide/rna5.hpp +++ b/include/seqan3/alphabet/nucleotide/rna5.hpp @@ -78,11 +78,9 @@ class rna5 : public nucleotide_base } //!\} -protected: - //!\privatesection - - //!\copydoc seqan3::dna4::rank_to_char - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'A', 'C', @@ -91,11 +89,20 @@ class rna5 : public nucleotide_base 'U' }; - //!\copydoc seqan3::dna4::char_to_rank - static constexpr std::array char_to_rank = dna5::char_to_rank; - //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + return dna5::char_to_rank(chr); + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/nucleotide/sam_dna16.hpp b/include/seqan3/alphabet/nucleotide/sam_dna16.hpp index f930faf7da..4dc23363ee 100644 --- a/include/seqan3/alphabet/nucleotide/sam_dna16.hpp +++ b/include/seqan3/alphabet/nucleotide/sam_dna16.hpp @@ -68,11 +68,9 @@ class sam_dna16 : public nucleotide_base using base_t::base_t; //!\} -protected: - //!\privatesection - - //!\brief The representation is the same as in the SAM specifications (which is NOT in alphabetical order). - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { '=', 'A', @@ -92,8 +90,8 @@ class sam_dna16 : public nucleotide_base 'N' }; - //!\copydoc seqan3::dna4::char_to_rank - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -106,8 +104,8 @@ class sam_dna16 : public nucleotide_base // reverse mapping for characters and their lowercase for (size_t rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[ rank_to_char[rnk] ] = rnk; - ret[to_lower(rank_to_char[rnk])] = rnk; + ret[rank_to_char_table[rnk]] = rnk; + ret[to_lower(rank_to_char_table[rnk])] = rnk; } // set U equal to T @@ -119,6 +117,22 @@ class sam_dna16 : public nucleotide_base //!\copydoc seqan3::dna4::complement_table static const std::array complement_table; + + /*!\copydoc seqan3::dna4::rank_to_char + * + * The representation is the same as in the SAM specifications (which is NOT in alphabetical order). + */ + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; // ------------------------------------------------------------------ diff --git a/include/seqan3/alphabet/quality/qualified.hpp b/include/seqan3/alphabet/quality/qualified.hpp index 0b2aa92318..e993703c48 100644 --- a/include/seqan3/alphabet/quality/qualified.hpp +++ b/include/seqan3/alphabet/quality/qualified.hpp @@ -136,7 +136,7 @@ class qualified : //!\brief Return a character. This reads the internal sequence letter. constexpr char_type to_char() const noexcept { - return rank_to_char[to_rank()]; + return rank_to_char(to_rank()); } /*!\brief Return a qualified where the quality is preserved, but the sequence letter is complemented. @@ -156,11 +156,9 @@ class qualified : return char_is_valid_for(c); } -protected: - //!\privatesection - - //!\brief Rank to char conversion table. - static std::array constexpr rank_to_char +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static std::array constexpr rank_to_char_table { [] () constexpr { @@ -196,6 +194,12 @@ class qualified : return ret; }() }; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(typename base_type::rank_type const rank) + { + return rank_to_char_table[rank]; + } }; //!\brief Type deduction guide enables usage of qualified without specifying template args. diff --git a/include/seqan3/alphabet/quality/quality_base.hpp b/include/seqan3/alphabet/quality/quality_base.hpp index 75fce6dd6a..c76c70394d 100644 --- a/include/seqan3/alphabet/quality/quality_base.hpp +++ b/include/seqan3/alphabet/quality/quality_base.hpp @@ -39,6 +39,9 @@ class quality_base : public alphabet_base //!\brief The base type. using base_t = alphabet_base; + //!\brief Befriend the base type so it can access #char_to_rank and #rank_to_char. + friend base_t; + /*!\name Constructors, destructor and assignment * \{ */ @@ -119,7 +122,7 @@ class quality_base : public alphabet_base } //!\} -protected: +private: //!\brief Phred to rank conversion table. static std::array constexpr phred_to_rank { @@ -140,27 +143,6 @@ class quality_base : public alphabet_base }() }; - //!\brief Char to rank conversion table. - static std::array constexpr char_to_rank - { - [] () constexpr - { - std::array ret{}; - - for (int64_t i = std::numeric_limits::lowest(); i <= std::numeric_limits::max(); ++i) - { - if (i < derived_type::offset_char) // map too-small to smallest possible - ret[static_cast(i)] = 0; - else if (i >= derived_type::offset_char + alphabet_size) // map too-large to highest possible - ret[static_cast(i)] = alphabet_size - 1; - else // map valid range to identity - ret[static_cast(i)] = i - derived_type::offset_char; - } - - return ret; - }() - }; - //!\brief Rank to phred conversion table. static std::array constexpr rank_to_phred { @@ -175,19 +157,18 @@ class quality_base : public alphabet_base }() }; - //!\brief Rank to char conversion table. - static std::array constexpr rank_to_char + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) { - [] () constexpr - { - std::array ret{}; - - for (size_t i = 0; i < alphabet_size; ++i) - ret[i] = i + derived_type::offset_char; + int64_t difference = static_cast(chr) - static_cast(derived_type::offset_char); + return std::clamp(difference, 0, alphabet_size - 1); + } - return ret; - }() - }; + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank + derived_type::offset_char; + } }; } // namespace seqan3 diff --git a/include/seqan3/alphabet/structure/dot_bracket3.hpp b/include/seqan3/alphabet/structure/dot_bracket3.hpp index 1b4091a35e..a629734eb3 100644 --- a/include/seqan3/alphabet/structure/dot_bracket3.hpp +++ b/include/seqan3/alphabet/structure/dot_bracket3.hpp @@ -116,19 +116,17 @@ class dot_bracket3 : public alphabet_base } //!\} -protected: - //!\privatesection - - //!\brief Value-to-char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { '.', '(', ')' }; - //!\brief Char-to-value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -146,6 +144,19 @@ class dot_bracket3 : public alphabet_base return rank_table; } () }; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; /*!\name Literals diff --git a/include/seqan3/alphabet/structure/dssp9.hpp b/include/seqan3/alphabet/structure/dssp9.hpp index 84aab48b27..7d80b3a31c 100644 --- a/include/seqan3/alphabet/structure/dssp9.hpp +++ b/include/seqan3/alphabet/structure/dssp9.hpp @@ -79,17 +79,15 @@ class dssp9 : public alphabet_base //!\} -protected: - //!\privatesection - - //!\brief Value-to-char conversion table. - static constexpr char_type rank_to_char[alphabet_size] +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr char_type rank_to_char_table[alphabet_size] { 'H', 'B', 'E', 'G', 'I', 'T', 'S', 'C', 'X' }; - //!\brief Char-to-value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -102,12 +100,25 @@ class dssp9 : public alphabet_base // reverse mapping for characters for (rank_type rnk = 0u; rnk < alphabet_size; ++rnk) { - ret[static_cast(rank_to_char[rnk])] = rnk; + ret[static_cast(rank_to_char_table[rnk])] = rnk; } return ret; } () }; + + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } }; /*!\name Literals diff --git a/include/seqan3/alphabet/structure/wuss.hpp b/include/seqan3/alphabet/structure/wuss.hpp index c8c5877c42..a84e76bc00 100644 --- a/include/seqan3/alphabet/structure/wuss.hpp +++ b/include/seqan3/alphabet/structure/wuss.hpp @@ -132,10 +132,9 @@ class wuss : public alphabet_base, SIZE> } //!\} -protected: - //!\privatesection - //!\brief Value-to-char conversion table. - static constexpr std::array rank_to_char +private: + //!\copydoc seqan3::dna4::rank_to_char_table + static constexpr std::array rank_to_char_table { [] () constexpr { @@ -156,8 +155,8 @@ class wuss : public alphabet_base, SIZE> } () }; - //!\brief Char-to-value conversion table. - static constexpr std::array char_to_rank + //!\copydoc seqan3::dna4::char_to_rank_table + static constexpr std::array char_to_rank_table { [] () constexpr { @@ -169,11 +168,24 @@ class wuss : public alphabet_base, SIZE> // set alphabet values for (rank_type rnk = 0u; rnk < alphabet_size; ++rnk) - rank_table[rank_to_char[rnk]] = rnk; + rank_table[rank_to_char_table[rnk]] = rnk; return rank_table; } () }; + //!\copydoc seqan3::dna4::rank_to_char + static constexpr char_type rank_to_char(rank_type const rank) + { + return rank_to_char_table[rank]; + } + + //!\copydoc seqan3::dna4::char_to_rank + static constexpr rank_type char_to_rank(char_type const chr) + { + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + } + /*!\brief Lookup table for interactions: unpaired (0), pair-open (< 0), pair-close (> 0). * Paired brackets have the same absolute value. */ diff --git a/include/seqan3/core/platform.hpp b/include/seqan3/core/platform.hpp index 0b12cd2602..81380c5704 100644 --- a/include/seqan3/core/platform.hpp +++ b/include/seqan3/core/platform.hpp @@ -323,6 +323,15 @@ # endif #endif +//!\brief See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99318 +#ifndef SEQAN3_WORKAROUND_GCC_99318 // not yet fixed, this is a regression since gcc-10 +# if defined(__GNUC__) && (__GNUC__ >= 10) +# define SEQAN3_WORKAROUND_GCC_99318 1 +# else +# define SEQAN3_WORKAROUND_GCC_99318 0 +# endif +#endif + /*!\brief This is needed to support CentOS 7 or RHEL 7; Newer CentOS's include a more modern default-gcc version making * this macro obsolete. * diff --git a/test/snippet/alphabet/alphabet_base.cpp b/test/snippet/alphabet/alphabet_base.cpp new file mode 100644 index 0000000000..1b9a09307f --- /dev/null +++ b/test/snippet/alphabet/alphabet_base.cpp @@ -0,0 +1,55 @@ +#include +#include +#include // seqan3::to_lower + +class ab : public seqan3::alphabet_base +{ +private: + // make the base class a friend so it can access the tables: + friend alphabet_base; + + // This function is expected by seqan3::alphabet_base + static constexpr char_type rank_to_char(rank_type const rank) + { + // via a lookup table + return rank_to_char_table[rank]; + // or via an arithmetic expression + return rank == 1 ? 'B' : 'A'; + } + + // This function is expected by seqan3::alphabet_base + static constexpr rank_type char_to_rank(char_type const chr) + { + // via a lookup table + using index_t = std::make_unsigned_t; + return char_to_rank_table[static_cast(chr)]; + // or via an arithmetic expression + return seqan3::to_lower(chr) == 'b' ? 1 : 0; + } + +private: + // === lookup-table implementation detail === + + // map 0 -> A and 1 -> B + static std::array constexpr rank_to_char_table{'A', 'B'}; + + // map every letter to rank zero, except Bs + static std::array constexpr char_to_rank_table + { + // initialise with an immediately evaluated lambda expression: + []() + { + std::array ret{}; // initialise all values with 0 / 'A' + + // only 'b' and 'B' result in rank 1 + ret['b'] = 1; + ret['B'] = 1; + + return ret; + }() + }; +}; + +// The class ab satisfies the alphabet concept. +static_assert(seqan3::alphabet); +static_assert(seqan3::writable_alphabet); diff --git a/test/snippet/alphabet/detail/alphabet_base.cpp b/test/snippet/alphabet/detail/alphabet_base.cpp deleted file mode 100644 index ff8b0b8324..0000000000 --- a/test/snippet/alphabet/detail/alphabet_base.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -class ab : public seqan3::alphabet_base -{ -private: - // map 0 -> A and 1 -> B - static std::array constexpr rank_to_char{'A', 'B'}; - - // map every letter to rank zero, except Bs - static std::array constexpr char_to_rank - { - // initialise with an immediately evaluated lambda expression: - []() - { - std::array ret{}; // initialise all values with 0 / 'A' - - // only 'b' and 'B' result in rank 1 - ret['b'] = 1; - ret['B'] = 1; - - return ret; - }() - }; - - // make the base class a friend so it can access the tables: - friend alphabet_base; -}; - -static_assert(seqan3::alphabet); diff --git a/test/unit/alphabet/composite/alphabet_variant_detail_test.cpp b/test/unit/alphabet/composite/alphabet_variant_detail_test.cpp index a0cecdd01e..5e5b3f64df 100644 --- a/test/unit/alphabet/composite/alphabet_variant_detail_test.cpp +++ b/test/unit/alphabet/composite/alphabet_variant_detail_test.cpp @@ -19,8 +19,8 @@ class detail_alphabet_variant : public seqan3::alphabet_variant::partial_sum_sizes; - using seqan3::alphabet_variant::rank_to_char; - using seqan3::alphabet_variant::char_to_rank; + using seqan3::alphabet_variant::rank_to_char_table; + using seqan3::alphabet_variant::char_to_rank_table; using seqan3::alphabet_variant::first_valid_char_table; }; @@ -51,9 +51,9 @@ TEST(alphabet_variant_detail_test, partial_sum_sizes) EXPECT_EQ(partial_sum4[3], 10); } -TEST(alphabet_variant_detail_test, rank_to_char) +TEST(alphabet_variant_detail_test, rank_to_char_table) { - constexpr std::array rank_to_char2 = detail_alphabet_variant::rank_to_char; + constexpr std::array rank_to_char2 = detail_alphabet_variant::rank_to_char_table; EXPECT_EQ(rank_to_char2.size(), 5u); EXPECT_EQ(rank_to_char2[0], 'A'); EXPECT_EQ(rank_to_char2[1], 'C'); @@ -61,7 +61,9 @@ TEST(alphabet_variant_detail_test, rank_to_char) EXPECT_EQ(rank_to_char2[3], 'T'); EXPECT_EQ(rank_to_char2[4], '-'); - constexpr std::array rank_to_char3 = detail_alphabet_variant::rank_to_char; + constexpr std::array rank_to_char3 = detail_alphabet_variant::rank_to_char_table; EXPECT_EQ(rank_to_char3.size(), 10u); EXPECT_EQ(rank_to_char3[0], 'A'); EXPECT_EQ(rank_to_char3[1], 'C'); @@ -74,7 +76,9 @@ TEST(alphabet_variant_detail_test, rank_to_char) EXPECT_EQ(rank_to_char3[8], 'N'); EXPECT_EQ(rank_to_char3[9], 'T'); - constexpr std::array rank_to_char4 = detail_alphabet_variant::rank_to_char; + constexpr std::array rank_to_char4 = detail_alphabet_variant::rank_to_char_table; EXPECT_EQ(rank_to_char4.size(), 10u); EXPECT_EQ(rank_to_char4[0], 'A'); EXPECT_EQ(rank_to_char4[1], 'C'); @@ -88,9 +92,9 @@ TEST(alphabet_variant_detail_test, rank_to_char) EXPECT_EQ(rank_to_char4[9], 'T'); } -TEST(alphabet_variant_detail_test, char_to_rank) +TEST(alphabet_variant_detail_test, char_to_rank_table) { - constexpr std::array char_to_rank2 = detail_alphabet_variant::char_to_rank; + constexpr std::array char_to_rank2 = detail_alphabet_variant::char_to_rank_table; EXPECT_EQ(char_to_rank2.size(), 256u); EXPECT_EQ(char_to_rank2['A'], 0); EXPECT_EQ(char_to_rank2['C'], 1); @@ -98,7 +102,9 @@ TEST(alphabet_variant_detail_test, char_to_rank) EXPECT_EQ(char_to_rank2['T'], 3); EXPECT_EQ(char_to_rank2['-'], 4); - constexpr std::array char_to_rank3 = detail_alphabet_variant::char_to_rank; + constexpr std::array char_to_rank3 = detail_alphabet_variant::char_to_rank_table; EXPECT_EQ(char_to_rank3.size(), 256u); EXPECT_EQ(char_to_rank3['A'], 0); EXPECT_EQ(char_to_rank3['C'], 1); @@ -111,7 +117,9 @@ TEST(alphabet_variant_detail_test, char_to_rank) EXPECT_EQ(char_to_rank3['N'], 8); EXPECT_EQ(char_to_rank3['T'], 3); - constexpr std::array char_to_rank4 = detail_alphabet_variant::char_to_rank; + constexpr std::array char_to_rank4 = detail_alphabet_variant::char_to_rank_table; EXPECT_EQ(char_to_rank4.size(), 256u); EXPECT_EQ(char_to_rank4['A'], 0); EXPECT_EQ(char_to_rank4['C'], 1);