Skip to content

Commit

Permalink
[DOC] Cookbook entry on auto-vectorizable dna4.
Browse files Browse the repository at this point in the history
  • Loading branch information
smehringer committed Jun 21, 2022
1 parent febd0f4 commit e9e2d06
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
10 changes: 10 additions & 0 deletions doc/cookbook/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,13 @@ This will use `4` threads by default and can be adjusted by setting `seqan3::con
the desired value:

\snippet doc/cookbook/compression_threads.cpp example

# Auto vectorized dna4 complement

Our alphabet seqan3::dna4 cannot be easily auto-vectorized by the compiler.

See discussion here: https://github.com/seqan/seqan3/issues/1970

You can add your own alphabet that is auto-vectorizable in some use cases:

\include doc/cookbook/simdyfyable_alphabet_complement.cpp
73 changes: 73 additions & 0 deletions doc/cookbook/simdyfyable_alphabet_complement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <seqan3/alphabet/nucleotide/nucleotide_base.hpp>
#include <seqan3/alphabet/nucleotide/rna4.hpp>

class simd_dna4 : public seqan3::nucleotide_base<simd_dna4, 256>
{
private:
using base_t = nucleotide_base<simd_dna4, 256>;

friend base_t;
//!\cond \brief Befriend seqan3::alphabet_base.
friend base_t::base_t;
//!\endcond
friend seqan3::rna4;

public:
constexpr simd_dna4() noexcept = default;
constexpr simd_dna4(simd_dna4 const &) noexcept = default;
constexpr simd_dna4(simd_dna4 &&) noexcept = default;
constexpr simd_dna4 & operator=(simd_dna4 const &) noexcept = default;
constexpr simd_dna4 & operator=(simd_dna4 &&) noexcept = default;
~simd_dna4() noexcept = default;

using base_t::base_t;

template <std::same_as<seqan3::rna4> t> // template parameter t to accept incomplete type
constexpr simd_dna4(t const & r) noexcept
{
assign_rank(r.to_rank());
}

static uint8_t constexpr alphabet_size = 4;

constexpr simd_dna4 & assign_rank(rank_type const c) noexcept
{
base_t::assign_rank(c == 0 ? 'A' : (c == 1 ? 'C' : (c == 2 ? 'G' : 'T')));
return *this;
}

constexpr simd_dna4 & assign_char(char_type const c) noexcept
{
base_t::assign_rank(c);
return *this;
}

constexpr char_type to_char() const noexcept
{
return base_t::to_rank();
}

constexpr rank_type to_rank() const noexcept
{
char_type c{to_char()};
char_type upper_char = c & 0b0101'1111; // to_upper
rank_type rank{};
rank = (upper_char == 'T') * 3 + (upper_char == 'G') * 2 + (upper_char == 'C');
return rank;
}

constexpr simd_dna4 complement() const noexcept
{
char_type rank{to_char()};
rank ^= rank % 2 ? ('C' ^ 'G') : ('A' ^ 'T');

simd_dna4 ret{};
static_cast<base_t &>(ret).assign_rank(rank);
return ret;
}
};

int main()
{
// ...
}

0 comments on commit e9e2d06

Please sign in to comment.