[med-svn] [Git][med-team/spoa][upstream] New upstream version 4.1.4

Michael R. Crusoe (@crusoe) gitlab at salsa.debian.org
Thu Mar 21 11:58:26 GMT 2024



Michael R. Crusoe pushed to branch upstream at Debian Med / spoa


Commits:
ccf4f105 by Michael R. Crusoe at 2024-03-21T12:23:32+01:00
New upstream version 4.1.4
- - - - -


28 changed files:

- + .github/workflows/spoa.yml
- .gitignore
- − .travis.yml
- CMakeLists.txt
- README.md
- + include/meson.build
- include/spoa/graph.hpp
- include/spoa/spoa.hpp
- + include/spoa/version.hpp
- + meson.build
- + meson_options.txt
- include/spoa/architectures.hpp → src/architectures.hpp
- src/graph.cpp
- src/main.cpp
- + src/meson.build
- src/simd_alignment_engine.hpp
- src/simd_alignment_engine_dispatcher.cpp
- src/simd_alignment_engine_implementation.hpp
- + src/spoa_config.h.in
- + src/version.cpp
- + subprojects/bioparser.wrap
- + subprojects/biosoup.wrap
- + subprojects/cereal.wrap
- + subprojects/gtest.wrap
- + subprojects/simde.wrap
- + test/meson.build
- test/spoa_test.cpp
- + test/spoa_test_config.h.in


Changes:

=====================================
.github/workflows/spoa.yml
=====================================
@@ -0,0 +1,68 @@
+name: spoa CI
+
+on:
+  push:
+  pull_request:
+    branches:
+      - master
+
+env:
+  BUILD_TYPE: Release
+
+jobs:
+  test:
+    strategy:
+      matrix:
+        compiler:
+          - g++-7
+          - g++
+          - clang++-6.0
+          - clang++
+
+    runs-on: ubuntu-20.04
+
+    steps:
+      - uses: actions/checkout at v3
+
+      - if: ${{ contains(matrix.compiler, '-') }}
+        name: Get compiler version
+        id: get-compiler-version
+        run: |
+          version=$(echo ${{ matrix.compiler }} | cut -d- -f2)
+          echo "version=$version" >> $GITHUB_OUTPUT
+
+      - if: ${{ startsWith(matrix.compiler, 'g++-') }}
+        name: Setup GCC
+        uses: egor-tensin/setup-gcc at v1
+        with:
+          version: "${{ steps.get-compiler-version.outputs.version }}"
+          platform: x64
+
+      - if: ${{ startsWith(matrix.compiler, 'clang++-') }}
+        name: Setup Clang
+        uses: egor-tensin/setup-clang at v1
+        with:
+          version: "${{ steps.get-compiler-version.outputs.version }}"
+          platform: x64
+
+      - name: Configure CMake
+        run: |
+          cmake -B ${{ github.workspace }}/build_cmake -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
+          cmake --build ${{ github.workspace }}/build_cmake
+        env:
+          CXX: ${{ matrix.compiler }}
+
+      - name: Configure Meson
+        uses: BSFishy/meson-build at v1.0.3
+        with:
+          action: build
+          directory: build_meson
+          meson-version: 0.60.0
+
+      - name: Test
+        working-directory: ${{ github.workspace }}
+        run: |
+          build_cmake/bin/spoa --version
+          build_cmake/bin/spoa_test
+          build_meson/src/spoa --version
+          build_meson/test/spoa_test


=====================================
.gitignore
=====================================
@@ -1,2 +1,5 @@
 # Compiled Object files
 build/
+
+/subprojects/*
+!/subprojects/*.wrap


=====================================
.travis.yml deleted
=====================================
@@ -1,44 +0,0 @@
-language: cpp
-
-matrix:
-  include:
-    - name: "GCC 4.8 (Linux)"  # GCC 4.8.5 & CMake 3.12.4
-      os: linux
-      dist: xenial
-      addons:
-        apt:
-          sources:
-            - ubuntu-toolchain-r-test
-          packages:
-            - g++-4.8
-      env:
-        - SET_COMPILER="export CC=gcc-4.8 && export CXX=g++-4.8"
-
-    - name: "Clang 3.5 (Linux)"  # Clang 3.5.0 & CMake 3.12.4
-      os: linux
-      dist: xenial
-      addons:
-        apt:
-          packages:
-            - clang-3.5
-      env:
-        - SET_COMPILER="export CC=clang-3.5 && export CXX=clang++-3.5"
-
-    - name: "Clang Xcode 9.4 (OSX)"  # Clang 9.4.1 & CMake 3.15.5
-      os: osx
-      osx_image: xcode9.4
-
-before_install:
-  - eval "${SET_COMPILER}"
-
-install:
-  - mkdir build && cd build
-  - cmake -DCMAKE_BUILD_TYPE=Release .. && make
-
-script:
-  - ./bin/spoa --version
-  - ./bin/spoa_test
-
-notifications:
-  email:
-    on_failure: always


=====================================
CMakeLists.txt
=====================================
@@ -1,23 +1,14 @@
 cmake_minimum_required(VERSION 3.12)
 
-project(spoa VERSION 4.0.8
+project(spoa VERSION 4.1.4
              LANGUAGES CXX
              DESCRIPTION "Spoa is a c++ library (and tool) for SIMD vectorized partial order alignment.")
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
-set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 
-if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
-  if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "5.0.0")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-aligned-new")
-  endif ()
-  if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "6.1.0")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-ignored-attributes")
-  endif ()
-endif ()
-
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
@@ -55,7 +46,7 @@ if (spoa_use_simde OR
   FetchContent_Declare(
     simde
     GIT_REPOSITORY https://github.com/simd-everywhere/simde
-    GIT_TAG v0.7.0)
+    GIT_TAG v0.7.6)
 
   FetchContent_GetProperties(simde)
   if (NOT simde_POPULATED)
@@ -125,14 +116,14 @@ if (spoa_use_cereal)
 endif ()
 
 if (spoa_build_exe OR spoa_build_tests)
-  find_package(bioparser 3.0.13 QUIET)
-  find_package(biosoup 0.10.0 QUIET)
+  find_package(bioparser 3.1.0 QUIET)
+  find_package(biosoup 0.11.0 QUIET)
 
   if (NOT bioparser_FOUND)
     FetchContent_Declare(
       bioparser
       GIT_REPOSITORY https://github.com/rvaser/bioparser
-      GIT_TAG 3.0.13)
+      GIT_TAG 3.1.0)
 
     FetchContent_GetProperties(bioparser)
     if (NOT bioparser_POPULATED)
@@ -148,7 +139,7 @@ if (spoa_build_exe OR spoa_build_tests)
     FetchContent_Declare(
       biosoup
       GIT_REPOSITORY https://github.com/rvaser/biosoup
-      GIT_TAG 0.10.0)
+      GIT_TAG 0.11.0)
 
     FetchContent_GetProperties(biosoup)
     if (NOT biosoup_POPULATED)
@@ -181,15 +172,20 @@ if (spoa_build_tests)
   endif ()
 endif ()
 
+set(SPOA_VERSION "${PROJECT_VERSION}")
+configure_file(src/spoa_config.h.in spoa_config.h)
+
 add_library(spoa
   src/alignment_engine.cpp
   src/graph.cpp
   src/simd_alignment_engine_dispatcher.cpp
-  src/sisd_alignment_engine.cpp)
+  src/sisd_alignment_engine.cpp
+  src/version.cpp)
 add_library(spoa::spoa ALIAS spoa)
 
 target_include_directories(spoa PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+  $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
   $<BUILD_INTERFACE:${simde_SOURCE_DIR}>
   $<INSTALL_INTERFACE:include>)
 
@@ -267,13 +263,15 @@ if (spoa_build_exe)
     bioparser::bioparser
     biosoup::biosoup)
 
-  target_compile_definitions(spoa_exe PRIVATE VERSION="${PROJECT_VERSION}")
   set_property(TARGET spoa_exe PROPERTY OUTPUT_NAME spoa)
 
   install(TARGETS spoa_exe DESTINATION ${CMAKE_INSTALL_BINDIR})
 endif ()
 
 if (spoa_build_tests)
+  set(SPOA_TEST_DATA "${PROJECT_SOURCE_DIR}/test/data/sample.fastq.gz")
+  configure_file(test/spoa_test_config.h.in spoa_test_config.h)
+
   add_executable(spoa_test
     test/spoa_test.cpp)
 
@@ -283,6 +281,6 @@ if (spoa_build_tests)
     biosoup::biosoup
     GTest::Main)
 
-  target_compile_definitions(spoa_test
-    PRIVATE TEST_DATA="${PROJECT_SOURCE_DIR}/test/data/sample.fastq.gz")
+  target_include_directories(spoa_test PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
 endif ()


=====================================
README.md
=====================================
@@ -1,21 +1,69 @@
 # Spoa
 
 [![Latest GitHub release](https://img.shields.io/github/release/rvaser/spoa.svg)](https://github.com/rvaser/spoa/releases/latest)
-[![Build status for gcc/clang](https://travis-ci.com/rvaser/spoa.svg?branch=master)](https://travis-ci.com/rvaser/spoa)
+![Build status for gcc/clang](https://github.com/rvaser/spoa/actions/workflows/spoa.yml/badge.svg)
 [![Published in Genome Research](https://img.shields.io/badge/published%20in-Genome%20Research-blue.svg)](https://doi.org/10.1101/gr.214270.116)
 
 Spoa (SIMD POA) is a c++ implementation of the partial order alignment (POA) algorithm (as described in 10.1093/bioinformatics/18.3.452) which is used to generate consensus sequences (as described in 10.1093/bioinformatics/btg109). It supports three alignment modes: local (Smith-Waterman), global (Needleman-Wunsch) and semi-global alignment (overlap), and three gap modes: linear, affine and convex (piecewise affine). It also supports Intel SSE4.1+ and AVX2 vectorization (marginally faster due to high latency shifts), [SIMDe](https://github.com/simd-everywhere/simde) and dispatching.
 
-## Usage
+## Build
+
+### Dependencies
+
+- gcc 7+ | clang 4+
+- (spoa_exe)(spoa_test) zlib 1.2.8+
+
+#### Hidden
+
+- \[optional\] USCiLab/cereal 1.3.0
+- \[optional\] simd-everywhere/simde 0.7.6
+- \[optional\] google/cpu_features 0.6.0
+- (spoa_exe)(spoa_test) rvaser/bioparser 3.1.0
+- (spoa_exe)(spoa_test) rvaser/biosoup 0.11.0
+- (spoa_test) google/googletest 1.10.0
+
+### CMake (3.12+)
+
+```bash
+git clone https://github.com/rvaser/spoa && cd spoa
+cmake -B build -DCMAKE_BUILD_TYPE=Release
+make -C build
+```
+
+#### Options
 
-To build spoa run the following commands:
+- `spoa_install`: generate library install target
+- `spoa_build_exe`: build executable
+- `spoa_build_tests`: build unit tests
+- `spoa_optimize_for_native`: build with `-march=native`
+- `spoa_optimize_for_portability`: build with `-msse4.1`
+- `spoa_use_cereal`: use cereal library
+- `spoa_use_simde`: build with SIMDe for porting vectorized code
+- `spoa_use_simde_nonvec`: use SIMDe library for nonvectorized code
+- `spoa_use_simde_openmp`: use SIMDe support for OpenMP SIMD
+- `spoa_generate_dispatch`: use SIMDe to generate x86 dispatch
+
+### Meson (0.60.0+)
 
 ```bash
-git clone https://github.com/rvaser/spoa && cd spoa && mkdir build && cd build
-cmake -DCMAKE_BUILD_TYPE=Release .. && make
+git clone https://github.com/rvaser/spoa && cd spoa
+meson setup build
+ninja -C build
 ```
 
-which will create spoa library, executable and unit tests. Running the executable will display the following usage:
+#### Options
+
+- `exe`: build executable
+- `tests`: build unit tests
+- `avx2`: build with `-mavx2`
+- `sse41`: build with `-msse4.1`
+- `cereal`: build serialization funcitons
+- `simde`: build with SIMDe
+- `simde_nonvec`: use SIMDe for nonvectorized code
+- `simde_openmp`: use SIMDe support for OpenMP SIMD
+- `dispatch`: use SIMDe to generate x86 dispatch
+
+## Usage
 
 ```bash
 usage: spoa [options ...] <sequences>
@@ -74,48 +122,6 @@ usage: spoa [options ...] <sequences>
     convex otherwise (default)
 ```
 
-Running `make install` will install the library and the executable. If you choose to build with cereal or want to generate the dispatcher, cereal and cpu_features (see Dependencies) need to be installed beforehand, respectively. Once the library is installed, with or without additional options, a package will be copied to your system that can be searched and linked with:
-
-```cmake
-find_package(spoa)
-target_link_libraries(<target> spoa::spoa)
-```
-
-On the other hand, you can include spoa as a submodule and add it to your project with the following:
-
-```cmake
-if (NOT TARGET spoa)
-  add_subdirectory(<path_to_submodules>/spoa EXCLUDE_FROM_ALL)
-endif ()
-target_link_libraries(<target> spoa::spoa)
-```
-
-#### Build options
-
-- `spoa_install`: generate library install target
-- `spoa_build_exe`: build executable
-- `spoa_build_tests`: build unit tests
-- `spoa_optimize_for_native`: build with `-march=native`
-- `spoa_optimize_for_portability`: build with `-msse4.1`
-- `spoa_use_cereal`: use cereal library
-- `spoa_use_simde`: build with SIMDe for porting vectorized code
-- `spoa_use_simde_nonvec`: use SIMDe library for nonvectorized code
-- `spoa_use_simde_openmp`: use SIMDe support for OpenMP SIMD
-- `spoa_generate_dispatch`: use SIMDe to generate x86 dispatch
-
-#### Dependencies
-- gcc 4.8+ | clang 3.5+
-- cmake 3.12+
-- (spoa_exe)(spoa_test) zlib 1.2.8+
-
-###### Hidden
-- (optional) USCiLab/cereal 1.3.0
-- (optional) simd-everywhere/simde 0.7.0
-- (optional) google/cpu_features 0.6.0
-- (spoa_exe)(spoa_test) rvaser/bioparser 3.0.13
-- (spoa_exe)(spoa_test) rvaser/biosoup 0.10.0
-- (spoa_test) google/googletest 1.10.0
-
 ## Examples
 
 ```cpp


=====================================
include/meson.build
=====================================
@@ -0,0 +1,18 @@
+###########
+# Headers #
+###########
+
+spoa_include_directories = include_directories(['.'])
+
+if meson.is_subproject()
+  subdir_done()
+endif
+
+install_headers(
+  files([
+    'spoa/alignment_engine.hpp',
+    'spoa/graph.hpp',
+    'spoa/spoa.hpp',
+    'spoa/version.hpp',
+  ]),
+  subdir : 'spoa')


=====================================
include/spoa/graph.hpp
=====================================
@@ -166,6 +166,12 @@ class Graph {
 
   std::string GenerateConsensus();
 
+  std::string GenerateConsensus(std::int32_t min_coverage);
+
+  std::string GenerateConsensus(
+      std::int32_t min_coverage,
+      std::vector<std::uint32_t> *summary);
+
   std::string GenerateConsensus(
       std::vector<std::uint32_t>* summary,
       bool verbose = false);


=====================================
include/spoa/spoa.hpp
=====================================
@@ -5,5 +5,6 @@
 
 #include "graph.hpp"
 #include "alignment_engine.hpp"
+#include "version.hpp"
 
 #endif  // SPOA_SPOA_HPP_


=====================================
include/spoa/version.hpp
=====================================
@@ -0,0 +1,14 @@
+// Copyright (c) 2023 Robert Vaser
+
+#ifndef SPOA_VERSION_HPP_
+#define SPOA_VERSION_HPP_
+
+#include <string>
+
+namespace spoa {
+
+std::string Version();
+
+}  // namespace spoa
+
+#endif  // SPOA_VERSION_HPP_


=====================================
meson.build
=====================================
@@ -0,0 +1,111 @@
+project(
+  'spoa',
+  ['cpp'],
+  version : '4.1.4',
+  default_options : [
+    'buildtype=release',
+    'warning_level=3',
+    'cpp_std=c++17',
+    'b_ndebug=if-release'],
+  license : 'MIT',
+  meson_version : '>=0.60.0'
+)
+
+################
+# Dependencies #
+################
+
+spoa_lib_flags = []
+spoa_lib_deps = []
+
+if get_option('cereal')
+  # cereal
+  spoa_cereal_dep = dependency('cereal', version : '>= 1.3.0', fallback : ['cereal', 'cereal_dep'])
+
+  spoa_lib_flags += '-DSPOA_USE_CEREAL'
+  spoa_lib_deps += spoa_cereal_dep
+endif
+
+if (not meson.is_subproject()) and (get_option('exe') or get_option('tests'))
+  # biosoup
+  spoa_biosoup_dep = dependency('biosoup', version : '>= 0.11.0', fallback : ['biosoup', 'biosoup_dep'])
+
+  # bioparser
+  spoa_bioparser_dep = dependency('bioparser', version : '>= 3.1.0', fallback : ['bioparser', 'bioparser_dep'])
+endif
+
+if not get_option('dispatch')
+  if get_option('sse41')
+    spoa_lib_flags += '-msse4.1'
+  elif get_option('avx2')
+    spoa_lib_flags += '-mavx2'
+  endif
+endif
+
+if (get_option('simde') or
+    get_option('simde_nonvec') or
+    get_option('simde_openmp') or
+    get_option('dispatch'))
+  # simde
+  spoa_simde_dep = dependency('simde', version : '>= 0.7.6', fallback : ['simde', 'simde_dep'])
+
+  add_project_arguments('-DSIMDE_ENABLE_NATIVE_ALIASES', language : ['c', 'cpp'])
+  spoa_lib_flags += '-DSPOA_USE_SIMDE'
+  spoa_lib_deps += spoa_simde_dep
+
+  if get_option('simde_nonvec')
+    add_project_arguments('-DSIMDE_NO_NATIVE', language : ['c', 'cpp'])
+  endif
+
+  if get_option('simde_openmp')
+    add_project_arguments('-DSIMDE_ENABLE_OPENMP', language : ['c', 'cpp'])
+    spoa_lib_flags += '-fopenmp-simd'
+  endif
+
+  if get_option('dispatch')
+    spoa_lib_flags += '-DSPOA_GENERATE_DISPATCH_CPUIDEX'
+  endif
+endif
+
+###########
+# Headers #
+###########
+
+subdir('include')
+
+###########
+# Sources #
+###########
+
+subdir('src')
+
+#########
+# Tests #
+#########
+
+if (not meson.is_subproject()) and get_option('tests')
+  # gtest
+  spoa_gtest_dep = dependency('gtest', version : '>= 1.10.0', main : true, fallback : ['gtest', 'gtest_main_dep'])
+
+  subdir('test')
+endif
+
+###################
+# Dependency info #
+###################
+
+if (not meson.is_subproject())
+  import('pkgconfig').generate(
+    spoa_lib,
+    name : 'spoa',
+    version : meson.project_version(),
+    filebase : 'spoa',
+    description : 'C++ tool/library for SIMD vectorized partial order alignment.')
+endif
+
+spoa_dep = declare_dependency(
+  include_directories : spoa_include_directories,
+  link_with : spoa_lib,
+  dependencies : spoa_lib_deps,
+  version : meson.project_version()
+)


=====================================
meson_options.txt
=====================================
@@ -0,0 +1,56 @@
+#################
+# Build options #
+#################
+
+option('cereal',
+  type : 'boolean',
+  value : false,
+  description : 'Enable serialization through cereal')
+
+option('avx2',
+  type : 'boolean',
+  value : false,
+  description : 'Build with -mavx2')
+
+option('sse41',
+  type : 'boolean',
+  value : false,
+  description : 'Build with -msse4.1')
+
+option('simde',
+  type : 'boolean',
+  value : false,
+  description : 'Build with SIMDe')
+
+option('simde_nonvec',
+  type : 'boolean',
+  value : false,
+  description : 'Use SIMDe for nonvectorized code')
+
+option('simde_openmp',
+  type : 'boolean',
+  value : false,
+  description : 'Use SIMDe support for OpenMP SIMD')
+
+option('dispatch',
+  type : 'boolean',
+  value : false,
+  description : 'Use SIMDe to generate x86 dispatch')
+
+##############
+# Executable #
+##############
+
+option('exe',
+  type : 'boolean',
+  value : true,
+  description : 'Build spoa executable')
+
+#########
+# Tests #
+#########
+
+option('tests',
+  type : 'boolean',
+  value : true,
+  description : 'Enable dependencies required for testing')


=====================================
include/spoa/architectures.hpp → src/architectures.hpp
=====================================


=====================================
src/graph.cpp
=====================================
@@ -374,6 +374,39 @@ std::string Graph::GenerateConsensus() {
   return dst;
 }
 
+std::string Graph::GenerateConsensus(std::int32_t min_coverage) {
+  TraverseHeaviestBundle();
+  std::string dst{};
+  for (const auto& it : consensus_) {
+    if (static_cast<std::int32_t>(it->Coverage()) >= min_coverage) {
+      dst += decoder_[it->code];
+    }
+  }
+  return dst;
+}
+
+std::string Graph::GenerateConsensus(std::int32_t min_coverage,
+                                     std::vector<std::uint32_t> *summary) {
+  if (!summary) {
+    throw std::invalid_argument(
+        "[spoa::Graph::GenerateConsensus] error: invalid ptr to summary");
+  }
+  summary->clear();
+
+  auto dst = GenerateConsensus(min_coverage);
+  for (const auto &it : consensus_) {
+    if (static_cast<std::int32_t>(it->Coverage()) >= min_coverage) {
+      summary->emplace_back(0);
+      summary->back() += it->Coverage();
+      for (const auto &jt : it->aligned_nodes) {
+        summary->back() += jt->Coverage();
+      }
+    }
+  }
+
+  return dst;
+}
+
 std::string Graph::GenerateConsensus(
     std::vector<std::uint32_t>* summary,
     bool verbose) {


=====================================
src/main.cpp
=====================================
@@ -15,6 +15,7 @@ namespace {
 static struct option options[] = {
   {"algorithm", required_argument, nullptr, 'l'},
   {"result", required_argument, nullptr, 'r'},
+  {"min-coverage", required_argument, nullptr, 'M'},
   {"dot", required_argument, nullptr, 'd'},
   {"strand-ambiguous", no_argument, nullptr, 's'},
   {"version", no_argument, nullptr, 'v'},
@@ -101,6 +102,9 @@ void Help() {
       "        2 - 0 & 1 (FASTA)\n"
       "        3 - partial order graph (GFA)\n"
       "        4 - 0 & 3 (GFA)\n"
+      "    --min-coverage <int>\n"
+      "      default: -1\n"
+      "      minimal consensus coverage (usable only with -r 0)\n"
       "    -d, --dot <file>\n"
       "      output file for the partial order graph in DOT format\n"
       "    -s, --strand-ambiguous\n"
@@ -208,6 +212,8 @@ int main(int argc, char** argv) {
   std::int8_t q = -10;
   std::int8_t c = -4;
 
+  std::int32_t min_coverage = -1;
+
   std::uint8_t algorithm = 0;
   std::vector<std::uint8_t> results = { 0 };
   std::string dot_path{};
@@ -223,11 +229,12 @@ int main(int argc, char** argv) {
       case 'e': e = atoi(optarg); break;
       case 'q': q = atoi(optarg); break;
       case 'c': c = atoi(optarg); break;
+      case 'M': min_coverage = atoi(optarg); break;
       case 'l': algorithm = atoi(optarg); break;
       case 'r': results.emplace_back(atoi(optarg)); break;
       case 'd': dot_path = optarg; break;
       case 's': is_strand_ambiguous = true; break;
-      case 'v': std::cout << VERSION << std::endl; return 0;
+      case 'v': std::cout << spoa::Version() << std::endl; return 0;
       case 'h': Help(); return 0;
       default: return 1;
     }
@@ -316,7 +323,7 @@ int main(int argc, char** argv) {
   for (const auto& it : results) {
     switch (it) {
       case 0: {
-        auto consensus = graph.GenerateConsensus();
+        auto consensus = graph.GenerateConsensus(min_coverage);
         std::cout << ">Consensus LN:i:" << consensus.size() << std::endl
                   << consensus << std::endl;
         break;


=====================================
src/meson.build
=====================================
@@ -0,0 +1,68 @@
+spoa_config = configuration_data()
+spoa_config.set('SPOA_VERSION', meson.project_version())
+
+###########
+# Library #
+###########
+
+spoa_config_headers = [
+  configure_file(
+    input : 'spoa_config.h.in',
+    output : 'spoa_config.h',
+    configuration : spoa_config)
+]
+
+spoa_sources = files([
+  'alignment_engine.cpp',
+  'graph.cpp',
+  'simd_alignment_engine_dispatcher.cpp',
+  'sisd_alignment_engine.cpp',
+  'version.cpp',
+]) + spoa_config_headers
+
+spoa_simd_lib = []
+
+if get_option('dispatch')
+  simd = import('unstable_simd')
+
+  spoa_simd_sources = files([
+    'simd_alignment_engine_dispatch.cpp',
+  ])
+
+  spoa_simd_lib += simd.check(
+    'spoa',
+    sse2 : spoa_simd_sources,
+    sse41 : spoa_simd_sources,
+    avx2 : spoa_simd_sources,
+    dependencies : spoa_lib_deps,
+    include_directories : spoa_include_directories,
+    cpp_args : spoa_lib_flags,
+    compiler : meson.get_compiler('cpp'))[0]
+endif
+
+spoa_lib_install = (not meson.is_subproject()) or (get_option('default_library') != 'static')
+
+spoa_lib = library(
+  'spoa',
+  spoa_sources,
+  soversion : meson.project_version(),
+  version : meson.project_version(),
+  install : spoa_lib_install,
+  dependencies : spoa_lib_deps,
+  include_directories : spoa_include_directories,
+  link_with : spoa_simd_lib,
+  cpp_args : spoa_lib_flags)
+
+##############
+# Executable #
+##############
+
+if (not meson.is_subproject()) and get_option('exe')
+  spoa_exe = executable(
+    'spoa',
+    files(['main.cpp']),
+    install : true,
+    dependencies : [spoa_lib_deps, spoa_biosoup_dep, spoa_bioparser_dep],
+    include_directories : spoa_include_directories,
+    link_with : spoa_lib)
+endif


=====================================
src/simd_alignment_engine.hpp
=====================================
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "spoa/alignment_engine.hpp"
-#include "spoa/architectures.hpp"
+#include "architectures.hpp"
 
 namespace spoa {
 


=====================================
src/simd_alignment_engine_dispatcher.cpp
=====================================
@@ -2,18 +2,78 @@
 
 #include "simd_alignment_engine_implementation.hpp"
 
-#ifdef SPOA_GENERATE_DISPATCH
+#if defined(SPOA_GENERATE_DISPATCH)
 
 #include "cpuinfo_x86.h"  // NOLINT
 
 static const cpu_features::X86Features features =
     cpu_features::GetX86Info().features;
 
+#elif defined(SPOA_GENERATE_DISPATCH_CPUIDEX)
+
+#  if defined(_MSC_VER)
+
+#include <intrin.h>
+
+#  endif
+
+// adapted from https://github.com/intel/linux-sgx/blob/master/common/inc/internal/linux/cpuid_gnu.h
+void RunCpuidex(int cpu_info[4], int function_id, int subfunction_id) {
+#  if defined(_MSC_VER)
+  __cpuidex(cpu_info, function_id, subfunction_id);
+#  elif defined(__X86_64__)
+  __asm__ volatile ("cpuid")
+                  : "=a" (cpu_info[0]), "=b" (cpu_info[1]), "=c" (cpu_info[2]), "=d" (cpu_info[3])
+                  : "0" (function_id), "2" (subfunction_id));
+#  else
+  __asm__ volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+                  : "=a" (cpu_info[0]), "=r" (cpu_info[1]), "=c" (cpu_info[2]), "=d" (cpu_info[3])
+                  : "0" (function_id), "2" (subfunction_id));
+#  endif
+}
+
+constexpr int SPOA_SSE2 = 0x1;
+constexpr int SPOA_SSE4_1 = 0x2;
+constexpr int SPOA_AVX2 = 0x4;
+
+static int GetX86Info() {
+  int cpu_info[4] = {0};
+
+  RunCpuidex(cpu_info, 0, 0);
+
+  const int n = cpu_info[0];
+  if (n == 0) {
+    return 0;
+  }
+
+  RunCpuidex(cpu_info, 1, 0);
+
+  int features = 0;
+  if (cpu_info[3] >> 26) {
+    features |= SPOA_SSE2;
+  }
+  if (cpu_info[2] >> 19) {
+    features |= SPOA_SSE4_1;
+  }
+
+  if (n >= 7) {
+    RunCpuidex(cpu_info, 7, 0);
+
+    if (cpu_info[1] >> 5) {
+      features |= SPOA_AVX2;
+    }
+  }
+
+  return features;
+}
+
+static const int features = GetX86Info();
+
 #endif
 
 namespace spoa {
-
-#ifndef SPOA_GENERATE_DISPATCH
+ 
+#if !defined(SPOA_GENERATE_DISPATCH) && !defined(SPOA_GENERATE_DISPATCH_CPUIDEX)
 
 template class SimdAlignmentEngine<Architecture::kAutomatic>;
 
@@ -28,7 +88,7 @@ std::unique_ptr<AlignmentEngine> CreateSimdAlignmentEngine(
     std::int8_t e,
     std::int8_t q,
     std::int8_t c) {
-#ifdef SPOA_GENERATE_DISPATCH
+#if defined(SPOA_GENERATE_DISPATCH)
   if (features.avx2) {
     return SimdAlignmentEngine<Architecture::kAVX2>::Create(
         type, subtype, m, n, g, e, q, c);
@@ -39,6 +99,17 @@ std::unique_ptr<AlignmentEngine> CreateSimdAlignmentEngine(
     return SimdAlignmentEngine<Architecture::kSSE2>::Create(
         type, subtype, m, n, g, e, q, c);
   }
+#elif defined(SPOA_GENERATE_DISPATCH_CPUIDEX)
+  if (features & SPOA_AVX2) {
+    return SimdAlignmentEngine<Architecture::kAVX2>::Create(
+        type, subtype, m, n, g, e, q, c);
+  } else if (features & SPOA_SSE4_1) {
+    return SimdAlignmentEngine<Architecture::kSSE4_1>::Create(
+        type, subtype, m, n, g, e, q, c);
+  } else {
+    return SimdAlignmentEngine<Architecture::kSSE2>::Create(
+        type, subtype, m, n, g, e, q, c);
+  }
 #else
   return SimdAlignmentEngine<Architecture::kAutomatic>::Create(
       type, subtype, m, n, g, e, q, c);


=====================================
src/simd_alignment_engine_implementation.hpp
=====================================
@@ -29,34 +29,6 @@ extern "C" {
 
 namespace spoa {
 
-// Taken from https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=216149
-inline void* align(
-    std::size_t __align,
-    std::size_t __size,
-    void*& __ptr,  // NOLINT
-    std::size_t& __space) noexcept {  // NOLINT
-  const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);
-  const auto __aligned = (__intptr - 1u + __align) & -__align;
-  const auto __diff = __aligned - __intptr;
-  if ((__size + __diff) > __space) {
-    return nullptr;
-  } else {
-    __space -= __diff;
-    return __ptr = reinterpret_cast<void*>(__aligned);
-  }
-}
-
-template<Architecture A, typename T>
-T* AllocateAlignedMemory(
-    T** storage,
-    std::size_t size,
-    std::size_t alignment) {
-  *storage = new T[size + alignment - 1];
-  void* ptr = static_cast<void*>(*storage);
-  std::size_t storage_size = (size + alignment - 1) * sizeof(T);
-  return static_cast<T*>(align(alignment, size * sizeof(T), ptr, storage_size));
-}
-
 template<Architecture A, typename T>
 struct InstructionSet;
 
@@ -88,6 +60,9 @@ template<Architecture A>
 struct InstructionSet<A, std::int16_t> {
   using type = std::int16_t;
   static constexpr std::uint32_t kNumVar = kRegisterSize / (8 * sizeof(type));
+  struct alignas(kRegisterSize / 8) Storage {
+    type arr[kNumVar];
+  };
   static constexpr std::uint32_t kLogNumVar = 4;
   static constexpr std::uint32_t kLSS = 2;   // Left Shift Size
   static constexpr std::uint32_t kRSS = 30;  // Right Shift Size
@@ -121,6 +96,9 @@ template<Architecture A>
 struct InstructionSet<A, std::int32_t> {
   using type = std::int32_t;
   static constexpr std::uint32_t kNumVar = kRegisterSize / (8 * sizeof(type));
+  struct alignas(kRegisterSize / 8) Storage {
+    type arr[kNumVar];
+  };
   static constexpr std::uint32_t kLogNumVar = 3;
   static constexpr std::uint32_t kLSS = 4;
   static constexpr std::uint32_t kRSS = 28;
@@ -176,6 +154,9 @@ template<Architecture A>
 struct InstructionSet<A, std::int16_t> {
   using type = std::int16_t;
   static constexpr std::uint32_t kNumVar = kRegisterSize / (8 * sizeof(type));
+  struct alignas(kRegisterSize / 8) Storage {
+    type arr[kNumVar];
+  };
   static constexpr std::uint32_t kLogNumVar = 3;
   static constexpr std::uint32_t kLSS = 2;
   static constexpr std::uint32_t kRSS = 14;
@@ -208,6 +189,9 @@ template<Architecture A>
 struct InstructionSet<A, std::int32_t> {
   using type = std::int32_t;
   static constexpr std::uint32_t kNumVar = kRegisterSize / (8 * sizeof(type));
+  struct alignas(kRegisterSize / 8) Storage {
+    type arr[kNumVar];
+  };
   static constexpr std::uint32_t kLogNumVar = 2;
   static constexpr std::uint32_t kLSS = 4;
   static constexpr std::uint32_t kRSS = 12;
@@ -239,6 +223,10 @@ struct InstructionSet<A, std::int32_t> {
 
 #if defined(__AVX2__) || defined(__SSE4_1__) || defined(SPOA_USE_SIMDE)
 
+struct Storage {
+  __mxxxi val;
+};
+
 template<Architecture A, typename T>
 void _mmxxx_print(const __mxxxi& a) {
   __attribute__((aligned(kRegisterSize / 8))) typename T::type unpacked[T::kNumVar];  // NOLINT
@@ -320,45 +308,38 @@ struct SimdAlignmentEngine<A>::Implementation {
 #if defined(__AVX2__) || defined(__SSE4_1__) || defined(SPOA_USE_SIMDE)
   std::vector<std::uint32_t> node_id_to_rank;
 
-  std::unique_ptr<__mxxxi[]> sequence_profile_storage;
-  std::uint64_t sequence_profile_size;
+  std::vector<Storage> sequence_profile_storage;
   __mxxxi* sequence_profile;
 
   std::vector<std::int32_t> first_column;
-  std::unique_ptr<__mxxxi[]> M_storage;
-  std::uint64_t M_size;
+
+  std::vector<Storage> M_storage;
   __mxxxi* H;
   __mxxxi* F;
   __mxxxi* E;
   __mxxxi* O;
   __mxxxi* Q;
 
-  std::unique_ptr<__mxxxi[]> masks_storage;
-  std::uint32_t masks_size;
+  std::vector<Storage> masks_storage;
   __mxxxi* masks;
 
-  std::unique_ptr<__mxxxi[]> penalties_storage;
-  std::uint32_t penalties_size;
+  std::vector<Storage> penalties_storage;
   __mxxxi* penalties;
 
   Implementation()
       : node_id_to_rank(),
-        sequence_profile_storage(nullptr),
-        sequence_profile_size(0),
+        sequence_profile_storage(),
         sequence_profile(nullptr),
         first_column(),
-        M_storage(nullptr),
-        M_size(0),
+        M_storage(),
         H(nullptr),
         F(nullptr),
         E(nullptr),
         O(nullptr),
         Q(nullptr),
-        masks_storage(nullptr),
-        masks_size(0),
+        masks_storage(),
         masks(nullptr),
-        penalties_storage(nullptr),
-        penalties_size(0),
+        penalties_storage(),
         penalties(nullptr) {
   }
 #endif
@@ -430,84 +411,48 @@ void SimdAlignmentEngine<A>::Realloc(
   if (pimpl_->node_id_to_rank.size() < matrix_height - 1) {
     pimpl_->node_id_to_rank.resize(matrix_height - 1, 0);
   }
-  if (pimpl_->sequence_profile_size < num_codes * matrix_width) {
-    __mxxxi* storage = nullptr;
-    pimpl_->sequence_profile_size = num_codes * matrix_width;
-    pimpl_->sequence_profile = AllocateAlignedMemory<A>(
-        &storage,
-        pimpl_->sequence_profile_size,
-        kRegisterSize / 8);
-    pimpl_->sequence_profile_storage.reset();
-    pimpl_->sequence_profile_storage = std::unique_ptr<__mxxxi[]>(storage);
+  if (pimpl_->sequence_profile_storage.size() < num_codes * matrix_width) {
+    pimpl_->sequence_profile_storage.resize(num_codes * matrix_width);
+    pimpl_->sequence_profile = reinterpret_cast<__mxxxi*>(pimpl_->sequence_profile_storage.data());
   }
   if (subtype_ == AlignmentSubtype::kLinear) {
     if (pimpl_->first_column.size() < matrix_height) {
       pimpl_->first_column.resize(matrix_height, 0);
     }
-    if (pimpl_->M_size < matrix_height * matrix_width) {
-      __mxxxi* storage = nullptr;
-      pimpl_->M_size = matrix_height * matrix_width;
-      pimpl_->H = AllocateAlignedMemory<A>(
-        &storage,
-        pimpl_->M_size,
-        kRegisterSize / 8);
-      pimpl_->M_storage.reset();
-      pimpl_->M_storage = std::unique_ptr<__mxxxi[]>(storage);
+    if (pimpl_->M_storage.size() < matrix_height * matrix_width) {
+      pimpl_->M_storage.resize(matrix_height * matrix_width);
+      pimpl_->H = reinterpret_cast<__mxxxi*>(pimpl_->M_storage.data());
     }
   } else if (subtype_ == AlignmentSubtype::kAffine) {
     if (pimpl_->first_column.size() < 2 * matrix_height) {
       pimpl_->first_column.resize(2 * matrix_height, 0);
     }
-    if (pimpl_->M_size < 3 * matrix_height * matrix_width) {
-      __mxxxi* storage = nullptr;
-      pimpl_->M_size = 3 * matrix_height * matrix_width;
-      pimpl_->H = AllocateAlignedMemory<A>(
-        &storage,
-        pimpl_->M_size,
-        kRegisterSize / 8);
+    if (pimpl_->M_storage.size() < 3 * matrix_height * matrix_width) {
+      pimpl_->M_storage.resize(3 * matrix_height * matrix_width);
+      pimpl_->H = reinterpret_cast<__mxxxi*>(pimpl_->M_storage.data());
       pimpl_->F = pimpl_->H + matrix_height * matrix_width;
       pimpl_->E = pimpl_->F + matrix_height * matrix_width;
-      pimpl_->M_storage.reset();
-      pimpl_->M_storage = std::unique_ptr<__mxxxi[]>(storage);
     }
   } else if (subtype_ == AlignmentSubtype::kConvex) {
     if (pimpl_->first_column.size() < 3 * matrix_height) {
       pimpl_->first_column.resize(3 * matrix_height, 0);
     }
-    if (pimpl_->M_size < 5 * matrix_height * matrix_width) {
-      __mxxxi* storage = nullptr;
-      pimpl_->M_size = 5 * matrix_height * matrix_width;
-      pimpl_->H = AllocateAlignedMemory<A>(
-          &storage,
-          pimpl_->M_size,
-          kRegisterSize / 8);
+    if (pimpl_->M_storage.size() < 5 * matrix_height * matrix_width) {
+      pimpl_->M_storage.resize(5 * matrix_height * matrix_width);
+      pimpl_->H = reinterpret_cast<__mxxxi*>(pimpl_->M_storage.data());
       pimpl_->F = pimpl_->H + matrix_height * matrix_width;
       pimpl_->E = pimpl_->F + matrix_height * matrix_width;
       pimpl_->O = pimpl_->E + matrix_height * matrix_width;
       pimpl_->Q = pimpl_->O + matrix_height * matrix_width;
-      pimpl_->M_storage.reset();
-      pimpl_->M_storage = std::unique_ptr<__mxxxi[]>(storage);
     }
   }
-  if (pimpl_->masks_size < InstructionSet<A, std::int16_t>::kLogNumVar + 1) {
-    __mxxxi* storage = nullptr;
-    pimpl_->masks_size = InstructionSet<A, std::int16_t>::kLogNumVar + 1;
-    pimpl_->masks = AllocateAlignedMemory<A>(
-        &storage,
-        pimpl_->masks_size,
-        kRegisterSize / 8);
-    pimpl_->masks_storage.reset();
-    pimpl_->masks_storage = std::unique_ptr<__mxxxi[]>(storage);
-  }
-  if (pimpl_->penalties_size < 2 * InstructionSet<A, std::int16_t>::kLogNumVar) {  // NOLINT
-    __mxxxi* storage = nullptr;
-    pimpl_->penalties_size = 2 * InstructionSet<A, std::int16_t>::kLogNumVar;
-    pimpl_->penalties = AllocateAlignedMemory<A>(
-        &storage,
-        pimpl_->penalties_size,
-        kRegisterSize / 8);
-    pimpl_->penalties_storage.reset();
-    pimpl_->penalties_storage = std::unique_ptr<__mxxxi[]>(storage);
+  if (pimpl_->masks_storage.size() < InstructionSet<A, std::int16_t>::kLogNumVar + 1) {
+    pimpl_->masks_storage.resize(InstructionSet<A, std::int16_t>::kLogNumVar + 1);
+    pimpl_->masks = reinterpret_cast<__mxxxi*>(pimpl_->masks_storage.data());
+  }
+  if (pimpl_->penalties_storage.size() < 2 * InstructionSet<A, std::int16_t>::kLogNumVar) {  // NOLINT
+    pimpl_->penalties_storage.resize(2 * InstructionSet<A, std::int16_t>::kLogNumVar);
+    pimpl_->penalties = reinterpret_cast<__mxxxi*>(pimpl_->penalties_storage.data());
   }
 #endif
   (void) matrix_width;
@@ -960,11 +905,8 @@ Alignment SimdAlignmentEngine<A>::Linear(
         static_cast<std::uint32_t>(rank_to_node[i]->inedges.size()));
   }
 
-  typename T::type* backtrack_storage = nullptr;
-  typename T::type* H = AllocateAlignedMemory<A>(
-      &backtrack_storage,
-      3 * T::kNumVar + 2 * T::kNumVar * max_num_predecessors,
-      kRegisterSize / 8);
+  std::vector<typename T::Storage> backtrack_storage(3 * T::kNumVar + 2 * T::kNumVar * max_num_predecessors);
+  typename T::type* H = reinterpret_cast<typename T::type*>(backtrack_storage.data());
   typename T::type* H_pred = H + T::kNumVar;
   typename T::type* H_diag_pred = H_pred + T::kNumVar * max_num_predecessors;
   typename T::type* H_left_pred = H_diag_pred + T::kNumVar * max_num_predecessors;  // NOLINT
@@ -1097,8 +1039,6 @@ Alignment SimdAlignmentEngine<A>::Linear(
     j_mod = j % T::kNumVar;
   } while (true);
 
-  delete[] backtrack_storage;
-
   // update alignment for NW (backtrack stops on first row or column)
   if (type_ == AlignmentType::kNW) {
     while (i == 0 && j != -1) {
@@ -1329,11 +1269,8 @@ Alignment SimdAlignmentEngine<A>::Affine(
         static_cast<std::uint32_t>(rank_to_node[i]->inedges.size()));
   }
 
-  typename T::type* backtrack_storage = nullptr;
-  typename T::type* H = AllocateAlignedMemory<A>(
-      &backtrack_storage,
-      6 * T::kNumVar + 3 * T::kNumVar * max_num_predecessors,
-      kRegisterSize / 8);
+  std::vector<typename T::Storage> backtrack_storage(6 * T::kNumVar + 3 * T::kNumVar * max_num_predecessors);
+  typename T::type* H = reinterpret_cast<typename T::type*>(backtrack_storage.data());
   typename T::type* H_pred = H + T::kNumVar;
   typename T::type* H_diag_pred = H_pred + T::kNumVar * max_num_predecessors;
   typename T::type* H_left = H_diag_pred + T::kNumVar * max_num_predecessors;
@@ -1547,8 +1484,6 @@ Alignment SimdAlignmentEngine<A>::Affine(
     }
   } while (true);
 
-  delete[] backtrack_storage;
-
   // update alignment for NW (backtrack stops on first row or column)
   if (type_ == AlignmentType::kNW) {
     while (i == 0 && j != -1) {
@@ -1831,11 +1766,8 @@ Alignment SimdAlignmentEngine<A>::Convex(
         static_cast<std::uint32_t>(rank_to_node[i]->inedges.size()));
   }
 
-  typename T::type* backtrack_storage = nullptr;
-  typename T::type* H = AllocateAlignedMemory<A>(
-      &backtrack_storage,
-      9 * T::kNumVar + 4 * T::kNumVar * max_num_predecessors,
-      kRegisterSize / 8);
+  std::vector<typename T::Storage> backtrack_storage(9 * T::kNumVar + 4 * T::kNumVar * max_num_predecessors);
+  typename T::type* H = reinterpret_cast<typename T::type*>(backtrack_storage.data());
   typename T::type* H_pred = H + T::kNumVar;
   typename T::type* H_diag_pred = H_pred + T::kNumVar * max_num_predecessors;
   typename T::type* H_left = H_diag_pred + T::kNumVar * max_num_predecessors;
@@ -2093,8 +2025,6 @@ Alignment SimdAlignmentEngine<A>::Convex(
     }
   } while (true);
 
-  delete[] backtrack_storage;
-
   // update alignment for NW (backtrack stops on first row or column)
   if (type_ == AlignmentType::kNW) {
     while (i == 0 && j != -1) {


=====================================
src/spoa_config.h.in
=====================================
@@ -0,0 +1,12 @@
+// Copyright (c) 2023 Robert Vaser
+
+#ifndef SPOA_CONFIG_H_
+#define SPOA_CONFIG_H_
+
+namespace spoa {
+
+constexpr char SPOA_VERSION[] = "@SPOA_VERSION@";
+
+}  // namespace spoa
+
+#endif  // SPOA_CONFIG_H_


=====================================
src/version.cpp
=====================================
@@ -0,0 +1,13 @@
+// Copyright (c) 2023 Robert Vaser
+
+#include "spoa/version.hpp"
+
+#include "spoa_config.h"
+
+namespace spoa {
+
+std::string Version() {
+    return std::string(SPOA_VERSION);
+}
+
+}  // namespace spoa


=====================================
subprojects/bioparser.wrap
=====================================
@@ -0,0 +1,5 @@
+[wrap-git]
+directory = bioparser
+
+url = https://github.com/rvaser/bioparser
+revision = 3.1.0


=====================================
subprojects/biosoup.wrap
=====================================
@@ -0,0 +1,5 @@
+[wrap-git]
+directory = biosoup
+
+url = https://github.com/rvaser/biosoup
+revision = 0.11.0


=====================================
subprojects/cereal.wrap
=====================================
@@ -0,0 +1,15 @@
+[wrap-file]
+directory = cereal-1.3.0
+
+source_url = https://github.com/USCiLab/cereal/archive/v1.3.0.tar.gz
+source_filename = cereal-1.3.0.tar.gz
+source_hash = 329ea3e3130b026c03a4acc50e168e7daff4e6e661bc6a7dfec0d77b570851d5
+
+patch_url = https://wrapdb.mesonbuild.com/v2/cereal_1.3.0-1/get_patch
+patch_filename = cereal-1.3.0-1-wrap.zip
+patch_hash = 418724e544fb7cf2eab4b0dbd623925f81e79e7b38f098f6dc07bf2c27cb48a6
+
+wrapdb_version = 1.3.0-1
+
+[provide]
+cereal = cereal_dep


=====================================
subprojects/gtest.wrap
=====================================
@@ -0,0 +1,16 @@
+[wrap-file]
+directory = googletest-release-1.10.0
+
+source_url = https://github.com/google/googletest/archive/release-1.10.0.zip
+source_filename = gtest-1.10.0.zip
+source_hash = 94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91
+
+patch_url = https://wrapdb.mesonbuild.com/v2/gtest_1.10.0-1/get_patch
+patch_filename = gtest-1.10.0-1-wrap.zip
+patch_hash = 04ff14e8880e4e465f6260221e9dfd56fea6bc7cce4c4aff0dc528e4a2c8f514
+
+wrapdb_version = 1.10.0-1
+
+[provide]
+gtest = gtest_dep
+gtest_main = gtest_main_dep


=====================================
subprojects/simde.wrap
=====================================
@@ -0,0 +1,9 @@
+[wrap-file]
+directory = simde-0.7.6
+
+source_url = https://github.com/simd-everywhere/simde/archive/refs/tags/v0.7.6.zip
+source_filename = simde-0.7.6.zip
+source_hash = ed05e7d6f94c7c1c4ee6aa60f829c3a943a046f45061a3d291c63bbd4f89e5bb
+
+[provide]
+simde = simde_dep


=====================================
test/meson.build
=====================================
@@ -0,0 +1,31 @@
+spoa_test_config = configuration_data()
+spoa_test_config.set('SPOA_TEST_DATA',  meson.project_source_root() + '/test/data/sample.fastq.gz')
+
+###########
+# Sources #
+###########
+
+spoa_test_config_headers = [
+  configure_file(
+    input : 'spoa_test_config.h.in',
+    output : 'spoa_test_config.h',
+    configuration : spoa_test_config)
+]
+
+spoa_test_sources = files([
+  'spoa_test.cpp',
+]) + spoa_test_config_headers
+
+spoa_test = executable(
+  'spoa_test',
+  spoa_test_sources,
+  dependencies : [spoa_lib_deps, spoa_biosoup_dep, spoa_bioparser_dep, spoa_gtest_dep],
+  include_directories : spoa_include_directories,
+  link_with : spoa_lib,
+  install : false)
+
+#########
+# Tests #
+#########
+
+test('spoa gtest unit tests', spoa_test)


=====================================
test/spoa_test.cpp
=====================================
@@ -11,6 +11,8 @@
 
 #include "spoa/spoa.hpp"
 
+#include "spoa_test_config.h"
+
 std::atomic<std::uint32_t> biosoup::Sequence::num_objects{0};
 
 namespace spoa {
@@ -18,7 +20,7 @@ namespace test {
 
 class SpoaTest: public ::testing::Test {
  public:
-  void Setup(
+  void Initialize(
       AlignmentType type,
       std::int8_t m,
       std::int8_t n,
@@ -27,7 +29,7 @@ class SpoaTest: public ::testing::Test {
       std::int8_t q,
       std::int8_t c,
       bool quality) {
-    auto p = bioparser::Parser<biosoup::Sequence>::Create<bioparser::FastqParser>(TEST_DATA);  // NOLINT
+    auto p = bioparser::Parser<biosoup::Sequence>::Create<bioparser::FastqParser>(SPOA_TEST_DATA);  // NOLINT
     s = p->Parse(-1);
     EXPECT_EQ(55, s.size());
 
@@ -109,17 +111,10 @@ TEST(SpoaAlignmentTest, LargeInput) {
         std::string(exception.what()).substr(11),
         "AlignmentEngine::Prealloc] error: too large sequence!");
   }
-  try {
-    ae->Prealloc((1ULL << 31) - 1, -1);
-  } catch (std::invalid_argument& exception) {
-    EXPECT_EQ(
-        std::string(exception.what()).substr(11),
-        "AlignmentEngine::Prealloc] error: insufficient memory!");
-  }
 }
 
 TEST_F(SpoaTest, Clear) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -8, -8, -8, false);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -8, -8, -8, false);
   Align();
   auto c = gr.GenerateConsensus();
 
@@ -130,7 +125,7 @@ TEST_F(SpoaTest, Clear) {
 
 #ifdef SPOA_USE_CEREAL
 TEST_F(SpoaTest, Archive) {
-  Setup(AlignmentType::kNW, 2, -5, -2, -2, -2, -2, true);
+  Initialize(AlignmentType::kNW, 2, -5, -2, -2, -2, -2, true);
 
   {
     std::ofstream os("spoa.test.cereal");
@@ -152,7 +147,7 @@ TEST_F(SpoaTest, Archive) {
 #endif
 
 TEST_F(SpoaTest, Local) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -8, -8, -8, false);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -8, -8, -8, false);
   Align();
 
   std::string c =
@@ -168,7 +163,7 @@ TEST_F(SpoaTest, Local) {
 }
 
 TEST_F(SpoaTest, LocalAffine) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -6, -8, -6, false);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -6, -8, -6, false);
   Align();
 
   std::string c =
@@ -184,7 +179,7 @@ TEST_F(SpoaTest, LocalAffine) {
 }
 
 TEST_F(SpoaTest, LocalConvex) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -6, -10, -2, false);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -6, -10, -2, false);
   Align();
 
   std::string c =
@@ -200,7 +195,7 @@ TEST_F(SpoaTest, LocalConvex) {
 }
 
 TEST_F(SpoaTest, LocalWithQualities) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -8, -8, -8, true);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -8, -8, -8, true);
   Align();
 
   std::string c =
@@ -216,7 +211,7 @@ TEST_F(SpoaTest, LocalWithQualities) {
 }
 
 TEST_F(SpoaTest, LocalAffineWithQualities) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -6, -8, -6, true);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -6, -8, -6, true);
   Align();
 
   std::string c =
@@ -232,7 +227,7 @@ TEST_F(SpoaTest, LocalAffineWithQualities) {
 }
 
 TEST_F(SpoaTest, LocalConvexWithQualities) {
-  Setup(AlignmentType::kSW, 5, -4, -8, -6, -10, -2, true);
+  Initialize(AlignmentType::kSW, 5, -4, -8, -6, -10, -2, true);
   Align();
 
   std::string c =
@@ -248,7 +243,7 @@ TEST_F(SpoaTest, LocalConvexWithQualities) {
 }
 
 TEST_F(SpoaTest, Global) {
-  Setup(AlignmentType::kNW, 5, -4, -8, -8, -8, -8, false);
+  Initialize(AlignmentType::kNW, 5, -4, -8, -8, -8, -8, false);
   Align();
 
   std::string c =
@@ -264,7 +259,7 @@ TEST_F(SpoaTest, Global) {
 }
 
 TEST_F(SpoaTest, GlobalAffine) {
-  Setup(AlignmentType::kNW, 5, -4, -8, -6, -8, -6, false);
+  Initialize(AlignmentType::kNW, 5, -4, -8, -6, -8, -6, false);
   Align();
 
   std::string c =
@@ -280,7 +275,7 @@ TEST_F(SpoaTest, GlobalAffine) {
 }
 
 TEST_F(SpoaTest, GlobalConvex) {
-  Setup(AlignmentType::kNW, 5, -4, -8, -6, -10, -2, false);
+  Initialize(AlignmentType::kNW, 5, -4, -8, -6, -10, -2, false);
   Align();
 
   std::string c =
@@ -296,7 +291,7 @@ TEST_F(SpoaTest, GlobalConvex) {
 }
 
 TEST_F(SpoaTest, GlobalWithQualities) {
-  Setup(AlignmentType::kNW, 5, -4, -8, -8, -8, -8, true);
+  Initialize(AlignmentType::kNW, 5, -4, -8, -8, -8, -8, true);
   Align();
 
   std::string c =
@@ -312,7 +307,7 @@ TEST_F(SpoaTest, GlobalWithQualities) {
 }
 
 TEST_F(SpoaTest, GlobalAffineWithQualities) {
-  Setup(AlignmentType::kNW, 5, -4, -8, -6, -8, -6, true);
+  Initialize(AlignmentType::kNW, 5, -4, -8, -6, -8, -6, true);
   Align();
 
   std::string c =
@@ -328,7 +323,7 @@ TEST_F(SpoaTest, GlobalAffineWithQualities) {
 }
 
 TEST_F(SpoaTest, GlobalConvexWithQualities) {
-  Setup(AlignmentType::kNW, 5, -4, -8, -6, -10, -2, true);
+  Initialize(AlignmentType::kNW, 5, -4, -8, -6, -10, -2, true);
   Align();
 
   std::string c =
@@ -344,7 +339,7 @@ TEST_F(SpoaTest, GlobalConvexWithQualities) {
 }
 
 TEST_F(SpoaTest, SemiGlobal) {
-  Setup(AlignmentType::kOV, 5, -4, -8, -8, -8, -8, false);
+  Initialize(AlignmentType::kOV, 5, -4, -8, -8, -8, -8, false);
   Align();
 
   std::string c =
@@ -360,7 +355,7 @@ TEST_F(SpoaTest, SemiGlobal) {
 }
 
 TEST_F(SpoaTest, SemiGlobalAffine) {
-  Setup(AlignmentType::kOV, 5, -4, -8, -6, -8, -6, false);
+  Initialize(AlignmentType::kOV, 5, -4, -8, -6, -8, -6, false);
   Align();
 
   std::string c =
@@ -376,7 +371,7 @@ TEST_F(SpoaTest, SemiGlobalAffine) {
 }
 
 TEST_F(SpoaTest, SemiGlobalConvex) {
-  Setup(AlignmentType::kOV, 5, -4, -8, -6, -10, -2, false);
+  Initialize(AlignmentType::kOV, 5, -4, -8, -6, -10, -2, false);
   Align();
 
   std::string c =
@@ -392,7 +387,7 @@ TEST_F(SpoaTest, SemiGlobalConvex) {
 }
 
 TEST_F(SpoaTest, SemiGlobalWithQualities) {
-  Setup(AlignmentType::kOV, 5, -4, -8, -8, -8, -8, true);
+  Initialize(AlignmentType::kOV, 5, -4, -8, -8, -8, -8, true);
   Align();
 
   std::string c =
@@ -408,7 +403,7 @@ TEST_F(SpoaTest, SemiGlobalWithQualities) {
 }
 
 TEST_F(SpoaTest, SemiGlobalAffineWithQualities) {
-  Setup(AlignmentType::kOV, 5, -4, -8, -6, -8, -6, true);
+  Initialize(AlignmentType::kOV, 5, -4, -8, -6, -8, -6, true);
   Align();
 
   std::string c =
@@ -424,7 +419,7 @@ TEST_F(SpoaTest, SemiGlobalAffineWithQualities) {
 }
 
 TEST_F(SpoaTest, SemiGlobalConvexWithQualities) {
-  Setup(AlignmentType::kOV, 5, -4, -8, -6, -10, -2, true);
+  Initialize(AlignmentType::kOV, 5, -4, -8, -6, -10, -2, true);
   Align();
 
   std::string c =


=====================================
test/spoa_test_config.h.in
=====================================
@@ -0,0 +1,14 @@
+// Copyright (c) 2023 Robert Vaser
+
+#ifndef SPOA_TEST_CONFIG_H_
+#define SPOA_TEST_CONFIG_H_
+
+namespace spoa {
+namespace test {
+
+constexpr char SPOA_TEST_DATA[] = "@SPOA_TEST_DATA@";
+
+}  // namespace test
+}  // namespace spoa
+
+#endif  // SPOA_TEST_CONFIG_H_



View it on GitLab: https://salsa.debian.org/med-team/spoa/-/commit/ccf4f10523a198e6f5a341e4050d59b45d6738d7

-- 
View it on GitLab: https://salsa.debian.org/med-team/spoa/-/commit/ccf4f10523a198e6f5a341e4050d59b45d6738d7
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20240321/34c219de/attachment-0001.htm>


More information about the debian-med-commit mailing list