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);