Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[TEST] Add seqan3::simd_dna4
Co-authored-by: Enrico Seiler <enrico.seiler@hotmail.de>
  • Loading branch information
smehringer and eseiler committed Oct 21, 2022
commit 507dba1d80071beb1098977f1586a6bcd242ed08
102 changes: 102 additions & 0 deletions test/include/seqan3/test/performance/simd_dna4.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// -----------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
// -----------------------------------------------------------------------------------------------------

#pragma once

#include <seqan3/alphabet/nucleotide/nucleotide_base.hpp>
#include <seqan3/alphabet/nucleotide/rna4.hpp>

// Conditionally add the seqan3 namespace:
// unit/performance tests: in seqan3 namespace
// cookbook entry: no namespace
#ifndef SEQAN3_USE_NAMESPACE
# define SEQAN3_USE_NAMESPACE 1
#endif

#if SEQAN3_USE_NAMESPACE
namespace seqan3
{
#endif
/* See discussion here: https://github.com/seqan/seqan3/issues/1970
*
* If AVX2 is available, this significantly improves the performance
* (roughly 5 times faster). But if no AVX2 is available. this decreases the
* performance (roughly 3 times slower).
*/
//![cookbook]
class simd_dna4 : public seqan3::nucleotide_base<simd_dna4, 256>
{
private:
using base_t = seqan3::nucleotide_base<simd_dna4, 256>;

friend base_t; // nucleotide_base
friend base_t::base_t; // alphabet_base
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;

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

using base_t::assign_rank;
using base_t::base_t;
using base_t::to_rank;

static constexpr uint8_t alphabet_size = 4;

constexpr simd_dna4 & assign_char(char_type const c) noexcept
{
char_type const upper_case_char = c & 0b0101'1111;
rank_type rank = (upper_case_char == 'T') * 3 + (upper_case_char == 'G') * 2 + (upper_case_char == 'C');
return assign_rank(rank);
}

constexpr char_type to_char() const noexcept
{
rank_type const rank = to_rank();
switch (rank)
{
case 0u:
return 'A';
case 1u:
return 'C';
case 2u:
return 'G';
default:
return 'T';
}
}

constexpr simd_dna4 complement() const noexcept
{
rank_type rank{to_rank()};
rank ^= 0b11;
simd_dna4 ret{};
return ret.assign_rank(rank);
}

static constexpr bool char_is_valid(char_type const c) noexcept
{
char_type const upper_case_char = c & 0b0101'1111;
return (upper_case_char == 'A') || (upper_case_char == 'C') || (upper_case_char == 'G')
|| (upper_case_char == 'T');
}
};
//![cookbook]

#if SEQAN3_USE_NAMESPACE
}
#endif
2 changes: 2 additions & 0 deletions test/performance/alphabet/alphabet_assign_char_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <numeric>

#include <seqan3/alphabet/all.hpp>
#include <seqan3/test/performance/simd_dna4.hpp>
#include <seqan3/test/seqan2.hpp>

#if SEQAN3_HAS_SEQAN2
Expand All @@ -38,6 +39,7 @@ void assign_char(benchmark::State & state)
BENCHMARK_TEMPLATE(assign_char, seqan3::gap);
BENCHMARK_TEMPLATE(assign_char, seqan3::dna4);
BENCHMARK_TEMPLATE(assign_char, seqan3::rna4);
BENCHMARK_TEMPLATE(assign_char, seqan3::simd_dna4);
BENCHMARK_TEMPLATE(assign_char, seqan3::dna5);
BENCHMARK_TEMPLATE(assign_char, seqan3::rna5);
BENCHMARK_TEMPLATE(assign_char, seqan3::dna15);
Expand Down
2 changes: 2 additions & 0 deletions test/performance/alphabet/alphabet_assign_rank_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <cstring>

#include <seqan3/alphabet/all.hpp>
#include <seqan3/test/performance/simd_dna4.hpp>
#include <seqan3/test/seqan2.hpp>

#if SEQAN3_HAS_SEQAN2
Expand Down Expand Up @@ -45,6 +46,7 @@ void assign_rank(benchmark::State & state)
BENCHMARK_TEMPLATE(assign_rank, seqan3::gap);
BENCHMARK_TEMPLATE(assign_rank, seqan3::dna4);
BENCHMARK_TEMPLATE(assign_rank, seqan3::rna4);
BENCHMARK_TEMPLATE(assign_rank, seqan3::simd_dna4);
BENCHMARK_TEMPLATE(assign_rank, seqan3::dna5);
BENCHMARK_TEMPLATE(assign_rank, seqan3::rna5);
BENCHMARK_TEMPLATE(assign_rank, seqan3::dna15);
Expand Down
2 changes: 2 additions & 0 deletions test/performance/alphabet/alphabet_to_char_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <cstring>

#include <seqan3/alphabet/all.hpp>
#include <seqan3/test/performance/simd_dna4.hpp>
#include <seqan3/test/seqan2.hpp>

#if SEQAN3_HAS_SEQAN2
Expand Down Expand Up @@ -58,6 +59,7 @@ void to_char(benchmark::State & state)
BENCHMARK_TEMPLATE(to_char, seqan3::gap);
BENCHMARK_TEMPLATE(to_char, seqan3::dna4);
BENCHMARK_TEMPLATE(to_char, seqan3::rna4);
BENCHMARK_TEMPLATE(to_char, seqan3::simd_dna4);
BENCHMARK_TEMPLATE(to_char, seqan3::dna5);
BENCHMARK_TEMPLATE(to_char, seqan3::rna5);
BENCHMARK_TEMPLATE(to_char, seqan3::dna15);
Expand Down
2 changes: 2 additions & 0 deletions test/performance/alphabet/alphabet_to_rank_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <algorithm>

#include <seqan3/alphabet/all.hpp>
#include <seqan3/test/performance/simd_dna4.hpp>
#include <seqan3/test/seqan2.hpp>

#if SEQAN3_HAS_SEQAN2
Expand Down Expand Up @@ -52,6 +53,7 @@ void to_rank(benchmark::State & state)
BENCHMARK_TEMPLATE(to_rank, seqan3::gap);
BENCHMARK_TEMPLATE(to_rank, seqan3::dna4);
BENCHMARK_TEMPLATE(to_rank, seqan3::rna4);
BENCHMARK_TEMPLATE(to_rank, seqan3::simd_dna4);
BENCHMARK_TEMPLATE(to_rank, seqan3::dna5);
BENCHMARK_TEMPLATE(to_rank, seqan3::rna5);
BENCHMARK_TEMPLATE(to_rank, seqan3::dna15);
Expand Down
1 change: 1 addition & 0 deletions test/unit/alphabet/nucleotide/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ seqan3_test (rna4_test.cpp)
seqan3_test (rna5_test.cpp)
seqan3_test (rna15_test.cpp)
seqan3_test (nucleotide_conversion_integration_test.cpp)
seqan3_test (simd_dna4_test.cpp)
35 changes: 35 additions & 0 deletions test/unit/alphabet/nucleotide/simd_dna4_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// -----------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
// -----------------------------------------------------------------------------------------------------

#include <seqan3/core/debug_stream/range.hpp>
#include <seqan3/test/performance/simd_dna4.hpp>
#include <seqan3/utility/char_operations/predicate.hpp>

#include "../alphabet_constexpr_test_template.hpp"
#include "../alphabet_test_template.hpp"
#include "../semi_alphabet_constexpr_test_template.hpp"
#include "../semi_alphabet_test_template.hpp"
#include "nucleotide_test_template.hpp"

INSTANTIATE_TYPED_TEST_SUITE_P(simdifyable_dna4, alphabet, seqan3::simd_dna4, );
INSTANTIATE_TYPED_TEST_SUITE_P(simdifyable_dna4, semi_alphabet_test, seqan3::simd_dna4, );
INSTANTIATE_TYPED_TEST_SUITE_P(simdifyable_dna4, alphabet_constexpr, seqan3::simd_dna4, );
INSTANTIATE_TYPED_TEST_SUITE_P(simdifyable_dna4, semi_alphabet_constexpr, seqan3::simd_dna4, );
INSTANTIATE_TYPED_TEST_SUITE_P(simdifyable_dna4, nucleotide, seqan3::simd_dna4, );

TEST(simdifyable_dna4, to_char_assign_char)
{
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('A')), 'A');
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('C')), 'C');
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('G')), 'G');
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('T')), 'T');

EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('a')), 'A');
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('c')), 'C');
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('g')), 'G');
EXPECT_EQ(seqan3::to_char(seqan3::simd_dna4{}.assign_char('t')), 'T');
}