[med-svn] [diamond] 01/03: New upstream version 0.8.31

Andreas Tille tille at debian.org
Thu Jan 5 10:24:14 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository diamond.

commit d6d7781eebf0404747f22541f7c56552b4b81b9c
Author: Andreas Tille <tille at debian.org>
Date:   Thu Jan 5 10:58:11 2017 +0100

    New upstream version 0.8.31
---
 .gitattributes                       |   17 +
 .gitignore                           |   54 +
 CMakeLists.txt                       |   85 ++
 README.rst                           |   37 +
 build_simple.sh                      |   49 +
 diamond_manual.pdf                   |  Bin 0 -> 92606 bytes
 src/COPYING                          |   12 +
 src/ChangeLog                        |  204 +++
 src/align/align.cpp                  |  170 +++
 src/align/align.h                    |   64 +
 src/align/align_queries.h            |   67 +
 src/align/align_struct.h             |   49 +
 src/align/align_target.cpp           |  158 +++
 src/align/extend_ungapped.h          |   43 +
 src/align/match_func.h               |   40 +
 src/align/query_mapper.cpp           |  222 ++++
 src/align/query_mapper.h             |  117 ++
 src/basic/basic.cpp                  |  270 ++++
 src/basic/config.cpp                 |  348 +++++
 src/basic/config.h                   |  195 +++
 src/basic/const.h                    |   46 +
 src/basic/hssp.cpp                   |  130 ++
 src/basic/match.h                    |  368 ++++++
 src/basic/packed_loc.h               |   54 +
 src/basic/packed_sequence.h          |  110 ++
 src/basic/packed_transcript.h        |  171 +++
 src/basic/reduction.h                |  105 ++
 src/basic/score_matrix.cpp           |  274 ++++
 src/basic/score_matrix.h             |  136 ++
 src/basic/seed.h                     |  100 ++
 src/basic/seed_iterator.h            |   38 +
 src/basic/sequence.h                 |  142 +++
 src/basic/shape.h                    |  148 +++
 src/basic/shape_config.h             |   80 ++
 src/basic/statistics.h               |   93 ++
 src/basic/translate.h                |  153 +++
 src/basic/value.h                    |  109 ++
 src/blast/blast_def.h                |  340 +++++
 src/blast/blast_encoding.h           |  113 ++
 src/blast/blast_filter.cpp           |  359 ++++++
 src/blast/blast_filter.h             |  171 +++
 src/blast/blast_message.h            |  174 +++
 src/blast/blast_program.h            |  175 +++
 src/blast/blast_query_info.h         |  212 ++++
 src/blast/blast_seg.cpp              | 2314 ++++++++++++++++++++++++++++++++++
 src/blast/blast_seg.h                |   77 ++
 src/blast/blast_stat.h               |  861 +++++++++++++
 src/blast/ncbi_math.h                |  146 +++
 src/blast/ncbi_std.h                 |  270 ++++
 src/blast/ncbitype.h                 |  174 +++
 src/blast/raw_scoremat.h             |  121 ++
 src/blast/sm_blosum45.c              |   97 ++
 src/blast/sm_blosum50.c              |   97 ++
 src/blast/sm_blosum62.c              |   96 ++
 src/blast/sm_blosum80.c              |   97 ++
 src/blast/sm_blosum90.c              |   96 ++
 src/blast/sm_pam250.c                |   96 ++
 src/blast/sm_pam30.c                 |   96 ++
 src/blast/sm_pam70.c                 |   96 ++
 src/data/count_approximate.cpp       |  110 ++
 src/data/frequent_seeds.cpp          |  109 ++
 src/data/frequent_seeds.h            |   53 +
 src/data/index.cpp                   |   86 ++
 src/data/index.h                     |   75 ++
 src/data/load_seqs.h                 |   90 ++
 src/data/queries.cpp                 |   42 +
 src/data/queries.h                   |   63 +
 src/data/reference.cpp               |  186 +++
 src/data/reference.h                 |  202 +++
 src/data/seed_histogram.cpp          |   21 +
 src/data/seed_histogram.h            |  168 +++
 src/data/sequence_set.h              |  244 ++++
 src/data/sorted_list.h               |  310 +++++
 src/data/string_set.h                |  133 ++
 src/dp/comp_based_stats.cpp          |  116 ++
 src/dp/dp.h                          |  144 +++
 src/dp/dp_matrix.h                   |  149 +++
 src/dp/floating_sw.cpp               |  130 ++
 src/dp/floating_sw.h                 |   43 +
 src/dp/greedy_align.cpp              |  589 +++++++++
 src/dp/growing_buffer.h              |   71 ++
 src/dp/needleman_wunsch.cpp          |  192 +++
 src/dp/padded_banded_sw.cpp          |  147 +++
 src/dp/scalar_dp_matrix.h            |  140 ++
 src/dp/scalar_traceback.h            |  194 +++
 src/dp/score_profile.h               |  160 +++
 src/dp/score_vector.h                |  213 ++++
 src/dp/smith_waterman.cpp            |  157 +++
 src/dp/smith_waterman.h              |  126 ++
 src/dp/traceback.h                   |   89 ++
 src/dp/ungapped_align.cpp            |  130 ++
 src/extra/blast_record.h             |   33 +
 src/extra/compare.h                  |  188 +++
 src/extra/match_file.h               |  337 +++++
 src/extra/model_sim.cpp              |  358 ++++++
 src/extra/roc.cpp                    |  142 +++
 src/output/blast_pairwise_format.cpp |   84 ++
 src/output/blast_tab_format.cpp      |  279 ++++
 src/output/daa_file.h                |  216 ++++
 src/output/daa_record.cpp            |   87 ++
 src/output/daa_record.h              |  147 +++
 src/output/daa_write.h               |  115 ++
 src/output/join_blocks.cpp           |  250 ++++
 src/output/output.h                  |  124 ++
 src/output/output_file.h             |   64 +
 src/output/output_format.cpp         |  169 +++
 src/output/output_format.h           |  146 +++
 src/output/sam_format.cpp            |  130 ++
 src/output/view.h                    |  149 +++
 src/run/benchmark.cpp                |  320 +++++
 src/run/double_indexed.cpp           |  305 +++++
 src/run/main.cpp                     |  108 ++
 src/run/mapper.cpp                   |  112 ++
 src/run/tools.cpp                    |  107 ++
 src/run/tools.h                      |   31 +
 src/search/align_range.h             |  126 ++
 src/search/collision.cpp             |  116 ++
 src/search/collision.h               |   31 +
 src/search/hit_filter.h              |  105 ++
 src/search/search.cpp                |  148 +++
 src/search/search_query.cpp          |   51 +
 src/search/setup.cpp                 |   66 +
 src/search/sse_dist.h                |  228 ++++
 src/search/stage2.cpp                |  126 ++
 src/search/trace_pt_buffer.h         |  190 +++
 src/util/Timer.cpp                   |  130 ++
 src/util/Timer.h                     |   63 +
 src/util/async_buffer.h              |  134 ++
 src/util/binary_buffer.h             |   89 ++
 src/util/binary_file.h               |  446 +++++++
 src/util/command_line_parser.cpp     |  122 ++
 src/util/command_line_parser.h       |  173 +++
 src/util/complexity_filter.h         |   89 ++
 src/util/compressed_stream.cpp       |  152 +++
 src/util/compressed_stream.h         |   68 +
 src/util/direction.h                 |   45 +
 src/util/double_buffer.h             |   55 +
 src/util/fast_mutex.h                |  250 ++++
 src/util/hash_function.h             |   36 +
 src/util/hash_table.h                |  277 ++++
 src/util/log_stream.h                |  114 ++
 src/util/map.h                       |   66 +
 src/util/merge_sort.h                |   50 +
 src/util/ptr_vector.h                |   64 +
 src/util/radix_sort.h                |   75 ++
 src/util/seq_file_format.cpp         |  114 ++
 src/util/seq_file_format.h           |   76 ++
 src/util/simd.h                      |   62 +
 src/util/system.h                    |   53 +
 src/util/system_c.h                  |   10 +
 src/util/task_queue.h                |  152 +++
 src/util/temp_file.h                 |   38 +
 src/util/text_buffer.h               |  216 ++++
 src/util/thread.h                    |  287 +++++
 src/util/tinythread.cpp              |  319 +++++
 src/util/tinythread.h                |  716 +++++++++++
 src/util/util.cpp                    |  101 ++
 src/util/util.h                      |  542 ++++++++
 158 files changed, 25790 insertions(+)

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..bdb0cab
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,17 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Custom for Visual Studio
+*.cs     diff=csharp
+
+# Standard to msysgit
+*.doc	 diff=astextplain
+*.DOC	 diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot  diff=astextplain
+*.DOT  diff=astextplain
+*.pdf  diff=astextplain
+*.PDF	 diff=astextplain
+*.rtf	 diff=astextplain
+*.RTF	 diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bf245ec
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,54 @@
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# =========================
+# Operating System Files
+# =========================
+
+# OSX
+# =========================
+
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# CMake files
+CMakeCache.txt
+CMakeFiles
+cmake_install.cmake
+install_manifest.txt
+
+build/
+.idea
+Makefile
+diamond
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..c667855
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,85 @@
+cmake_minimum_required (VERSION 2.6)
+project (DIAMOND)
+
+option(BUILD_STATIC "BUILD_STATIC" OFF)
+
+if(BUILD_STATIC)
+    set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
+    set(BUILD_SHARED_LIBRARIES OFF)
+    set(CMAKE_EXE_LINKER_FLAGS "-static")
+endif()
+
+include(CheckCXXCompilerFlag)
+CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCHNATIVE)
+if(COMPILER_SUPPORTS_MARCHNATIVE)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
+endif()
+
+find_package(ZLIB REQUIRED)
+find_package(Threads REQUIRED)
+
+set(CMAKE_BUILD_TYPE Release)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-uninitialized -Wno-deprecated-declarations -Wno-ignored-attributes -Wno-unused-variable")
+
+include_directories(
+  "${CMAKE_SOURCE_DIR}/src"
+  "${ZLIB_INCLUDE_DIR}")
+
+add_executable(diamond src/run/main.cpp
+  src/basic/config.cpp
+  src/util/tinythread.cpp
+  src/util/compressed_stream.cpp
+  src/basic/score_matrix.cpp
+  src/blast/blast_filter.cpp
+  src/blast/blast_seg.cpp
+  src/blast/sm_blosum45.c
+  src/blast/sm_blosum50.c
+  src/blast/sm_blosum62.c
+  src/blast/sm_blosum80.c
+  src/blast/sm_blosum90.c
+  src/blast/sm_pam30.c
+  src/blast/sm_pam70.c
+  src/blast/sm_pam250.c
+  src/data/queries.cpp
+  src/data/reference.cpp
+  src/data/seed_histogram.cpp
+  src/output/daa_record.cpp
+  src/search/search.cpp
+  src/util/command_line_parser.cpp
+  src/util/seq_file_format.cpp
+  src/util/util.cpp 
+  src/util/Timer.cpp
+  src/basic/basic.cpp
+  src/dp/floating_sw.cpp
+  src/basic/hssp.cpp
+  src/dp/ungapped_align.cpp
+  src/run/tools.cpp
+  src/dp/greedy_align.cpp
+  src/run/benchmark.cpp
+  src/search/stage2.cpp
+  src/output/output_format.cpp
+  src/output/join_blocks.cpp
+  src/run/mapper.cpp
+  src/data/count_approximate.cpp
+  src/data/index.cpp
+  src/data/frequent_seeds.cpp
+  src/align/query_mapper.cpp
+  src/align/align_target.cpp
+  src/output/blast_tab_format.cpp
+  src/dp/padded_banded_sw.cpp
+  src/dp/needleman_wunsch.cpp
+  src/output/blast_pairwise_format.cpp
+  src/extra/roc.cpp
+  src/dp/comp_based_stats.cpp
+  src/extra/model_sim.cpp
+  src/run/double_indexed.cpp
+  src/search/search_query.cpp
+  src/search/collision.cpp
+  src/output/sam_format.cpp
+  src/align/align.cpp
+  src/search/setup.cpp
+)
+
+target_link_libraries(diamond ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
+
+install(TARGETS diamond DESTINATION bin)
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..11565a1
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,37 @@
+Introduction
+============
+DIAMOND is a sequence aligner for protein and translated DNA searches and functions as a drop-in replacement for the NCBI BLAST software tools. It is suitable for protein-protein search as well as DNA-protein search on short reads and longer sequences including contigs and assemblies, providing a speedup of BLAST ranging up to x20,000.
+
+Quick start guide
+=================
+Please read the `manual <https://github.com/bbuchfink/diamond/raw/master/diamond_manual.pdf>`_ for detailed installation and usage instructions. This demonstrates a quick example for setting up and using the program on Linux.
+
+Installing the software on your system may be done by downloading it in binary format for immediate use::
+
+    wget http://github.com/bbuchfink/diamond/releases/download/v0.8.31/diamond-linux64.tar.gz
+    tar xzf diamond-linux64.tar.gz
+
+The extracted ``diamond`` binary file should be moved to a directory contained in your executable search path (PATH environment variable).
+
+To now run an alignment task, we assume to have a protein database file in FASTA format named ``nr.faa`` and a file of DNA reads that we want to align named ``reads.fna``.
+
+In order to set up a reference database for DIAMOND, the ``makedb`` command needs to be executed with the following command line::
+
+    $ diamond makedb --in nr.faa -d nr
+
+This will create a binary DIAMOND database file with the specified name (``nr.dmnd``). The alignment task may then be initiated using the ``blastx`` command like this::
+
+    $ diamond blastx -d nr -q reads.fna -o matches.m8
+
+The output file here is specified with the ``–o`` option and named ``matches.m8``. By default, it is generated in BLAST tabular format.
+
+*Note*:
+  - The program may use quite a lot of memory and also temporary disk space. Should the program fail due to running out of either one, you need to set a lower value for the block size parameter ``-b`` (see the `manual <https://github.com/bbuchfink/diamond/raw/master/diamond_manual.pdf>`_).
+  - The default (fast) mode was mainly designed for short reads. For longer sequences, the sensitive modes (options ``--sensitive`` or ``--more-sensitive``) are recommended.
+  - The full speed of the program is only attained on large query datasets. It is currently not efficient in mapping a smaller number of query sequences.
+  - The default e-value cutoff of DIAMOND is 0.001 while that of BLAST is 10, so by default the program will search a lot more stringently than BLAST and not report weak hits.  
+About
+=====
+DIAMOND is developed by Benjamin Buchfink. Feel free to contact me for support (`Email <mailto:buchfink at gmail.com>`_ `Twitter <http://twitter.com/bbuchfink>`_).
+
+If you use DIAMOND in published research, please cite B. Buchfink, Xie C., D. Huson, "Fast and sensitive protein alignment using DIAMOND", Nature Methods 12, 59-60 (2015).
diff --git a/build_simple.sh b/build_simple.sh
new file mode 100755
index 0000000..c20e281
--- /dev/null
+++ b/build_simple.sh
@@ -0,0 +1,49 @@
+gcc -c -O3 -DNDEBUG src/blast/sm_blosum45.c src/blast/sm_blosum50.c src/blast/sm_blosum62.c src/blast/sm_blosum80.c src/blast/sm_blosum90.c src/blast/sm_pam30.c src/blast/sm_pam70.c src/blast/sm_pam250.c
+g++ -DNDEBUG -O3 -mssse3 -Wno-deprecated-declarations -std=gnu++98 $1 \
+  sm*.o \
+  src/run/main.cpp \
+  src/basic/config.cpp \
+  src/util/tinythread.cpp \
+  src/util/compressed_stream.cpp \
+  src/basic/score_matrix.cpp \
+  src/blast/blast_filter.cpp \
+  src/blast/blast_seg.cpp \
+  src/data/queries.cpp \
+  src/data/reference.cpp \
+  src/data/seed_histogram.cpp \
+  src/output/daa_record.cpp \
+  src/search/search.cpp \
+  src/util/command_line_parser.cpp \
+  src/util/seq_file_format.cpp \
+  src/util/util.cpp  \
+  src/util/Timer.cpp \
+  src/basic/basic.cpp \
+  src/dp/floating_sw.cpp \
+  src/basic/hssp.cpp \
+  src/dp/ungapped_align.cpp \
+  src/run/tools.cpp \
+  src/dp/greedy_align.cpp \
+  src/run/benchmark.cpp \
+  src/search/stage2.cpp \
+  src/output/output_format.cpp \
+  src/output/join_blocks.cpp \
+  src/run/mapper.cpp \
+  src/data/count_approximate.cpp \
+  src/data/index.cpp \
+  src/data/frequent_seeds.cpp \
+  src/align/query_mapper.cpp \
+  src/align/align_target.cpp \
+  src/output/blast_tab_format.cpp \
+  src/dp/padded_banded_sw.cpp \
+  src/dp/needleman_wunsch.cpp \
+  src/output/blast_pairwise_format.cpp \
+  src/extra/roc.cpp \
+  src/dp/comp_based_stats.cpp \
+  src/extra/model_sim.cpp \
+  src/run/double_indexed.cpp \
+  src/search/search_query.cpp \
+  src/search/collision.cpp \
+  src/output/sam_format.cpp \
+  src/align/align.cpp \
+  src/search/setup.cpp \
+-lz -lpthread -o diamond
diff --git a/diamond_manual.pdf b/diamond_manual.pdf
new file mode 100644
index 0000000..c1d0538
Binary files /dev/null and b/diamond_manual.pdf differ
diff --git a/src/COPYING b/src/COPYING
new file mode 100644
index 0000000..abdac22
--- /dev/null
+++ b/src/COPYING
@@ -0,0 +1,12 @@
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROF [...]
diff --git a/src/ChangeLog b/src/ChangeLog
new file mode 100644
index 0000000..fa5261c
--- /dev/null
+++ b/src/ChangeLog
@@ -0,0 +1,204 @@
+[0.8.31]
+- renamed option --run-len to --min-orf
+- added compositional score adjustments (option --comp-based-stats (0,1), enabled by default)
+- removed --single-domain option and replaced by --max-hsps
+- added option --no-self-hits
+
+[0.8.30]
+- slightly improved sensitivity
+- added option to report unaligned queries (--unal)
+- pairwise, XML and SAM format will report unaligned queries by default
+- added option to filter alignments by subject cover (--subject-cover)
+
+[0.8.29]
+- fixed an issue that could cause a crash when using view on incomplete DAA files
+
+[0.8.28]
+- slightly improved sensitivity
+- added support for the BLAST pairwise format (option -f 0)
+
+[0.8.27]
+- added support for gzip compressed files containing multiple gzip streams
+
+[0.8.26]
+- fixed a compiler error
+- now compiles as generic C++ code without SSE being available
+- added option to write unaligned queries to file (--un)
+
+[0.8.25]
+- fixed a bug with the qseq field in the blast tabular format
+- added qtitle and btop fields to the blast tabular format
+- fixed a bug that could cause a crash when passing a nonexistant input file
+- fixed an issue that could cause unexpectedly long runtimes in certain cases
+
+[0.8.24]
+- error messages when reading sequence files include line numbers
+
+[0.8.23]
+- added option to change the genetic code used for translation in blastx mode
+
+[0.8.22]
+- the Hit_id and Hit_accession fields are now filled for the BLAST XML format
+
+[0.8.21]
+- fixed an error of 'diamond view' when using a custom scoring matrix
+
+[0.8.20]
+- added support for customizing the BLAST tabular output format
+
+[0.8.19]
+- ungapped xdrop score and ungapped and gapped filter scores are now set in bits
+- added support for custom scoring matrices
+
+[0.8.18]
+- fixed a crash bug
+- implemented getseq command to retrieve sequences from database files
+
+[0.8.17]
+- slightly improved sensitivity of fast and sensitive mode
+- added new alignment mode (option --more-sensitive)
+- the scoring matrix parameter will accept upper case spelling
+
+[0.8.16]
+- optimized performance
+
+[0.8.15]
+- fixed a compiler error on Mac
+- fixed a crash on some systems
+
+[0.8.14]
+- fixed a memory leak
+
+[0.8.13]
+- fixed a compiler error for GCC 4.1 and 4.2
+
+[0.8.12]
+- changed database format
+- block size parameter is set only for the alignment commands
+- the program will accept databases created by later versions if the format is compatible
+- improved sensitivity of sensitive mode with some loss in performance
+
+[0.8.11]
+- fixed a compiler error
+
+[0.8.10]
+- added option to directly generate all output formats
+- fixed some GCC 6.1 compiler errors
+
+[0.8.9]
+- optimized performance
+- improved local alignment accuracy
+- fixed some fields in the XML format
+
+[0.8.8]
+- fixed a clang compiler error
+
+[0.8.7]
+- added support for BLAST XML format
+- fixed the gzip compressed output option
+
+[0.8.6]
+- fixed a problem of the Windows version that could cause errors for larger files
+- optimized performance
+
+[0.8.5]
+- optimized performance
+
+[0.8.4]
+- fixed a problem that could cause very long runtimes for highly repetitive sequences
+- optimized performance
+- fixed a bug that could cause too high memory usage in blastp mode
+
+[0.8.3]
+- fixed a problem that could sometimes cause alignments to be missed
+- suppressed reporting of alignments that are enveloped by better alignments
+
+[0.8.2]
+- use parameter -k0 to report unlimited number of alignments
+- fixed a crash bug on Mac OS X
+- fixed a crash when view was used with terminal output
+
+[0.8.1]
+- added option to disable auto appending of DAA and DMND file extensions (--no-auto-append)
+- fixed some compiler errors for GCC 4.6
+
+[0.8.0]
+- fixed a bug that would sometimes cause alignments to be missed
+- fixed a bug that would cause alignments on the reverse strand to be missed in blastx mode
+- temporary directory now defaults to output directory
+- removed dependency on Boost
+- fixed a bug that would cause stop codons to be translated into 'X'
+
+[0.7.12]
+- fixed header string in SAM output to correctly identify the blastp alignment mode
+- added option to filter alignments for a given query cover (option --query-cover)
+- added option to print full subject titles in output files (option --salltitles)
+
+[0.7.11]
+- added --version switch
+- added static build optiom for CMake build
+- fixed a bug that would cause a return code of 1 without an error
+
+[0.7.10]
+- --log option works on OS X
+- added option to set effective database size (--dbsize)
+- added CMake build option
+- fixed a Clang compiler warning
+- dash characters (-) are ignored (treated as X) in protein sequences
+
+[0.7.9]
+- added --single-domain option
+- fixed a bug that could cause the program not to use all available threads
+- optimized performance
+
+[0.7.8]
+- fixed a bug that could produce an incorrect sort order of HSPs
+
+[0.7.7]
+- fixed a number formatting error in the SAM output format
+
+[0.7.6]
+- fixed a formatting error in CIGAR strings
+
+[0.7.5]
+- fixed a compiler error for Clang
+- compiles on OS X
+- fixed a bug that would not produce the correct sort order for HSPs with e-value 0
+- option --run-len defaults to 1 for sequences shorter than 30 letters
+
+[0.7.4]
+- removed OpenMP dependency
+- using explicit Makefile instead of autoconf
+- file extensions can be named explicitly for DAA and database files
+- HSPs are grouped by target sequence
+- fixed a bug that could produce incorrect output for view
+- fixed a bug that could report an incorrect number of alignments
+- fixed a compiler error for GCC 4.1.2
+
+[0.7.3]
+- changed database format (makedb required)
+- optimized multithreading load balancing
+- removed a non-determinism in alignment computation
+- IUPAC nucleotide ambiguity codes in DNA sequences are accepted and converted into N's
+- SEG masking is disabled by default for blastp mode
+- fixed a memory leak
+- reduced database file sizes
+
+[0.7.2]
+- fixed a bug that could create invalid DAA files when using the --id option
+- added integrity check of DAA files to view command
+- fixed a bug that could cause segmentation fault or file seek errors
+
+[0.7.1]
+- fixed a race condition for opening temporary files
+- temporary files are deleted on ungraceful termination of the program
+- blank lines in FASTA files are tolerated
+- fixed a compiler error for GCC 4.4.7
+- view command can write to standard output
+
+[0.7.0]
+- introduced DAA format
+- reduced usage of temporary disk space and memory
+- fixed a compiler error for GCC 4.1.2
+- fixed a bug that could cause the program to hang when running out of temporary space or memory
+- added --forwardonly option to view command
diff --git a/src/align/align.cpp b/src/align/align.cpp
new file mode 100644
index 0000000..9be8d2b
--- /dev/null
+++ b/src/align/align.cpp
@@ -0,0 +1,170 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "align_queries.h"
+#include "../data/reference.h"
+#include "../output/output_format.h"
+
+Query_queue query_queue;
+
+void Query_queue::init(Trace_pt_list::iterator begin, Trace_pt_list::iterator end)
+{
+	trace_pt_pos = begin;
+	trace_pt_end = end;
+	assert(queue.empty());
+	assert(out_queue.empty());
+	n = 0;
+}
+	
+void Query_queue::flush(Output_stream *out, Statistics &stat)
+{
+	writing = true;
+	std::queue<Query_data*> q;
+	while (true) {
+		while (!out_queue.empty() && out_queue.front()->state == Query_data::finished) {
+			q.push(out_queue.front());
+			out_queue.pop();
+		}
+		if (q.empty()) {
+			writing = false;
+			lock.unlock();
+			return;
+		}
+		lock.unlock();
+
+		unsigned k = 0;
+		while (!q.empty()) {
+			out->write(q.front()->buf.get_begin(), q.front()->buf.size());
+			delete q.front();
+			q.pop();
+			++k;
+		}
+
+		lock.lock();
+		n -= k;
+		/*if (n > 100)
+		cout << "qlen=" << out_queue.size() << " finished=" << n << endl;*/
+	}
+}
+
+Query_data* Query_queue::get()
+{
+	for (std::deque<Query_data*>::iterator i = queue.begin(); i != queue.end(); ++i)
+		if ((*i)->state == Query_data::free)
+			return *i;
+	return 0;
+}
+
+void Query_queue::pop_busy()
+{
+	while (!queue.empty() && (queue.front()->state == Query_data::closing || queue.front()->state == Query_data::finished)) {
+		out_queue.push(queue.front());
+		queue.pop_front();
+	}
+}
+
+void align_worker(Output_stream *out)
+{
+	Statistics stat;
+	Query_data *data = 0;
+	unsigned n_targets = 0;
+
+	while (true) {
+
+		query_queue.lock.lock();
+
+		if (data) {
+			data->mapper->targets_finished += n_targets;
+			if (data->mapper->finished()) {
+				query_queue.lock.unlock();
+				const bool aligned = data->mapper->generate_output(data->buf, stat);
+				const unsigned query_id = data->mapper->query_id;
+				delete data->mapper;
+				query_queue.lock.lock();
+				data->state = Query_data::finished;
+				if (aligned && !config.unaligned.empty())
+					query_aligned[query_id] = true;
+				++query_queue.n;
+				if (!query_queue.writing && !query_queue.out_queue.empty() && data == query_queue.out_queue.front()) {
+					query_queue.flush(out, stat);
+					data = 0;
+					continue;
+				}
+			}
+		}
+
+		if (!(data = query_queue.get())) {
+			if (query_queue.trace_pt_pos >= query_queue.trace_pt_end) {
+				query_queue.lock.unlock();
+				break;
+			}
+			else {
+				query_queue.queue.push_back(new Query_data(new Query_mapper()));
+				data = query_queue.queue.back();
+				query_queue.lock.unlock();
+				data->mapper->init();
+				data->state = Query_data::free;
+				data = 0;
+			}
+		}
+		else {
+			size_t target = data->mapper->next_target;
+			n_targets = std::min(config.target_fetch_size, (unsigned)data->mapper->n_targets() - data->mapper->next_target);
+			data->mapper->next_target += n_targets;
+			if (target + n_targets == data->mapper->n_targets()) {
+				data->state = Query_data::closing;
+				query_queue.pop_busy();
+			}
+			query_queue.lock.unlock();
+
+			for (unsigned i = 0; i < n_targets; ++i)
+				data->mapper->align_target(target + i, stat);
+		}
+
+	}
+
+	statistics += stat;
+}
+
+void align_queries(const Trace_pt_buffer &trace_pts, Output_stream* output_file)
+{
+	Trace_pt_list v;
+	query_queue.last_query = (unsigned)-1;
+	for (unsigned bin = 0; bin < trace_pts.bins(); ++bin) {
+		log_stream << "Processing query bin " << bin + 1 << '/' << trace_pts.bins() << '\n';
+		task_timer timer("Loading trace points", 3);
+		statistics.max(Statistics::TEMP_SPACE, trace_pts.load(v, bin));
+		timer.go("Sorting trace points");
+		merge_sort(v.begin(), v.end(), config.threads_);
+		v.init();
+		timer.go("Computing alignments");
+		query_queue.init(v.begin(), v.end());
+		Thread_pool threads;
+		for (unsigned i = 0; i < config.threads_; ++i)
+			threads.push_back(launch_thread(align_worker, output_file));
+		threads.join_all();
+	}
+	if (!blocked_processing && *output_format != Output_format::daa && config.report_unaligned != 0) {
+		Text_buffer buf;
+		for (unsigned i = query_queue.last_query + 1; i < query_ids::get().get_length(); ++i) {
+			output_format->print_query_intro(i, query_ids::get()[i].c_str(), get_source_query_len(i), buf, true);
+			output_format->print_query_epilog(buf, true);
+		}
+		output_file->write(buf.get_begin(), buf.size());
+	}
+}
diff --git a/src/align/align.h b/src/align/align.h
new file mode 100644
index 0000000..668a4e3
--- /dev/null
+++ b/src/align/align.h
@@ -0,0 +1,64 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef ALIGN_H_
+#define ALIGN_H_
+
+#include <vector>
+#include "../search/trace_pt_buffer.h"
+#include "../util/task_queue.h"
+#include "../basic/statistics.h"
+#include "align_struct.h"
+
+using std::vector;
+
+struct Output_writer
+{
+	Output_writer(Output_stream* f) :
+		f_(f)
+	{ }
+	void operator()(Text_buffer &buf)
+	{
+		f_->write(buf.get_begin(), buf.size());
+		buf.clear();
+	}
+private:
+	Output_stream* const f_;
+};
+
+template<typename _buffer>
+struct Ring_buffer_sink
+{
+	Ring_buffer_sink(Output_stream *output_file):
+		writer(output_file),
+		queue(config.threads_ * 4, writer)
+	{}
+	bool get(size_t &i, _buffer *& buffer, Trace_pt_list::Query_range &query_range)
+	{
+		return queue.get(i, buffer, query_range);
+	}
+	void push(size_t i)
+	{
+		queue.push(i);
+	}
+private:
+	Output_writer writer;
+	Task_queue<_buffer, Output_writer> queue;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/align/align_queries.h b/src/align/align_queries.h
new file mode 100644
index 0000000..6dfae85
--- /dev/null
+++ b/src/align/align_queries.h
@@ -0,0 +1,67 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef ALIGN_QUERIES_H_
+#define ALIGN_QUERIES_H_
+
+#include <deque>
+#include "../util/merge_sort.h"
+#include "../search/trace_pt_buffer.h"
+#include "../util/map.h"
+#include "../util/task_queue.h"
+#include "align.h"
+#include "query_mapper.h"
+
+using std::vector;
+
+struct Query_data
+{
+	Query_data():
+		mapper(0)
+	{}
+	Query_data(Query_mapper *mapper):
+		mapper(mapper),
+		state(init)
+	{}
+	Query_mapper *mapper;
+	Text_buffer buf;
+	enum { init, free, closing, finished };
+	unsigned state;
+};
+
+struct Query_queue
+{
+	void init(Trace_pt_list::iterator begin, Trace_pt_list::iterator end);
+	void flush(Output_stream *out, Statistics &stat);
+	Query_data* get();
+	void pop_busy();
+
+	tthread::mutex lock;
+	std::deque<Query_data*> queue;
+	std::queue<Query_data*> out_queue;
+	Trace_pt_list::iterator trace_pt_pos, trace_pt_end;
+	bool writing;
+	unsigned n, last_query;
+};
+
+extern Query_queue query_queue;
+
+void align_worker(Output_stream *out);
+void align_queries(const Trace_pt_buffer &trace_pts, Output_stream* output_file);
+
+#endif /* ALIGN_QUERIES_H_ */
diff --git a/src/align/align_struct.h b/src/align/align_struct.h
new file mode 100644
index 0000000..bedeee8
--- /dev/null
+++ b/src/align/align_struct.h
@@ -0,0 +1,49 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef ALIGN_STRUCT_H_
+#define ALIGN_STRUCT_H_
+
+#include "../basic/match.h"
+
+struct local_match : public Hsp_data
+{
+	local_match() :
+		query_anchor_(0),
+		subject_(0)
+	{ }
+	local_match(int score) :
+		Hsp_data(score)
+	{ }
+	local_match(int query_anchor, int subject_anchor, const Letter *subject, unsigned total_subject_len = 0) :
+		total_subject_len_(total_subject_len),
+		query_anchor_(query_anchor),
+		subject_anchor(subject_anchor),
+		subject_(subject)
+	{ }
+	local_match(unsigned len, unsigned query_begin, unsigned query_len, unsigned subject_len, unsigned gap_openings, unsigned identities, unsigned mismatches, signed subject_begin, signed score) :
+		Hsp_data(score),
+		query_anchor_(0),
+		subject_(0)
+	{ }
+	unsigned total_subject_len_;
+	signed query_anchor_, subject_anchor;
+	const Letter *subject_;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/align/align_target.cpp b/src/align/align_target.cpp
new file mode 100644
index 0000000..573f476
--- /dev/null
+++ b/src/align/align_target.cpp
@@ -0,0 +1,158 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "query_mapper.h"
+#include "../data/reference.h"
+#include "../dp/floating_sw.h"
+
+using std::list;
+
+void Query_mapper::get_prefilter_score(size_t idx)
+{
+	static const int max_dist = 64;
+
+	Target& target = targets[idx];
+	const size_t n = target.end - target.begin;
+	vector<Seed_hit>::iterator hits = seed_hits.begin() + target.begin;
+	std::sort(seed_hits.begin() + target.begin, seed_hits.begin() + target.end, Seed_hit::compare_pos);
+	
+	int max_score = 0;
+	for (unsigned node = 0; node < n; ++node) {
+		Seed_hit& d = hits[node];
+		if (d.ungapped.len == 0)
+			continue;
+		for (int k = node - 1; k >= 0; --k) {
+			const Seed_hit &e = hits[k];
+			if (e.ungapped.len == 0)
+				continue;
+			if (d.ungapped.j - e.ungapped.subject_last() < max_dist) {
+				if (abs(d.ungapped.i - e.ungapped.query_last()) >= max_dist)
+					continue;
+				const int shift = d.ungapped.diag() - e.ungapped.diag();
+				int gap_score = -config.gap_open - abs(shift)*config.gap_extend;
+				const int space = shift > 0 ? d.ungapped.j - e.ungapped.subject_last() : d.ungapped.i - e.ungapped.query_last();
+				int prefix_score;
+				if (space <= 0)
+					prefix_score = std::max(e.prefix_score - (e.ungapped.score - e.ungapped.partial_score(abs(space))) + d.ungapped.score, e.prefix_score + d.ungapped.partial_score(abs(space))) + gap_score;
+				else
+					prefix_score = e.prefix_score + d.ungapped.score + gap_score;
+
+				d.prefix_score = std::max(d.prefix_score, (unsigned)prefix_score);
+			}
+			else
+				break;
+		}
+		max_score = std::max(max_score, (int)d.prefix_score);
+	}
+	target.filter_score = max_score;
+}
+
+bool is_contained(const vector<Seed_hit>::const_iterator &hits, size_t i)
+{
+	for (size_t j = 0; j < i; ++j)
+		if (hits[i].frame_ == hits[j].frame_ && hits[i].ungapped.is_enveloped(hits[j].ungapped))
+			return true;
+	return false;
+}
+
+bool is_contained(const list<Hsp_data> &hsps, const Seed_hit &hit)
+{
+	for (list<Hsp_data>::const_iterator i = hsps.begin(); i != hsps.end(); ++i)
+		if (hit.frame_ == i->frame && i->pass_through(hit.ungapped))
+			return true;
+	return false;
+}
+
+void Query_mapper::align_target(size_t idx, Statistics &stat)
+{
+	typedef float score_t;
+	Target& target = targets[idx];
+	std::sort(seed_hits.begin() + target.begin, seed_hits.begin() + target.end);
+	const size_t n = target.end - target.begin,
+		max_len = query_seq(0).length() + 100 * query_seqs::get().avg_len();
+	size_t aligned_len = 0;
+	const vector<Seed_hit>::const_iterator hits = seed_hits.begin() + target.begin;
+
+	for (size_t i = 0; i < n; ++i) {
+		if (!is_contained(hits, i) && !is_contained(target.hsps, hits[i])) {
+			const unsigned frame = hits[i].frame_;
+			target.hsps.push_back(Hsp_data());
+			target.hsps.back().frame = frame;
+			uint64_t cell_updates;
+
+			if (false && config.comp_based_stats == 1)
+				floating_sw(&query_seq(frame)[hits[i].query_pos_],
+					&ref_seqs::get()[hits[i].subject_][hits[i].subject_pos_],
+					target.hsps.back(),
+					config.read_padding(query_seq(frame).length()),
+					(score_t)score_matrix.rawscore(config.gapped_xdrop),
+					(score_t)(config.gap_open + config.gap_extend),
+					(score_t)config.gap_extend,
+					cell_updates,
+					hits[i].query_pos_,
+					hits[i].subject_pos_,
+					query_cb[frame],
+					Traceback(),
+					score_t());
+			else
+				floating_sw(&query_seq(frame)[hits[i].query_pos_],
+					&ref_seqs::get()[hits[i].subject_][hits[i].subject_pos_],
+					target.hsps.back(),
+					config.read_padding(query_seq(frame).length()),
+					score_matrix.rawscore(config.gapped_xdrop),
+					config.gap_open + config.gap_extend,
+					config.gap_extend,
+					cell_updates,
+					hits[i].query_pos_,
+					hits[i].subject_pos_,
+					No_score_correction(),
+					Traceback(),
+					int());
+
+			if (config.comp_based_stats) {
+				const int score = (int)target.hsps.back().score + query_cb[frame](target.hsps.back());
+				target.hsps.back().score = (unsigned)std::max(0, score);
+			}
+
+			stat.inc(Statistics::OUT_HITS);
+			if (i > 0)
+				stat.inc(Statistics::SECONDARY_HITS);
+			aligned_len += target.hsps.back().length;
+			if (aligned_len > max_len)
+				break;
+		}
+		else
+			stat.inc(Statistics::DUPLICATES);
+	}
+
+	for (list<Hsp_data>::iterator i = target.hsps.begin(); i != target.hsps.end(); ++i)
+		for (list<Hsp_data>::iterator j = target.hsps.begin(); j != target.hsps.end();)
+			if (j != i && j->is_weakly_enveloped(*i)) {
+				stat.inc(Statistics::ERASED_HITS);
+				j = target.hsps.erase(j);
+			}
+			else
+				++j;
+
+	for (list<Hsp_data>::iterator i = target.hsps.begin(); i != target.hsps.end(); ++i)
+		i->set_source_range(i->frame, source_query_len);
+
+	target.hsps.sort();
+	if(target.hsps.size() > 0)
+		target.filter_score = target.hsps.front().score;
+}
\ No newline at end of file
diff --git a/src/align/extend_ungapped.h b/src/align/extend_ungapped.h
new file mode 100644
index 0000000..0aad37b
--- /dev/null
+++ b/src/align/extend_ungapped.h
@@ -0,0 +1,43 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef EXTEND_UNGAPPED_H_
+#define EXTEND_UNGAPPED_H_
+
+#include "../dp/dp.h"
+#include "../data/reference.h"
+
+inline Diagonal_segment ungapped_extension(unsigned subject, unsigned subject_pos, unsigned query_pos, const sequence &query)
+{
+	const Letter* s = ref_seqs::data_->data(ref_seqs::data_->position(subject, subject_pos)),
+		*q = &query[query_pos];
+	unsigned delta, len;
+	int score = xdrop_ungapped(q, s, delta, len);
+	return Diagonal_segment(query_pos - delta, subject_pos - delta, len, score);
+}
+
+inline Diagonal_segment ungapped_extension(unsigned subject_pos, unsigned query_pos, const sequence &query, const sequence &subject)
+{
+	const Letter* s = &subject[subject_pos],
+		*q = &query[query_pos];
+	unsigned delta, len;
+	int score = xdrop_ungapped(q, s, delta, len);
+	return Diagonal_segment(query_pos - delta, subject_pos - delta, len, score);
+}
+
+#endif
\ No newline at end of file
diff --git a/src/align/match_func.h b/src/align/match_func.h
new file mode 100644
index 0000000..c8ab2b0
--- /dev/null
+++ b/src/align/match_func.h
@@ -0,0 +1,40 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef MATCH_FUNC_H_
+#define MATCH_FUNC_H_
+
+#include "../basic/match.h"
+
+inline int blast_frame(unsigned frame)
+{ return frame <= 2 ? (int)frame+1 : 2-(int)frame; }
+
+inline unsigned query_translated_begin(unsigned query_begin, unsigned frame, unsigned dna_len, bool query_translated)
+{
+	if(!query_translated)
+		return query_begin;
+	int f = frame <= 2 ? frame+1 : 2-frame;
+	if (f > 0)
+		return (query_begin - (f-1))/3;
+	else
+		return (dna_len + f - query_begin)/3;
+}
+
+#endif /* MATCH_FUNC_H_ */
diff --git a/src/align/query_mapper.cpp b/src/align/query_mapper.cpp
new file mode 100644
index 0000000..8b803b5
--- /dev/null
+++ b/src/align/query_mapper.cpp
@@ -0,0 +1,222 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "align_queries.h"
+#include "query_mapper.h"
+#include "../data/reference.h"
+#include "extend_ungapped.h"
+#include "../output/output.h"
+#include "../output/output_format.h"
+#include "../output/daa_write.h"
+
+Query_mapper::Query_mapper() :
+	source_hits(get_query_data()),
+	query_id(source_hits.first->query_ / align_mode.query_contexts),
+	targets_finished(0),
+	next_target(0),
+	source_query_len(get_source_query_len(query_id)),
+	unaligned_from(query_queue.last_query+1),
+	seed_hits(source_hits.second - source_hits.first)
+{	
+	query_queue.last_query = query_id;
+}
+
+void Query_mapper::init()
+{
+	targets.resize(count_targets());
+	load_targets();
+	rank_targets();
+	if(config.comp_based_stats == 1)
+		for (unsigned i = 0; i < align_mode.query_contexts; ++i)
+			query_cb.push_back(Bias_correction(query_seq(i)));
+}
+
+pair<Trace_pt_list::iterator, Trace_pt_list::iterator> Query_mapper::get_query_data()
+{
+	const Trace_pt_list::iterator begin = query_queue.trace_pt_pos;
+	if (begin == query_queue.trace_pt_end)
+		return pair<Trace_pt_list::iterator, Trace_pt_list::iterator>(begin, begin);
+	const unsigned c = align_mode.query_contexts, query = begin->query_ / c;
+	Trace_pt_list::iterator end = begin;
+	for (; end < query_queue.trace_pt_end && end->query_ / c == query; ++end);
+	query_queue.trace_pt_pos = end;
+	return pair<Trace_pt_list::iterator, Trace_pt_list::iterator>(begin, end);
+}
+
+unsigned Query_mapper::count_targets()
+{
+	std::sort(source_hits.first, source_hits.second, hit::cmp_subject);
+	const size_t n = source_hits.second - source_hits.first;
+	const Trace_pt_list::iterator hits = source_hits.first;
+	size_t subject_id = std::numeric_limits<size_t>::max();
+	unsigned n_subject = 0;
+	for (size_t i = 0; i < n; ++i) {
+		std::pair<size_t, size_t> l = ref_seqs::data_->local_position(hits[i].subject_);
+		if (l.first != subject_id) {
+			subject_id = l.first;
+			++n_subject;
+		}
+		const unsigned frame = hits[i].query_ % align_mode.query_contexts;
+		seed_hits[i] = Seed_hit(frame,
+			(unsigned)l.first,
+			(unsigned)l.second,
+			hits[i].seed_offset_,
+			ungapped_extension((unsigned)l.first,
+				(unsigned)l.second,
+				hits[i].seed_offset_,
+				query_seq(frame)));
+	}
+	return n_subject;
+}
+
+void Query_mapper::load_targets()
+{
+	unsigned subject_id = std::numeric_limits<unsigned>::max(), n = 0;
+	for (size_t i = 0; i < seed_hits.size(); ++i) {
+		if (seed_hits[i].subject_ != subject_id) {
+			if (n > 0) {
+				targets[n - 1].end = i;
+				get_prefilter_score(n - 1);
+			}
+			targets.get(n) = new Target(i, seed_hits[i].subject_);
+			++n;
+			subject_id = seed_hits[i].subject_;
+		}
+	}
+	targets[n - 1].end = seed_hits.size();
+	get_prefilter_score(n - 1);
+}
+
+void Query_mapper::rank_targets()
+{
+	std::sort(targets.begin(), targets.end(), Target::compare);
+
+	unsigned score = 0;
+	if (config.toppercent < 100) {
+		score = unsigned((double)targets[0].filter_score * (1.0 - config.toppercent / 100.0) * config.rank_ratio);
+	}
+	else {
+		size_t min_idx = std::min(targets.size(), (size_t)config.max_alignments);
+		score = unsigned((double)targets[min_idx - 1].filter_score * config.rank_ratio);
+	}
+
+	unsigned i = 0;
+	for (; i < targets.size(); ++i)
+		if (targets[i].filter_score < score)
+			break;
+
+	targets.erase(targets.begin() + std::min((unsigned)targets.size(), std::max((unsigned)(config.max_alignments*config.rank_factor), i)), targets.end());
+}
+
+bool Query_mapper::generate_output(Text_buffer &buffer, Statistics &stat)
+{
+	if (!blocked_processing && *output_format != Output_format::daa && config.report_unaligned != 0) {
+		for (unsigned i = unaligned_from; i < query_id; ++i) {
+			output_format->print_query_intro(i, query_ids::get()[i].c_str(), get_source_query_len(i), buffer, true);
+			output_format->print_query_epilog(buffer, true);
+		}
+	}
+
+	std::sort(targets.begin(), targets.end(), Target::compare);
+
+	unsigned n_hsp = 0, n_target_seq = 0, hit_hsps = 0;
+	const unsigned top_score = targets[0].filter_score, query_len = (unsigned)query_seq(0).length();
+	size_t seek_pos = 0;
+
+	for (size_t i = 0; i < targets.size(); ++i) {
+		if (config.min_bit_score == 0 && score_matrix.evalue(targets[i].filter_score, config.db_size, query_len) > config.max_evalue
+			|| score_matrix.bitscore(targets[i].filter_score) < config.min_bit_score)
+			break;
+
+		if (!config.output_range(n_target_seq, targets[i].filter_score, top_score))
+			break;
+
+		const unsigned subject_len = (unsigned)ref_seqs::get()[targets[i].subject_id].length();
+		
+		hit_hsps = 0;
+		for (list<Hsp_data>::iterator j = targets[i].hsps.begin(); j != targets[i].hsps.end(); ++j) {
+			if (hit_hsps >= config.max_hsps)
+				break;
+			if (j->id_percent() < config.min_id
+				|| j->query_cover_percent(source_query_len) < config.query_cover
+				|| j->subject_cover_percent(subject_len) < config.subject_cover
+				|| (config.no_self_hits && j->identities == j->length && j->query_source_range.length() == source_query_len && j->subject_range.length() == subject_len))
+				continue;
+
+			if (blocked_processing) {
+				if (n_hsp == 0)
+					seek_pos = Intermediate_record::write_query_intro(buffer, query_id);
+				Intermediate_record::write(buffer, *j, query_id, targets[i].subject_id);
+			}
+			else {
+				if (n_hsp == 0) {
+					if (*output_format == Output_format::daa)
+						seek_pos = write_daa_query_record(buffer, query_ids::get()[query_id].c_str(), align_mode.query_translated ? query_source_seqs::get()[query_id] : query_seqs::get()[query_id]);
+					else
+						output_format->print_query_intro(query_id, query_ids::get()[query_id].c_str(), source_query_len, buffer, false);
+				}
+				if (*output_format == Output_format::daa)
+					write_daa_record(buffer, *j, query_id, targets[i].subject_id);
+				else
+					output_format->print_match(Hsp_context(*j,
+						query_id,
+						query_seq(j->frame),
+						query_source_seq(),
+						query_ids::get()[query_id].c_str(),
+						targets[i].subject_id,
+						targets[i].subject_id,
+						ref_ids::get()[targets[i].subject_id].c_str(),
+						subject_len,
+						n_target_seq,
+						hit_hsps), buffer);
+			}
+
+			if(hit_hsps == 0)
+				++n_target_seq;
+			++n_hsp;
+			++hit_hsps;
+			if (config.alignment_traceback && j->gap_openings > 0)
+				stat.inc(Statistics::GAPPED);
+			stat.inc(Statistics::SCORE_TOTAL, j->score);
+		}
+	}
+
+	if (n_hsp > 0) {
+		if (!blocked_processing) {
+			if (*output_format == Output_format::daa)
+				finish_daa_query_record(buffer, seek_pos);
+			else
+				output_format->print_query_epilog(buffer, false);
+		}
+		else
+			Intermediate_record::finish_query(buffer, seek_pos);
+	}
+	else if (!blocked_processing && *output_format != Output_format::daa && config.report_unaligned != 0) {
+		output_format->print_query_intro(query_id, query_ids::get()[query_id].c_str(), source_query_len, buffer, true);
+		output_format->print_query_epilog(buffer, true);
+	}
+
+	if (!blocked_processing) {
+		stat.inc(Statistics::MATCHES, n_hsp);
+		stat.inc(Statistics::PAIRWISE, n_target_seq);
+		if (n_hsp > 0)
+			stat.inc(Statistics::ALIGNED);
+	}
+	
+	return n_hsp > 0;
+}
\ No newline at end of file
diff --git a/src/align/query_mapper.h b/src/align/query_mapper.h
new file mode 100644
index 0000000..7be11c3
--- /dev/null
+++ b/src/align/query_mapper.h
@@ -0,0 +1,117 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef QUERY_MAPPER_H_
+#define QUERY_MAPPER_H_
+
+#include <queue>
+#include <vector>
+#include <list>
+#include "../util/tinythread.h"
+#include "../search/trace_pt_buffer.h"
+#include "../data/queries.h"
+#include "../util/ptr_vector.h"
+#include "../dp/dp.h"
+
+using std::vector;
+using std::pair;
+using std::list;
+
+struct Seed_hit
+{
+	Seed_hit()
+	{}
+	Seed_hit(unsigned frame, unsigned subject, unsigned subject_pos, unsigned query_pos, const Diagonal_segment &ungapped) :
+		frame_(frame),
+		subject_(subject),
+		subject_pos_(subject_pos),
+		query_pos_(query_pos),
+		ungapped(ungapped),
+		prefix_score(ungapped.score)
+	{ }
+	int diagonal() const
+	{
+		return (int)subject_pos_ - (int)query_pos_;
+	}
+	bool operator<(const Seed_hit &rhs) const
+	{
+		return ungapped.score > rhs.ungapped.score;
+	}
+	static bool compare_pos(const Seed_hit &x, const Seed_hit &y)
+	{
+		return Diagonal_segment::cmp_subject_end(x.ungapped, y.ungapped);
+	}
+	unsigned frame_, subject_, subject_pos_, query_pos_;
+	Diagonal_segment ungapped;
+	unsigned prefix_score;
+};
+
+struct Target
+{
+	Target(size_t begin, unsigned subject_id) :
+		subject_id(subject_id),
+		filter_score(0),
+		begin(begin)
+	{}		
+	static bool compare(Target* lhs, Target *rhs)
+	{
+		return lhs->filter_score > rhs->filter_score;
+	}
+	unsigned subject_id, filter_score;
+	size_t begin, end;
+	list<Hsp_data> hsps;
+};
+
+struct Query_mapper
+{
+	Query_mapper();
+	void init();
+	void get_prefilter_score(size_t idx);
+	void align_target(size_t idx, Statistics &stat);
+	bool generate_output(Text_buffer &buffer, Statistics &stat);
+	size_t n_targets() const
+	{
+		return targets.size();
+	}
+	bool finished() const
+	{
+		return targets_finished == targets.size();
+	}
+	pair<Trace_pt_list::iterator, Trace_pt_list::iterator> source_hits;
+	unsigned query_id, targets_finished, next_target;
+private:
+	static pair<Trace_pt_list::iterator, Trace_pt_list::iterator> get_query_data();
+	unsigned count_targets();
+	sequence query_seq(unsigned frame) const
+	{
+		return query_seqs::get()[query_id*align_mode.query_contexts + frame];
+	}
+	sequence query_source_seq() const
+	{
+		return align_mode.query_translated ? query_source_seqs::get()[query_id] : query_seqs::get()[query_id];
+	}
+	void load_targets();
+	void rank_targets();
+
+	unsigned source_query_len, unaligned_from;
+	vector<Seed_hit> seed_hits;
+	Ptr_vector<Target> targets;
+	vector<Bias_correction> query_cb;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/basic/basic.cpp b/src/basic/basic.cpp
new file mode 100644
index 0000000..ca4338d
--- /dev/null
+++ b/src/basic/basic.cpp
@@ -0,0 +1,270 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "value.h"
+#include "reduction.h"
+#include "shape_config.h"
+#include "translate.h"
+#include "statistics.h"
+#include "sequence.h"
+
+const char* Const::version_string = "0.8.31";
+const char* Const::program_name = "diamond";
+const char* Const::id_delimiters = " \a\b\f\n\r\t\v";
+
+Value_traits::Value_traits(const char *alphabet, Letter mask_char, const char *ignore) :
+	alphabet(alphabet),
+	alphabet_size((unsigned)strlen(alphabet)),
+	mask_char(mask_char),
+	from_char(Char_representation((unsigned)alphabet_size, alphabet, mask_char, ignore))
+{}
+
+const char Char_representation::invalid = '\xff';
+
+const Value_traits amino_acid_traits("ARNDCQEGHILKMFPSTWYVBJZX*", 23, "UO-");
+const Value_traits nucleotide_traits("ACGTN", 4, "MRWSYKVHDBX");
+Value_traits value_traits(amino_acid_traits);
+Value_traits input_value_traits(amino_acid_traits);
+
+Align_mode::Align_mode(unsigned mode) :
+	mode(mode)
+{
+	sequence_type = amino_acid;
+	switch (mode) {
+	case blastx:
+		input_sequence_type = nucleotide;
+		query_contexts = 6;
+		query_translated = true;
+		query_len_factor = 3;
+		break;
+	default:
+		input_sequence_type = amino_acid;
+		query_contexts = 1;
+		query_translated = false;
+		query_len_factor = 1;
+	}
+}
+
+unsigned Align_mode::from_command(unsigned command)
+{
+	switch (command) {
+	case Config::blastx:
+		return blastx;
+	default:
+		return blastp;
+	}
+}
+
+Align_mode align_mode (Align_mode::blastp);
+
+Reduction Reduction::reduction("KREDQN C G H M F Y ILV W P STA");
+//Reduction Reduction::reduction("A KR EDNQ C G H ILVM FYW P ST"); // murphy.10
+//const Reduction Reduction::reduction("G D N AEFIKLMQRVW Y H C T S P"); // gmbr.10
+//const Reduction Reduction::reduction("EKQR IV LY F AM W HT C DNS"); // dssp.10
+//const Reduction Reduction::reduction("K R E D Q N C G H M F Y I L V W P S T A");
+
+Statistics statistics;
+
+const char* shape_codes[][Const::max_shapes] = {
+	{ "111101011101111", "111011001100101111", "1111001001010001001111", "111100101000010010010111", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },				// 4x12
+	{ "1111011111",		// 16x9
+	"111001101111",
+	"11101100101011",
+	"11010010111011",
+	"111010100001111",
+	"1110100011001011",
+	"11100010100101011",
+	"11011000001100111",
+	"1101010010000010111",
+	"11100001000100100111",
+	"110110000100010001101",
+	"1110000100001000101011",
+	"1101010000010001001011",
+	"1101001001000010000111",
+	"1101000100100000100000111",
+	"1110001000100000001010011" },
+	{
+		"11001011",		// 16x5
+		"101010011",
+	"100110101",
+	"1110000101",
+	"110000100011",
+	"1010010000011",
+	"1100000010011",
+	"11010000000101",
+	"100100010000101",
+	"1010000000000100011",
+	"1010000001000001001",
+	"1100000000100001001",
+	"10100010000000100001",
+	"10010001000000000101",
+	"110000000100000010001",
+	"10010000100000000000011" },
+
+	{
+		"11101011", // 16x6
+"110100111",
+"11001000111",
+"1100001001011",
+"10101000010011",
+"101001000001011",
+"1100010000001011",
+"11010000010001001",
+"100100100000010101",
+"101001000100000101",
+"1010001000010000101",
+"11001000000100000011",
+"101000001000000010011",
+"1100010000000100000101",
+"11000001000000000100011",
+"101000010000000000010011"
+	},
+
+	{ "1110010111", // 16x7
+	"11001101011",
+	"1101001000111",
+	"11100010010011",
+	"110100101000011",
+	"1100100010010101",
+	"1101010000010011",
+	"1100100000101011",
+	"11010001000010011",
+	"10101000010001011",
+	"11000010010000111",
+	"11100000001000001011",
+	"110000100010000001101",
+	"11010000100000000010011",
+	"10100010000010000001011",
+	"110001000000010001000101"
+
+	},
+	{
+		"101011",		// 16x4
+		"110011",
+	"110000101",
+	"1001000011",
+	"10010000011",
+	"110000010001",
+	"1100000001001",
+	"10001000000101",
+	"10100000100001",
+	"100100000000011",
+	"101000000010001",
+	"1010000001000001",
+	"1000010000001001",
+	"101000000000000011",
+	"100010000000000000101",
+	"1000100000000000100001"
+	}
+};
+
+shape_config shapes;
+unsigned shape_from, shape_to;
+
+const Letter Translator::reverseLetter[5] = { 3, 2, 1, 0, 4 };
+
+Letter Translator::lookup[5][5][5];
+Letter Translator::lookupReverse[5][5][5];
+
+const Letter Translator::STOP(value_traits.from_char('*'));
+
+const char* Translator::codes[] = {
+	0,
+	"FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 1
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSS**VVVVAAAADDEEGGGG", // 2
+	"FFLLSSSSYY**CCWWTTTTPPPPHHQQRRRRIIMMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 3
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 4
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSSSSVVVVAAAADDEEGGGG", // 5
+	"FFLLSSSSYYQQCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 6
+	0,
+	0,
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNNKSSSSVVVVAAAADDEEGGGG", // 9
+	"FFLLSSSSYY**CCCWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 10
+	"FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 11
+	"FFLLSSSSYY**CC*WLLLSPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 12
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSSGGVVVVAAAADDEEGGGG", // 13
+	"FFLLSSSSYYY*CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNNKSSSSVVVVAAAADDEEGGGG", // 14
+	0,
+	"FFLLSSSSYY*LCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 16
+	0,
+	0,
+	0,
+	0,
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNNKSSSSVVVVAAAADDEEGGGG", // 21
+	"FFLLSS*SYY*LCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 22
+	"FF*LSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 23
+	"FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSSKVVVVAAAADDEEGGGG", // 24
+	"FFLLSSSSYY**CCGWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", // 25
+	"FFLLSSSSYY**CC*WLLLAPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG" // 26
+};
+
+void Translator::init(unsigned id)
+{
+	static const unsigned idx[] = { 2, 1, 3, 0 };
+	if (id >= sizeof(codes) / sizeof(codes[0]) || codes[id] == 0)
+		throw std::runtime_error("Invalid genetic code id.");
+	for (unsigned i = 0; i < 5; ++i)
+		for (unsigned j = 0; j < 5; ++j)
+			for (unsigned k = 0; k < 5; ++k)
+				if (i == 4 || j == 4 || k == 4) {
+					lookup[i][j][k] = value_traits.mask_char;
+					lookupReverse[i][j][k] = value_traits.mask_char;
+				}
+				else {
+					lookup[i][j][k] = value_traits.from_char(codes[id][(int)idx[i] * 16 + (int)idx[j] * 4 + (int)idx[k]]);
+					lookupReverse[i][j][k] = value_traits.from_char(codes[id][idx[(int)reverseLetter[i]] * 16 + idx[(int)reverseLetter[j]] * 4 + idx[(int)reverseLetter[k]]]);
+				}
+	for (unsigned i = 0; i < 4; ++i)
+		for (unsigned j = 0; j < 4; ++j) {
+			if (equal(lookup[i][j], 4))
+				lookup[i][j][4] = lookup[i][j][0];
+			if (equal(lookupReverse[i][j], 4))
+				lookupReverse[i][j][4] = lookupReverse[i][j][0];
+		}
+}
+
+vector<Letter> sequence::from_string(const char* str)
+{
+	vector<Letter> seq;
+	while (*str)
+		seq.push_back(value_traits.from_char(*(str++)));
+	return seq;
+}
+
+void Seed::enum_neighborhood(unsigned pos, int treshold, vector<Seed>& out, int score)
+{
+	Letter l = data_[pos];
+	score -= score_matrix(l, l);
+	for (unsigned i = 0; i < 20; ++i) {
+		int new_score = score + score_matrix(l, i);
+		data_[pos] = i;
+		if (new_score >= treshold) {
+			if (pos < config.seed_weight - 1)
+				enum_neighborhood(pos + 1, treshold, out, new_score);
+			else
+				out.push_back(*this);
+		}
+	}
+	data_[pos] = l;
+}
+
+void Seed::enum_neighborhood(int treshold, vector<Seed>& out)
+{
+	out.clear();
+	enum_neighborhood(0, treshold, out, score(*this));
+}
\ No newline at end of file
diff --git a/src/basic/config.cpp b/src/basic/config.cpp
new file mode 100644
index 0000000..c480bad
--- /dev/null
+++ b/src/basic/config.cpp
@@ -0,0 +1,348 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "../util/command_line_parser.h"
+#include "config.h"
+#include "../util/util.h"
+#include "../util/log_stream.h"
+#include "../util/tinythread.h"
+#include "../basic/value.h"
+#include "score_matrix.h"
+#include "../util/system.h"
+#include "reduction.h"
+#include "shape_config.h"
+#include "../util/temp_file.h"
+#include "../basic/match.h"
+#include "../data/sorted_list.h"
+#include "../basic/translate.h"
+#include "../dp/dp.h"
+
+Config config;
+
+Config::Config(int argc, const char **argv)
+{
+	Command_line_parser parser;
+	parser.add_command("makedb", "Build DIAMOND database from a FASTA file")
+		.add_command("blastp", "Align amino acid query sequences against a protein reference database")
+		.add_command("blastx", "Align DNA query sequences against a protein reference database")
+		.add_command("view", "View DIAMOND alignment archive (DAA) formatted file")
+		.add_command("help", "Produce help message")
+		.add_command("version", "Display version information")
+		.add_command("getseq", "Retrieve sequences from a DIAMOND database file")
+		.add_command("benchmark", "")
+		.add_command("random-seqs", "")
+		.add_command("compare", "")
+		.add_command("sort", "")
+		.add_command("roc", "")
+		.add_command("dbstat", "")
+		.add_command("modelsim", "")
+		.add_command("match-file-stat", "")
+		.add_command("model-seqs", "");
+
+	Options_group general("General options");
+	general.add()
+		("threads", 'p', "number of CPU threads", threads_)
+		("db", 'd', "database file", database)
+		("out", 'o', "output file", output_file)
+		("outfmt", 'f', "output format\n\
+\t0   = BLAST pairwise\n\
+\t5   = BLAST XML\n\
+\t6   = BLAST tabular\n\
+\t100 = DIAMOND alignment archive (DAA)\n\
+\t101 = SAM\n\n\
+\tValue 6 may be followed by a space-separated list of these keywords:\n\n\
+\tqseqid means Query Seq - id\n\
+\tqlen means Query sequence length\n\
+\tsseqid means Subject Seq - id\n\
+\tsallseqid means All subject Seq - id(s), separated by a ';'\n\
+\tslen means Subject sequence length\n\
+\tqstart means Start of alignment in query\n\
+\tqend means End of alignment in query\n\
+\tsstart means Start of alignment in subject\n\
+\tsend means End of alignment in subject\n\
+\tqseq means Aligned part of query sequence\n\
+\tsseq means Aligned part of subject sequence\n\
+\tevalue means Expect value\n\
+\tbitscore means Bit score\n\
+\tscore means Raw score\n\
+\tlength means Alignment length\n\
+\tpident means Percentage of identical matches\n\
+\tnident means Number of identical matches\n\
+\tmismatch means Number of mismatches\n\
+\tpositive means Number of positive - scoring matches\n\
+\tgapopen means Number of gap openings\n\
+\tgaps means Total number of gaps\n\
+\tppos means Percentage of positive - scoring matches\n\
+\tqframe means Query frame\n\
+\tbtop means Blast traceback operations(BTOP)\n\
+\tstitle means Subject Title\n\
+\tsalltitles means All Subject Title(s), separated by a '<>'\n\
+\tqcovhsp means Query Coverage Per HSP\n\
+\tqtitle means Query title\n\n\
+\tDefault: qseqid sseqid pident length mismatch gapopen qstart qend sstart send evalue bitscore", output_format)
+("verbose", 'v', "verbose console output", verbose)
+("log", 0, "enable debug log", debug_log)
+("quiet", 0, "disable console output", quiet);
+
+	Options_group makedb("Makedb options");
+	makedb.add()
+		("in", 0, "input reference file in FASTA format", input_ref_file);
+
+	Options_group aligner("Aligner options");
+	aligner.add()
+		("query", 'q', "input query file", query_file)
+		("un", 0, "file for unaligned queries", unaligned)
+		("unal", 0, "report unaligned queries (0=no, 1=yes)", report_unaligned, -1)
+		("max-target-seqs", 'k', "maximum number of target sequences to report alignments for", max_alignments, uint64_t(25))
+		("top", 0, "report alignments within this percentage range of top alignment score (overrides --max-target-seqs)", toppercent, 100.0)
+		("compress", 0, "compression for output files (0=none, 1=gzip)", compression)
+		("evalue", 'e', "maximum e-value to report alignments", max_evalue, 0.001)
+		("min-score", 0, "minimum bit score to report alignments (overrides e-value setting)", min_bit_score)
+		("id", 0, "minimum identity% to report an alignment", min_id)
+		("query-cover", 0, "minimum query cover% to report an alignment", query_cover)
+		("subject-cover", 0, "minimum subject cover% to report an alignment", subject_cover)
+		("sensitive", 0, "enable sensitive mode (default: fast)", mode_sensitive)
+		("more-sensitive", 0, "enable more sensitive mode (default: fast)", mode_more_sensitive)
+		("block-size", 'b', "sequence block size in billions of letters (default=2.0)", chunk_size)
+		("index-chunks", 'c', "number of chunks for index processing", lowmem)
+		("tmpdir", 't', "directory for temporary files", tmpdir)
+		("gapopen", 0, "gap open penalty (default=11 for protein)", gap_open, -1)
+		("gapextend", 0, "gap extension penalty (default=1 for protein)", gap_extend, -1)
+		("matrix", 0, "score matrix for protein alignment (default=BLOSUM62)", matrix, string("blosum62"))
+		("custom-matrix", 0, "file containing custom scoring matrix", matrix_file)
+		("lambda", 0, "lambda parameter for custom matrix", lambda)
+		("K", 0, "K parameter for custom matrix", K)
+		("comp-based-stats", 0, "enable composition based statistics (0/1=default)", comp_based_stats, 1u)
+		("seg", 0, "enable SEG masking of queries (yes/no)", seg)
+		("query-gencode", 0, "genetic code to use to translate query (see user manual)", query_gencode, 1u)
+		("salltitles", 0, "print full subject titles in output files", salltitles)
+		("no-self-hits", 0, "suppress reporting of identical self hits", no_self_hits);
+
+	Options_group advanced("Advanced options");
+	advanced.add()
+		("min-orf", 'l', "ignore translated sequences without an open reading frame of at least this length", run_len)
+		("freq-sd", 0, "number of standard deviations for ignoring frequent seeds", freq_sd, 0.0)
+		("id2", 0, "minimum number of identities for stage 1 hit", min_identities)
+		("window", 'w', "window size for local hit search", window)
+		("xdrop", 'x', "xdrop for ungapped alignment", ungapped_xdrop, 12.3)
+		("ungapped-score", 0, "minimum alignment score to continue local extension", min_ungapped_score)
+		("hit-band", 0, "band for hit verification", hit_band)
+		("hit-score", 0, "minimum score to keep a tentative alignment", min_hit_score)
+		("gapped-xdrop", 'X', "xdrop for gapped alignment in bits", gapped_xdrop, 20)
+		("band", 0, "band for dynamic programming computation", padding)
+		("shapes", 's', "number of seed shapes (0 = all available)", shapes)
+		("shape-mask", 0, "seed shapes", shape_mask)
+		("index-mode", 0, "index mode (0=4x12, 1=16x9)", index_mode)
+		("fetch-size", 0, "trace point fetch size", fetch_size, 4096u)
+		("rank-factor", 0, "include subjects within this range of max-target-seqs", rank_factor, 2.0)
+		("rank-ratio", 0, "include subjects within this ratio of last hit", rank_ratio, 0.6)
+		("max-hsps", 0, "maximum number of HSPs per subject sequence to save for each query", max_hsps, 1u)
+		("dbsize", 0, "effective database size (in letters)", db_size)
+		("no-auto-append", 0, "disable auto appending of DAA and DMND file extensions", no_auto_append)
+		("target-fetch-size", 0, "number of target sequences to fetch for seed extension", target_fetch_size, 4u);
+
+	Options_group view_options("View options");
+	view_options.add()
+		("daa", 'a', "DIAMOND alignment archive (DAA) file", daa_file)
+		("forwardonly", 0, "only show alignments of forward strand", forwardonly);
+
+	Options_group getseq_options("Getseq options");
+	getseq_options.add()
+		("seq", 0, "Sequence numbers to display.", seq_no);
+
+	Options_group hidden_options("");
+	hidden_options.add()
+		("extend-all", 0, "extend all seed hits", extend_all)
+		("local-align", 0, "Local alignment algorithm", local_align_mode, 0u)
+		("slow-search", 0, "", slow_search)
+		("ht", 0, "", ht_mode)
+		("old-freq", 0, "", old_freq)
+		("qp", 0, "", query_parallel)
+		("match1", 0, "", match_file1)
+		("match2", 0, "", match_file2)
+		("max-hits", 'C', "maximum number of hits to consider for one seed", hit_cap)
+		("seed-freq", 0, "maximum seed frequency", max_seed_freq, -15.0)
+		("space-penalty", 0, "", space_penalty, 4.9)
+		("min-diag-score", 0, "", min_diag_score, 10.5)
+		("reverse", 0, "", reverse)
+		("neighborhood-score", 0, "", neighborhood_score)
+		("algo", 0, "", algo, 0u)
+		("seed-weight", 'w', "", seed_weight, 7u)
+		("very-sensitive", 0, "", mode_very_sensitive);
+
+	parser.add(general).add(makedb).add(aligner).add(advanced).add(view_options).add(getseq_options).add(hidden_options);
+	parser.store(argc, argv, command);
+
+	switch (command) {
+	case Config::makedb:
+		if (input_ref_file == "")
+			throw std::runtime_error("Missing parameter: input file (--in)");
+		if (database == "")
+			throw std::runtime_error("Missing parameter: database file (--db/-d)");
+		if (chunk_size != 0.0)
+			throw std::runtime_error("Invalid option: --block-size/-b. Block size is set for the alignment commands.");
+		break;
+	case Config::blastp:
+	case Config::blastx:
+		if (query_file == "")
+			throw std::runtime_error("Missing parameter: query file (--query/-q)");
+		if (database == "")
+			throw std::runtime_error("Missing parameter: database file (--db/-d)");
+		if (daa_file.length() > 0) {
+			if (output_file.length() > 0)
+				throw std::runtime_error("Options --daa and --out cannot be used together.");
+			if (output_format.size() > 0 && output_format[0] != "daa")
+				throw std::runtime_error("Invalid parameter: --daa/-a. Output file is specified with the --out/-o parameter.");
+			output_file = daa_file;
+		}
+		if (daa_file.length() > 0 || (output_format.size() > 0 && (output_format[0] == "daa" || output_format[0] == "100"))) {
+			if (compression != 0)
+				throw std::runtime_error("Compression is not supported for DAA format.");
+			if (!no_auto_append)
+				auto_append_extension(output_file, ".daa");
+		}
+		break;
+	case Config::view:
+		if (daa_file == "")
+			throw std::runtime_error("Missing parameter: DAA file (--daa/-a)");
+	default:
+		;
+	}
+
+	if (hit_cap != 0)
+		throw std::runtime_error("Deprecated parameter: --max-hits/-C.");
+
+	if (debug_log)
+		verbosity = 3;
+	else if (quiet)
+		verbosity = 0;
+	else if (verbose)
+		verbosity = 2;
+	else if (((command == Config::view || command == blastx || command == blastp) && output_file == "")
+		|| command == Config::version || command == getseq)
+		verbosity = 0;
+	else
+		verbosity = 1;
+
+	switch (verbosity) {
+	case 0:
+		message_stream = Message_stream(false);
+		break;
+	case 3:
+		log_stream = Message_stream();
+	case 2:
+		verbose_stream = Message_stream();
+	default:
+		;
+	}
+
+	if (!no_auto_append) {
+		auto_append_extension(database, ".dmnd");
+		if (command == Config::view)
+			auto_append_extension(daa_file, ".daa");
+		if (compression == 1)
+			auto_append_extension(output_file, ".gz");
+	}
+
+	message_stream << Const::program_name << " v" << Const::version_string << "." << (unsigned)Const::build_version << " | by Benjamin Buchfink <buchfink at gmail.com>" << endl;
+	message_stream << "Check http://github.com/bbuchfink/diamond for updates." << endl << endl;
+#ifndef NDEBUG
+	verbose_stream << "Assertions enabled." << endl;
+#endif
+	set_option(threads_, tthread::thread::hardware_concurrency());
+
+	switch (command) {
+	case Config::makedb:
+	case Config::blastp:
+	case Config::blastx:
+	case Config::view:
+		message_stream << "#CPU threads: " << threads_ << endl;
+	default:
+		;
+	}
+
+	if (command == Config::blastp || command == Config::blastx || command == Config::benchmark || command == Config::model_sim) {
+		if (tmpdir == "")
+			tmpdir = extract_dir(output_file);
+		if (gap_open == -1)
+			gap_open = 11;
+		if (gap_extend == -1)
+			gap_extend = 1;
+		if (matrix_file == "")
+			score_matrix = Score_matrix(to_upper_case(matrix), gap_open, gap_extend, reward, penalty);
+		else {
+			if (lambda == 0 || K == 0)
+				throw std::runtime_error("Custom scoring matrices require setting the --lambda and --K options.");
+			score_matrix = Score_matrix(matrix_file, lambda, K, gap_open, gap_extend);
+		}
+		message_stream << "Scoring parameters: " << score_matrix << endl;
+		raw_ungapped_xdrop = score_matrix.rawscore(ungapped_xdrop);
+		min_diag_raw_score = score_matrix.rawscore(min_diag_score);
+		raw_space_penalty = score_matrix.rawscore(space_penalty, double());
+		log_stream << "Min_diag_score=" << min_diag_raw_score << " space_penalty=" << raw_space_penalty << endl;
+		init_cbs();
+
+		if (seg == "" && command == blastx)
+			seg = "yes";
+		verbose_stream << "SEG masking = " << (seg == "yes") << endl;
+		have_ssse3 = check_SSSE3();
+		if (have_ssse3)
+			verbose_stream << "SSSE3 enabled." << endl;
+		verbose_stream << "Reduction: " << Reduction::reduction << endl;
+
+		if (mode_more_sensitive) {
+			set_option(index_mode, 1u);
+			set_option(freq_sd, 200.0);
+		}
+		else if (mode_sensitive) {
+			set_option(index_mode, 1u);
+			set_option(freq_sd, 10.0);
+		}
+		else {
+			set_option(index_mode, 0u);
+			set_option(freq_sd, 50.0);
+		}
+
+		verbose_stream << "Seed frequency SD: " << freq_sd << endl;
+		::shapes = shape_config(index_mode, shapes, shape_mask);
+		verbose_stream << "Shape configuration: " << ::shapes << endl;
+		seed_anchor = std::min(::shapes[0].length_ - 1, 8u);
+
+		message_stream << "#Target sequences to report alignments for: ";
+		if (max_alignments == 0) {
+			max_alignments = std::numeric_limits<uint64_t>::max();
+			message_stream << "unlimited" << endl;
+		}
+		else
+			message_stream << max_alignments << endl;
+
+		if(mode_very_sensitive)
+			set_option(chunk_size, 0.4);
+	}
+
+	Translator::init(query_gencode);
+
+	if (command == blastx)
+		input_value_traits = nucleotide_traits;
+
+	if (command == help)
+		parser.print_help();
+
+	/*log_stream << "sizeof(hit)=" << sizeof(hit) << " sizeof(packed_uint40_t)=" << sizeof(packed_uint40_t)
+		<< " sizeof(sorted_list::entry)=" << sizeof(sorted_list::entry) << endl;*/
+}
diff --git a/src/basic/config.h b/src/basic/config.h
new file mode 100644
index 0000000..c6fe486
--- /dev/null
+++ b/src/basic/config.h
@@ -0,0 +1,195 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+using std::string;
+using std::vector;
+
+struct Config
+{
+	string	input_ref_file;
+	unsigned	threads_;
+	string	database;
+	string	query_file;
+	unsigned	merge_seq_treshold;
+	unsigned	hit_cap;
+	double min_ungapped_score;
+	int		min_ungapped_raw_score;
+	unsigned shapes;
+	unsigned	index_mode;
+	uint64_t	max_alignments;
+	string	match_file1;
+	string	match_file2;
+	int		padding;
+	unsigned	output_threads;
+	unsigned compression;
+	unsigned		lowmem;
+	double	chunk_size;
+	unsigned min_identities;
+	unsigned min_identities2;
+	double ungapped_xdrop;
+	int		raw_ungapped_xdrop;
+	unsigned window;
+	double		min_hit_score;
+	int min_hit_raw_score;
+	int		hit_band;
+	unsigned	min_compressed_identities;
+	int		min_seed_score;
+	unsigned	seed_signatures;
+	double	min_bit_score;
+	unsigned	run_len;
+	bool		alignment_traceback;
+	double	max_seed_freq;
+	string	tmpdir;
+	bool		long_mode;
+	int		gapped_xdrop;
+	double	max_evalue;
+	string	kegg_file;
+	int		gap_open;
+	int		gap_extend;
+	string	matrix;
+	string	seg;
+	bool debug_log, verbose, quiet;
+	bool		have_ssse3;
+	bool		salltitles;
+	int		reward;
+	int		penalty;
+	string	db_type;
+	double	min_id;
+	unsigned	compress_temp;
+	double	toppercent;
+	string	daa_file;
+	vector<string>	output_format;
+	string	output_file;
+	bool		forwardonly;
+	unsigned fetch_size;
+	uint64_t	db_size;
+	double	query_cover;
+
+	bool		mode_sensitive;
+	unsigned	verbosity;
+	bool no_auto_append;
+	unsigned local_align_mode;
+	bool extend_all;
+	bool slow_search;
+	vector<string> seq_no;
+	double rank_factor;
+	double rank_ratio;
+	bool ht_mode;
+	bool old_freq;
+	double freq_sd;
+	bool query_parallel;
+	unsigned target_fetch_size;
+	bool mode_more_sensitive;
+	string matrix_file;
+	double lambda, K;
+	vector<string> shape_mask;
+	unsigned seed_anchor;
+	unsigned query_gencode;
+	string unaligned;
+	double space_penalty, raw_space_penalty;
+	double min_diag_score;
+	int min_diag_raw_score;
+	bool new_prefilter;
+	bool reverse;
+	unsigned comp_based_stats;
+	int neighborhood_score;
+	unsigned seed_weight;
+	int report_unaligned;
+	double subject_cover;
+	bool mode_very_sensitive;
+	unsigned max_hsps;
+	bool no_self_hits;
+
+	enum {
+		makedb = 0, blastp = 1, blastx = 2, view = 3, help = 4, version = 5, getseq = 6, benchmark = 7, random_seqs = 8, compare = 9, sort = 10, roc = 11, db_stat = 12, model_sim = 13,
+		match_file_stat = 14, model_seqs = 15
+	};
+	unsigned	command;
+
+	enum { double_indexed = 0, subject_indexed = 1 };
+	unsigned algo;
+
+	Config() {}
+	Config(int argc, const char **argv);
+
+	inline unsigned get_run_len(unsigned length)
+	{
+		if (run_len == 0) {
+			if (length < 30)
+				return 1;
+			else if (length < 100)
+				return 20;
+			else
+				return 40;
+		}
+		else
+			return run_len;
+	}
+
+	inline bool output_range(unsigned n_target_seq, int score, int top_score)
+	{
+		if (toppercent < 100)
+			return (1.0 - (double)score / top_score) * 100 <= toppercent;
+		else
+			return n_target_seq < max_alignments;
+	}
+
+	/*unsigned read_padding(size_t len)
+	{
+		if (padding == 0) {
+			if (len <= 255)
+				return 10;
+			else
+				return 32;
+		}
+		else
+			return padding;
+	}*/
+
+	unsigned read_padding(size_t len)
+	{
+		if (padding == 0) {
+			if (mode_very_sensitive)
+				return 60;
+			else if (len <= 35)
+				return 5;
+			else if (len <= 55)
+				return 16;
+			else
+				return 32;
+		}
+		else
+			return padding;
+	}
+
+	bool mem_buffered() const { return tmpdir == "/dev/shm"; }
+
+  	template<typename _t>
+	static void set_option(_t& option, _t value) { if (option == 0) option = value; }
+};
+
+extern Config config;
+
+#endif
\ No newline at end of file
diff --git a/src/basic/const.h b/src/basic/const.h
new file mode 100644
index 0000000..ef72f05
--- /dev/null
+++ b/src/basic/const.h
@@ -0,0 +1,46 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef CONST_H_
+#define CONST_H_
+
+struct Const
+{
+
+	enum {
+		build_version = 93,
+		daa_version = 0,
+		seedp_bits = 10,
+		seedp = 1<<seedp_bits,
+		max_seed_weight = 32,
+		max_shapes = 16,
+		max_shape_len = 32
+	};
+
+	static const char* version_string;
+	static const char* program_name;
+	static const char* id_delimiters;
+
+};
+
+#define SIMPLE_SEARCH
+// #define FREQUENCY_MASKING
+// #define ST_JOIN
+// #define NO_COLLISION_FILTER
+
+#endif /* CONST_H_ */
diff --git a/src/basic/hssp.cpp b/src/basic/hssp.cpp
new file mode 100644
index 0000000..518a526
--- /dev/null
+++ b/src/basic/hssp.cpp
@@ -0,0 +1,130 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "../align/align.h"
+
+bool Hsp_data::pass_through(const Diagonal_segment &d) const
+{
+	if (intersect(d.query_range(), query_range).length() != (size_t)d.len
+		|| intersect(d.subject_range(), subject_range).length() != (size_t)d.len)
+		return false;
+
+	Iterator it = begin();
+	const unsigned subject_end = d.j + d.len;
+	const unsigned diag = d.diag();
+	while (it.good()) {
+		if ((int)it.subject_pos >= d.j) {
+			if (it.subject_pos >= subject_end)
+				return true;
+			if (it.query_pos - it.subject_pos != diag)
+				return false;
+		}
+		++it;
+	}
+	return true;
+}
+
+bool Hsp_data::is_weakly_enveloped(const Hsp_data &j) const
+{
+	static const double overlap_factor = 0.9;
+	return score <= j.score
+		&& subject_range.overlap_factor(j.subject_range) >= overlap_factor
+		&& query_range.overlap_factor(j.query_range) >= overlap_factor;
+}
+
+void Hsp_data::merge(const Hsp_data &right, const Hsp_data &left, unsigned query_anchor, unsigned subject_anchor)
+{
+	length = right.length + left.length;
+	gap_openings = right.gap_openings + left.gap_openings;
+	identities = right.identities + left.identities;
+	mismatches = right.mismatches + left.mismatches;
+	score = right.score + left.score;
+	gaps = right.gaps + left.gaps;
+	gap_openings = right.gap_openings + left.gap_openings;
+	positives = right.positives + left.positives;
+	subject_range = interval(subject_anchor + 1 - left.subject_range.end_, subject_anchor + 1 + right.subject_range.end_);
+	query_range = interval(query_anchor + 1 - left.query_range.end_, query_anchor + 1 + right.query_range.end_);
+	transcript.data_.insert(transcript.data_.end(), left.transcript.data_.begin(), left.transcript.data_.end());
+	transcript.data_.insert(transcript.data_.end(), right.transcript.data_.rbegin(), right.transcript.data_.rend());
+	transcript.push_terminator();
+}
+
+void Hsp_data::set_source_range(unsigned frame, unsigned dna_len)
+{
+	this->frame = frame;
+	if (!align_mode.query_translated)
+		query_source_range = query_range;
+	else {
+		signed f = frame <= 2 ? frame + 1 : 2 - frame;
+		if (f > 0) {
+			query_source_range.begin_ = (f - 1) + 3 * query_range.begin_;
+			query_source_range.end_ = query_source_range.begin_ + 3 * query_range.length();
+			//query_end_dna = (f-1) + 3 * (l.query_begin_+l.query_len_-1) + 3;
+		}
+		else {
+			query_source_range.end_ = dna_len + f - 3 * query_range.begin_ + 1;
+			//query_end_dna = dna_len + (f + 1) - 3 * (l.query_begin_+l.query_len_-1) - 2;
+			query_source_range.begin_ = query_source_range.end_ - 3 * query_range.length();
+		}
+	}
+}
+
+Hsp_context& Hsp_context::parse()
+{
+	hsp_.length = hsp_.identities = hsp_.mismatches = hsp_.gap_openings = hsp_.positives = hsp_.gaps = 0;
+	unsigned d = 0;
+	Iterator i = begin();
+
+	for (; i.good(); ++i) {
+		++hsp_.length;
+		switch (i.op()) {
+		case op_match:
+			++hsp_.identities;
+			++hsp_.positives;
+			d = 0;
+			break;
+		case op_substitution:
+			++hsp_.mismatches;
+			if (i.score() > 0)
+				++hsp_.positives;
+			d = 0;
+			break;
+		case op_insertion:
+		case op_deletion:
+			if (d == 0)
+				++hsp_.gap_openings;
+			++d;
+			++hsp_.gaps;
+			break;
+		}
+	}
+
+	hsp_.query_range.end_ = i.query_pos;
+	hsp_.subject_range.end_ = i.subject_pos;
+
+	return *this;
+}
+
+Hsp_context& Hsp_context::set_query_source_range(unsigned oriented_query_begin)
+{
+	if(align_mode.query_translated)
+		hsp_.set_source_range(oriented_query_begin);
+	else
+		hsp_.query_source_range = hsp_.query_range;
+	return *this;
+}
\ No newline at end of file
diff --git a/src/basic/match.h b/src/basic/match.h
new file mode 100644
index 0000000..e10f0a5
--- /dev/null
+++ b/src/basic/match.h
@@ -0,0 +1,368 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef MATCH_H_
+#define MATCH_H_
+
+#include <limits>
+#include "sequence.h"
+#include "../util/util.h"
+#include "../util/async_buffer.h"
+#include "packed_loc.h"
+#include "../util/system.h"
+#include "value.h"
+#include "packed_transcript.h"
+#include "score_matrix.h"
+
+enum Strand { FORWARD, REVERSE };
+
+inline interval normalized_range(unsigned pos, int len, Strand strand)
+{
+	return strand == FORWARD
+			? interval (pos, pos + len)
+			: interval (pos + 1 + len, pos + 1);
+}
+
+struct Diagonal_segment
+{
+	Diagonal_segment():
+		len(0)
+	{}
+	Diagonal_segment(int query_pos, int subject_pos, int len, int score):
+		i(query_pos),
+		j(subject_pos),
+		len(len),
+		score (score)
+	{}
+	bool empty() const
+	{
+		return len == 0;
+	}
+	interval query_range() const
+	{
+		return interval(i, i + len);
+	}
+	interval subject_range() const
+	{
+		return interval(j, j + len);
+	}
+	int subject_last() const
+	{
+		return j + len - 1;
+	}
+	int query_last() const
+	{
+		return i + len - 1;
+	}
+	int subject_end() const
+	{
+		return j + len;
+	}
+	int query_end() const
+	{
+		return i + len;
+	}
+	int diag() const
+	{
+		return i - j;
+	}
+	bool is_enveloped(const Diagonal_segment &x) const
+	{
+		return score <= x.score
+			&& query_range().overlap_factor(x.query_range()) == 1
+			&& subject_range().overlap_factor(x.subject_range()) == 1;
+	}
+	Diagonal_segment transpose() const
+	{
+		return Diagonal_segment(j, i, len, score);
+	}
+	int partial_score(int diff) const
+	{
+		return score*std::max(len - diff, 0) / len;
+	}
+	bool operator<=(const Diagonal_segment &rhs) const
+	{
+		return i + len <= rhs.i && j + len <= rhs.j;
+	}
+	static bool cmp_subject(const Diagonal_segment &x, const Diagonal_segment &y)
+	{
+		return x.j < y.j;
+	}
+	static bool cmp_subject_end(const Diagonal_segment &x, const Diagonal_segment &y)
+	{
+		return x.subject_end() < y.subject_end();
+	}
+	friend int abs_shift(const Diagonal_segment &x, const Diagonal_segment &y)
+	{
+		return abs(x.diag() - y.diag());
+	}
+	int i, j, len, score;
+};
+
+struct Intermediate_record;
+
+struct Hsp_data
+{
+	Hsp_data():
+		score(0),
+		frame(0),
+		length(0),
+		identities(0),
+		mismatches(0),
+		positives(0),
+		gap_openings(0),
+		gaps(0)
+	{}
+	Hsp_data(int score):
+		score(unsigned(score)),
+		frame(0),
+		length(0),
+		identities(0),
+		mismatches(0),
+		positives(0),
+		gap_openings(0),
+		gaps(0)
+	{}
+	Hsp_data(const Intermediate_record &r, unsigned query_source_len);
+	struct Iterator
+	{
+		Iterator(const Hsp_data &parent):
+			query_pos(parent.query_range.begin_),
+			subject_pos(parent.subject_range.begin_),
+			ptr_(parent.transcript.ptr()),
+			count_(ptr_->count())
+		{ }
+		bool good() const
+		{
+			return *ptr_ != Packed_operation::terminator();
+		}
+		Iterator& operator++()
+		{
+			switch (op()) {
+			case op_deletion:
+				++subject_pos;
+				break;
+			case op_insertion:
+				++query_pos;
+				break;
+			case op_match:
+			case op_substitution:
+				++query_pos;
+				++subject_pos;
+			}
+			--count_;
+			if (count_ == 0) {
+				++ptr_;
+				count_ = ptr_->count();
+			}
+			return *this;
+		}
+		Edit_operation op() const
+		{
+			return ptr_->op();
+		}
+		bool to_next_match()
+		{
+			do {
+				this->operator++();
+			} while (good() && (op() == op_deletion || op() == op_insertion));
+			return good();
+		}
+		unsigned query_pos, subject_pos;
+	protected:
+		const Packed_operation *ptr_;
+		unsigned count_;
+	};
+	Iterator begin() const
+	{
+		return Iterator(*this);
+	}
+	void set_source_range(unsigned frame, unsigned dna_len);
+	void set_source_range(unsigned oriented_query_begin)
+	{
+		query_source_range = frame < 3 ? interval(oriented_query_begin, oriented_query_begin + 3 * query_range.length()) : interval(oriented_query_begin + 1 - 3 * query_range.length(), oriented_query_begin + 1);
+	}
+	interval oriented_range() const
+	{
+		if (frame < 3)
+			return interval(query_source_range.begin_, query_source_range.end_ - 1);
+		else
+			return interval(query_source_range.end_ - 1, query_source_range.begin_);
+	}
+	void set_translated_query_begin(unsigned oriented_query_begin, unsigned dna_len)
+	{
+		int f = frame <= 2 ? frame + 1 : 2 - frame;
+		if (f > 0)
+			query_range.begin_ = (oriented_query_begin - (f - 1)) / 3;
+		else
+			query_range.begin_ = (dna_len + f - oriented_query_begin) / 3;
+	}
+	int blast_query_frame() const
+	{
+		return align_mode.query_translated ? (frame <= 2 ? (int)frame + 1 : 2 - (int)frame) : 0;
+	}
+	bool operator<(const Hsp_data &rhs) const
+	{
+		return score > rhs.score;
+	}
+	double id_percent() const
+	{
+		return (double)identities * 100.0 / (double)length;
+	}
+	double query_cover_percent(unsigned query_source_len) const
+	{
+		return (double)query_source_range.length() * 100 / query_source_len;
+	}
+	double subject_cover_percent(unsigned subject_len) const
+	{
+		return (double)subject_range.length() * 100 / subject_len;
+	}
+	bool pass_through(const Diagonal_segment &d) const;
+	bool is_weakly_enveloped(const Hsp_data &j) const;
+	void merge(const Hsp_data &right, const Hsp_data &left, unsigned query_anchor, unsigned subject_anchor);
+	unsigned score, frame, length, identities, mismatches, positives, gap_openings, gaps;
+	interval query_source_range, query_range, subject_range;
+	Packed_transcript transcript;
+};
+
+struct Hsp_context
+{
+	Hsp_context(Hsp_data& hsp, unsigned query_id, const sequence &query, const sequence &source_query, const char *query_name, unsigned subject_id, unsigned orig_subject_id, const char *subject_name, unsigned subject_len, unsigned hit_num, unsigned hsp_num) :		
+		query(query),
+		source_query(source_query),
+		query_name(query_name),
+		subject_name(subject_name),
+		query_id(query_id),
+		subject_id(subject_id),
+		orig_subject_id(orig_subject_id),
+		subject_len(subject_len),
+		hit_num(hit_num),
+		hsp_num(hsp_num),
+		hsp_(hsp)
+	{}
+	struct Iterator : public Hsp_data::Iterator
+	{
+		Iterator(const Hsp_context &parent) :
+			Hsp_data::Iterator(parent.hsp_),
+			parent_(parent)
+		{ }
+		Letter query() const
+		{
+			return parent_.query[query_pos];
+		}
+		Letter subject() const
+		{
+			switch (op()) {
+			case op_substitution:
+			case op_deletion:
+				return ptr_->letter();
+			default:
+				return query();
+			}
+		}
+		char query_char() const
+		{
+			switch (op()) {
+			case op_deletion:
+				return '-';
+			default:
+				return value_traits.alphabet[(long)query()];
+			}
+		}
+		char subject_char() const
+		{
+			switch (op()) {
+			case op_insertion:
+				return '-';
+			default:
+				return value_traits.alphabet[(long)subject()];
+			}
+		}
+		char midline_char() const
+		{
+			switch (op()) {
+			case op_match:
+				return value_traits.alphabet[(long)query()];
+			case op_substitution:
+				return score() > 0 ? '+' : ' ';
+			default:
+				return ' ';
+			}
+		}
+		int score() const
+		{
+			return score_matrix(query(), subject());
+		}
+	private:
+		const Hsp_context &parent_;
+	};
+	Iterator begin() const
+	{
+		return Iterator(*this);
+	}
+	Packed_transcript::Const_iterator begin_old() const
+	{
+		return hsp_.transcript.begin();
+	}
+	unsigned score() const
+	{ return hsp_.score; }
+	double evalue() const
+	{
+		return score_matrix.evalue(score(), config.db_size, (unsigned)query.length());
+	}
+	double bit_score() const
+	{
+		return score_matrix.bitscore(score());
+	}
+	unsigned frame() const
+	{ return hsp_.frame; }
+	unsigned length() const
+	{ return hsp_.length; }
+	unsigned identities() const
+	{ return hsp_.identities; }
+	unsigned mismatches() const
+	{ return hsp_.mismatches; }
+	unsigned positives() const
+	{ return hsp_.positives; }
+	unsigned gap_openings() const
+	{ return hsp_.gap_openings; }
+	unsigned gaps() const
+	{ return hsp_.gaps; }
+	const interval& query_source_range() const
+	{ return hsp_.query_source_range; }
+	const interval& query_range() const
+	{ return hsp_.query_range; }
+	const interval& subject_range() const
+	{ return hsp_.subject_range; }
+	interval oriented_query_range() const
+	{ return hsp_.oriented_range(); }
+	int blast_query_frame() const
+	{ return hsp_.blast_query_frame(); }
+	Packed_transcript transcript() const
+	{ return hsp_.transcript; }
+	Hsp_context& parse();
+	Hsp_context& set_query_source_range(unsigned oriented_query_begin);
+
+	const sequence query, source_query;
+	const char *query_name, *subject_name;
+	const unsigned query_id, subject_id, orig_subject_id, subject_len, hit_num, hsp_num;
+private:	
+	Hsp_data &hsp_;
+};
+
+#endif /* MATCH_H_ */
diff --git a/src/basic/packed_loc.h b/src/basic/packed_loc.h
new file mode 100644
index 0000000..09294f4
--- /dev/null
+++ b/src/basic/packed_loc.h
@@ -0,0 +1,54 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef PACKED_LOC_H_
+#define PACKED_LOC_H_
+
+#include <stdint.h>
+#include "../util/system.h"
+
+#pragma pack(1)
+
+struct packed_uint40_t
+{
+	uint8_t		high;
+	uint32_t	low;
+	packed_uint40_t():
+		high (),
+		low ()
+	{ }
+	packed_uint40_t(uint64_t v):
+		high ((uint8_t)(v>>32)),
+		low ((uint32_t)(v&0xfffffffflu))
+	{ }
+	operator const uint64_t() const
+	{ return (uint64_t(high) << 32) | low; }
+	bool operator<(const packed_uint40_t &rhs) const
+	{ return high < rhs.high || (high == rhs.high && low < rhs.low); }
+	friend uint64_t operator-(const packed_uint40_t &x, const packed_uint40_t &y)
+	{ return (const uint64_t)(x) - (const uint64_t)(y); }
+} PACKED_ATTRIBUTE ;
+
+typedef packed_uint40_t Packed_loc;
+typedef size_t Loc;
+
+#pragma pack()
+
+#endif /* PACKED_LOC_H_ */
diff --git a/src/basic/packed_sequence.h b/src/basic/packed_sequence.h
new file mode 100644
index 0000000..572cc5f
--- /dev/null
+++ b/src/basic/packed_sequence.h
@@ -0,0 +1,110 @@
+/****
+Copyright (c) 2015, University of Tuebingen
+Author: Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef PACKED_SEQUENCE_H_
+#define PACKED_SEQUENCE_H_
+
+#include <vector>
+#include "value.h"
+#include "../util/binary_buffer.h"
+#include "sequence.h"
+
+using std::vector;
+
+inline bool has_n(const sequence &seq)
+{
+	for(unsigned i=0;i<seq.length();++i)
+		if(seq[i] == 4)
+			return true;
+	return false;
+}
+
+struct Packed_sequence
+{
+
+	Packed_sequence(const sequence &seq, Sequence_type type):
+		has_n_ (type == nucleotide ? ::has_n(seq) : false)
+	{
+		switch (type) {
+		case nucleotide:
+			if (has_n_)
+				pack<3>(seq);
+			else
+				pack<2>(seq);
+			break;
+		case amino_acid:
+			pack<5>(seq);
+		}
+	}
+
+	Packed_sequence(Binary_buffer::Iterator &it, unsigned len, bool has_n, unsigned b):
+		has_n_ (has_n)
+	{
+		const size_t l = (len*b+7)/8;
+		it.read(data_, l);
+	}
+
+	void unpack(vector<Letter> &dst, unsigned b, unsigned len)
+	{
+		dst.clear();
+		unsigned x = 0, n = 0, l = 0;
+		const unsigned mask = (1<<b)-1;
+		for(unsigned i=0;i<data_.size();++i) {
+			x |= (unsigned)data_[i] << n;
+			n += 8;
+			while(n >= b && l < len) {
+				dst.push_back(x & mask);
+				n -= b;
+				x >>= b;
+				++l;
+			}
+		}
+	}
+
+	const vector<uint8_t>& data() const
+	{ return data_; }
+
+	bool has_n() const
+	{ return has_n_; }
+
+private:
+
+	template<unsigned _b>
+	void pack(const sequence &seq)
+	{
+		unsigned x = 0, n = 0;
+		for(unsigned i=0;i<seq.length();++i) {
+			x |= (unsigned)seq[i] << n;
+			n += _b;
+			if(n >= 8) {
+				data_.push_back(x & 0xff);
+				n -= 8;
+				x >>= 8;
+			}
+		}
+		if(n > 0)
+			data_.push_back(x & 0xff);
+	}
+
+	bool has_n_;
+	vector<uint8_t> data_;
+
+};
+
+#endif /* PACKED_SEQUENCE_H_ */
diff --git a/src/basic/packed_transcript.h b/src/basic/packed_transcript.h
new file mode 100644
index 0000000..7c4856e
--- /dev/null
+++ b/src/basic/packed_transcript.h
@@ -0,0 +1,171 @@
+/****
+Copyright (c) 2015-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef PACKED_TRANSCRIPT_H_
+#define PACKED_TRANSCRIPT_H_
+
+#include "../util/binary_buffer.h"
+#include "../basic/value.h"
+
+typedef enum { op_match=0, op_insertion=1, op_deletion=2, op_substitution=3 } Edit_operation;
+
+struct Packed_operation
+{
+	Packed_operation(uint8_t code):
+		code (code)
+	{ }
+	Packed_operation(Edit_operation op, unsigned count):
+		code ((op<<6) | count)
+	{ }
+	Packed_operation(Edit_operation op, Letter v):
+		code ((op<<6) | (int)v)
+	{ }
+	operator uint8_t() const
+	{ return code; }
+	Edit_operation op() const
+	{ return (Edit_operation)(code>>6); }
+	unsigned count() const
+	{
+		switch (op()) {
+		case op_match:
+		case op_insertion:
+			return code & 63;
+		default:
+			return 1;
+		}
+	}
+	Letter letter() const
+	{ return code&63; }
+	static Packed_operation terminator()
+	{ return Packed_operation(op_match, 0u); }
+	uint8_t code;
+};
+
+struct Combined_operation
+{
+	Edit_operation op;
+	unsigned count;
+	Letter letter;
+};
+
+struct Packed_transcript
+{
+
+	struct Const_iterator
+	{
+		Const_iterator(const Packed_operation *op):
+			ptr_ (op)
+		{ gather(); }
+		bool good() const
+		{ return *ptr_ != Packed_operation::terminator(); }
+		Const_iterator& operator++()
+		{ ++ptr_; gather(); return *this; }
+		const Combined_operation& operator*() const
+		{ return op_; }
+		const Combined_operation* operator->() const
+		{ return &op_; }
+	private:
+		void gather()
+		{
+			if(!good())
+				return;
+			op_.op = ptr_->op();
+			if(op_.op == op_deletion || op_.op == op_substitution) {
+				op_.letter = ptr_->letter();
+				op_.count = 1;
+			} else {
+				op_.count = 0;
+				do {
+					op_.count += ptr_->count();
+					++ptr_;
+				} while(good() && ptr_->op() == op_.op);
+				--ptr_;
+			}
+		}
+		const Packed_operation *ptr_;
+		Combined_operation op_;
+	};
+
+	void read(Buffered_file &f)
+	{
+		data_.clear();
+		uint8_t code;
+		do {
+			f.read(code);
+			data_.push_back(code);
+		} while (code != Packed_operation::terminator());
+	}
+
+	void read(Binary_buffer::Iterator &it)
+	{
+		data_.clear();
+		uint8_t code;
+		do {
+			it >> code;
+			data_.push_back(code);
+		} while (code != Packed_operation::terminator());
+	}
+
+	Const_iterator begin() const
+	{ return Const_iterator (data_.data()); }
+
+	const vector<Packed_operation>& data() const
+	{ return data_; }
+
+	const Packed_operation* ptr() const
+	{
+		return &data_[0];
+	}
+
+	void push_back(Edit_operation op)
+	{
+		if (data_.empty() || data_.back().op() != op || (data_.back().op() == op && data_.back().count() == 63))
+			data_.push_back(Packed_operation(op, 1u));
+		else
+			++data_.back().code;
+	}
+
+	void push_back(Edit_operation op, Letter l)
+	{
+		data_.push_back(Packed_operation(op, l));
+	}
+
+	void push_back(Edit_operation op, unsigned count)
+	{
+		data_.push_back(Packed_operation(op, count));
+	}
+
+	void push_terminator()
+	{
+		data_.push_back(Packed_operation::terminator());
+	}
+
+	void clear()
+	{
+		data_.clear();
+	}
+
+private:
+
+	vector<Packed_operation> data_;
+
+	friend struct Hsp_data;
+
+};
+
+#endif /* PACKED_TRANSCRIPT_H_ */
diff --git a/src/basic/reduction.h b/src/basic/reduction.h
new file mode 100644
index 0000000..41cc45a
--- /dev/null
+++ b/src/basic/reduction.h
@@ -0,0 +1,105 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef REDUCTION_H_
+#define REDUCTION_H_
+
+#include <vector>
+#include <string>
+#include <string.h>
+#include "value.h"
+#include "../util/util.h"
+#include "sequence.h"
+
+using std::string;
+using std::vector;
+
+struct Reduction
+{
+
+	Reduction(const char *definition_string)
+	{
+		memset(map_, 0, sizeof(map_));
+		memset(map8_, 0, sizeof(map8_));
+		map_[(long)value_traits.mask_char] = value_traits.mask_char;
+		const vector<string> tokens(tokenize(definition_string, " "));
+		size_ = (unsigned)tokens.size();
+		for (unsigned i = 0; i<size_; ++i)
+			for (unsigned j = 0; j<tokens[i].length(); ++j) {
+				const char ch = tokens[i][j];
+				map_[(long)value_traits.from_char(ch)] = i;
+				map8_[(long)value_traits.from_char(ch)] = i;
+			}
+		map8_[(long)value_traits.mask_char] = (char)size_;
+	}
+
+	unsigned size() const
+	{
+		return size_;
+	}
+
+	unsigned operator()(Letter a) const
+	{
+		return map_[(long)a];
+	}
+
+	const char* map8() const
+	{
+		return map8_;
+	}
+
+	inline friend std::ostream& operator<<(std::ostream &os, const Reduction &r)
+	{
+		for (unsigned i = 0; i < r.size_; ++i) {
+			os << '[';
+			for (unsigned j = 0; j < 20; ++j)
+				if (r. map_[j] == i)
+					os << value_traits.alphabet[j];
+			os << ']';
+		}
+		return os;
+	}
+
+	static void reduce_seq(const sequence &seq, vector<char> &dst)
+	{
+		dst.resize(seq.length());
+		for (unsigned i = 0; i < seq.length(); ++i)
+			dst[i] = reduction(seq[i]);
+	}
+
+	static Reduction reduction;
+
+private:
+
+	unsigned map_[256];
+#ifdef _MSC_VER
+	__declspec(align(16)) char map8_[256];
+#else
+	char map8_[256] __attribute__((aligned(16)));
+#endif
+	unsigned size_;
+
+};
+
+#ifdef EXTRA
+#include "../../../extra/reduction.h"
+#endif
+
+#endif /* REDUCTION_H_ */
diff --git a/src/basic/score_matrix.cpp b/src/basic/score_matrix.cpp
new file mode 100644
index 0000000..1a925e3
--- /dev/null
+++ b/src/basic/score_matrix.cpp
@@ -0,0 +1,274 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <string>
+#include <limits>
+#include <algorithm>
+#include <stdexcept>
+#include <fstream>
+#include "score_matrix.h"
+#include "../blast/raw_scoremat.h"
+
+using std::string;
+
+Score_matrix score_matrix;
+
+/** Number of statistical parameters in each row of the precomputed tables. */
+#define BLAST_NUM_STAT_VALUES 11  /**< originally 8, now 11 to support Spouge's FSC. see notes below */
+
+/** Holds values (gap-opening, extension, etc.) for a matrix. */
+typedef double array_of_8[BLAST_NUM_STAT_VALUES];
+
+const double INT2_MAX = std::numeric_limits<double>::max();
+
+#define BLOSUM45_VALUES_MAX 14 /**< Number of different combinations supported for BLOSUM45. */
+static array_of_8 blosum45_values[BLOSUM45_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.2291, 0.0924, 0.2514, 0.9113, -5.7, 0.641318, 9.611060, 9.611060 },
+	{ 13, 3, (double)INT2_MAX, 0.207, 0.049, 0.14, 1.5, -22, 0.671128, 35.855900, 35.963900 },
+	{ 12, 3, (double)INT2_MAX, 0.199, 0.039, 0.11, 1.8, -34, 0.691530, 45.693600, 45.851700 },
+	{ 11, 3, (double)INT2_MAX, 0.190, 0.031, 0.095, 2.0, -38, 0.691181, 62.874100, 63.103700 },
+	{ 10, 3, (double)INT2_MAX, 0.179, 0.023, 0.075, 2.4, -51, 0.710529, 88.286800, 88.639100 },
+	{ 16, 2, (double)INT2_MAX, 0.210, 0.051, 0.14, 1.5, -24, 0.666680, 36.279800, 36.452400 },
+	{ 15, 2, (double)INT2_MAX, 0.203, 0.041, 0.12, 1.7, -31, 0.673871, 44.825700, 45.060400 },
+	{ 14, 2, (double)INT2_MAX, 0.195, 0.032, 0.10, 1.9, -36, 0.685753, 60.736200, 61.102300 },
+	{ 13, 2, (double)INT2_MAX, 0.185, 0.024, 0.084, 2.2, -45, 0.698480, 85.148100, 85.689400 },
+	{ 12, 2, (double)INT2_MAX, 0.171, 0.016, 0.061, 2.8, -65, 0.713429, 127.758000, 128.582000 },
+	{ 19, 1, (double)INT2_MAX, 0.205, 0.040, 0.11, 1.9, -43, 0.672302, 53.071400, 53.828200 },
+	{ 18, 1, (double)INT2_MAX, 0.198, 0.032, 0.10, 2.0, -43, 0.682580, 72.342400, 73.403900 },
+	{ 17, 1, (double)INT2_MAX, 0.189, 0.024, 0.079, 2.4, -57, 0.695035, 103.055000, 104.721000 },
+	{ 16, 1, (double)INT2_MAX, 0.176, 0.016, 0.063, 2.8, -67, 0.712966, 170.100000, 173.003000 },
+};  /**< Supported values (gap-existence, extension, etc.) for BLOSUM45. */
+
+#define BLOSUM50_VALUES_MAX 16 /**< Number of different combinations supported for BLOSUM50. */
+static array_of_8 blosum50_values[BLOSUM50_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.2318, 0.112, 0.3362, 0.6895, -4.0, 0.609639, 5.388310, 5.388310 },
+	{ 13, 3, (double)INT2_MAX, 0.212, 0.063, 0.19, 1.1, -16, 0.639287, 18.113800, 18.202800 },
+	{ 12, 3, (double)INT2_MAX, 0.206, 0.055, 0.17, 1.2, -18, 0.644715, 22.654600, 22.777700 },
+	{ 11, 3, (double)INT2_MAX, 0.197, 0.042, 0.14, 1.4, -25, 0.656327, 29.861100, 30.045700 },
+	{ 10, 3, (double)INT2_MAX, 0.186, 0.031, 0.11, 1.7, -34, 0.671150, 42.393800, 42.674000 },
+	{ 9, 3, (double)INT2_MAX, 0.172, 0.022, 0.082, 2.1, -48, 0.694326, 66.069600, 66.516400 },
+	{ 16, 2, (double)INT2_MAX, 0.215, 0.066, 0.20, 1.05, -15, 0.633899, 17.951800, 18.092100 },
+	{ 15, 2, (double)INT2_MAX, 0.210, 0.058, 0.17, 1.2, -20, 0.641985, 21.940100, 22.141800 },
+	{ 14, 2, (double)INT2_MAX, 0.202, 0.045, 0.14, 1.4, -27, 0.650682, 28.681200, 28.961900 },
+	{ 13, 2, (double)INT2_MAX, 0.193, 0.035, 0.12, 1.6, -32, 0.660984, 42.059500, 42.471600 },
+	{ 12, 2, (double)INT2_MAX, 0.181, 0.025, 0.095, 1.9, -41, 0.678090, 63.747600, 64.397300 },
+	{ 19, 1, (double)INT2_MAX, 0.212, 0.057, 0.18, 1.2, -21, 0.635714, 26.311200, 26.923300 },
+	{ 18, 1, (double)INT2_MAX, 0.207, 0.050, 0.15, 1.4, -28, 0.643523, 34.903700, 35.734800 },
+	{ 17, 1, (double)INT2_MAX, 0.198, 0.037, 0.12, 1.6, -33, 0.654504, 48.895800, 50.148600 },
+	{ 16, 1, (double)INT2_MAX, 0.186, 0.025, 0.10, 1.9, -42, 0.667750, 76.469100, 78.443000 },
+	{ 15, 1, (double)INT2_MAX, 0.171, 0.015, 0.063, 2.7, -76, 0.694575, 140.053000, 144.160000 },
+};  /**< Supported values (gap-existence, extension, etc.) for BLOSUM50. */
+
+#define BLOSUM62_VALUES_MAX 12 /**< Number of different combinations supported for BLOSUM62. */
+static array_of_8 blosum62_values[BLOSUM62_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.3176, 0.134, 0.4012, 0.7916, -3.2, 0.623757, 4.964660, 4.964660 },
+	{ 11, 2, (double)INT2_MAX, 0.297, 0.082, 0.27, 1.1, -10, 0.641766, 12.673800, 12.757600 },
+	{ 10, 2, (double)INT2_MAX, 0.291, 0.075, 0.23, 1.3, -15, 0.649362, 16.474000, 16.602600 },
+	{ 9, 2, (double)INT2_MAX, 0.279, 0.058, 0.19, 1.5, -19, 0.659245, 22.751900, 22.950000 },
+	{ 8, 2, (double)INT2_MAX, 0.264, 0.045, 0.15, 1.8, -26, 0.672692, 35.483800, 35.821300 },
+	{ 7, 2, (double)INT2_MAX, 0.239, 0.027, 0.10, 2.5, -46, 0.702056, 61.238300, 61.886000 },
+	{ 6, 2, (double)INT2_MAX, 0.201, 0.012, 0.061, 3.3, -58, 0.740802, 140.417000, 141.882000 },
+	{ 13, 1, (double)INT2_MAX, 0.292, 0.071, 0.23, 1.2, -11, 0.647715, 19.506300, 19.893100 },
+	{ 12, 1, (double)INT2_MAX, 0.283, 0.059, 0.19, 1.5, -19, 0.656391, 27.856200, 28.469900 },
+	{ 11, 1, (double)INT2_MAX, 0.267, 0.041, 0.14, 1.9, -30, 0.669720, 42.602800, 43.636200 },
+	{ 10, 1, (double)INT2_MAX, 0.243, 0.024, 0.10, 2.5, -44, 0.693267, 83.178700, 85.065600 },
+	{ 9, 1, (double)INT2_MAX, 0.206, 0.010, 0.052, 4.0, -87, 0.731887, 210.333000, 214.842000 },
+}; /**< Supported values (gap-existence, extension, etc.) for BLOSUM62. */
+
+#define BLOSUM80_VALUES_MAX 10 /**< Number of different combinations supported for BLOSUM80. */
+static array_of_8 blosum80_values[BLOSUM80_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.3430, 0.177, 0.6568, 0.5222, -1.6, 0.564057, 1.918130, 1.918130 },
+	{ 25, 2, (double)INT2_MAX, 0.342, 0.17, 0.66, 0.52, -1.6, 0.563956, 1.731000, 1.731300 },
+	{ 13, 2, (double)INT2_MAX, 0.336, 0.15, 0.57, 0.59, -3, 0.570979, 2.673470, 2.692300 },
+	{ 9, 2, (double)INT2_MAX, 0.319, 0.11, 0.42, 0.76, -6, 0.587837, 5.576090, 5.667860 },
+	{ 8, 2, (double)INT2_MAX, 0.308, 0.090, 0.35, 0.89, -9, 0.597556, 7.536950, 7.686230 },
+	{ 7, 2, (double)INT2_MAX, 0.293, 0.070, 0.27, 1.1, -14, 0.615254, 11.586600, 11.840400 },
+	{ 6, 2, (double)INT2_MAX, 0.268, 0.045, 0.19, 1.4, -19, 0.644054, 19.958100, 20.441200 },
+	{ 11, 1, (double)INT2_MAX, 0.314, 0.095, 0.35, 0.90, -9, 0.590702, 8.808610, 9.223320 },
+	{ 10, 1, (double)INT2_MAX, 0.299, 0.071, 0.27, 1.1, -14, 0.609620, 13.833800, 14.533400 },
+	{ 9, 1, (double)INT2_MAX, 0.279, 0.048, 0.20, 1.4, -19, 0.623800, 24.252000, 25.490400 },
+}; /**< Supported values (gap-existence, extension, etc.) for BLOSUM80. */
+
+#define BLOSUM90_VALUES_MAX 8 /**< Number of different combinations supported for BLOSUM90. */
+static array_of_8 blosum90_values[BLOSUM90_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.3346, 0.190, 0.7547, 0.4434, -1.4 , 0.544178, 1.377760, 1.377760 },
+	{ 9, 2, (double)INT2_MAX, 0.310, 0.12, 0.46, 0.67, -6 , 0.570267, 4.232290, 4.334170 },
+	{ 8, 2, (double)INT2_MAX, 0.300, 0.099, 0.39, 0.76, -7, 0.581580, 5.797020, 5.961420 },
+	{ 7, 2, (double)INT2_MAX, 0.283, 0.072, 0.30, 0.93, -11, 0.600024, 9.040880, 9.321600 },
+	{ 6, 2, (double)INT2_MAX, 0.259, 0.048, 0.22, 1.2, -16, 0.629344, 16.024400, 16.531600 },
+	{ 11, 1, (double)INT2_MAX, 0.302, 0.093, 0.39, 0.78, -8, 0.576919, 7.143250, 7.619190 },
+	{ 10, 1, (double)INT2_MAX, 0.290, 0.075, 0.28, 1.04, -15, 0.591366, 11.483900, 12.269800 },
+	{ 9, 1, (double)INT2_MAX, 0.265, 0.044, 0.20, 1.3, -19, 0.613013, 21.408300, 22.840900 },
+};  /**< Supported values (gap-existence, extension, etc.) for BLOSUM90. */
+
+#define PAM250_VALUES_MAX 16 /**< Number of different combinations supported for PAM250. */
+static array_of_8 pam250_values[PAM250_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.2252, 0.0868, 0.2223, 0.98, -5.0, 0.660059, 11.754300, 11.754300 },
+	{ 15, 3, (double)INT2_MAX, 0.205, 0.049, 0.13, 1.6, -23, 0.687656, 34.578400, 34.928000 },
+	{ 14, 3, (double)INT2_MAX, 0.200, 0.043, 0.12, 1.7, -26, 0.689768, 43.353000, 43.443800 },
+	{ 13, 3, (double)INT2_MAX, 0.194, 0.036, 0.10, 1.9, -31, 0.697431, 50.948500, 51.081700 },
+	{ 12, 3, (double)INT2_MAX, 0.186, 0.029, 0.085, 2.2, -41, 0.704565, 69.606500, 69.793600 },
+	{ 11, 3, (double)INT2_MAX, 0.174, 0.020, 0.070, 2.5, -48, 0.722438, 98.653500, 98.927100 },
+	{ 17, 2, (double)INT2_MAX, 0.204, 0.047, 0.12, 1.7, -28, 0.684799, 41.583800, 41.735800 },
+	{ 16, 2, (double)INT2_MAX, 0.198, 0.038, 0.11, 1.8, -29, 0.691098, 51.635200, 51.843900 },
+	{ 15, 2, (double)INT2_MAX, 0.191, 0.031, 0.087, 2.2, -44, 0.699051, 67.256700, 67.558500 },
+	{ 14, 2, (double)INT2_MAX, 0.182, 0.024, 0.073, 2.5, -53, 0.714103, 96.315100, 96.756800 },
+	{ 13, 2, (double)INT2_MAX, 0.171, 0.017, 0.059, 2.9, -64, 0.728738, 135.653000, 136.339000 },
+	{ 21, 1, (double)INT2_MAX, 0.205, 0.045, 0.11, 1.8, -34, 0.683265, 48.728200, 49.218800 },
+	{ 20, 1, (double)INT2_MAX, 0.199, 0.037, 0.10, 1.9, -35, 0.689380, 60.832000, 61.514100 },
+	{ 19, 1, (double)INT2_MAX, 0.192, 0.029, 0.083, 2.3, -52, 0.696344, 84.019700, 84.985600 },
+	{ 18, 1, (double)INT2_MAX, 0.183, 0.021, 0.070, 2.6, -60, 0.710525, 113.829000, 115.184000 },
+	{ 17, 1, (double)INT2_MAX, 0.171, 0.014, 0.052, 3.3, -86, 0.727000, 175.071000, 177.196000 },
+}; /**< Supported values (gap-existence, extension, etc.) for PAM250. */
+
+#define PAM30_VALUES_MAX 7 /**< Number of different combinations supported for PAM30. */
+static array_of_8 pam30_values[PAM30_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.3400, 0.283, 1.754, 0.1938, -0.3, 0.436164, 0.161818, 0.161818 },
+	{ 7, 2, (double)INT2_MAX, 0.305, 0.15, 0.87, 0.35, -3, 0.479087, 1.014010, 1.162730 },
+	{ 6, 2, (double)INT2_MAX, 0.287, 0.11, 0.68, 0.42, -4, 0.499980, 1.688060, 1.951430 },
+	{ 5, 2, (double)INT2_MAX, 0.264, 0.079, 0.45, 0.59, -7, 0.533009, 3.377010, 3.871950 },
+	{ 10, 1, (double)INT2_MAX, 0.309, 0.15, 0.88, 0.35, -3, 0.474741, 1.372050, 1.788770 },
+	{ 9, 1, (double)INT2_MAX, 0.294, 0.11, 0.61, 0.48, -6, 0.492716, 2.463920, 3.186150 },
+	{ 8, 1, (double)INT2_MAX, 0.270, 0.072, 0.40, 0.68, -10, 0.521286, 5.368130, 6.763480 },
+}; /**< Supported values (gap-existence, extension, etc.) for PAM30. */
+
+
+#define PAM70_VALUES_MAX 7 /**< Number of different combinations supported for PAM70. */
+static array_of_8 pam70_values[PAM70_VALUES_MAX] = {
+	{ (double)INT2_MAX, (double)INT2_MAX, (double)INT2_MAX, 0.3345, 0.229, 1.029, 0.3250,   -0.7, 0.511296, 0.633439, 0.633439 },
+	{ 8, 2, (double)INT2_MAX, 0.301, 0.12, 0.54, 0.56, -5, 0.549019, 2.881650, 3.025710 },
+	{ 7, 2, (double)INT2_MAX, 0.286, 0.093, 0.43, 0.67, -7, 0.565659, 4.534540, 4.785780 },
+	{ 6, 2, (double)INT2_MAX, 0.264, 0.064, 0.29, 0.90, -12, 0.596330, 7.942630, 8.402720 },
+	{ 11, 1, (double)INT2_MAX, 0.305, 0.12, 0.52, 0.59, -6, 0.543514, 3.681400, 4.108020 },
+	{ 10, 1, (double)INT2_MAX, 0.291, 0.091, 0.41, 0.71, -9, 0.560723, 6.002970, 6.716570 },
+	{ 9, 1, (double)INT2_MAX, 0.270, 0.060, 0.28, 0.97, -14, 0.585186, 11.360800, 12.636700 },
+}; /**< Supported values (gap-existence, extension, etc.) for PAM70. */
+
+struct Matrix_info
+{
+	const char *name;
+	const array_of_8 *constants;
+	const char *scores;
+	const unsigned count;
+
+	static const Matrix_info& get(const string &name)
+	{
+		for (unsigned i = 0; i < sizeof(matrices) / sizeof(matrices[0]); ++i)
+			if (name == matrices[i].name)
+				return matrices[i];
+		throw std::runtime_error("Invalid scoring matrix: " + name);
+		return matrices[0];
+	}
+
+	const double* get_constants(int gap_open, int gap_extend) const
+	{
+		for (unsigned i = 0; i < count; ++i)
+			if (constants[i][0] == gap_open && constants[i][1] == gap_extend)
+				return constants[i];
+		throw std::runtime_error("Invalid gap open and/or gap extend scores.");
+		return 0;
+	}
+
+	static const Matrix_info matrices[8];
+};
+
+const Matrix_info Matrix_info::matrices[] = {
+	{ "BLOSUM45", blosum45_values, (const char*)NCBISM_Blosum45.scores, BLOSUM45_VALUES_MAX },
+	{ "BLOSUM50", blosum50_values, (const char*)NCBISM_Blosum50.scores, BLOSUM50_VALUES_MAX },
+	{ "BLOSUM62", blosum62_values, (const char*)NCBISM_Blosum62.scores, BLOSUM62_VALUES_MAX },
+	{ "BLOSUM80", blosum80_values, (const char*)NCBISM_Blosum80.scores, BLOSUM80_VALUES_MAX },
+	{ "BLOSUM90", blosum90_values, (const char*)NCBISM_Blosum90.scores, BLOSUM90_VALUES_MAX },
+	{ "PAM70", pam70_values, (const char*)NCBISM_Pam70.scores, PAM70_VALUES_MAX },
+	{ "PAM250", pam250_values, (const char*)NCBISM_Pam250.scores, PAM250_VALUES_MAX },
+	{ "PAM30", pam30_values, (const char*)NCBISM_Pam30.scores, PAM30_VALUES_MAX }
+};
+
+Score_matrix::Score_matrix(const string & matrix, int gap_open, int gap_extend, int reward, int penalty):
+	gap_open_ (gap_open),
+	gap_extend_ (gap_extend),
+	constants_ (Matrix_info::get(matrix).get_constants(gap_open, gap_extend)),	
+	name_(matrix),
+	matrix8_(Matrix_info::get(matrix).scores),
+	bias_((char)(-low_score())),
+	matrix8u_(Matrix_info::get(matrix).scores, bias_),
+	matrix16_(Matrix_info::get(matrix).scores)
+{ }
+
+char Score_matrix::low_score() const
+{
+	char low = std::numeric_limits<char>::max();
+	for (Letter i = 0; i < (char)value_traits.alphabet_size; ++i)
+		for (Letter j = i + 1; j < (char)value_traits.alphabet_size; ++j)
+			low = std::min(low, (char)this->operator()(i, j));
+	return low;
+}
+
+const char* custom_scores(const string &matrix_file)
+{
+	static char scores[25 * 25];
+	string l, s;
+	std::stringstream ss;
+	vector<Letter> pos;
+	unsigned n = 0;
+	memset(scores, 0xff, sizeof(scores));
+	if (matrix_file == "")
+		return scores;
+	std::ifstream f(matrix_file.c_str());
+	while (!f.eof()) {
+		std::getline(f, l);
+		if (l[0] == '#')
+			continue;
+		if (pos.size() == 0) {
+			for (string::const_iterator i = l.begin(); i != l.end(); ++i)
+				if (*i == ' ' || *i == '\t')
+					continue;
+				else
+					pos.push_back(value_traits.from_char(*i));
+		}
+		else {
+			if (n >= pos.size())
+				break;
+			ss << l;
+			if (value_traits.from_char(ss.get()) != pos[n])
+				throw std::runtime_error("Invalid custom scoring matrix file format.");
+			for (unsigned i = 0; i < pos.size(); ++i) {
+				int score;
+				ss >> score;
+				scores[(int)pos[n] * 25 + (int)pos[i]] = score;
+			}
+			ss.clear();
+			++n;
+		}
+	}
+	return scores;
+}
+
+Score_matrix::Score_matrix(const string &matrix_file, double lambda, double K, int gap_open, int gap_extend):
+	gap_open_(gap_open),
+	gap_extend_(gap_extend),
+	name_("custom"),
+	matrix8_(custom_scores(matrix_file)),
+	bias_((char)(-low_score())),
+	matrix8u_(custom_scores(matrix_file), bias_),
+	matrix16_(custom_scores(matrix_file))
+{
+	static double constants[5];
+	constants[3] = lambda;
+	constants[4] = K;
+	constants_ = constants;
+}
\ No newline at end of file
diff --git a/src/basic/score_matrix.h b/src/basic/score_matrix.h
new file mode 100644
index 0000000..fd599c0
--- /dev/null
+++ b/src/basic/score_matrix.h
@@ -0,0 +1,136 @@
+/****
+Copyright (c) 2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SCORE_MATRIX_H_
+#define SCORE_MATRIX_H_
+
+#include <limits>
+#include <iostream>
+#include <math.h>
+#include <stdint.h>
+#include "../util/log_stream.h"
+#include "value.h"
+
+using std::string;
+using std::cout;
+using std::endl;
+
+const double LN_2 = 0.69314718055994530941723212145818;
+
+struct Score_matrix
+{
+
+	Score_matrix() {}
+	Score_matrix(const string &matrix, int gap_open, int gap_extend, int reward, int penalty);
+	Score_matrix(const string &matrix_file, double lambda, double K, int gap_open, int gap_extend);
+
+	friend std::ostream& operator<<(std::ostream& s, const Score_matrix &m)
+	{
+		s << "(Matrix=" << m.name_
+			<< " Lambda=" << m.lambda()
+			<< " K=" << m.k()
+			<< " Penalties=" << m.gap_open_
+			<< '/' << m.gap_extend_ << ')';
+		return s;
+	}
+
+	const int8_t* matrix8() const
+	{ return matrix8_.data; }
+
+	const uint8_t* matrix8u() const
+	{ return matrix8u_.data; }
+
+	const int16_t* matrix16() const
+	{ return matrix16_.data; }
+
+	int operator()(Letter a, Letter b) const
+	{
+		return matrix8_.data[(int(a) << 5) + int(b)];
+	}
+
+	uint8_t biased_score(Letter a, Letter b) const
+	{ return matrix8u_.data[(int(a) << 5) + int(b)]; }
+
+	char bias() const
+	{ return bias_; }
+
+	double bitscore(int raw_score) const
+	{ return ( lambda() * raw_score - ln_k()) / LN_2; }
+
+	double rawscore(double bitscore, double) const
+	{ return (bitscore*LN_2 + ln_k()) / lambda(); }
+
+	int rawscore(double bitscore) const
+	{ return (int)ceil(rawscore(bitscore, double ())); }
+
+	double evalue(int raw_score, size_t db_letters, unsigned query_len) const
+	{ return static_cast<double>(db_letters) * query_len * pow(2,-bitscore(raw_score)); }
+
+	double bitscore(double evalue, size_t db_letters, unsigned query_len) const
+	{ return -log(evalue/db_letters/query_len)/log(2); }
+
+	double lambda() const
+	{
+		return constants_[3];
+	}
+
+	double k() const
+	{
+		return constants_[4];
+	}
+
+	double ln_k() const
+	{
+		return log(k());
+	}
+
+	char low_score() const;
+
+private:
+
+	template<typename _t>
+	struct Scores
+	{
+		Scores() {}
+		Scores(const char *scores, char bias = 0)
+		{
+			const unsigned n = value_traits.alphabet_size;
+			for(unsigned i=0;i<32;++i)
+				for(unsigned j=0;j<32;++j)
+					data[i*32+j] = i < n && j < n ? (_t)(scores[i*n+j] + (int)bias) : std::numeric_limits<_t>::min();
+		}
+#ifdef _MSC_VER
+		__declspec(align(16)) _t data[32 * 32];
+#else
+		_t data[32 * 32] __attribute__((aligned(16)));
+#endif
+	};
+
+	int gap_open_, gap_extend_;
+	const double *constants_;
+	string name_;
+	Scores<int8_t> matrix8_;
+	char bias_;
+	Scores<uint8_t> matrix8u_;
+	Scores<int16_t> matrix16_;
+
+};
+
+extern Score_matrix score_matrix;
+
+#endif /* SCORE_MATRIX_H_ */
diff --git a/src/basic/seed.h b/src/basic/seed.h
new file mode 100644
index 0000000..0d7d8e1
--- /dev/null
+++ b/src/basic/seed.h
@@ -0,0 +1,100 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SEED_H_
+#define SEED_H_
+
+#include <stdint.h>
+#include "const.h"
+#include "../util/hash_function.h"
+#include "config.h"
+#include "value.h"
+#include "score_matrix.h"
+
+typedef uint64_t Packed_seed;
+
+inline unsigned seed_partition(Packed_seed s)
+{
+	return (unsigned)(s & (Const::seedp-1));
+}
+
+inline unsigned seed_partition_offset(Packed_seed s)
+{
+	return (unsigned)(s >> Const::seedp_bits);
+}
+
+struct Hashed_seed
+{
+	Hashed_seed()
+	{}
+	explicit Hashed_seed(uint64_t seed):
+		hash(murmur_hash()(seed))
+	{}
+	unsigned partition() const
+	{
+		return unsigned(hash&(p - 1));
+	}
+	uint64_t offset() const
+	{
+		return hash >> p_bits;
+	}
+	operator uint64_t() const
+	{
+		return hash;
+	}
+	enum {
+		p_bits = 10, p = 1 << p_bits
+	};
+	uint64_t hash;
+};
+
+struct Seed
+{
+	Letter& operator[](unsigned i)
+	{
+		return data_[i];
+	}
+	friend std::ostream& operator<<(std::ostream &str, const Seed &s)
+	{
+		for (unsigned i = 0; i < config.seed_weight; ++i)
+			str << value_traits.alphabet[(size_t)s.data_[i]];
+		return str;
+	}
+	int score(const Seed &rhs) const
+	{
+		int s = 0;
+		for (unsigned i = 0; i < config.seed_weight; ++i)
+			s += score_matrix(data_[i], rhs.data_[i]);
+		return s;
+	}
+	uint64_t packed() const
+	{
+		uint64_t s = 0;
+		for (unsigned i = 0; i < config.seed_weight; ++i) {
+			s *= 20;
+			s += data_[i];			
+		}
+		return s;
+	}
+	void enum_neighborhood(int treshold, vector<Seed> &out);
+private:
+	void enum_neighborhood(unsigned pos, int treshold, vector<Seed>& out, int score);
+	Letter data_[Const::max_seed_weight];
+};
+
+#endif /* SEED_H_ */
diff --git a/src/basic/seed_iterator.h b/src/basic/seed_iterator.h
new file mode 100644
index 0000000..169adef
--- /dev/null
+++ b/src/basic/seed_iterator.h
@@ -0,0 +1,38 @@
+/****
+Copyright (c) 2014-2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "shape.h"
+#include "sequence.h"
+
+struct Seed_iterator
+{
+	Seed_iterator(vector<char> &seq, const shape &sh):
+		ptr_ (seq.data()),
+		end_ (ptr_ + seq.size() - sh.length_ + 1)
+	{}
+	bool good() const
+	{
+		return ptr_ < end_;
+	}
+	bool get(uint64_t &seed, const shape &sh)
+	{
+		return sh.set_seed_reduced(seed, ptr_++);
+	}
+private:
+	const char *ptr_, *end_;
+};
\ No newline at end of file
diff --git a/src/basic/sequence.h b/src/basic/sequence.h
new file mode 100644
index 0000000..479aeab
--- /dev/null
+++ b/src/basic/sequence.h
@@ -0,0 +1,142 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef SEQUENCE_H_
+#define SEQUENCE_H_
+
+#include <iostream>
+#include <vector>
+#include "../basic/value.h"
+#include "../util/binary_buffer.h"
+#include "../util/text_buffer.h"
+
+using std::vector;
+
+struct sequence
+{
+	struct Reversed {};
+	sequence():
+		len_ (0),
+		clipping_offset_ (0),
+		data_ (0)
+	{ }
+	sequence(const Letter *data, size_t len, int clipping_offset = 0):
+		len_ (len),
+		clipping_offset_ (clipping_offset),
+		data_ (data)
+	{ }
+	sequence(const vector<Letter> &data):
+		len_(data.size()),
+		clipping_offset_(0),
+		data_(data.data())
+	{}
+	sequence(const sequence &seq, int from, int to):
+		len_(to-from+1),
+		clipping_offset_(0),
+		data_(&seq[from])
+	{}
+	size_t length() const
+	{
+		return len_;
+	}
+	size_t clipped_length() const
+	{
+		return len_ - clipping_offset_;
+	}
+	size_t aligned_clip(unsigned padding) const
+	{
+		return clipping_offset_ > (int)padding ? clipping_offset_ - padding : 0;
+	}
+	const Letter* data() const
+	{
+		return data_;
+	}
+	const Letter* clipped_data() const
+	{
+		return data_ + clipping_offset_;
+	}
+	const Letter* aligned_data(unsigned padding) const
+	{
+		return data_ + padding;
+	}
+	const Letter& operator [](size_t i) const
+	{
+		return data_[i];
+	}
+	bool empty() const
+	{ return len_ == 0; }
+	const char* c_str() const
+	{ return reinterpret_cast<const char*>(data_); }
+	size_t print(char *ptr, unsigned begin, unsigned len) const
+	{
+		for(unsigned i=begin;i<begin+len;++i)
+			*(ptr++) = to_char(data_[i]);
+		return len;
+	}
+	Text_buffer& print(Text_buffer &buf, size_t begin, size_t end, const Value_traits& value_traits) const
+	{
+		for (size_t i = begin; i < end; ++i)
+			buf << value_traits.alphabet[(long)data_[i]];
+		return buf;
+	}
+	std::ostream& print(std::ostream &os, const Value_traits &v) const
+	{
+		for (unsigned i = 0; i<len_; ++i)
+			os << v.alphabet[(long)data_[i]];
+		return os;
+	}
+	std::ostream& print(std::ostream &os, const Value_traits &v, Reversed) const
+	{
+		for (int i = (int)len_ - 1; i >= 0; --i)
+			os << v.alphabet[(long)data_[i]];
+		return os;
+	}
+	sequence subseq(int begin, int end) const
+	{
+		return sequence(*this, begin, end - 1);
+	}
+	friend std::ostream& operator<<(std::ostream &os, const sequence &s)
+	{
+		return s.print(os, value_traits);
+	}
+	friend Text_buffer& operator<<(Text_buffer &buf, const sequence &s)
+	{
+		for(unsigned i=0;i<s.len_;++i)
+			buf << value_traits.alphabet[(long)s.data_[i]];
+		return buf;
+	}
+	/*friend std::ostream& operator<<(std::ostream &os, const sequence &s)
+	{
+		std::cout << "co = " << s.clipping_offset_ << std::endl;
+		for(unsigned i=s.clipping_offset_;i<s.len_;++i) {
+			if(s.data_[i] == 24)
+				break;
+			os << mask_critical(s.data_[i]);
+		}
+		return os;
+	}*/
+	static vector<Letter> from_string(const char* str);
+	size_t			len_;
+	int				clipping_offset_;
+	const Letter	*data_;
+};
+
+
+#endif /* SEQUENCE_H_ */
diff --git a/src/basic/shape.h b/src/basic/shape.h
new file mode 100644
index 0000000..ec5ceb6
--- /dev/null
+++ b/src/basic/shape.h
@@ -0,0 +1,148 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SHAPE_H_
+#define SHAPE_H_
+
+#include <string.h>
+#include "const.h"
+#include "value.h"
+#include "seed.h"
+#include "score_matrix.h"
+#include "reduction.h"
+#include "../util/util.h"
+#include "config.h"
+
+/*struct All_partitions {};
+struct Filter_partition {};
+
+template<typename _f>
+bool include_partition(unsigned p)
+{
+	return true;
+}
+
+template<>
+bool include_partition<Filter_partition>(unsigned p)
+{
+	return current_range.contains(p);
+}*/
+
+struct shape
+{
+
+	shape():
+		length_ (0),
+		weight_ (0),
+		d_ (0),
+		mask_ (0),
+		rev_mask_ (0),
+		id_ (0)
+	{ memset(positions_, 0, sizeof(uint32_t)*Const::max_seed_weight); }
+
+	shape(const char *code, unsigned id):
+		weight_ (0),
+		mask_ (0),
+		rev_mask_ (0),
+		id_ (id)
+	{
+		assert(id < Const::max_shapes);
+		assert(strlen(code) <= 32);
+		memset(positions_, 0, sizeof(uint32_t)*Const::max_seed_weight);
+		unsigned i (0);
+		for(;i<strlen(code);++i) {
+			rev_mask_ <<= 1;
+			if(code[i] == '1') {
+				assert(weight_ < Const::max_seed_weight);
+				positions_[weight_] = i;
+				++weight_;
+				mask_ |= 1 << i;
+				rev_mask_ |= 1;
+			}
+		}
+		length_ = i;
+		d_ = positions_[weight_/2-1];
+	}
+
+	inline bool set_seed(Packed_seed &s, const Letter *seq) const
+	{
+		s = 0;
+#ifdef FREQUENCY_MASKING
+		double f = 0;
+#endif
+		for(unsigned i=0;i<weight_;++i) {
+			Letter l = seq[positions_[i]];
+			if (l == value_traits.mask_char || l == '\xff')
+				return false;
+			unsigned r = Reduction::reduction(l);
+#ifdef FREQUENCY_MASKING
+			f += background_freq[r];
+#endif
+			s *= Reduction::reduction.size();
+			s += uint64_t(r);
+		}
+#ifdef FREQUENCY_MASKING
+		if(use_seed_freq() && f > config.max_seed_freq) return false;
+#endif
+		return true;
+	}
+
+	inline bool set_seed_reduced(Packed_seed &s, const Letter *seq) const
+	{
+		s = 0;
+		for (unsigned i = 0; i < weight_; ++i) {
+			Letter l = seq[positions_[i]];
+			if (l == value_traits.mask_char)
+				return false;
+			s *= Reduction::reduction.size();
+			s += uint64_t(l);
+		}
+		return true;
+	}
+
+	inline bool set_seed(Seed &s, const Letter *seq) const
+	{
+		for (unsigned i = 0; i < weight_; ++i) {
+			Letter l = seq[positions_[i]];
+			if (l >= 20)
+				return false;
+			s[i] = l;
+		}
+		return true;
+	}
+	
+	friend std::ostream& operator<<(std::ostream&s, const shape &sh)
+	{
+		for (unsigned i = 0; i < sh.length_; ++i)
+			s << ((sh.mask_ & (1 << i)) ? '1' : '0');
+		return s;
+	}
+
+	int score(const Letter *x, const Letter *y) const
+	{
+		int score = 0;
+		for (unsigned i = 0; i < weight_; ++i)
+			score += score_matrix(x[positions_[i]], y[positions_[i]]);
+		return score;
+	}
+
+	uint32_t length_, weight_, positions_[Const::max_seed_weight], d_, mask_, rev_mask_, id_;
+
+};
+
+#endif /* SHAPE_H_ */
diff --git a/src/basic/shape_config.h b/src/basic/shape_config.h
new file mode 100644
index 0000000..4e89d72
--- /dev/null
+++ b/src/basic/shape_config.h
@@ -0,0 +1,80 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef SHAPE_CONFIG_H_
+#define SHAPE_CONFIG_H_
+
+#include "shape.h"
+
+extern const char* shape_codes[6][Const::max_shapes];
+
+class shape_config
+{
+
+public:
+	
+	shape_config():
+		n_ (0),
+		mode_ (0)
+	{ }
+
+	shape_config(unsigned mode, unsigned count, const vector<string> &shape_mask):
+		n_ (0),
+		mode_ (mode)
+	{
+		if (shape_mask.size() == 0) {
+			unsigned maxShapes = count == 0 ? Const::max_shapes : count;
+			for (unsigned i = 0; i < maxShapes; ++i)
+				if (shape_codes[mode_][i])
+					shapes_[n_++] = shape(shape_codes[mode_][i], i);
+		}
+		else {
+			for (unsigned i = 0; i < (count == 0 ? shape_mask.size() : std::min((unsigned)shape_mask.size(), count)); ++i)
+				shapes_[n_++] = shape(shape_mask[i].c_str(), i);
+		}
+	}
+
+	unsigned count() const
+	{ return n_; }
+
+	const shape& operator[](unsigned i) const
+	{ return shapes_[i]; }
+
+	unsigned mode() const
+	{ return mode_; }
+
+	friend std::ostream& operator<<(std::ostream&s, const shape_config &cfg)
+	{
+		for (unsigned i = 0; i < cfg.n_; ++i)
+			s << cfg.shapes_[i] << (i<cfg.n_-1?",":"");
+		return s;
+	}
+
+private:
+
+	shape shapes_[Const::max_shapes];
+	unsigned n_, mode_;
+
+};
+
+extern shape_config shapes;
+extern unsigned shape_from, shape_to;
+
+#endif /* SHAPE_CONFIG_H_ */
diff --git a/src/basic/statistics.h b/src/basic/statistics.h
new file mode 100644
index 0000000..2326107
--- /dev/null
+++ b/src/basic/statistics.h
@@ -0,0 +1,93 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef STATISTICS_H_
+#define STATISTICS_H_
+
+#include <algorithm>
+#include <stdint.h>
+#include <string.h>
+#include "../util/tinythread.h"
+#include "../util/log_stream.h"
+
+typedef uint64_t stat_type;
+
+struct Statistics
+{
+
+	enum value { SEED_HITS, TENTATIVE_MATCHES0, TENTATIVE_MATCHES1, TENTATIVE_MATCHES2, TENTATIVE_MATCHES3, TENTATIVE_MATCHES4, MATCHES, ALIGNED, GAPPED, DUPLICATES,
+		GAPPED_HITS, QUERY_SEEDS, QUERY_SEEDS_HIT, REF_SEEDS, REF_SEEDS_HIT, QUERY_SIZE, REF_SIZE, OUT_HITS, OUT_MATCHES, COLLISION_LOOKUPS, QCOV, BIAS_ERRORS, SCORE_TOTAL, ALIGNED_QLEN, PAIRWISE, HIGH_SIM,
+		TEMP_SPACE, SECONDARY_HITS, ERASED_HITS, COUNT };
+
+	Statistics()
+	{ memset(data_, 0, sizeof(data_)); }
+
+	Statistics& operator+=(const Statistics &rhs)
+	{
+		mtx_.lock();
+		for(unsigned i=0;i<COUNT;++i)
+			data_[i] += rhs.data_[i];
+		mtx_.unlock();
+		return *this;
+	}
+
+	void inc(const value v, stat_type n = 1lu)
+	{ data_[v] += n; }
+
+	void max(const value v, stat_type n)
+	{
+		data_[v] = std::max(data_[v], n);
+	}
+
+	stat_type get(const value v) const
+	{ return data_[v]; }
+
+	void print() const
+	{
+		log_stream << "Used ref size = " << data_[REF_SIZE] << endl;
+		log_stream << "Traceback errors = " << data_[BIAS_ERRORS] << endl;
+		verbose_stream << "Hits (filter stage 0) = " << data_[SEED_HITS] << endl;
+		verbose_stream << "Hits (filter stage 1) = " << data_[TENTATIVE_MATCHES1] << " (" << data_[TENTATIVE_MATCHES1]*100.0/ data_[SEED_HITS] << " %)" << endl;
+		verbose_stream << "Hits (filter stage 2) = " << data_[TENTATIVE_MATCHES2] << " (" << data_[TENTATIVE_MATCHES2] * 100.0 / data_[TENTATIVE_MATCHES1] << " %)" << endl;
+		verbose_stream << "Hits (filter stage 3) = " << data_[TENTATIVE_MATCHES3] << " (" << data_[TENTATIVE_MATCHES3] * 100.0 / data_[TENTATIVE_MATCHES2] << " %)" << endl;
+		verbose_stream << "Hits (filter stage 4) = " << data_[TENTATIVE_MATCHES4] << " (" << data_[TENTATIVE_MATCHES4] * 100.0 / data_[TENTATIVE_MATCHES3] << " %)" << endl;
+		log_stream << "Gapped hits = " << data_[GAPPED_HITS] << endl;
+		log_stream << "Overlap hits = " << data_[DUPLICATES] << endl;
+		log_stream << "Secondary hits = " << data_[SECONDARY_HITS] << endl;
+		log_stream << "Erased hits = " << data_[ERASED_HITS] << endl;
+		log_stream << "High similarity hits = " << data_[HIGH_SIM] << endl;
+		log_stream << "Net hits = " << data_[OUT_HITS] << endl;
+		log_stream << "Matches = " << data_[OUT_MATCHES] << endl;
+		log_stream << "Total score = " << data_[SCORE_TOTAL] << endl;
+		log_stream << "Aligned query len = " << data_[ALIGNED_QLEN] << endl;
+		log_stream << "Gapped matches = " << data_[GAPPED] << endl;
+		verbose_stream << "Temporary disk space used: " << (double)data_[TEMP_SPACE] / (1 << 30) << " GB" << endl;
+		message_stream << "Reported " << data_[PAIRWISE] << " pairwise alignments, " << data_[MATCHES] << " HSSPs." << endl;
+		message_stream << data_[ALIGNED] << " queries aligned." << endl;
+	}
+
+	stat_type data_[COUNT];
+	tthread::mutex mtx_;
+
+};
+
+extern Statistics statistics;
+
+#endif /* STATISTICS_H_ */
diff --git a/src/basic/translate.h b/src/basic/translate.h
new file mode 100644
index 0000000..83b82a7
--- /dev/null
+++ b/src/basic/translate.h
@@ -0,0 +1,153 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef TRANSLATE_H_
+#define TRANSLATE_H_
+
+#include <vector>
+#include "value.h"
+
+using std::vector;
+
+struct Translator
+{
+
+public:
+
+	static const Letter reverseLetter[5];
+	static Letter lookup[5][5][5];
+	static Letter lookupReverse[5][5][5];
+	static const Letter STOP;
+	static const char* codes[27];
+
+	static void init(unsigned id);
+
+	static Letter getReverseComplement(Letter letter)
+	{ return reverseLetter[(int) letter]; }
+
+	static Letter getAminoAcid(vector<Letter> const &dnaSequence, size_t pos)
+	{ return lookup[(int) dnaSequence[pos]][(int)dnaSequence[pos+1]][(int)dnaSequence[pos+2]]; }
+
+	static Letter getAminoAcidReverse(vector<Letter> const &dnaSequence, size_t pos)
+	{ return lookupReverse[(int) dnaSequence[pos + 2]][(int)dnaSequence[pos + 1]][(int)dnaSequence[pos]]; }
+
+	static vector<Letter> reverse(const vector<Letter> &seq)
+	{
+		vector<Letter> r;
+		for(vector<Letter>::const_reverse_iterator i=seq.rbegin(); i!=seq.rend(); ++i)
+			r.push_back(getReverseComplement(*i));
+		return r;
+	}
+
+	static size_t translate(vector<Letter> const &dnaSequence, vector<Letter> *proteins)
+	{
+		size_t length_ = dnaSequence.size(), d, n;
+		proteins[0].resize(d = length_ / 3);
+		proteins[3].resize(d);
+		n = 2*d;
+		proteins[1].resize(d = (length_-1) / 3);
+		proteins[4].resize(d);
+		n += 2*d;
+		proteins[2].resize(d = (length_-2) / 3);
+		proteins[5].resize(d);
+		n += 2*d;
+
+		size_t r = length_ - 2;
+		unsigned pos = 0;
+		unsigned i = 0;
+		while(r > 2) {
+			proteins[0][i] = getAminoAcid(dnaSequence, pos++);
+			proteins[3][i] = getAminoAcidReverse(dnaSequence, --r);
+			proteins[1][i] = getAminoAcid(dnaSequence, pos++);
+			proteins[4][i] = getAminoAcidReverse(dnaSequence, --r);
+			proteins[2][i] = getAminoAcid(dnaSequence, pos++);
+			proteins[5][i] = getAminoAcidReverse(dnaSequence, --r);
+			++i;
+		}
+		if(r) {
+			proteins[0][i] = getAminoAcid(dnaSequence, pos++);
+			proteins[3][i] = getAminoAcidReverse(dnaSequence, --r);
+		}
+		if(r) {
+			proteins[1][i] = getAminoAcid(dnaSequence, pos);
+			proteins[4][i] = getAminoAcidReverse(dnaSequence, r);
+		}
+		return n;
+	}
+
+	static Letter const* nextChar(Letter const*p, Letter const*end)
+	{
+		while(*(p) != STOP && p < end)
+			++p;
+		return p;
+	}
+
+	static void mask_runs(vector<Letter> &query, unsigned run_len)
+	{
+		Letter *last = &query[0]-1, *i = &query[0], *end = &query.back();
+		while (i <= end) {
+			if(*i == STOP) {
+				if(last != 0 && i - last - 1 < (int)run_len) {
+					for(Letter *j = last+1; j < i; ++j)
+						*j = 23;
+				}
+				last = i;
+			}
+			++i;
+		}
+		if(last != 0 && i - last - 1 < (int)run_len) {
+			for(Letter *j = last+1; j < i; ++j)
+				*j = 23;
+		}
+	}
+
+	static unsigned computeGoodFrames(vector<Letter>  const *queries, unsigned runLen)
+	{
+		unsigned set = 0;
+
+		for (unsigned i = 0; i < 6; ++i) {
+			if (queries[i].size() > 0) {
+				unsigned run = 0;
+				Letter const*p =  &(queries[i][0]);
+				Letter const*q;
+				Letter const*end = p + queries[i].size();
+				while((q = nextChar(p, end)) < end) {
+					run = (unsigned)(q-p);
+					if (run >= runLen)
+						set |= 1 << i;
+					p=q+1;
+				}
+				run = (unsigned)(q-p);
+				if (run >= runLen)
+					set |= 1 << i;
+			}
+		}
+		return set;
+	}
+
+	static void mask_runs(vector<Letter> *queries, unsigned run_len)
+	{
+		for (unsigned i = 0; i < 6; ++i)
+			mask_runs(queries[i], run_len);
+	}
+
+};
+
+#endif /* TRANSLATE_H_ */
diff --git a/src/basic/value.h b/src/basic/value.h
new file mode 100644
index 0000000..7ee3867
--- /dev/null
+++ b/src/basic/value.h
@@ -0,0 +1,109 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef VALUE_H_
+#define VALUE_H_
+
+#include <assert.h>
+#include <string.h>
+#include <sstream>
+#include "const.h"
+#include "config.h"
+#include "../util/util.h"
+
+typedef char Letter;
+typedef enum { amino_acid=0, nucleotide=1 } Sequence_type;
+struct Amino_acid {};
+struct Nucleotide {};
+
+struct invalid_sequence_char_exception : public std::exception
+{
+	const std::string msg;
+	invalid_sequence_char_exception(char ch) :
+		msg(std::string("Invalid character (") + print_char(ch) + ") in sequence")
+	{ }
+	~invalid_sequence_char_exception() throw()
+	{ }
+	virtual const char* what() const throw()
+	{
+		return msg.c_str();
+	}
+};
+
+struct Char_representation
+{
+	Char_representation(unsigned size, const char *chars, char mask, const char *mask_chars)
+	{
+		memset(data_, invalid, sizeof(data_));
+		for (unsigned i = 0; i<size; ++i) {
+			assert(chars[i] != (char)invalid);
+			data_[(long)chars[i]] = i;
+			data_[(long)tolower(chars[i])] = i;
+		}
+		while (*mask_chars != 0) {
+			const char ch = *mask_chars;
+			data_[(long)ch] = mask;
+			data_[(long)tolower(ch)] = mask;
+			++mask_chars;
+		}
+	}
+	Letter operator()(char c) const
+	{
+		if (data_[(long)c] == invalid)
+			throw invalid_sequence_char_exception(c);
+		return data_[(long)c];
+	}
+private:
+	static const char invalid;
+	Letter data_[256];
+};
+
+struct Value_traits
+{
+	Value_traits(const char *alphabet, Letter mask_char, const char *ignore);	
+	const char *alphabet;
+	unsigned alphabet_size;
+	Letter mask_char;
+	Char_representation from_char;
+};
+
+extern const Value_traits amino_acid_traits;
+extern const Value_traits nucleotide_traits;
+extern Value_traits value_traits;
+extern Value_traits input_value_traits;
+
+inline char to_char(Letter a)
+{
+	return value_traits.alphabet[(long)a];
+}
+
+struct Align_mode
+{
+	Align_mode(unsigned mode);
+	static unsigned from_command(unsigned command);
+	enum { blastp = 2, blastx = 3, blastn = 4 };
+	Sequence_type sequence_type, input_sequence_type;
+	unsigned mode, query_contexts;
+	int query_len_factor;
+	bool query_translated;
+};
+
+extern Align_mode align_mode;
+extern const double background_freq[20];
+
+#endif /* VALUE_H_ */
diff --git a/src/blast/blast_def.h b/src/blast/blast_def.h
new file mode 100644
index 0000000..e1f90bb
--- /dev/null
+++ b/src/blast/blast_def.h
@@ -0,0 +1,340 @@
+/* $Id: blast_def.h 365511 2012-06-06 16:00:13Z fongah2 $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ * 
+ *
+ */
+
+/** @file blast_def.h
+ * Definitions used throughout BLAST
+ */
+
+#ifndef ALGO_BLAST_CORE__BLAST_DEF__H
+#define ALGO_BLAST_CORE__BLAST_DEF__H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/****************************** Constants *********************************/
+
+extern const int kDustLevel;  /**< Level parameter used by dust. */
+extern const int kDustWindow; /**< Window parameter used by dust. */
+extern const int kDustLinker; /**< Parameter used by dust to link together close low-complexity segments. */
+
+extern const int kSegWindow;  /**< Window that SEG examines at once. */
+extern const double kSegLocut;   /**< Locut parameter for SEG. */
+extern const double kSegHicut;   /**< Hicut parameter for SEG. */
+
+/** Maximum number of HPSs to be saved in an ungapped search.
+ * Value defined in blast_options.c
+ */
+extern const int kUngappedHSPNumMax;
+
+/******************** Preprocessor definitions ******************************/
+
+/** Codons are always of length 3 */
+#ifndef CODON_LENGTH
+#define CODON_LENGTH 3
+#endif
+
+/** For translated gapped searches, this is the default value in
+ * nucleotides of longest_intron (for ungapped translated searches,
+ * the default value of longest_intron is zero, which causes a legacy
+ * method of HSP linking that does not use longest_intron to be
+ * invoked).
+ *
+ * The value 122 corresponds to 40 amino acids: 40 codons * 3
+ * nucleotides per codon + up to 2 frame shifts.  40 amino acids is
+ * the maximum gap size in the untranslated sequence, so
+ * DEFAULT_LONGEST_INTRON makes these two gap sizes equal.
+ */ 
+#ifndef DEFAULT_LONGEST_INTRON
+#define DEFAULT_LONGEST_INTRON 122
+#endif
+
+/** Compression ratio of nucleotide bases (4 bases in 1 byte) */
+#ifndef COMPRESSION_RATIO
+#define COMPRESSION_RATIO 4
+#endif
+
+/** Number of frames to which we translate in translating searches */
+#ifndef NUM_FRAMES
+#define NUM_FRAMES 6
+#endif
+
+/** Number of frames in a nucleotide sequence */
+#ifndef NUM_STRANDS
+#define NUM_STRANDS 2
+#endif
+
+/** Length of the genetic code string */
+#ifndef GENCODE_STRLEN
+#define GENCODE_STRLEN 64
+#endif
+
+/**
+ * A macro expression that returns 1, 0, -1 if a is greater than,
+ * equal to or less than b, respectively.  This macro evaluates its
+ * arguments more than once.
+ */
+#ifndef BLAST_CMP
+#define BLAST_CMP(a,b) ((a)>(b) ? 1 : ((a)<(b) ? -1 : 0))
+#endif
+
+/** Safe free a pointer: belongs to a higher level header. */
+#ifndef sfree
+#define sfree(x) __sfree((void**)(void*)&(x))
+#endif
+
+/** Implemented in blast_util.c. @sa sfree */
+inline void
+__sfree(void **x)
+{
+    free(*x);
+    *x = NULL;
+    return;
+}
+
+/** This symbol enables the verbose option in makeblastdb and other BLAST+
+ * search command line applications, as well as the option to submit searches
+ * to the test server in NCBI for remote BLAST searches 
+#define _BLAST_DEBUG 1
+*/
+
+#if 0
+/** Define this symbol to enable debugging APIs in the BlastSeqSrc interface to
+ * allow diagnostics/debugging to be performed in the composition based
+ * statistics code */
+#define KAPPA_PRINT_DIAGNOSTICS 1
+#endif
+
+/********************* Structure definitions ********************************/
+
+/** Structure holding a pair of offsets. Used for storing offsets for the
+ * initial seeds. In most programs the offsets are query offset and subject 
+ * offset of an initial word match. For PHI BLAST, the offsets are start and 
+ * end of the pattern occurrence in subject, with no query information, 
+ * because all pattern occurrences in subjects are aligned to all pattern 
+ * occurrences in query.
+ */
+typedef union BlastOffsetPair {
+    struct {
+        uint32_t q_off;  /**< Query offset */
+        uint32_t s_off;  /**< Subject offset */
+    } qs_offsets;     /**< Query/subject offset pair */
+    struct {
+        uint32_t s_start;/**< Start offset of pattern in subject */
+        uint32_t s_end;  /**< End offset of pattern in subject */
+    } phi_offsets;    /**< Pattern offsets in subject (PHI BLAST only) */
+} BlastOffsetPair;
+
+/** A structure containing two integers, used e.g. for locations for the 
+ * lookup table.
+ */
+typedef struct SSeqRange {
+   int32_t left;  /**< left endpoint of range (zero based) */
+   int32_t right;  /**< right endpoint of range (zero based) */
+} SSeqRange;
+
+/** Create a new SSeqRange structure with both fields initialized
+ * @param start the start of the range [in]
+ * @param stop the end of the range [in]
+ */
+SSeqRange SSeqRangeNew(int32_t start, int32_t stop);
+
+/** Returns the index of the range, such that this element is the
+ * first range that either contains the target or if no such range exists, the
+ * index of the first range, such that the target is less than this range.
+ * @pre ranges array is sorted on the starting coordinates (i.e.:
+ * SSeqRange::left)
+ * @param ranges array of SSeqRange structures to search [in]
+ * @param num_ranges number of elements in the ranges array [in]
+ * @param target element to look for [in]
+ * @return the index of interest in the ranges array or -1 if the function was
+ * called with invalid parameters
+ */
+int32_t
+SSeqRangeArrayLessThanOrEqual(const SSeqRange* ranges, int32_t num_ranges,
+                              int32_t target);
+
+/** Used to hold a set of positions, mostly used for filtering. 
+ * oid holds the index of the query sequence.
+*/
+typedef struct BlastSeqLoc {
+        struct BlastSeqLoc *next;  /**< next in linked list */
+        SSeqRange *ssr;            /**< location data on the sequence. */
+} BlastSeqLoc;
+
+/** Structure for keeping the query masking information */
+typedef struct BlastMaskLoc {
+   /** Total size of the BlastSeqLoc array below. This is always the number 
+     of queries times the number of contexts. Note that in the case of 
+     translated query searches, these locations must be provided in protein 
+     coordinates to BLAST_MainSetUp.
+     @sa BLAST_GetNumberOfContexts 
+     @sa BlastMaskLocDNAToProtein
+    */
+   int32_t total_size;
+
+   /** Array of masked locations. 
+     Every query is allocated the number of contexts associated with the 
+     program. In the case of nucleotide searches, the strand(s) to search 
+     dictatate which elements of the array for a given query are filled. For 
+     translated searches, this should also be the same (by design) but the 
+     C toolkit API does NOT implement this, it rather fills all elements 
+     for all queries with masked locations in protein coordinates (if any). 
+     The C++ API does follow the convention which populates each element, only
+     if so dictated by the strand(s) to search for each query.
+     @sa BLAST_GetNumberOfContexts
+    */
+   BlastSeqLoc** seqloc_array; 
+} BlastMaskLoc;
+
+/** Define the possible subject masking types */
+typedef enum ESubjectMaskingType {
+    eNoSubjMasking,
+    eSoftSubjMasking,
+    eHardSubjMasking
+} ESubjectMaskingType;
+
+/** Structure to hold a sequence. */
+typedef struct BLAST_SequenceBlk {
+   uint8_t* sequence; /**< Sequence used for search (could be translation). */
+   uint8_t* sequence_start; /**< Start of sequence, usually one byte before
+                               sequence as that byte is a NULL sentinel byte.*/
+   int32_t length;         /**< Length of sequence. */
+   int16_t frame; /**< Frame of the query, needed for translated searches */
+   int16_t subject_strand; /**< Strand of the subject sequence for translated searches.
+                          Uses the same values as ENa_strand. */
+   int32_t oid; /**< The ordinal id of the current sequence */
+   bool sequence_allocated; /**< TRUE if memory has been allocated for
+                                  sequence */
+   bool sequence_start_allocated; /**< TRUE if memory has been allocated
+                                        for sequence_start */
+   uint8_t* sequence_start_nomask; /**< Query sequence without masking. */
+   uint8_t* sequence_nomask; /**< Start of query sequence without masking. */
+   bool nomask_allocated; /**< If false the two above are just pointers to
+                                   sequence and sequence_start. */
+   uint8_t* oof_sequence; /**< Mixed-frame protein representation of a
+                             nucleotide sequence for out-of-frame alignment */
+   bool oof_sequence_allocated; /**< TRUE if memory has been allocated
+                                        for oof_sequence */
+   uint8_t* compressed_nuc_seq; /**< 4-to-1 compressed version of sequence */
+   uint8_t* compressed_nuc_seq_start; /**< start of compressed_nuc_seq */
+   BlastMaskLoc* lcase_mask; /**< Locations to be masked from operations on 
+                                this sequence: lookup table for query; 
+                                scanning for subject. */
+   bool lcase_mask_allocated; /**< TRUE if memory has been allocated for
+                                    lcase_mask */
+   int32_t chunk;  /**< Used for indexing only: the chunk number within the
+                     subject sequence. */
+   uint8_t *gen_code_string;  /**< for nucleotide subject sequences (tblast[nx]),
+                              the genetic code used to create a translated
+                              protein sequence (NULL if not applicable). This
+                              field is NOT owned by this data structure, it's
+                              owned by the genetic code singleton. 
+                              @sa gencode_singleton.h
+                              */
+   /* BEGIN: Data members needed for masking subjects from a BLAST database */
+   SSeqRange* seq_ranges;   /**< Ranges of the sequence to search */
+   uint32_t num_seq_ranges;    /**< Number of elements in seq_ranges */
+   bool seq_ranges_allocated;   /**< TRUE if memory has been allocated for
+                                      seq_ranges */
+   ESubjectMaskingType mask_type;          /**< type of subject masking */
+   /* END: Data members needed for masking subjects from a BLAST database */
+
+   uint8_t bases_offset; /* Bases offset in first byte for SRA seq */
+
+} BLAST_SequenceBlk;
+
+/** Information about a single pattern occurence in the query. */
+typedef struct SPHIPatternInfo {
+    int32_t offset;  /**< Starting offset of this pattern occurrence. */
+    int32_t length;  /**< Length of this pattern occurrence. */
+} SPHIPatternInfo;
+
+/** In PHI BLAST, structure containing information about all pattern 
+ * occurrences in query.
+ */
+typedef struct SPHIQueryInfo {
+    int32_t num_patterns;  /**< Number of pattern occurrences in query. */
+    SPHIPatternInfo *occurrences; /**< Array of pattern occurrence information
+                                        structures. */
+    int32_t allocated_size; /**< Allocated size of the occurrences array. */
+    double probability; /**< Estimated probability of the pattern */
+    char* pattern;   /**< Pattern used, saved here for formatting purposes. */
+} SPHIQueryInfo;
+
+
+/************************* Progress monitoring/interruptible API *************/
+
+/** Enumeration for the stages in the BLAST search */
+typedef enum EBlastStage {
+    /** None specified */
+    eNone               = 0x0,
+    /** Preliminary stage */
+    ePrelimSearch       = 0x1 << 0,
+    /** Traceback stage */
+    eTracebackSearch    = 0x1 << 1,
+    /** Both preliminary and traceback stages */
+    eBoth               = (ePrelimSearch | eTracebackSearch)
+} EBlastStage;
+
+/** Progress monitoring structure. This is updated by the engine to provided to
+ * the user as an argument to the user-supplied callback function 
+ * (TInterruptFnPtr). This function then can assess whether the search 
+ * should proceed or exit prematurely.
+ * @sa TInterruptFnPtr
+ */
+typedef struct SBlastProgress {
+    EBlastStage stage;      /**< Stage of the BLAST search currently in
+                              progress */
+    void* user_data;        /**< Pointer to user-provided data */
+} SBlastProgress;
+
+/** Prototype for function pointer to determine whether the BLAST search
+ * should proceed or be interrupted. If this function returns true, all 
+ * processing must stop and the search must discard all interim results 
+ * @note In order to avoid undue overhead, this function should not perform any
+ * time consuming operations and should always return (i.e.: it should never 
+ * block)
+ */
+typedef bool (*TInterruptFnPtr) (SBlastProgress* progress_info);
+
+/** Allocates and initializes a new SBlastProgress structure.
+ * @param user_data user-provided data (not owned by the resulting structure)
+ * [in]
+ * Implemented in blast_util.c 
+ */
+SBlastProgress* SBlastProgressNew(void* user_data);
+
+/** Deallocates a SBlastProgress structure.
+ * Implemented in blast_util.c */
+SBlastProgress* SBlastProgressFree(SBlastProgress* progress_info);
+
+/** Resets the progress structure to its original state (as if newly allocated)
+ * for a fresh start without touching the user_data field */
+void SBlastProgressReset(SBlastProgress* progress_info);
+
+#endif /* !ALGO_BLAST_CORE__BLAST_DEF__H */
diff --git a/src/blast/blast_encoding.h b/src/blast/blast_encoding.h
new file mode 100644
index 0000000..07a040c
--- /dev/null
+++ b/src/blast/blast_encoding.h
@@ -0,0 +1,113 @@
+/*  $Id: blast_encoding.h 118195 2008-01-24 21:22:19Z camacho $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Christiam Camacho
+ *
+ */
+
+/** @file blast_encoding.h
+ *  Declarations of static arrays used to define some NCBI encodings to be used
+ *  in a toolkit independent manner by the BLAST engine.
+ */
+
+#ifndef ALGO_BLAST_CORE___BLAST_ENCODING__H
+#define ALGO_BLAST_CORE___BLAST_ENCODING__H
+
+#include "ncbi_std.h"
+
+#define NCBI_XBLAST_EXPORT
+
+/** @addtogroup AlgoBlast
+ *
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Different types of sequence encodings for sequence retrieval from the 
+ * BLAST database 
+ */
+typedef enum { 
+    eBlastEncodingProtein       = 0, /**< NCBIstdaa */
+    eBlastEncodingNucleotide    = 1, /**< Special encoding for preliminary 
+                                       stage of BLAST: permutation of NCBI4na.
+                                       A.k.a.: BLASTNA encoding
+                                      */
+    eBlastEncodingNcbi4na       = 2, /**< NCBI4na */
+    eBlastEncodingNcbi2na       = 3, /**< NCBI2na */
+    eBlastEncodingError         = 255 /**< Error value for encoding */
+} EBlastEncoding;
+
+/* Nucleotide encodings */
+
+/** Translates between ncbi4na and blastna. The first four elements
+ *	of this array match ncbi2na. */
+NCBI_XBLAST_EXPORT extern const Uint1 NCBI4NA_TO_BLASTNA[];
+
+/** Translates between blastna and ncbi4na. */
+NCBI_XBLAST_EXPORT extern const Uint1 BLASTNA_TO_NCBI4NA[];
+
+/** Translates between iupacna and blastna. */
+NCBI_XBLAST_EXPORT extern const Uint1 IUPACNA_TO_BLASTNA[];
+
+/** Translates between iupacna and ncbi4na. */
+NCBI_XBLAST_EXPORT extern const Uint1 IUPACNA_TO_NCBI4NA[];
+
+/** Translates between ncbieaa and ncbistdaa. */
+NCBI_XBLAST_EXPORT extern const Uint1 AMINOACID_TO_NCBISTDAA[];
+
+/** Translates between ncbieaa and ncbistdaa. */
+NCBI_XBLAST_EXPORT extern const char NCBISTDAA_TO_AMINOACID[];
+
+/** Translates between blastna and iupacna. */
+NCBI_XBLAST_EXPORT extern const char BLASTNA_TO_IUPACNA[];
+
+/** Translates between ncbi4na and iupacna. */
+NCBI_XBLAST_EXPORT extern const char NCBI4NA_TO_IUPACNA[];
+
+#define BLAST2NA_SIZE 4     /**< Size of compressed nucleic acid alphabet */
+#define BLASTNA_SIZE 16     /**< Size of nucleic acid alphabet */
+#define BLASTAA_SIZE 28     /**< Size of aminoacid alphabet */
+
+
+#define BLASTNA_SEQ_CODE 99 /**< Identifies the blastna alphabet, for use in 
+                                blast only. */
+#define BLASTAA_SEQ_CODE 11 /**< == Seq_code_ncbistdaa */
+#define NCBI4NA_SEQ_CODE 4  /**< == Seq_code_ncbi4na */	
+
+/** Sentinel byte for protein sequences */
+NCBI_XBLAST_EXPORT extern const Uint1 kProtSentinel;
+/** Sentinel nibble for nucleotide sequences */
+NCBI_XBLAST_EXPORT extern const Uint1 kNuclSentinel;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* @} */
+
+#endif  /* ALGO_BLAST_CORE___BLAST_ENCODING__H */
diff --git a/src/blast/blast_filter.cpp b/src/blast/blast_filter.cpp
new file mode 100644
index 0000000..571e334
--- /dev/null
+++ b/src/blast/blast_filter.cpp
@@ -0,0 +1,359 @@
+/* $Id: blast_filter.c 306966 2011-06-20 13:16:49Z maning $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ */
+
+/** @file blast_filter.c
+ * All code related to query sequence masking/filtering for BLAST
+ */
+
+#include <cstddef>
+#include <algorithm>
+#include <assert.h>
+#include "blast_filter.h"
+#include "blast_seg.h"
+
+#ifndef NULLB
+/** terminating byte of a char* string. */
+#define NULLB '\0'
+#endif
+
+/****************************************************************************/
+/* Constants */
+const uint8_t kNuclMask = 14;     /* N in BLASTNA */
+const uint8_t kProtMask = 21;     /* X in NCBISTDAA */
+
+
+/** Allowed length of the filtering options string. */
+#define BLASTOPTIONS_BUFFER_SIZE 128
+
+BlastSeqLoc* BlastSeqLocNew(BlastSeqLoc** head, int32_t from, int32_t to)
+{
+   BlastSeqLoc* loc = (BlastSeqLoc*) calloc(1, sizeof(BlastSeqLoc));
+   if ( !loc ) {
+       return NULL;
+   }
+   loc->ssr = (SSeqRange*) calloc(1, sizeof(SSeqRange));
+   loc->ssr->left = from;
+   loc->ssr->right = to;
+
+   return BlastSeqLocAppend(head, loc);
+}
+
+BlastSeqLoc* BlastSeqLocAppend(BlastSeqLoc** head, BlastSeqLoc* node)
+{
+    if ( !node ) {
+        return NULL;
+    }
+
+    if (head)
+    {
+        if (*head)
+        {
+            BlastSeqLoc* tmp = *head;
+            while (tmp->next)
+               tmp = tmp->next;
+            tmp->next = node;
+        }
+        else
+        {
+            *head = node;
+        }
+    }
+        
+    return node;
+}
+
+/** Makes a copy of the BlastSeqLoc and also a copy of the 
+ * SSRange element.  Does not copy BlastSeqLoc that is pointed
+ * to by "next".
+ * @param source the object to be copied [in]
+ * @return another BlastSeqLoc*
+ */
+static BlastSeqLoc* s_BlastSeqLocNodeDup(BlastSeqLoc* source)
+{
+    if ( !source ) {
+        return NULL;
+    }
+    assert(source->ssr);
+    return BlastSeqLocNew(NULL, source->ssr->left, source->ssr->right);
+}
+
+/** Calculates number of links in a chain of BlastSeqLoc's.
+ * @param var Chain of BlastSeqLoc structures [in]
+ * @return Number of links in the chain.
+ */
+static int32_t s_BlastSeqLocLen(const BlastSeqLoc* var)
+{
+    BlastSeqLoc* itr = NULL;
+    int32_t retval = 0;
+   
+    for (itr = (BlastSeqLoc*)var; itr; itr = itr->next, retval++) {
+        ;
+    }
+    return retval;
+}
+
+/** Converts a BlastSeqLoc list to an array of pointers, each pointing to an
+ * element of the list passed in to this function and the last element points
+ * to NULL 
+ * @param list List to convert to an array of pointers [in]
+ * @param count number of elements populated in the array [out]
+ */
+static BlastSeqLoc**
+s_BlastSeqLocListToArrayOfPointers(const BlastSeqLoc* list, int32_t* count)
+{
+    BlastSeqLoc* tmp,** retval;
+    int32_t i;
+    *count = 0;
+
+    if (list == NULL) 
+       return NULL;
+
+    *count = s_BlastSeqLocLen(list);
+    retval = (BlastSeqLoc**) calloc(((size_t)(*count)+1), sizeof(BlastSeqLoc*));
+    for (tmp = (BlastSeqLoc*)list, i = 0; tmp != NULL && i < *count; i++) {
+        retval[i] = tmp;
+        tmp = tmp->next;
+    }
+    return retval;
+}
+
+/** Reverse elements in the list 
+ * @param head pointer to pointer to the head of the list. [in|out]
+ * (this is not declared static so that it can be tested in the unit tests
+ */
+void BlastSeqLocListReverse(BlastSeqLoc** head)
+{
+    BlastSeqLoc** ptrs = NULL;  /* array of pointers to BlastSeqLoc elements */
+    int32_t num_elems = 0, i = 0;
+
+    if ( !head ) {
+        return;
+    }
+
+    ptrs = s_BlastSeqLocListToArrayOfPointers(*head, &num_elems);
+    if (num_elems == 0) {
+        return;
+    }
+    assert(ptrs);
+    *head = ptrs[num_elems-1];
+    for (i = num_elems-1; i > 0; i--) {
+        ptrs[i]->next = ptrs[i-1];
+    }
+    ptrs[0]->next = NULL;
+    sfree(ptrs);
+}
+
+BlastSeqLoc* BlastSeqLocNodeFree(BlastSeqLoc* loc)
+{
+    if ( !loc ) {
+        return NULL;
+    }
+    sfree(loc->ssr);
+    sfree(loc);
+    return NULL;
+}
+
+BlastSeqLoc* BlastSeqLocFree(BlastSeqLoc* loc)
+{
+    while (loc) {
+        BlastSeqLoc* next_loc = loc->next;
+        loc = BlastSeqLocNodeFree(loc);
+        loc = next_loc;
+    }
+    return NULL;
+}
+
+BlastSeqLoc* BlastSeqLocListDup(BlastSeqLoc* head)
+{
+    BlastSeqLoc* retval = NULL;
+    BlastSeqLoc* retval_tail = NULL;
+
+    for (; head; head = head->next) {
+        retval_tail = BlastSeqLocAppend(retval_tail ? &retval_tail : &retval, 
+                                        s_BlastSeqLocNodeDup(head));
+    }
+
+    return retval;
+}
+
+BlastMaskLoc* BlastMaskLocNew(int32_t total)
+{
+    BlastMaskLoc* retval = (BlastMaskLoc *) calloc(1, sizeof(BlastMaskLoc));
+    retval->total_size = total;
+    if (total > 0)
+        retval->seqloc_array = (BlastSeqLoc **) calloc(total, 
+                                                       sizeof(BlastSeqLoc *));
+    return retval;
+}
+
+BlastMaskLoc* BlastMaskLocDup(const BlastMaskLoc* mask_loc)
+{
+    BlastMaskLoc* retval = NULL;
+    int32_t index = 0;
+
+    if ( !mask_loc ) {
+        return NULL;
+    }
+
+    retval = BlastMaskLocNew(mask_loc->total_size);
+
+    for (index = 0; index < mask_loc->total_size; index++) {
+        retval->seqloc_array[index] =
+            BlastSeqLocListDup(mask_loc->seqloc_array[index]);
+    }
+
+    return retval;
+}
+
+BlastMaskLoc* BlastMaskLocFree(BlastMaskLoc* mask_loc)
+{
+   int32_t index;
+
+   if (mask_loc == NULL)
+      return NULL;
+
+   for (index=0; index<mask_loc->total_size; index++)
+   {
+      if (mask_loc->seqloc_array != NULL)
+         BlastSeqLocFree(mask_loc->seqloc_array[index]);
+   }
+   sfree(mask_loc->seqloc_array);
+   sfree(mask_loc);
+   return NULL;
+}
+
+/** Used for qsort, compares two SeqLoc's by starting position. */
+static int s_SeqRangeSortByStartPosition(const void *vp1, const void *vp2)
+{
+   BlastSeqLoc* v1 = *((BlastSeqLoc**) vp1);
+   BlastSeqLoc* v2 = *((BlastSeqLoc**) vp2);
+   SSeqRange* loc1 = (SSeqRange*) v1->ssr;
+   SSeqRange* loc2 = (SSeqRange*) v2->ssr;
+   
+   if (loc1->left < loc2->left)
+      return -1;
+   else if (loc1->left > loc2->left)
+      return 1;
+   else
+      return 0;
+}
+
+void
+BlastSeqLocCombine(BlastSeqLoc** mask_loc, int32_t link_value)
+{
+    BlastSeqLoc** ptrs = NULL;
+    int32_t i = 0, num_elems = 0;
+
+    /* Break up the list into an array of pointers and sort it */
+    ptrs = s_BlastSeqLocListToArrayOfPointers(*mask_loc, &num_elems);
+    if (num_elems == 0) {
+        return;
+    }
+    assert(ptrs);
+    qsort(ptrs, (size_t)num_elems, sizeof(*ptrs), 
+          s_SeqRangeSortByStartPosition);
+
+    /* Merge the overlapping elements */
+    {
+        BlastSeqLoc* curr_tail = *mask_loc = ptrs[0];
+        for (i = 0; i < num_elems - 1; i++) {
+            const SSeqRange* next_ssr = ptrs[i+1]->ssr;
+            const int32_t stop = curr_tail->ssr->right;
+
+            if ((stop + link_value) > next_ssr->left) {
+                curr_tail->ssr->right = std::max(stop, next_ssr->right);
+                ptrs[i+1] = BlastSeqLocNodeFree(ptrs[i+1]);
+            } else {
+                curr_tail = ptrs[i+1];
+            }
+        }
+    }
+
+    /* Rebuild the linked list */
+    {
+        BlastSeqLoc* tail = *mask_loc;
+        for (i = 1; i < num_elems; i++) {
+            if (ptrs[i]) {
+                tail->next = ptrs[i];
+                tail = ptrs[i];
+            }
+        }
+        tail->next = NULL;
+    }
+    sfree(ptrs);
+}
+
+void
+BlastSeqLocReverse(BlastSeqLoc* masks, int32_t query_length)
+{
+    for(; masks; masks = masks->next) {
+        masks->ssr->left    = query_length - 1 - masks->ssr->right;
+        masks->ssr->right   = query_length - 1 - masks->ssr->left;
+    }
+}
+
+void
+Blast_MaskTheResidues(uint8_t * buffer, int32_t length, bool is_na,
+                      const BlastSeqLoc* mask_loc, bool reverse, int32_t offset)
+{
+    const uint8_t kMaskingLetter = is_na ? kNuclMask : kProtMask;
+    assert(buffer);
+    for (; mask_loc; mask_loc = mask_loc->next) {
+
+        int32_t index, start, stop;
+        
+        if (reverse) {
+            start = length - 1 - mask_loc->ssr->right;
+            stop = length - 1 - mask_loc->ssr->left;
+        } else {
+            start = mask_loc->ssr->left;
+            stop = mask_loc->ssr->right;
+        }
+        
+        start -= offset;
+        stop -= offset;
+        
+        assert(start < length);
+        assert(stop <= length);
+        
+        for (index = start; index <= stop; index++)
+            buffer[index] = kMaskingLetter;
+    }
+}
+
+void
+Blast_MaskUnsupportedAA(BLAST_SequenceBlk* seq, uint8_t min_invalid)
+{
+    uint8_t *sequence = seq->sequence;
+    int32_t length = seq->length;
+    int32_t i;
+
+    for (i = 0; i < length; i++) {
+        if (sequence[i] >= min_invalid) {
+            sequence[i] = kProtMask;
+        }
+    }
+}
diff --git a/src/blast/blast_filter.h b/src/blast/blast_filter.h
new file mode 100644
index 0000000..945d1f8
--- /dev/null
+++ b/src/blast/blast_filter.h
@@ -0,0 +1,171 @@
+/* $Id: blast_filter.h 191335 2010-05-12 12:50:24Z madden $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Ilya Dondoshansky
+ *
+ */
+
+/** @file blast_filter.h
+ * BLAST filtering functions. @todo FIXME: contains more than filtering 
+ * functions, combine with blast_dust.h?
+ */
+
+#ifndef ALGO_BLAST_CORE__BLAST_FILTER__H
+#define ALGO_BLAST_CORE__BLAST_FILTER__H
+
+#include "blast_def.h"
+
+/** BLASTNA element used to mask bases in BLAST */
+extern const uint8_t kNuclMask;
+/** NCBISTDAA element used to mask residues in BLAST */
+extern const uint8_t kProtMask;
+
+/** Repeats filtering default options. */
+#define REPEATS_SEARCH_EVALUE 0.1       /**< Default e-value threshold, keep for C toolkit */
+#define REPEATS_SEARCH_MINSCORE 26       /**< Default score cutoff */
+#define REPEATS_SEARCH_PENALTY -1       /**< Default mismatch penalty */
+#define REPEATS_SEARCH_REWARD 1       /**< Default match reward */
+#define REPEATS_SEARCH_GAP_OPEN 2       /**< Default gap opening cost */
+#define REPEATS_SEARCH_GAP_EXTEND 1     /**< Default gap extension cost */
+#define REPEATS_SEARCH_WORD_SIZE 11     /**< Default word size */
+#define REPEATS_SEARCH_XDROP_UNGAPPED 40/**< Default X-dropoff for ungapped 
+                                           extension */
+#define REPEATS_SEARCH_XDROP_FINAL 90   /**< Default X-dropoff for gapped 
+                                           extension with traceback */
+#define REPEATS_SEARCH_FILTER_STRING "F"/**< Default filter string - 
+                                           no filtering */
+
+/** Largest gap allowed to be filled between repeat mask intervals */
+#define REPEAT_MASK_LINK_VALUE 5
+
+/** Create and initialize a new sequence interval.
+ * @param head existing BlastSeqLoc to append onto, if *head
+ *   is NULL then it will be set to new BlastSeqLoc, may be NULL [in|out]
+ * @param from Start of the interval [in]
+ * @param to End of the interval [in]
+ * @return Pointer to the allocated BlastSeqLoc structure (i.e.: tail of the
+ * list).
+ */
+BlastSeqLoc* BlastSeqLocNew(BlastSeqLoc** head, uint32_t from, uint32_t to);
+
+/** Appends the BlastSeqLoc to the list of BlastSeqLoc-s pointed to by head.
+ * @param head Pointer to the head of the linked list of BlastSeqLoc-s [in]
+ * @param node Pointer to the node to be added to the list. If this is NULL,
+ * this function does nothing. [in]
+ * @returns pointer to the second argument to this function (i.e.: tail of the
+ * list)
+ */
+BlastSeqLoc* BlastSeqLocAppend(BlastSeqLoc** head, BlastSeqLoc* node);
+
+/** Deallocate a single BlastSeqLoc structure and its contents, without
+ * following its next pointer
+ * @param node structure to deallocate [in]
+ * @return NULL
+ */
+BlastSeqLoc* BlastSeqLocNodeFree(BlastSeqLoc* node);
+
+/** Deallocate all BlastSeqLoc objects in a chain.
+ * @param loc object to be freed [in]
+ * @return NULL pointer returned.
+ */
+BlastSeqLoc* BlastSeqLocFree(BlastSeqLoc* loc);
+
+/** Make a deep copy of the linked list of BlastSeqLoc-s pointed to by its
+ * argument
+ * @param head head of the linked list [in]
+ * @return NULL on NULL input or memory allocation failure, else a copy of the
+ * list and its contents
+ */
+BlastSeqLoc* BlastSeqLocListDup(BlastSeqLoc* head);
+
+/** Converts reverse strand coordinates to forward strand in place.
+ * @param masks BlastSeqLoc to be reversed [in|out]
+ * @param query_length length of query [in]
+ */
+void BlastSeqLocReverse(BlastSeqLoc* masks, uint32_t query_length);
+
+/** Go through all mask locations in one sequence and combine any that overlap,
+ * deallocating the unneeded locations.
+ * @param mask_loc The list of masks to be merged (in place) [in|out] 
+ * @param link_value Largest gap size between locations for which they
+ *                   should be linked together [in] 
+*/
+void
+BlastSeqLocCombine(BlastSeqLoc** mask_loc, uint32_t link_value);
+
+/** Allocate memory for a BlastMaskLoc.
+ * @param total number of contexts for which SSeqLocs should be allocated 
+ * (result of number of queries * number of contexts for given program) [in]
+ * @return Pointer to the allocated BlastMaskLoc structure.
+*/
+BlastMaskLoc* BlastMaskLocNew(uint32_t total);
+
+/** 
+ * @brief Perform a deep copy of the BlastMaskLoc structure passed to this
+ * function
+ * 
+ * @param mask_loc Source masking location structure [in]
+ * 
+ * @return Deep copy of its argument, or NULL if the argument was NULL or if
+ * not enough memory was available
+ */
+BlastMaskLoc* BlastMaskLocDup(const BlastMaskLoc* mask_loc);
+
+/** Deallocate memory for a BlastMaskLoc structure
+ * as well as the BlastSeqLoc's pointed to.
+ * @param mask_loc the object to be deleted [in]
+ * @return NULL pointer
+ */
+BlastMaskLoc* BlastMaskLocFree(BlastMaskLoc* mask_loc);
+
+/** Masks the letters in buffer.
+ * This is a low-level routine and takes a raw buffer which it assumes
+ * to be in ncbistdaa (protein) or blastna (nucleotide).
+ * @param buffer the sequence to be masked (will be modified, cannot be NULL or
+ * undefined behavior will result).[in|out]
+ * @param length length of the sequence to be masked . [in]
+ * @param is_na nucleotide if TRUE [in]
+ * @param mask_loc the BlastSeqLoc to use for masking [in] 
+ * @param reverse minus strand if TRUE [in]
+ * @param offset how far along sequence is 1st residuse in buffer [in]
+*/
+void
+Blast_MaskTheResidues(uint8_t * buffer, uint32_t length, bool is_na,
+    const BlastSeqLoc* mask_loc, bool reverse, uint32_t offset);
+
+/** Mask protein letters that are currently unsupported. This routine
+ *  is used to make the core ignore letters within protein sequences
+ *  that cannot (yet) be correctly handled
+ * @param seq Protein sequence to be masked (ncbistdaa format required).
+ *            Letters whose numerical value exceeds a cutoff are
+ *            converted into kProtMask values [in|out]
+ * @param min_invalid The first ncbistdaa value that is considered invalid.
+ *            All sequence letters with numerical value >= this number
+ *            are masked [in]
+ */
+void
+Blast_MaskUnsupportedAA(BLAST_SequenceBlk* seq, uint8_t min_invalid);
+
+#endif /* !ALGO_BLAST_CORE__BLAST_FILTER__H */
diff --git a/src/blast/blast_message.h b/src/blast/blast_message.h
new file mode 100644
index 0000000..0534868
--- /dev/null
+++ b/src/blast/blast_message.h
@@ -0,0 +1,174 @@
+/* $Id: blast_message.h 403705 2013-06-18 11:19:40Z fongah2 $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Tom Madden
+ *
+ */
+
+/** @file blast_message.h
+ * Structures for BLAST messages
+ */
+
+#ifndef ALGO_BLAST_CORE__BLAST_MESSAGE__H
+#define ALGO_BLAST_CORE__BLAST_MESSAGE__H
+
+#include "ncbi_std.h"
+
+#define NCBI_XBLAST_EXPORT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Structure to enclose the origin of an error message or warning
+ */
+typedef struct SMessageOrigin {
+    char* filename;     /**< Name of the file */
+    int lineno;         /**< Line number in the file above */
+} SMessageOrigin;
+
+/** Blast error message severities .
+ * These start with 1 to be consistent
+ * with the C toolkit severity numbers.
+ */
+typedef enum {
+   eBlastSevInfo = 1,
+   eBlastSevWarning,
+   eBlastSevError,
+   eBlastSevFatal
+} EBlastSeverity;
+
+extern NCBI_XBLAST_EXPORT const int kBlastMessageNoContext;  /**< No single context is known to cause the error 
+                                                 (probably a setup issue). */
+
+/** Structure to hold the a message from the core of the BLAST engine. */
+typedef struct Blast_Message {
+     struct Blast_Message *next; /**< next message in this list */
+     EBlastSeverity severity; /**< severity code */
+     char* message;	/**< User message to be saved. */
+     SMessageOrigin* origin; /**< Optional: origin of the message */
+     int context; /**< Context, allows us to print message for query number. 
+                      kBlastMessageNoContext used if no context applies */
+} Blast_Message;
+
+/** Deallocates message memory.
+ * @param blast_msg structure to be deallocated [in]
+*/
+
+NCBI_XBLAST_EXPORT
+Blast_Message* Blast_MessageFree(Blast_Message* blast_msg);
+
+
+/** Writes a message to a structure.  The Blast_Message* is allocated.
+ * @param blast_msg structure to be filled in [in] 
+ * @param severity severity code [in] 
+ * @param context query context to which this error applies [in]
+ * @param message User message to be saved [in]
+*/
+
+NCBI_XBLAST_EXPORT
+Int2 Blast_MessageWrite(Blast_Message* *blast_msg, EBlastSeverity severity, 
+                        int context, const char *message);
+
+
+/** Print a message with ErrPostEx
+ * @param blast_msg message to be printed [in]
+*/
+
+NCBI_XBLAST_EXPORT
+Int2 Blast_MessagePost(Blast_Message* blast_msg);
+
+/* FIXME: should the code below and its implementation be moved to another
+ * file, say blast_error.[hc]? */
+
+/** Analogous to perror
+ * @param msg object to be appended to or created [in|out]
+ * @param error_code error code returned from BLAST function [in]
+ * @param context context number so that query or frame can be found [in]
+ * @return Blast_Message structure containing error description
+ */
+NCBI_XBLAST_EXPORT
+void Blast_Perror(Blast_Message* *msg, Int2 error_code, int context);
+
+/** Convenient define to call the function Blast_PerrorEx. */
+#define Blast_PerrorWithLocation(msg, error_code, context) \
+Blast_PerrorEx(msg, error_code, __FILE__, __LINE__, context)
+
+/** Extended version of Blast_Perror which includes parameters for the file
+ * name and line number where the error/warning occurred. This function should
+ * be invoked via the Blast_PerrorWithLocation macro.
+ * @param msg object to be appended to or created [in|out]
+ * @param error_code one of the error codes defined below [in]
+ * @param file_name name of the file where the error ocurred [in]
+ * @param lineno line number where the error ocurred in the file above [in]
+ * @param context context number so that query or frame can be found [in]
+ */
+NCBI_XBLAST_EXPORT
+void Blast_PerrorEx(Blast_Message* *msg,
+                              Int2 error_code, 
+                              const char* file_name, 
+                              int lineno,
+                              int context);
+
+/* BLAST error codes: these are meant to describe errors that can occur in the
+ * core of BLAST only 
+ */
+
+/** System error: out of memory condition */
+#define BLASTERR_MEMORY                             50
+
+/** Invalid parameter: possible programmer error or pre-condition not met */
+#define BLASTERR_INVALIDPARAM                       75
+
+/** Could not compute the ideal Karlin-Altschul parameters */
+#define BLASTERR_IDEALSTATPARAMCALC                 100
+
+/** Composition based statistics/Smith-Waterman not supported for a program 
+ * type */
+#define BLASTERR_REDOALIGNMENTCORE_NOTSUPPORTED     101
+
+/** All queries/contexts are determined invalid in the setup code */
+#define BLASTERR_INVALIDQUERIES                     102
+
+/** BLAST search was interrupted via a user-provided callback */
+#define BLASTERR_INTERRUPTED                        103
+
+/** Could not calculate Karlin-Altschul statistics for any context. */
+#define BLASTERR_NOVALIDKARLINALTSCHUL              104
+
+/** The option is not supported with the specified program. */
+#define BLASTERR_OPTION_PROGRAM_INVALID             201  
+
+  /** The value of the option is not supported (e.g., word size too small) */
+#define BLASTERR_OPTION_VALUE_INVALID               202
+
+/** Blast seqsrc returns  BLAST_SEQSRC_ERROR */
+#define BLASTERR_SEQSRC								300
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !ALGO_BLAST_CORE__BLAST_MESSAGE__H */
+
diff --git a/src/blast/blast_program.h b/src/blast/blast_program.h
new file mode 100644
index 0000000..2c5ce5e
--- /dev/null
+++ b/src/blast/blast_program.h
@@ -0,0 +1,175 @@
+/* $Id: blast_program.h 103498 2007-05-04 18:56:48Z camacho $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Christiam Camacho / Ilya Dondoshansky
+ *
+ */
+
+/** @file blast_program.h
+ * Definitions for various programs supported by core BLAST
+ */
+
+#ifndef ALGO_BLAST_CORE___BLAST_PROGRAM__H
+#define ALGO_BLAST_CORE___BLAST_PROGRAM__H
+
+#include "ncbi_std.h"
+
+#define NCBI_XBLAST_EXPORT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Low-level preprocessor definitions: these are not intended to be used
+ * directly, use the EBlastProgramType enumeration below */
+
+/** This bit is on if the query is protein */
+#define PROTEIN_QUERY_MASK      (0x1<<0)
+/** This bit is on if the subject is protein */
+#define PROTEIN_SUBJECT_MASK    (0x1<<1)
+/** This bit is on if the query is nucleotide */
+#define NUCLEOTIDE_QUERY_MASK   (0x1<<2)
+/** This bit is on if the subject is nucleotide */
+#define NUCLEOTIDE_SUBJECT_MASK (0x1<<3)
+/** This bit is on if the query is translated */
+#define TRANSLATED_QUERY_MASK   (0x1<<4)
+/** This bit is on if the subject is translated */
+#define TRANSLATED_SUBJECT_MASK (0x1<<5)
+/** This bit is on if the query is a PSSM (PSI-BLAST) */
+#define PSSM_QUERY_MASK         (0x1<<6)
+/** This bit is on if the subject is a PSSM (RPS-BLAST) */
+#define PSSM_SUBJECT_MASK       (0x1<<7)
+/** This bit is on if the query includes a pattern (PHI-BLAST) */
+#define PATTERN_QUERY_MASK      (0x1<<8)
+
+/******************** Main BLAST program definitions ***********************/
+
+/** Defines the engine's notion of the different applications of the BLAST 
+ * algorithm */
+typedef enum {
+    eBlastTypeBlastp        = (PROTEIN_QUERY_MASK | PROTEIN_SUBJECT_MASK),
+    eBlastTypeBlastn        = (NUCLEOTIDE_QUERY_MASK | NUCLEOTIDE_SUBJECT_MASK),
+    eBlastTypeBlastx        = (NUCLEOTIDE_QUERY_MASK | PROTEIN_SUBJECT_MASK | 
+                               TRANSLATED_QUERY_MASK),
+    eBlastTypeTblastn       = (PROTEIN_QUERY_MASK | NUCLEOTIDE_SUBJECT_MASK | 
+                               TRANSLATED_SUBJECT_MASK),
+    eBlastTypeTblastx       = (NUCLEOTIDE_QUERY_MASK | NUCLEOTIDE_SUBJECT_MASK
+                               | TRANSLATED_QUERY_MASK 
+                               | TRANSLATED_SUBJECT_MASK),
+    eBlastTypePsiBlast      = (PSSM_QUERY_MASK | eBlastTypeBlastp),
+    eBlastTypePsiTblastn    = (PSSM_QUERY_MASK | eBlastTypeTblastn),
+    eBlastTypeRpsBlast      = (PSSM_SUBJECT_MASK | eBlastTypeBlastp),
+    eBlastTypeRpsTblastn    = (PSSM_SUBJECT_MASK | eBlastTypeBlastx),
+    eBlastTypePhiBlastp     = (PATTERN_QUERY_MASK | eBlastTypeBlastp),
+    eBlastTypePhiBlastn     = (PATTERN_QUERY_MASK | eBlastTypeBlastn),
+    eBlastTypeUndefined     = 0x0
+} EBlastProgramType;
+
+/************* Functions to classify programs by query **********************/
+
+/** Returns true if the query is protein 
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_QueryIsProtein(EBlastProgramType p);
+
+/** Returns true if the query is nucleotide
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_QueryIsNucleotide(EBlastProgramType p);
+
+/** Returns true if the query is PSSM
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_QueryIsPssm(EBlastProgramType p);
+
+/************* Functions to classify programs by subject **********************/
+
+/** Returns true if the subject is protein 
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_SubjectIsProtein(EBlastProgramType p);
+
+/** Returns true if the subject is nucleotide
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_SubjectIsNucleotide(EBlastProgramType p);
+
+/** Returns true if the subject is PSSM
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_SubjectIsPssm(EBlastProgramType p);
+
+/************* Functions to classify programs by translation *****************/
+
+/** Returns true if the query is translated
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_QueryIsTranslated(EBlastProgramType p);
+
+/** Returns true if the subject is translated
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_SubjectIsTranslated(EBlastProgramType p);
+
+/************* Functions to classify special BLAST programs *****************/
+
+/** Returns true if program is PSI-BLAST (i.e.: involves a PSSM as query)
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_ProgramIsPsiBlast(EBlastProgramType p);
+
+/** Returns true if program is PHI-BLAST (i.e.: involves a pattern)
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_ProgramIsPhiBlast(EBlastProgramType p);
+
+/** Returns true if program is RPS-BLAST (i.e.: involves a PSSM as subject)
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_ProgramIsRpsBlast(EBlastProgramType p);
+
+/** Returns true if program is not undefined
+ * @param p program type [in]
+ */
+NCBI_XBLAST_EXPORT 
+bool Blast_ProgramIsValid(EBlastProgramType p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ALGO_BLAST_CORE__BLAST_PROGRAM__H */
+
diff --git a/src/blast/blast_query_info.h b/src/blast/blast_query_info.h
new file mode 100644
index 0000000..58415f3
--- /dev/null
+++ b/src/blast/blast_query_info.h
@@ -0,0 +1,212 @@
+/* $Id: blast_query_info.h 419604 2013-11-26 22:49:06Z rafanovi $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author: Christiam Camacho
+ *
+ */
+
+/** @file blast_query_info.h
+ * Definitions and functions associated with the BlastQueryInfo structure
+ */
+
+#ifndef ALGO_BLAST_CORE__BLAST_QUERY_INFO__H
+#define ALGO_BLAST_CORE__BLAST_QUERY_INFO__H
+
+#include "ncbi_std.h"
+#include "blast_def.h"
+#include "blast_program.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** The context related information */
+typedef struct BlastContextInfo {
+    Int4 query_offset;      /**< Offset of this query, strand or frame in the
+                               concatenated super-query. */
+    Int4 query_length;      /**< Length of this query, strand or frame */
+    Int8 eff_searchsp;      /**< Effective search space for this context. */
+    Int4 length_adjustment; /**< Length adjustment for boundary conditions */
+    Int4 query_index;       /**< Index of query (same for all frames) */
+    Int1 frame;             /**< Frame number (-1, -2, -3, 0, 1, 2, or 3) */
+    bool is_valid;       /**< Determine if this context is valid or not.
+                              This field should be set only by the setup code
+                              and read by subsequent stages of the BLAST search
+                              */
+} BlastContextInfo;
+
+/** Forward declaration of SPHIQueryInfo */
+struct SPHIQueryInfo;
+
+/** The query related information 
+ */
+typedef struct BlastQueryInfo {
+    Int4 first_context;  /**< Index of the first element of the context array */
+    Int4 last_context;   /**< Index of the last element of the context array */
+    int num_queries;     /**< Number of query sequences */
+    BlastContextInfo * contexts; /**< Information per context */
+    Uint4 max_length;    /**< Length of the longest among the concatenated
+                            queries */
+    struct SPHIQueryInfo* pattern_info; /**< Counts of PHI BLAST pattern
+                                      occurrences, used in PHI BLAST only. */
+} BlastQueryInfo;
+
+
+/** Allocate memory for query information structure */
+NCBI_XBLAST_EXPORT
+BlastQueryInfo* BlastQueryInfoNew(EBlastProgramType program, int num_queries);
+
+/** Deallocate memory for query information structure */
+NCBI_XBLAST_EXPORT
+BlastQueryInfo* BlastQueryInfoFree(BlastQueryInfo* query_info);
+
+/** Duplicates the query information structure */
+NCBI_XBLAST_EXPORT
+BlastQueryInfo* BlastQueryInfoDup(const BlastQueryInfo* query_info);
+
+/** Given a context from BLAST engine core, return the query index.
+ * @param context Context saved in a BlastHSP structure [in]
+ * @param program Type of BLAST program [in]
+ * @return Query index in a set of queries or -1 on error
+ */
+NCBI_XBLAST_EXPORT
+Int4 Blast_GetQueryIndexFromContext(Int4 context, EBlastProgramType program);
+
+
+/** Return the query index (zero based), given the query offset
+ *   in the initial HSP as the program.
+ * @param query_offset Offset of the query in the initial HSP [in]
+ * @param program EBlastProgramType [in]
+ * @param query_info information about all the queries [in]
+ * @return Query Index in a set of queries
+*/
+NCBI_XBLAST_EXPORT
+Int4 Blast_GetQueryIndexFromQueryOffset(Int4 query_offset, EBlastProgramType program, const BlastQueryInfo* query_info);
+
+
+/** Retrieve a query sequence's search space
+ * @param qinfo BlastQueryInfo structure [in]
+ * @param program CORE program type [in]
+ * @param query_index number of the query 
+ * (query_index < BlastQueryInfo::num_queries) [in]
+ * @return the search space of the query sequence requested or 0 if this is not
+ * set */
+NCBI_XBLAST_EXPORT
+Int8
+BlastQueryInfoGetEffSearchSpace(const BlastQueryInfo* qinfo,
+                                EBlastProgramType program,
+                                Int4 query_index);
+
+/** Set a query sequence's search space
+ * @param qinfo BlastQueryInfo structure [in]
+ * @param program CORE program type [in]
+ * @param query_index number of the query 
+ * (query_index < BlastQueryInfo::num_queries) [in]
+ * @param eff_searchsp the effective search space to use [in]
+ */
+NCBI_XBLAST_EXPORT
+void
+BlastQueryInfoSetEffSearchSpace(BlastQueryInfo* qinfo,
+                                EBlastProgramType program,
+                                Int4 query_index,
+                                Int8 eff_searchsp);
+
+/** Obtains the sequence length for a given query in the query, without taking
+ * into consideration any applicable translations 
+ * @param qinfo BlastQueryInfo structure [in]
+ * @param program CORE program type [in]
+ * @param query_index number of the query 
+ * (query_index < BlastQueryInfo::num_queries) [in]
+ * @return the length of the query sequence requested
+ */
+NCBI_XBLAST_EXPORT
+Int4 BlastQueryInfoGetQueryLength(const BlastQueryInfo* qinfo,
+                                  EBlastProgramType program,
+                                  Int4 query_index);
+
+/** Create auxiliary query structures with all data corresponding
+ * to a single query sequence within a concatenated set. Allocates the 
+ * structures if the pointers are NULL on input; otherwise only changes the
+ * contents.
+ * @param one_query_info_ptr Pointer to the query information structure for a 
+ *                           single query. Allocated and filled here, so the
+ *                           caller of this function will be responsible for
+ *                           freeing it. [out]
+ * @param one_query_ptr Pointer to the query sequence block structure; allocated
+ *                      here, but the contents are not allocated; it is still 
+ *                      safe to free by the caller after use. [out]
+ * @param query_info Query information structure containing information about a 
+ *                   concatenated set. [in]
+ * @param query Query sequence block corresponding to a concatenated set of 
+ *              queries. [in]
+ * @param query_index Which query index to create the auxiliary structures 
+ *                    for? [in]
+ * @return -1 if memory allocation failed; 0 on success
+ */
+NCBI_XBLAST_EXPORT
+Int2 Blast_GetOneQueryStructs(BlastQueryInfo** one_query_info_ptr, 
+                              BLAST_SequenceBlk** one_query_ptr,
+                              const BlastQueryInfo* query_info, 
+                              BLAST_SequenceBlk* query, Int4 query_index);
+
+/** Search BlastContextInfo structures for the specified offset */
+NCBI_XBLAST_EXPORT
+Int4 BSearchContextInfo(Int4 n, const BlastQueryInfo * A);
+
+/** Get the number of bytes required for the concatenated sequence
+ * buffer, given a query info structure.  The context data should
+ * already be assigned.
+ * @param qinfo  Query info structure. [in/out]
+ * @return Number of bytes for all queries and inter-query marks.
+ */
+NCBI_XBLAST_EXPORT
+Uint4
+QueryInfo_GetSeqBufLen(const BlastQueryInfo* qinfo);
+
+
+/** Copy the context query offsets to an allocated array of Int4.
+ * @param info Describes the concatenated query.
+ * @return Allocated array.
+ */
+NCBI_XBLAST_EXPORT
+Int4 * ContextOffsetsToOffsetArray(const BlastQueryInfo* info);
+
+
+/** Copy the context query offsets from an array of Int4, allocating
+ * the context array if needed.
+ * @param info Destination for the values.
+ * @param new_offsets Array of values to copy from.
+ * @param prog        The blast program type.
+ */
+NCBI_XBLAST_EXPORT
+void OffsetArrayToContextOffsets(BlastQueryInfo    * info,
+                                 Int4              * new_offsets,
+                                 EBlastProgramType   prog);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ALGO_BLAST_CORE__BLAST_QUERY_INFO__H */
diff --git a/src/blast/blast_seg.cpp b/src/blast/blast_seg.cpp
new file mode 100644
index 0000000..b984750
--- /dev/null
+++ b/src/blast/blast_seg.cpp
@@ -0,0 +1,2314 @@
+/* $Id: blast_seg.c 170558 2009-09-14 18:45:07Z maning $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE                          
+ *               National Center for Biotechnology Information
+ *                                                                          
+ *  This software/database is a "United States Government Work" under the   
+ *  terms of the United States Copyright Act.  It was written as part of    
+ *  the author's official duties as a United States Government employee and 
+ *  thus cannot be copyrighted.  This software/database is freely available 
+ *  to the public for use. The National Library of Medicine and the U.S.    
+ *  Government have not placed any restriction on its use or reproduction.  
+ *                                                                          
+ *  Although all reasonable efforts have been taken to ensure the accuracy  
+ *  and reliability of the software and data, the NLM and the U.S.          
+ *  Government do not and cannot warrant the performance or results that    
+ *  may be obtained by using this software or data. The NLM and the U.S.    
+ *  Government disclaim all warranties, express or implied, including       
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.                                                                
+ *                                                                          
+ *  Please cite the author in any work or product based on this material.   
+ *
+ * ===========================================================================
+ *
+ * Author: Ilya Dondoshansky
+ *
+ */
+
+/** @file blast_seg.c
+ * A utility to find low complexity AA regions. This parallels functionality 
+ * of seg.c from the C toolkit, but without using the structures generated 
+ * from ASN.1 spec.
+ * @todo FIXME needs comments
+ */
+
+#include <cstddef>
+#include <limits>
+#include <math.h>
+#include <algorithm>
+#include "blast_seg.h"
+#include "blast_filter.h"
+#include "ncbi_math.h"
+
+//#include <algo/blast/core/blast_filter.h>
+
+
+/** Declared in blast_def.h. */
+const int kSegWindow = 12;
+const double kSegLocut = 2.2;
+const double kSegHicut = 2.5;
+
+/** Natural log of factorials: 0!, 1!, 2!, 3! */
+double lnfact[] = 
+  {
+   0.000000, 0.000000, 0.693147, 1.791759, 3.178054, 4.787492, 6.579251, 8.525161, 
+   10.604603, 12.801827, 15.104413, 17.502308, 19.987214, 22.552164, 25.191221, 27.899271, 
+   30.671860, 33.505073, 36.395445, 39.339884, 42.335616, 45.380139, 48.471181, 51.606676, 
+   54.784729, 58.003605, 61.261702, 64.557539, 67.889743, 71.257039, 74.658236, 78.092224, 
+   81.557959, 85.054467, 88.580828, 92.136176, 95.719695, 99.330612, 102.968199, 106.631760, 
+   110.320640, 114.034212, 117.771881, 121.533082, 125.317271, 129.123934, 132.952575, 136.802723, 
+   140.673924, 144.565744, 148.477767, 152.409593, 156.360836, 160.331128, 164.320112, 168.327445, 
+   172.352797, 176.395848, 180.456291, 184.533829, 188.628173, 192.739047, 196.866182, 201.009316, 
+   205.168199, 209.342587, 213.532241, 217.736934, 221.956442, 226.190548, 230.439044, 234.701723, 
+   238.978390, 243.268849, 247.572914, 251.890402, 256.221136, 260.564941, 264.921650, 269.291098, 
+   273.673124, 278.067573, 282.474293, 286.893133, 291.323950, 295.766601, 300.220949, 304.686857, 
+   309.164194, 313.652830, 318.152640, 322.663499, 327.185288, 331.717887, 336.261182, 340.815059, 
+   345.379407, 349.954118, 354.539086, 359.134205, 363.739376, 368.354496, 372.979469, 377.614198, 
+   382.258589, 386.912549, 391.575988, 396.248817, 400.930948, 405.622296, 410.322777, 415.032307, 
+   419.750806, 424.478193, 429.214392, 433.959324, 438.712914, 443.475088, 448.245773, 453.024896, 
+   457.812388, 462.608179, 467.412200, 472.224384, 477.044665, 481.872979, 486.709261, 491.553448, 
+   496.405478, 501.265291, 506.132825, 511.008023, 515.890825, 520.781174, 525.679014, 530.584288, 
+   535.496943, 540.416924, 545.344178, 550.278652, 555.220294, 560.169054, 565.124881, 570.087726, 
+   575.057539, 580.034273, 585.017879, 590.008312, 595.005524, 600.009471, 605.020106, 610.037386, 
+   615.061266, 620.091704, 625.128657, 630.172082, 635.221938, 640.278184, 645.340779, 650.409683, 
+   655.484857, 660.566261, 665.653857, 670.747608, 675.847474, 680.953420, 686.065407, 691.183401, 
+   696.307365, 701.437264, 706.573062, 711.714726, 716.862220, 722.015512, 727.174567, 732.339353, 
+   737.509837, 742.685987, 747.867770, 753.055156, 758.248113, 763.446610, 768.650617, 773.860103, 
+   779.075039, 784.295395, 789.521141, 794.752250, 799.988692, 805.230439, 810.477463, 815.729736, 
+   820.987232, 826.249922, 831.517780, 836.790780, 842.068894, 847.352098, 852.640365, 857.933670, 
+   863.231987, 868.535292, 873.843560, 879.156766, 884.474886, 889.797896, 895.125772, 900.458491, 
+   905.796029, 911.138363, 916.485471, 921.837329, 927.193915, 932.555207, 937.921183, 943.291821, 
+   948.667100, 954.046997, 959.431492, 964.820564, 970.214191, 975.612354, 981.015031, 986.422203, 
+   991.833849, 997.249950, 1002.670485, 1008.095435, 1013.524780, 1018.958502, 1024.396582, 1029.838999, 
+   1035.285737, 1040.736775, 1046.192096, 1051.651682, 1057.115514, 1062.583574, 1068.055844, 1073.532308, 
+   1079.012947, 1084.497744, 1089.986681, 1095.479743, 1100.976911, 1106.478169, 1111.983501, 1117.492889, 
+   1123.006318, 1128.523771, 1134.045232, 1139.570685, 1145.100114, 1150.633503, 1156.170838, 1161.712101, 
+   1167.257279, 1172.806355, 1178.359314, 1183.916142, 1189.476824, 1195.041344, 1200.609689, 1206.181843, 
+   1211.757792, 1217.337522, 1222.921018, 1228.508267, 1234.099254, 1239.693965, 1245.292387, 1250.894506, 
+   1256.500308, 1262.109780, 1267.722908, 1273.339679, 1278.960080, 1284.584097, 1290.211718, 1295.842930, 
+   1301.477720, 1307.116075, 1312.757982, 1318.403428, 1324.052403, 1329.704892, 1335.360884, 1341.020366, 
+   1346.683326, 1352.349753, 1358.019634, 1363.692957, 1369.369711, 1375.049884, 1380.733463, 1386.420439, 
+   1392.110798, 1397.804530, 1403.501624, 1409.202067, 1414.905850, 1420.612960, 1426.323387, 1432.037120, 
+   1437.754148, 1443.474460, 1449.198045, 1454.924892, 1460.654992, 1466.388333, 1472.124906, 1477.864699, 
+   1483.607702, 1489.353905, 1495.103298, 1500.855871, 1506.611613, 1512.370515, 1518.132566, 1523.897757, 
+   1529.666078, 1535.437519, 1541.212071, 1546.989723, 1552.770467, 1558.554292, 1564.341189, 1570.131149, 
+   1575.924163, 1581.720221, 1587.519313, 1593.321432, 1599.126567, 1604.934709, 1610.745850, 1616.559981, 
+   1622.377092, 1628.197175, 1634.020221, 1639.846221, 1645.675166, 1651.507049, 1657.341860, 1663.179590, 
+   1669.020232, 1674.863776, 1680.710215, 1686.559540, 1692.411742, 1698.266814, 1704.124747, 1709.985533, 
+   1715.849165, 1721.715633, 1727.584930, 1733.457047, 1739.331978, 1745.209714, 1751.090247, 1756.973569, 
+   1762.859673, 1768.748551, 1774.640196, 1780.534598, 1786.431752, 1792.331650, 1798.234283, 1804.139645, 
+   1810.047728, 1815.958524, 1821.872027, 1827.788229, 1833.707123, 1839.628702, 1845.552957, 1851.479884, 
+   1857.409473, 1863.341718, 1869.276612, 1875.214148, 1881.154319, 1887.097119, 1893.042539, 1898.990574, 
+   1904.941217, 1910.894460, 1916.850298, 1922.808722, 1928.769728, 1934.733307, 1940.699454, 1946.668161, 
+   1952.639423, 1958.613233, 1964.589584, 1970.568470, 1976.549884, 1982.533820, 1988.520272, 1994.509233, 
+   2000.500698, 2006.494659, 2012.491111, 2018.490048, 2024.491463, 2030.495350, 2036.501703, 2042.510516, 
+   2048.521784, 2054.535499, 2060.551656, 2066.570249, 2072.591272, 2078.614720, 2084.640586, 2090.668864, 
+   2096.699550, 2102.732636, 2108.768117, 2114.805988, 2120.846243, 2126.888876, 2132.933881, 2138.981253, 
+   2145.030987, 2151.083076, 2157.137515, 2163.194299, 2169.253423, 2175.314879, 2181.378665, 2187.444773, 
+   2193.513198, 2199.583936, 2205.656981, 2211.732327, 2217.809969, 2223.889902, 2229.972121, 2236.056620, 
+   2242.143395, 2248.232440, 2254.323750, 2260.417320, 2266.513144, 2272.611219, 2278.711537, 2284.814096, 
+   2290.918889, 2297.025912, 2303.135160, 2309.246627, 2315.360309, 2321.476201, 2327.594299, 2333.714596, 
+   2339.837089, 2345.961772, 2352.088641, 2358.217692, 2364.348918, 2370.482316, 2376.617881, 2382.755608, 
+   2388.895493, 2395.037530, 2401.181716, 2407.328045, 2413.476513, 2419.627116, 2425.779849, 2431.934707, 
+   2438.091686, 2444.250781, 2450.411988, 2456.575303, 2462.740721, 2468.908238, 2475.077848, 2481.249549, 
+   2487.423335, 2493.599202, 2499.777146, 2505.957163, 2512.139248, 2518.323397, 2524.509606, 2530.697870, 
+   2536.888185, 2543.080548, 2549.274953, 2555.471397, 2561.669876, 2567.870385, 2574.072920, 2580.277478, 
+   2586.484054, 2592.692644, 2598.903244, 2605.115850, 2611.330458, 2617.547065, 2623.765665, 2629.986255, 
+   2636.208831, 2642.433390, 2648.659926, 2654.888437, 2661.118919, 2667.351367, 2673.585777, 2679.822147, 
+   2686.060472, 2692.300747, 2698.542971, 2704.787138, 2711.033244, 2717.281287, 2723.531263, 2729.783166, 
+   2736.036995, 2742.292745, 2748.550413, 2754.809994, 2761.071486, 2767.334884, 2773.600185, 2779.867386, 
+   2786.136482, 2792.407471, 2798.680348, 2804.955110, 2811.231753, 2817.510275, 2823.790671, 2830.072937, 
+   2836.357071, 2842.643070, 2848.930928, 2855.220644, 2861.512213, 2867.805632, 2874.100898, 2880.398007, 
+   2886.696957, 2892.997742, 2899.300361, 2905.604810, 2911.911085, 2918.219184, 2924.529102, 2930.840837, 
+   2937.154385, 2943.469743, 2949.786908, 2956.105876, 2962.426644, 2968.749209, 2975.073568, 2981.399718, 
+   2987.727655, 2994.057376, 3000.388877, 3006.722157, 3013.057211, 3019.394037, 3025.732631, 3032.072990, 
+   3038.415112, 3044.758992, 3051.104629, 3057.452018, 3063.801157, 3070.152043, 3076.504672, 3082.859042, 
+   3089.215150, 3095.572992, 3101.932566, 3108.293868, 3114.656896, 3121.021647, 3127.388118, 3133.756305, 
+   3140.126206, 3146.497818, 3152.871137, 3159.246162, 3165.622889, 3172.001315, 3178.381438, 3184.763254, 
+   3191.146760, 3197.531955, 3203.918834, 3210.307396, 3216.697636, 3223.089553, 3229.483144, 3235.878406, 
+   3242.275335, 3248.673930, 3255.074188, 3261.476105, 3267.879679, 3274.284908, 3280.691788, 3287.100316, 
+   3293.510491, 3299.922310, 3306.335768, 3312.750865, 3319.167598, 3325.585963, 3332.005958, 3338.427580, 
+   3344.850827, 3351.275696, 3357.702184, 3364.130290, 3370.560009, 3376.991340, 3383.424280, 3389.858827, 
+   3396.294977, 3402.732729, 3409.172079, 3415.613026, 3422.055566, 3428.499697, 3434.945417, 3441.392723, 
+   3447.841612, 3454.292083, 3460.744132, 3467.197757, 3473.652955, 3480.109725, 3486.568063, 3493.027968, 
+   3499.489436, 3505.952465, 3512.417053, 3518.883198, 3525.350897, 3531.820147, 3538.290947, 3544.763293, 
+   3551.237184, 3557.712616, 3564.189589, 3570.668098, 3577.148143, 3583.629720, 3590.112827, 3596.597463, 
+   3603.083624, 3609.571308, 3616.060512, 3622.551236, 3629.043476, 3635.537230, 3642.032495, 3648.529270, 
+   3655.027552, 3661.527339, 3668.028629, 3674.531419, 3681.035707, 3687.541491, 3694.048769, 3700.557538, 
+   3707.067797, 3713.579542, 3720.092772, 3726.607485, 3733.123678, 3739.641349, 3746.160496, 3752.681117, 
+   3759.203210, 3765.726773, 3772.251802, 3778.778297, 3785.306255, 3791.835674, 3798.366551, 3804.898886, 
+   3811.432675, 3817.967916, 3824.504607, 3831.042747, 3837.582333, 3844.123363, 3850.665835, 3857.209747, 
+   3863.755097, 3870.301882, 3876.850101, 3883.399752, 3889.950832, 3896.503340, 3903.057274, 3909.612630, 
+   3916.169409, 3922.727607, 3929.287222, 3935.848253, 3942.410697, 3948.974552, 3955.539817, 3962.106490, 
+   3968.674567, 3975.244049, 3981.814932, 3988.387214, 3994.960895, 4001.535970, 4008.112440, 4014.690301, 
+   4021.269553, 4027.850192, 4034.432217, 4041.015626, 4047.600417, 4054.186589, 4060.774139, 4067.363066, 
+   4073.953367, 4080.545040, 4087.138085, 4093.732498, 4100.328279, 4106.925425, 4113.523934, 4120.123804, 
+   4126.725034, 4133.327622, 4139.931566, 4146.536864, 4153.143514, 4159.751515, 4166.360864, 4172.971560, 
+   4179.583601, 4186.196985, 4192.811711, 4199.427776, 4206.045179, 4212.663918, 4219.283991, 4225.905397, 
+   4232.528133, 4239.152198, 4245.777591, 4252.404308, 4259.032350, 4265.661713, 4272.292396, 4278.924398, 
+   4285.557717, 4292.192350, 4298.828297, 4305.465555, 4312.104122, 4318.743998, 4325.385180, 4332.027667, 
+   4338.671457, 4345.316548, 4351.962938, 4358.610627, 4365.259611, 4371.909890, 4378.561462, 4385.214325, 
+   4391.868478, 4398.523918, 4405.180645, 4411.838656, 4418.497950, 4425.158525, 4431.820380, 4438.483512, 
+   4445.147921, 4451.813605, 4458.480562, 4465.148790, 4471.818288, 4478.489054, 4485.161087, 4491.834385, 
+   4498.508947, 4505.184770, 4511.861853, 4518.540196, 4525.219795, 4531.900649, 4538.582758, 4545.266119, 
+   4551.950731, 4558.636592, 4565.323700, 4572.012055, 4578.701654, 4585.392497, 4592.084580, 4598.777904, 
+   4605.472466, 4612.168265, 4618.865299, 4625.563567, 4632.263068, 4638.963799, 4645.665759, 4652.368947, 
+   4659.073361, 4665.779001, 4672.485863, 4679.193947, 4685.903251, 4692.613774, 4699.325515, 4706.038471, 
+   4712.752642, 4719.468025, 4726.184620, 4732.902424, 4739.621438, 4746.341658, 4753.063083, 4759.785713, 
+   4766.509546, 4773.234579, 4779.960813, 4786.688244, 4793.416873, 4800.146697, 4806.877715, 4813.609926, 
+   4820.343328, 4827.077919, 4833.813700, 4840.550666, 4847.288819, 4854.028156, 4860.768675, 4867.510376, 
+   4874.253256, 4880.997315, 4887.742552, 4894.488964, 4901.236550, 4907.985310, 4914.735241, 4921.486343, 
+   4928.238613, 4934.992051, 4941.746655, 4948.502424, 4955.259356, 4962.017451, 4968.776706, 4975.537121, 
+   4982.298694, 4989.061423, 4995.825308, 5002.590347, 5009.356539, 5016.123882, 5022.892375, 5029.662017, 
+   5036.432806, 5043.204742, 5049.977822, 5056.752046, 5063.527412, 5070.303919, 5077.081566, 5083.860351, 
+   5090.640273, 5097.421330, 5104.203522, 5110.986848, 5117.771305, 5124.556892, 5131.343609, 5138.131454, 
+   5144.920426, 5151.710523, 5158.501745, 5165.294089, 5172.087555, 5178.882142, 5185.677848, 5192.474671, 
+   5199.272612, 5206.071668, 5212.871838, 5219.673121, 5226.475515, 5233.279021, 5240.083635, 5246.889358, 
+   5253.696187, 5260.504122, 5267.313161, 5274.123304, 5280.934548, 5287.746893, 5294.560338, 5301.374881, 
+   5308.190521, 5315.007257, 5321.825087, 5328.644011, 5335.464028, 5342.285135, 5349.107333, 5355.930619, 
+   5362.754992, 5369.580452, 5376.406998, 5383.234627, 5390.063339, 5396.893133, 5403.724007, 5410.555960, 
+   5417.388992, 5424.223101, 5431.058286, 5437.894545, 5444.731878, 5451.570283, 5458.409759, 5465.250306, 
+   5472.091921, 5478.934605, 5485.778355, 5492.623170, 5499.469050, 5506.315993, 5513.163998, 5520.013065, 
+   5526.863191, 5533.714376, 5540.566618, 5547.419917, 5554.274272, 5561.129681, 5567.986143, 5574.843657, 
+   5581.702222, 5588.561837, 5595.422500, 5602.284212, 5609.146970, 5616.010773, 5622.875621, 5629.741512, 
+   5636.608445, 5643.476419, 5650.345434, 5657.215487, 5664.086579, 5670.958707, 5677.831871, 5684.706069, 
+   5691.581301, 5698.457566, 5705.334862, 5712.213188, 5719.092544, 5725.972928, 5732.854339, 5739.736777, 
+   5746.620240, 5753.504726, 5760.390236, 5767.276768, 5774.164320, 5781.052893, 5787.942484, 5794.833093, 
+   5801.724719, 5808.617361, 5815.511017, 5822.405687, 5829.301370, 5836.198064, 5843.095769, 5849.994483, 
+   5856.894207, 5863.794937, 5870.696674, 5877.599417, 5884.503164, 5891.407915, 5898.313668, 5905.220423, 
+   5912.128178, 5919.036933, 5925.946687, 5932.857437, 5939.769185, 5946.681927, 5953.595665, 5960.510396, 
+   5967.426119, 5974.342834, 5981.260540, 5988.179235, 5995.098919, 6002.019590, 6008.941249, 6015.863892, 
+   6022.787521, 6029.712133, 6036.637729, 6043.564306, 6050.491864, 6057.420401, 6064.349918, 6071.280413, 
+   6078.211885, 6085.144333, 6092.077756, 6099.012153, 6105.947523, 6112.883866, 6119.821180, 6126.759465, 
+   6133.698719, 6140.638941, 6147.580131, 6154.522288, 6161.465410, 6168.409497, 6175.354548, 6182.300562, 
+   6189.247538, 6196.195476, 6203.144373, 6210.094229, 6217.045044, 6223.996816, 6230.949545, 6237.903229, 
+   6244.857868, 6251.813460, 6258.770006, 6265.727503, 6272.685952, 6279.645350, 6286.605698, 6293.566994, 
+   6300.529237, 6307.492427, 6314.456563, 6321.421643, 6328.387668, 6335.354635, 6342.322544, 6349.291394, 
+   6356.261185, 6363.231915, 6370.203584, 6377.176190, 6384.149733, 6391.124212, 6398.099626, 6405.075974, 
+   6412.053255, 6419.031469, 6426.010614, 6432.990690, 6439.971696, 6446.953631, 6453.936493, 6460.920283, 
+   6467.905000, 6474.890641, 6481.877208, 6488.864698, 6495.853111, 6502.842447, 6509.832703, 6516.823880, 
+   6523.815976, 6530.808991, 6537.802924, 6544.797774, 6551.793541, 6558.790222, 6565.787818, 6572.786328, 
+   6579.785750, 6586.786085, 6593.787330, 6600.789486, 6607.792552, 6614.796526, 6621.801408, 6628.807197, 
+   6635.813892, 6642.821493, 6649.829998, 6656.839407, 6663.849719, 6670.860933, 6677.873048, 6684.886064, 
+   6691.899979, 6698.914794, 6705.930506, 6712.947116, 6719.964622, 6726.983024, 6734.002320, 6741.022511, 
+   6748.043595, 6755.065571, 6762.088439, 6769.112198, 6776.136847, 6783.162386, 6790.188813, 6797.216127, 
+   6804.244328, 6811.273416, 6818.303389, 6825.334246, 6832.365988, 6839.398612, 6846.432118, 6853.466506, 
+   6860.501775, 6867.537923, 6874.574951, 6881.612857, 6888.651641, 6895.691301, 6902.731837, 6909.773249, 
+   6916.815535, 6923.858695, 6930.902728, 6937.947633, 6944.993410, 6952.040057, 6959.087574, 6966.135961, 
+   6973.185215, 6980.235338, 6987.286327, 6994.338183, 7001.390904, 7008.444490, 7015.498939, 7022.554252, 
+   7029.610428, 7036.667465, 7043.725362, 7050.784121, 7057.843738, 7064.904215, 7071.965549, 7079.027741, 
+   7086.090789, 7093.154693, 7100.219452, 7107.285065, 7114.351532, 7121.418852, 7128.487024, 7135.556047, 
+   7142.625922, 7149.696646, 7156.768219, 7163.840641, 7170.913911, 7177.988027, 7185.062991, 7192.138799, 
+   7199.215453, 7206.292951, 7213.371293, 7220.450477, 7227.530504, 7234.611372, 7241.693080, 7248.775629, 
+   7255.859017, 7262.943243, 7270.028307, 7277.114209, 7284.200947, 7291.288521, 7298.376929, 7305.466172, 
+   7312.556249, 7319.647159, 7326.738901, 7333.831475, 7340.924880, 7348.019114, 7355.114179, 7362.210072, 
+   7369.306793, 7376.404342, 7383.502718, 7390.601920, 7397.701947, 7404.802799, 7411.904475, 7419.006974, 
+   7426.110296, 7433.214440, 7440.319406, 7447.425192, 7454.531798, 7461.639223, 7468.747468, 7475.856530, 
+   7482.966409, 7490.077105, 7497.188617, 7504.300945, 7511.414087, 7518.528043, 7525.642812, 7532.758395, 
+   7539.874789, 7546.991994, 7554.110010, 7561.228837, 7568.348472, 7575.468917, 7582.590169, 7589.712229, 
+   7596.835096, 7603.958769, 7611.083247, 7618.208530, 7625.334617, 7632.461508, 7639.589202, 7646.717698, 
+   7653.846995, 7660.977094, 7668.107992, 7675.239691, 7682.372189, 7689.505485, 7696.639578, 7703.774469, 
+   7710.910156, 7718.046640, 7725.183918, 7732.321991, 7739.460858, 7746.600518, 7753.740971, 7760.882217, 
+   7768.024253, 7775.167081, 7782.310698, 7789.455105, 7796.600301, 7803.746286, 7810.893058, 7818.040617, 
+   7825.188963, 7832.338095, 7839.488012, 7846.638713, 7853.790199, 7860.942467, 7868.095519, 7875.249353, 
+   7882.403968, 7889.559364, 7896.715541, 7903.872497, 7911.030233, 7918.188747, 7925.348039, 7932.508108, 
+   7939.668954, 7946.830576, 7953.992973, 7961.156146, 7968.320093, 7975.484813, 7982.650306, 7989.816572, 
+   7996.983610, 8004.151419, 8011.319999, 8018.489349, 8025.659469, 8032.830357, 8040.002014, 8047.174439, 
+   8054.347631, 8061.521589, 8068.696313, 8075.871803, 8083.048057, 8090.225076, 8097.402859, 8104.581404, 
+   8111.760712, 8118.940782, 8126.121613, 8133.303205, 8140.485557, 8147.668669, 8154.852540, 8162.037169, 
+   8169.222556, 8176.408700, 8183.595601, 8190.783258, 8197.971671, 8205.160839, 8212.350761, 8219.541437, 
+   8226.732866, 8233.925048, 8241.117983, 8248.311668, 8255.506105, 8262.701293, 8269.897230, 8277.093916, 
+   8284.291352, 8291.489535, 8298.688466, 8305.888145, 8313.088570, 8320.289741, 8327.491657, 8334.694318, 
+   8341.897724, 8349.101873, 8356.306765, 8363.512401, 8370.718778, 8377.925897, 8385.133757, 8392.342357, 
+   8399.551697, 8406.761777, 8413.972595, 8421.184152, 8428.396447, 8435.609478, 8442.823246, 8450.037751, 
+   8457.252991, 8464.468966, 8471.685675, 8478.903119, 8486.121296, 8493.340205, 8500.559847, 8507.780221, 
+   8515.001326, 8522.223162, 8529.445728, 8536.669024, 8543.893049, 8551.117802, 8558.343284, 8565.569493, 
+   8572.796429, 8580.024091, 8587.252480, 8594.481593, 8601.711432, 8608.941995, 8616.173282, 8623.405293, 
+   8630.638026, 8637.871481, 8645.105658, 8652.340557, 8659.576176, 8666.812515, 8674.049574, 8681.287353, 
+   8688.525849, 8695.765064, 8703.004997, 8710.245647, 8717.487013, 8724.729095, 8731.971893, 8739.215406, 
+   8746.459634, 8753.704575, 8760.950230, 8768.196598, 8775.443679, 8782.691472, 8789.939976, 8797.189191, 
+   8804.439116, 8811.689752, 8818.941097, 8826.193151, 8833.445913, 8840.699383, 8847.953561, 8855.208446, 
+   8862.464037, 8869.720335, 8876.977337, 8884.235045, 8891.493457, 8898.752573, 8906.012393, 8913.272915, 
+   8920.534141, 8927.796068, 8935.058696, 8942.322026, 8949.586056, 8956.850786, 8964.116216, 8971.382345, 
+   8978.649172, 8985.916697, 8993.184920, 9000.453841, 9007.723457, 9014.993770, 9022.264779, 9029.536483, 
+   9036.808881, 9044.081973, 9051.355760, 9058.630239, 9065.905412, 9073.181276, 9080.457833, 9087.735080, 
+   9095.013019, 9102.291648, 9109.570967, 9116.850975, 9124.131672, 9131.413058, 9138.695132, 9145.977893, 
+   9153.261341, 9160.545476, 9167.830297, 9175.115803, 9182.401995, 9189.688871, 9196.976432, 9204.264676, 
+   9211.553604, 9218.843215, 9226.133507, 9233.424482, 9240.716138, 9248.008476, 9255.301493, 9262.595191, 
+   9269.889568, 9277.184625, 9284.480360, 9291.776773, 9299.073864, 9306.371632, 9313.670077, 9320.969199, 
+   9328.268996, 9335.569469, 9342.870617, 9350.172439, 9357.474936, 9364.778106, 9372.081949, 9379.386465, 
+   9386.691653, 9393.997513, 9401.304045, 9408.611247, 9415.919120, 9423.227662, 9430.536875, 9437.846756, 
+   9445.157306, 9452.468525, 9459.780411, 9467.092965, 9474.406185, 9481.720072, 9489.034625, 9496.349843, 
+   9503.665726, 9510.982275, 9518.299487, 9525.617363, 9532.935903, 9540.255105, 9547.574970, 9554.895497, 
+   9562.216686, 9569.538535, 9576.861046, 9584.184217, 9591.508047, 9598.832537, 9606.157686, 9613.483494, 
+   9620.809959, 9628.137082, 9635.464863, 9642.793300, 9650.122394, 9657.452144, 9664.782549, 9672.113609, 
+   9679.445324, 9686.777694, 9694.110717, 9701.444393, 9708.778722, 9716.113704, 9723.449338, 9730.785624, 
+   9738.122561, 9745.460148, 9752.798387, 9760.137275, 9767.476812, 9774.816999, 9782.157835, 9789.499319, 
+   9796.841450, 9804.184230, 9811.527656, 9818.871729, 9826.216448, 9833.561813, 9840.907823, 9848.254478, 
+   9855.601778, 9862.949721, 9870.298309, 9877.647540, 9884.997414, 9892.347930, 9899.699088, 9907.050888, 
+   9914.403329, 9921.756411, 9929.110133, 9936.464495, 9943.819497, 9951.175138, 9958.531418, 9965.888337, 
+   9973.245893, 9980.604087, 9987.962917, 9995.322385, 10002.682489, 10010.043229, 10017.404604, 10024.766615, 
+   10032.129260, 10039.492540, 10046.856453, 10054.221000, 10061.586180, 10068.951993, 10076.318438, 10083.685515, 
+   10091.053224, 10098.421564, 10105.790534, 10113.160135, 10120.530366, 10127.901226, 10135.272715, 10142.644833, 
+   10150.017579, 10157.390954, 10164.764956, 10172.139585, 10179.514840, 10186.890722, 10194.267231, 10201.644364, 
+   10209.022123, 10216.400507, 10223.779515, 10231.159147, 10238.539403, 10245.920282, 10253.301784, 10260.683908, 
+   10268.066655, 10275.450023, 10282.834012, 10290.218623, 10297.603854, 10304.989705, 10312.376176, 10319.763266, 
+   10327.150975, 10334.539303, 10341.928249, 10349.317813, 10356.707994, 10364.098793, 10371.490208, 10378.882240, 
+   10386.274887, 10393.668150, 10401.062029, 10408.456522, 10415.851629, 10423.247351, 10430.643686, 10438.040635, 
+   10445.438196, 10452.836370, 10460.235157, 10467.634555, 10475.034564, 10482.435185, 10489.836416, 10497.238258, 
+   10504.640709, 10512.043770, 10519.447441, 10526.851720, 10534.256607, 10541.662103, 10549.068206, 10556.474917, 
+   10563.882235, 10571.290159, 10578.698690, 10586.107826, 10593.517568, 10600.927915, 10608.338867, 10615.750423, 
+   10623.162584, 10630.575348, 10637.988715, 10645.402685, 10652.817258, 10660.232433, 10667.648210, 10675.064589, 
+   10682.481568, 10689.899149, 10697.317330, 10704.736111, 10712.155491, 10719.575471, 10726.996050, 10734.417227, 
+   10741.839003, 10749.261377, 10756.684348, 10764.107917, 10771.532082, 10778.956844, 10786.382202, 10793.808155, 
+   10801.234704, 10808.661848, 10816.089587, 10823.517920, 10830.946848, 10838.376369, 10845.806483, 10853.237190, 
+   10860.668489, 10868.100381, 10875.532865, 10882.965940, 10890.399607, 10897.833864, 10905.268712, 10912.704150, 
+   10920.140178, 10927.576795, 10935.014002, 10942.451797, 10949.890180, 10957.329152, 10964.768711, 10972.208858, 
+   10979.649592, 10987.090912, 10994.532819, 11001.975312, 11009.418390, 11016.862054, 11024.306302, 11031.751136, 
+   11039.196553, 11046.642555, 11054.089140, 11061.536308, 11068.984059, 11076.432393, 11083.881309, 11091.330807, 
+   11098.780887, 11106.231548, 11113.682789, 11121.134612, 11128.587014, 11136.039996, 11143.493558, 11150.947699, 
+   11158.402419, 11165.857718, 11173.313594, 11180.770049, 11188.227081, 11195.684690, 11203.142876, 11210.601639, 
+   11218.060978, 11225.520893, 11232.981383, 11240.442449, 11247.904089, 11255.366304, 11262.829093, 11270.292456, 
+   11277.756393, 11285.220903, 11292.685985, 11300.151641, 11307.617868, 11315.084668, 11322.552039, 11330.019981, 
+   11337.488494, 11344.957578, 11352.427232, 11359.897457, 11367.368250, 11374.839613, 11382.311546, 11389.784046, 
+   11397.257115, 11404.730752, 11412.204957, 11419.679729, 11427.155069, 11434.630975, 11442.107447, 11449.584486, 
+   11457.062090, 11464.540259, 11472.018994, 11479.498294, 11486.978158, 11494.458586, 11501.939579, 11509.421134, 
+   11516.903253, 11524.385935, 11531.869179, 11539.352986, 11546.837355, 11554.322285, 11561.807777, 11569.293829, 
+   11576.780443, 11584.267616, 11591.755350, 11599.243644, 11606.732496, 11614.221909, 11621.711879, 11629.202409, 
+   11636.693496, 11644.185142, 11651.677345, 11659.170105, 11666.663423, 11674.157296, 11681.651727, 11689.146713, 
+   11696.642255, 11704.138352, 11711.635005, 11719.132212, 11726.629974, 11734.128289, 11741.627159, 11749.126582, 
+   11756.626559, 11764.127088, 11771.628171, 11779.129805, 11786.631991, 11794.134730, 11801.638019, 11809.141860, 
+   11816.646252, 11824.151194, 11831.656686, 11839.162728, 11846.669320, 11854.176461, 11861.684151, 11869.192390, 
+   11876.701177, 11884.210512, 11891.720395, 11899.230826, 11906.741804, 11914.253328, 11921.765400, 11929.278017, 
+   11936.791181, 11944.304890, 11951.819145, 11959.333944, 11966.849289, 11974.365178, 11981.881611, 11989.398589, 
+   11996.916109, 12004.434174, 12011.952781, 12019.471931, 12026.991623, 12034.511858, 12042.032634, 12049.553952, 
+   12057.075811, 12064.598212, 12072.121152, 12079.644634, 12087.168655, 12094.693216, 12102.218317, 12109.743957, 
+   12117.270136, 12124.796854, 12132.324110, 12139.851904, 12147.380235, 12154.909105, 12162.438511, 12169.968454, 
+   12177.498934, 12185.029951, 12192.561503, 12200.093591, 12207.626215, 12215.159374, 12222.693067, 12230.227296, 
+   12237.762058, 12245.297355, 12252.833186, 12260.369549, 12267.906447, 12275.443877, 12282.981839, 12290.520334, 
+   12298.059361, 12305.598920, 12313.139010, 12320.679632, 12328.220784, 12335.762468, 12343.304681, 12350.847425, 
+   12358.390698, 12365.934501, 12373.478833, 12381.023694, 12388.569084, 12396.115002, 12403.661448, 12411.208422, 
+   12418.755924, 12426.303953, 12433.852509, 12441.401592, 12448.951201, 12456.501336, 12464.051997, 12471.603184, 
+   12479.154896, 12486.707134, 12494.259896, 12501.813182, 12509.366993, 12516.921328, 12524.476187, 12532.031569, 
+   12539.587474, 12547.143902, 12554.700852, 12562.258325, 12569.816320, 12577.374837, 12584.933875, 12592.493435, 
+   12600.053515, 12607.614116, 12615.175238, 12622.736880, 12630.299041, 12637.861722, 12645.424923, 12652.988643, 
+   12660.552881, 12668.117638, 12675.682913, 12683.248707, 12690.815018, 12698.381846, 12705.949192, 12713.517054, 
+   12721.085434, 12728.654329, 12736.223741, 12743.793669, 12751.364112, 12758.935071, 12766.506544, 12774.078533, 
+   12781.651036, 12789.224053, 12796.797584, 12804.371629, 12811.946188, 12819.521259, 12827.096844, 12834.672941, 
+   12842.249551, 12849.826673, 12857.404307, 12864.982452, 12872.561109, 12880.140277, 12887.719956, 12895.300146, 
+   12902.880845, 12910.462055, 12918.043775, 12925.626004, 12933.208742, 12940.791990, 12948.375746, 12955.960011, 
+   12963.544784, 12971.130065, 12978.715854, 12986.302150, 12993.888954, 13001.476264, 13009.064082, 13016.652405, 
+   13024.241235, 13031.830571, 13039.420413, 13047.010759, 13054.601612, 13062.192969, 13069.784830, 13077.377196, 
+   13084.970067, 13092.563441, 13100.157319, 13107.751700, 13115.346584, 13122.941972, 13130.537862, 13138.134254, 
+   13145.731148, 13153.328545, 13160.926443, 13168.524842, 13176.123742, 13183.723144, 13191.323046, 13198.923448, 
+   13206.524351, 13214.125753, 13221.727655, 13229.330056, 13236.932957, 13244.536356, 13252.140254, 13259.744650, 
+   13267.349545, 13274.954937, 13282.560827, 13290.167214, 13297.774099, 13305.381480, 13312.989359, 13320.597733, 
+   13328.206604, 13335.815970, 13343.425832, 13351.036190, 13358.647043, 13366.258390, 13373.870233, 13381.482570, 
+   13389.095401, 13396.708726, 13404.322544, 13411.936857, 13419.551662, 13427.166960, 13434.782751, 13442.399035, 
+   13450.015811, 13457.633079, 13465.250838, 13472.869089, 13480.487832, 13488.107065, 13495.726789, 13503.347004, 
+   13510.967709, 13518.588904, 13526.210589, 13533.832764, 13541.455428, 13549.078581, 13556.702223, 13564.326353, 
+   13571.950972, 13579.576080, 13587.201675, 13594.827757, 13602.454328, 13610.081385, 13617.708929, 13625.336960, 
+   13632.965478, 13640.594482, 13648.223972, 13655.853948, 13663.484409, 13671.115355, 13678.746787, 13686.378704, 
+   13694.011105, 13701.643990, 13709.277360, 13716.911213, 13724.545551, 13732.180371, 13739.815675, 13747.451462, 
+   13755.087732, 13762.724484, 13770.361718, 13777.999435, 13785.637633, 13793.276313, 13800.915474, 13808.555116, 
+   13816.195239, 13823.835843, 13831.476927, 13839.118492, 13846.760536, 13854.403060, 13862.046064, 13869.689547, 
+   13877.333509, 13884.977950, 13892.622869, 13900.268267, 13907.914143, 13915.560496, 13923.207328, 13930.854637, 
+   13938.502423, 13946.150686, 13953.799425, 13961.448642, 13969.098334, 13976.748503, 13984.399148, 13992.050268, 
+   13999.701863, 14007.353934, 14015.006480, 14022.659500, 14030.312995, 14037.966964, 14045.621407, 14053.276325, 
+   14060.931715, 14068.587579, 14076.243916, 14083.900726, 14091.558009, 14099.215765, 14106.873992, 14114.532692, 
+   14122.191863, 14129.851506, 14137.511620, 14145.172206, 14152.833262, 14160.494789, 14168.156787, 14175.819255, 
+   14183.482192, 14191.145600, 14198.809477, 14206.473824, 14214.138640, 14221.803924, 14229.469678, 14237.135900, 
+   14244.802590, 14252.469748, 14260.137374, 14267.805468, 14275.474029, 14283.143057, 14290.812553, 14298.482515, 
+   14306.152943, 14313.823838, 14321.495199, 14329.167026, 14336.839318, 14344.512076, 14352.185299, 14359.858987, 
+   14367.533140, 14375.207758, 14382.882840, 14390.558386, 14398.234396, 14405.910869, 14413.587806, 14421.265207, 
+   14428.943070, 14436.621397, 14444.300186, 14451.979437, 14459.659151, 14467.339326, 14475.019964, 14482.701063, 
+   14490.382623, 14498.064645, 14505.747127, 14513.430070, 14521.113474, 14528.797338, 14536.481662, 14544.166446, 
+   14551.851690, 14559.537393, 14567.223555, 14574.910176, 14582.597256, 14590.284795, 14597.972792, 14605.661248, 
+   14613.350161, 14621.039532, 14628.729361, 14636.419647, 14644.110390, 14651.801590, 14659.493247, 14667.185360, 
+   14674.877930, 14682.570956, 14690.264437, 14697.958375, 14705.652767, 14713.347616, 14721.042919, 14728.738677, 
+   14736.434889, 14744.131556, 14751.828678, 14759.526253, 14767.224282, 14774.922765, 14782.621701, 14790.321091, 
+   14798.020933, 14805.721228, 14813.421976, 14821.123176, 14828.824829, 14836.526933, 14844.229489, 14851.932497, 
+   14859.635956, 14867.339866, 14875.044227, 14882.749039, 14890.454302, 14898.160014, 14905.866177, 14913.572790, 
+   14921.279853, 14928.987365, 14936.695327, 14944.403737, 14952.112597, 14959.821905, 14967.531662, 14975.241867, 
+   14982.952521, 14990.663622, 14998.375171, 15006.087167, 15013.799611, 15021.512502, 15029.225840, 15036.939625, 
+   15044.653856, 15052.368533, 15060.083657, 15067.799226, 15075.515242, 15083.231702, 15090.948609, 15098.665960, 
+   15106.383756, 15114.101997, 15121.820683, 15129.539812, 15137.259386, 15144.979404, 15152.699866, 15160.420771, 
+   15168.142120, 15175.863912, 15183.586146, 15191.308824, 15199.031944, 15206.755506, 15214.479511, 15222.203958, 
+   15229.928846, 15237.654176, 15245.379948, 15253.106160, 15260.832814, 15268.559908, 15276.287444, 15284.015419, 
+   15291.743835, 15299.472691, 15307.201986, 15314.931722, 15322.661897, 15330.392511, 15338.123564, 15345.855056, 
+   15353.586986, 15361.319356, 15369.052163, 15376.785409, 15384.519092, 15392.253214, 15399.987773, 15407.722769, 
+   15415.458202, 15423.194072, 15430.930380, 15438.667123, 15446.404303, 15454.141920, 15461.879972, 15469.618460, 
+   15477.357384, 15485.096743, 15492.836537, 15500.576767, 15508.317431, 15516.058530, 15523.800064, 15531.542032, 
+   15539.284434, 15547.027270, 15554.770540, 15562.514243, 15570.258380, 15578.002949, 15585.747952, 15593.493388, 
+   15601.239256, 15608.985557, 15616.732290, 15624.479455, 15632.227051, 15639.975080, 15647.723540, 15655.472431, 
+   15663.221754, 15670.971507, 15678.721691, 15686.472306, 15694.223351, 15701.974826, 15709.726732, 15717.479067, 
+   15725.231832, 15732.985026, 15740.738650, 15748.492702, 15756.247184, 15764.002094, 15771.757433, 15779.513200, 
+   15787.269395, 15795.026019, 15802.783070, 15810.540549, 15818.298455, 15826.056788, 15833.815549, 15841.574736, 
+   15849.334350, 15857.094391, 15864.854858, 15872.615751, 15880.377070, 15888.138815, 15895.900986, 15903.663582, 
+   15911.426603, 15919.190050, 15926.953921, 15934.718217, 15942.482938, 15950.248083, 15958.013652, 15965.779645, 
+   15973.546062, 15981.312902, 15989.080166, 15996.847853, 16004.615964, 16012.384497, 16020.153453, 16027.922832, 
+   16035.692633, 16043.462856, 16051.233501, 16059.004568, 16066.776057, 16074.547967, 16082.320299, 16090.093052, 
+   16097.866225, 16105.639820, 16113.413835, 16121.188270, 16128.963126, 16136.738402, 16144.514098, 16152.290213, 
+   16160.066748, 16167.843703, 16175.621076, 16183.398869, 16191.177080, 16198.955710, 16206.734759, 16214.514226, 
+   16222.294111, 16230.074414, 16237.855135, 16245.636274, 16253.417830, 16261.199803, 16268.982193, 16276.765000, 
+   16284.548224, 16292.331865, 16300.115922, 16307.900395, 16315.685285, 16323.470590, 16331.256311, 16339.042447, 
+   16346.828999, 16354.615966, 16362.403348, 16370.191145, 16377.979356, 16385.767982, 16393.557023, 16401.346477, 
+   16409.136346, 16416.926628, 16424.717324, 16432.508434, 16440.299957, 16448.091893, 16455.884242, 16463.677003, 
+   16471.470178, 16479.263764, 16487.057764, 16494.852175, 16502.646998, 16510.442233, 16518.237879, 16526.033937, 
+   16533.830407, 16541.627287, 16549.424578, 16557.222280, 16565.020393, 16572.818916, 16580.617849, 16588.417193, 
+   16596.216946, 16604.017109, 16611.817682, 16619.618664, 16627.420055, 16635.221855, 16643.024065, 16650.826683, 
+   16658.629710, 16666.433145, 16674.236988, 16682.041239, 16689.845899, 16697.650966, 16705.456440, 16713.262322, 
+   16721.068612, 16728.875308, 16736.682411, 16744.489921, 16752.297838, 16760.106161, 16767.914890, 16775.724026, 
+   16783.533567, 16791.343514, 16799.153867, 16806.964625, 16814.775788, 16822.587357, 16830.399330, 16838.211708, 
+   16846.024491, 16853.837678, 16861.651270, 16869.465266, 16877.279665, 16885.094469, 16892.909676, 16900.725286, 
+   16908.541300, 16916.357717, 16924.174537, 16931.991760, 16939.809385, 16947.627413, 16955.445844, 16963.264676, 
+   16971.083910, 16978.903547, 16986.723585, 16994.544024, 17002.364865, 17010.186107, 17018.007750, 17025.829794, 
+   17033.652239, 17041.475084, 17049.298330, 17057.121976, 17064.946022, 17072.770468, 17080.595314, 17088.420559, 
+   17096.246204, 17104.072248, 17111.898691, 17119.725533, 17127.552774, 17135.380413, 17143.208451, 17151.036888, 
+   17158.865722, 17166.694955, 17174.524585, 17182.354613, 17190.185039, 17198.015862, 17205.847082, 17213.678699, 
+   17221.510714, 17229.343124, 17237.175932, 17245.009136, 17252.842736, 17260.676733, 17268.511125, 17276.345913, 
+   17284.181097, 17292.016676, 17299.852651, 17307.689020, 17315.525785, 17323.362945, 17331.200499, 17339.038448, 
+   17346.876791, 17354.715529, 17362.554661, 17370.394186, 17378.234105, 17386.074418, 17393.915125, 17401.756225, 
+   17409.597718, 17417.439604, 17425.281882, 17433.124554, 17440.967618, 17448.811074, 17456.654923, 17464.499164, 
+   17472.343796, 17480.188821, 17488.034237, 17495.880044, 17503.726243, 17511.572833, 17519.419814, 17527.267186, 
+   17535.114948, 17542.963101, 17550.811645, 17558.660579, 17566.509902, 17574.359616, 17582.209720, 17590.060213, 
+   17597.911096, 17605.762368, 17613.614029, 17621.466079, 17629.318518, 17637.171346, 17645.024562, 17652.878167, 
+   17660.732160, 17668.586541, 17676.441311, 17684.296468, 17692.152012, 17700.007944, 17707.864264, 17715.720971, 
+   17723.578065, 17731.435545, 17739.293413, 17747.151667, 17755.010308, 17762.869335, 17770.728748, 17778.588547, 
+   17786.448732, 17794.309303, 17802.170259, 17810.031601, 17817.893328, 17825.755440, 17833.617938, 17841.480820, 
+   17849.344086, 17857.207738, 17865.071773, 17872.936193, 17880.800997, 17888.666185, 17896.531757, 17904.397712, 
+   17912.264051, 17920.130774, 17927.997879, 17935.865368, 17943.733239, 17951.601493, 17959.470130, 17967.339150, 
+   17975.208551, 17983.078335, 17990.948501, 17998.819049, 18006.689979, 18014.561290, 18022.432983, 18030.305056, 
+   18038.177512, 18046.050348, 18053.923565, 18061.797163, 18069.671141, 18077.545500, 18085.420239, 18093.295358, 
+   18101.170858, 18109.046737, 18116.922996, 18124.799634, 18132.676652, 18140.554049, 18148.431825, 18156.309981, 
+   18164.188515, 18172.067428, 18179.946719, 18187.826389, 18195.706438, 18203.586864, 18211.467668, 18219.348850, 
+   18227.230410, 18235.112348, 18242.994663, 18250.877355, 18258.760424, 18266.643871, 18274.527694, 18282.411894, 
+   18290.296470, 18298.181423, 18306.066752, 18313.952458, 18321.838539, 18329.724997, 18337.611830, 18345.499038, 
+   18353.386622, 18361.274582, 18369.162916, 18377.051626, 18384.940710, 18392.830169, 18400.720003, 18408.610211, 
+   18416.500794, 18424.391750, 18432.283081, 18440.174786, 18448.066864, 18455.959316, 18463.852142, 18471.745341, 
+   18479.638913, 18487.532858, 18495.427176, 18503.321867, 18511.216930, 18519.112366, 18527.008175, 18534.904355, 
+   18542.800908, 18550.697833, 18558.595129, 18566.492797, 18574.390837, 18582.289248, 18590.188030, 18598.087184, 
+   18605.986708, 18613.886604, 18621.786870, 18629.687506, 18637.588513, 18645.489891, 18653.391638, 18661.293756, 
+   18669.196243, 18677.099100, 18685.002327, 18692.905923, 18700.809889, 18708.714224, 18716.618928, 18724.524001, 
+   18732.429442, 18740.335253, 18748.241431, 18756.147979, 18764.054894, 18771.962178, 18779.869829, 18787.777849, 
+   18795.686236, 18803.594991, 18811.504113, 18819.413602, 18827.323459, 18835.233683, 18843.144273, 18851.055231, 
+   18858.966555, 18866.878245, 18874.790302, 18882.702725, 18890.615515, 18898.528670, 18906.442191, 18914.356077, 
+   18922.270330, 18930.184947, 18938.099930, 18946.015279, 18953.930992, 18961.847070, 18969.763513, 18977.680320, 
+   18985.597492, 18993.515029, 19001.432929, 19009.351194, 19017.269823, 19025.188815, 19033.108171, 19041.027891, 
+   19048.947974, 19056.868421, 19064.789230, 19072.710403, 19080.631939, 19088.553837, 19096.476098, 19104.398722, 
+   19112.321708, 19120.245056, 19128.168766, 19136.092839, 19144.017273, 19151.942069, 19159.867226, 19167.792745, 
+   19175.718626, 19183.644867, 19191.571470, 19199.498433, 19207.425758, 19215.353443, 19223.281488, 19231.209894, 
+   19239.138661, 19247.067787, 19254.997274, 19262.927120, 19270.857326, 19278.787892, 19286.718817, 19294.650102, 
+   19302.581746, 19310.513749, 19318.446112, 19326.378833, 19334.311912, 19342.245351, 19350.179148, 19358.113303, 
+   19366.047816, 19373.982688, 19381.917917, 19389.853505, 19397.789450, 19405.725753, 19413.662413, 19421.599430, 
+   19429.536805, 19437.474537, 19445.412625, 19453.351071, 19461.289873, 19469.229032, 19477.168547, 19485.108419, 
+   19493.048647, 19500.989230, 19508.930170, 19516.871466, 19524.813117, 19532.755124, 19540.697486, 19548.640204, 
+   19556.583276, 19564.526704, 19572.470487, 19580.414624, 19588.359116, 19596.303963, 19604.249164, 19612.194720, 
+   19620.140629, 19628.086893, 19636.033511, 19643.980482, 19651.927807, 19659.875485, 19667.823517, 19675.771903, 
+   19683.720641, 19691.669733, 19699.619177, 19707.568974, 19715.519124, 19723.469627, 19731.420482, 19739.371689, 
+   19747.323248, 19755.275159, 19763.227423, 19771.180038, 19779.133005, 19787.086323, 19795.039993, 19802.994014, 
+   19810.948386, 19818.903109, 19826.858184, 19834.813609, 19842.769385, 19850.725511, 19858.681988, 19866.638815, 
+   19874.595992, 19882.553520, 19890.511397, 19898.469624, 19906.428201, 19914.387128, 19922.346403, 19930.306029, 
+   19938.266003, 19946.226327, 19954.187000, 19962.148021, 19970.109391, 19978.071110, 19986.033177, 19993.995593, 
+   20001.958357, 20009.921469, 20017.884929, 20025.848737, 20033.812893, 20041.777396, 20049.742247, 20057.707445, 
+   20065.672991, 20073.638884, 20081.605123, 20089.571710, 20097.538644, 20105.505924, 20113.473550, 20121.441524, 
+   20129.409843, 20137.378509, 20145.347521, 20153.316878, 20161.286582, 20169.256631, 20177.227026, 20185.197767, 
+   20193.168852, 20201.140283, 20209.112059, 20217.084181, 20225.056647, 20233.029457, 20241.002613, 20248.976113, 
+   20256.949957, 20264.924146, 20272.898679, 20280.873556, 20288.848776, 20296.824341, 20304.800249, 20312.776501, 
+   20320.753097, 20328.730036, 20336.707318, 20344.684943, 20352.662911, 20360.641222, 20368.619875, 20376.598872, 
+   20384.578211, 20392.557892, 20400.537916, 20408.518281, 20416.498989, 20424.480039, 20432.461431, 20440.443164, 
+   20448.425239, 20456.407655, 20464.390413, 20472.373512, 20480.356952, 20488.340733, 20496.324855, 20504.309317, 
+   20512.294121, 20520.279265, 20528.264749, 20536.250574, 20544.236739, 20552.223244, 20560.210089, 20568.197273, 
+   20576.184798, 20584.172662, 20592.160865, 20600.149408, 20608.138291, 20616.127512, 20624.117073, 20632.106972, 
+   20640.097210, 20648.087787, 20656.078702, 20664.069956, 20672.061549, 20680.053479, 20688.045748, 20696.038354, 
+   20704.031299, 20712.024581, 20720.018201, 20728.012159, 20736.006454, 20744.001086, 20751.996056, 20759.991362, 
+   20767.987006, 20775.982986, 20783.979304, 20791.975958, 20799.972948, 20807.970275, 20815.967938, 20823.965937, 
+   20831.964273, 20839.962944, 20847.961951, 20855.961294, 20863.960973, 20871.960987, 20879.961336, 20887.962021, 
+   20895.963041, 20903.964396, 20911.966086, 20919.968111, 20927.970470, 20935.973165, 20943.976193, 20951.979556, 
+   20959.983254, 20967.987285, 20975.991651, 20983.996350, 20992.001384, 21000.006751, 21008.012451, 21016.018485, 
+   21024.024853, 21032.031554, 21040.038588, 21048.045955, 21056.053655, 21064.061688, 21072.070053, 21080.078752, 
+   21088.087782, 21096.097145, 21104.106841, 21112.116868, 21120.127228, 21128.137919, 21136.148943, 21144.160298, 
+   21152.171985, 21160.184003, 21168.196352, 21176.209033, 21184.222045, 21192.235389, 21200.249063, 21208.263068, 
+   21216.277404, 21224.292070, 21232.307067, 21240.322394, 21248.338052, 21256.354040, 21264.370357, 21272.387005, 
+   21280.403983, 21288.421291, 21296.438928, 21304.456894, 21312.475191, 21320.493816, 21328.512771, 21336.532055, 
+   21344.551667, 21352.571609, 21360.591879, 21368.612479, 21376.633406, 21384.654663, 21392.676247, 21400.698160, 
+   21408.720401, 21416.742970, 21424.765867, 21432.789091, 21440.812644, 21448.836524, 21456.860731, 21464.885266, 
+   21472.910128, 21480.935317, 21488.960834, 21496.986677, 21505.012847, 21513.039344, 21521.066168, 21529.093318, 
+   21537.120795, 21545.148597, 21553.176726, 21561.205182, 21569.233963, 21577.263070, 21585.292503, 21593.322261, 
+   21601.352345, 21609.382755, 21617.413490, 21625.444550, 21633.475935, 21641.507646, 21649.539681, 21657.572041, 
+   21665.604726, 21673.637736, 21681.671070, 21689.704728, 21697.738711, 21705.773018, 21713.807649, 21721.842604, 
+   21729.877883, 21737.913485, 21745.949412, 21753.985662, 21762.022235, 21770.059132, 21778.096352, 21786.133895, 
+   21794.171761, 21802.209950, 21810.248462, 21818.287297, 21826.326455, 21834.365934, 21842.405737, 21850.445862, 
+   21858.486308, 21866.527077, 21874.568168, 21882.609581, 21890.651316, 21898.693372, 21906.735750, 21914.778450, 
+   21922.821471, 21930.864813, 21938.908476, 21946.952461, 21954.996766, 21963.041392, 21971.086339, 21979.131607, 
+   21987.177195, 21995.223104, 22003.269333, 22011.315883, 22019.362752, 22027.409942, 22035.457451, 22043.505281, 
+   22051.553430, 22059.601898, 22067.650687, 22075.699794, 22083.749222, 22091.798968, 22099.849033, 22107.899418, 
+   22115.950121, 22124.001143, 22132.052484, 22140.104144, 22148.156122, 22156.208418, 22164.261033, 22172.313966, 
+   22180.367217, 22188.420787, 22196.474674, 22204.528879, 22212.583401, 22220.638241, 22228.693399, 22236.748874, 
+   22244.804667, 22252.860776, 22260.917203, 22268.973947, 22277.031008, 22285.088385, 22293.146079, 22301.204090, 
+   22309.262417, 22317.321061, 22325.380021, 22333.439297, 22341.498890, 22349.558798, 22357.619022, 22365.679562, 
+   22373.740418, 22381.801589, 22389.863076, 22397.924879, 22405.986996, 22414.049429, 22422.112177, 22430.175240, 
+   22438.238618, 22446.302310, 22454.366318, 22462.430639, 22470.495276, 22478.560227, 22486.625492, 22494.691071, 
+   22502.756965, 22510.823173, 22518.889694, 22526.956529, 22535.023678, 22543.091141, 22551.158917, 22559.227007, 
+   22567.295410, 22575.364126, 22583.433155, 22591.502498, 22599.572153, 22607.642121, 22615.712402, 22623.782996, 
+   22631.853902, 22639.925120, 22647.996651, 22656.068494, 22664.140650, 22672.213117, 22680.285896, 22688.358988, 
+   22696.432391, 22704.506105, 22712.580131, 22720.654469, 22728.729118, 22736.804078, 22744.879350, 22752.954933, 
+   22761.030826, 22769.107031, 22777.183546, 22785.260372, 22793.337509, 22801.414956, 22809.492714, 22817.570781, 
+   22825.649160, 22833.727848, 22841.806846, 22849.886154, 22857.965772, 22866.045700, 22874.125937, 22882.206484, 
+   22890.287341, 22898.368507, 22906.449982, 22914.531766, 22922.613859, 22930.696261, 22938.778972, 22946.861992, 
+   22954.945321, 22963.028958, 22971.112904, 22979.197158, 22987.281720, 22995.366591, 23003.451770, 23011.537257, 
+   23019.623051, 23027.709154, 23035.795564, 23043.882282, 23051.969308, 23060.056640, 23068.144281, 23076.232228, 
+   23084.320483, 23092.409045, 23100.497914, 23108.587089, 23116.676572, 23124.766361, 23132.856457, 23140.946859, 
+   23149.037568, 23157.128583, 23165.219904, 23173.311531, 23181.403465, 23189.495704, 23197.588250, 23205.681101, 
+   23213.774257, 23221.867720, 23229.961487, 23238.055560, 23246.149939, 23254.244623, 23262.339611, 23270.434905, 
+   23278.530504, 23286.626407, 23294.722616, 23302.819129, 23310.915946, 23319.013068, 23327.110494, 23335.208225, 
+   23343.306260, 23351.404598, 23359.503241, 23367.602188, 23375.701439, 23383.800993, 23391.900851, 23400.001012, 
+   23408.101477, 23416.202245, 23424.303317, 23432.404692, 23440.506369, 23448.608350, 23456.710634, 23464.813220, 
+   23472.916109, 23481.019301, 23489.122795, 23497.226592, 23505.330691, 23513.435092, 23521.539796, 23529.644801, 
+   23537.750109, 23545.855718, 23553.961629, 23562.067842, 23570.174357, 23578.281173, 23586.388290, 23594.495709, 
+   23602.603429, 23610.711450, 23618.819773, 23626.928396, 23635.037320, 23643.146545, 23651.256071, 23659.365897, 
+   23667.476024, 23675.586451, 23683.697179, 23691.808206, 23699.919534, 23708.031163, 23716.143091, 23724.255319, 
+   23732.367846, 23740.480674, 23748.593801, 23756.707228, 23764.820954, 23772.934979, 23781.049304, 23789.163928, 
+   23797.278851, 23805.394073, 23813.509594, 23821.625413, 23829.741532, 23837.857949, 23845.974664, 23854.091678, 
+   23862.208991, 23870.326602, 23878.444511, 23886.562718, 23894.681223, 23902.800026, 23910.919127, 23919.038525, 
+   23927.158221, 23935.278215, 23943.398507, 23951.519095, 23959.639981, 23967.761165, 23975.882645, 23984.004422, 
+   23992.126497, 24000.248868, 24008.371536, 24016.494501, 24024.617762, 24032.741320, 24040.865174, 24048.989325, 
+   24057.113772, 24065.238515, 24073.363554, 24081.488889, 24089.614520, 24097.740447, 24105.866669, 24113.993187, 
+   24122.120001, 24130.247110, 24138.374515, 24146.502215, 24154.630210, 24162.758500, 24170.887085, 24179.015965, 
+   24187.145140, 24195.274610, 24203.404374, 24211.534433, 24219.664787, 24227.795435, 24235.926377, 24244.057614, 
+   24252.189144, 24260.320969, 24268.453088, 24276.585501, 24284.718207, 24292.851207, 24300.984501, 24309.118089, 
+   24317.251970, 24325.386144, 24333.520611, 24341.655372, 24349.790426, 24357.925773, 24366.061413, 24374.197346, 
+   24382.333571, 24390.470090, 24398.606900, 24406.744004, 24414.881400, 24423.019088, 24431.157068, 24439.295341, 
+   24447.433906, 24455.572762, 24463.711911, 24471.851352, 24479.991084, 24488.131108, 24496.271423, 24504.412030, 
+   24512.552929, 24520.694119, 24528.835600, 24536.977372, 24545.119435, 24553.261789, 24561.404435, 24569.547371, 
+   24577.690597, 24585.834115, 24593.977923, 24602.122021, 24610.266410, 24618.411089, 24626.556059, 24634.701318, 
+   24642.846868, 24650.992708, 24659.138837, 24667.285256, 24675.431965, 24683.578964, 24691.726252, 24699.873830, 
+   24708.021697, 24716.169854, 24724.318299, 24732.467034, 24740.616058, 24748.765371, 24756.914973, 24765.064863, 
+   24773.215042, 24781.365510, 24789.516267, 24797.667312, 24805.818645, 24813.970267, 24822.122177, 24830.274375, 
+   24838.426861, 24846.579635, 24854.732697, 24862.886046, 24871.039684, 24879.193609, 24887.347822, 24895.502322, 
+   24903.657110, 24911.812184, 24919.967547, 24928.123196, 24936.279132, 24944.435355, 24952.591866, 24960.748663, 
+   24968.905746, 24977.063117, 24985.220774, 24993.378717, 25001.536947, 25009.695464, 25017.854266, 25026.013355, 
+   25034.172730, 25042.332390, 25050.492337, 25058.652569, 25066.813088, 25074.973892, 25083.134981, 25091.296356, 
+   25099.458017, 25107.619962, 25115.782193, 25123.944710, 25132.107511, 25140.270597, 25148.433969, 25156.597625, 
+   25164.761566, 25172.925791, 25181.090302, 25189.255097, 25197.420176, 25205.585539, 25213.751187, 25221.917120, 
+   25230.083336, 25238.249836, 25246.416620, 25254.583689, 25262.751041, 25270.918676, 25279.086596, 25287.254799, 
+   25295.423285, 25303.592055, 25311.761108, 25319.930444, 25328.100064, 25336.269967, 25344.440152, 25352.610621, 
+   25360.781372, 25368.952406, 25377.123723, 25385.295323, 25393.467205, 25401.639369, 25409.811816, 25417.984545, 
+   25426.157556, 25434.330850, 25442.504425, 25450.678283, 25458.852422, 25467.026843, 25475.201546, 25483.376531, 
+   25491.551797, 25499.727344, 25507.903173, 25516.079284, 25524.255675, 25532.432348, 25540.609302, 25548.786537, 
+   25556.964053, 25565.141849, 25573.319927, 25581.498285, 25589.676924, 25597.855843, 25606.035043, 25614.214523, 
+   25622.394284, 25630.574324, 25638.754645, 25646.935246, 25655.116127, 25663.297288, 25671.478729, 25679.660449, 
+   25687.842449, 25696.024729, 25704.207288, 25712.390127, 25720.573245, 25728.756642, 25736.940319, 25745.124275, 
+   25753.308510, 25761.493023, 25769.677816, 25777.862887, 25786.048238, 25794.233867, 25802.419774, 25810.605960, 
+   25818.792424, 25826.979167, 25835.166188, 25843.353488, 25851.541065, 25859.728920, 25867.917054, 25876.105465, 
+   25884.294154, 25892.483121, 25900.672366, 25908.861888, 25917.051687, 25925.241764, 25933.432119, 25941.622750, 
+   25949.813659, 25958.004845, 25966.196308, 25974.388048, 25982.580065, 25990.772359, 25998.964930, 26007.157777, 
+   26015.350900, 26023.544301, 26031.737977, 26039.931930, 26048.126160, 26056.320665, 26064.515447, 26072.710504, 
+   26080.905838, 26089.101448, 26097.297333, 26105.493494, 26113.689931, 26121.886643, 26130.083631, 26138.280895, 
+   26146.478434, 26154.676248, 26162.874337, 26171.072701, 26179.271341, 26187.470255, 26195.669444, 26203.868909, 
+   26212.068648, 26220.268661, 26228.468950, 26236.669512, 26244.870350, 26253.071461, 26261.272847, 26269.474507, 
+   26277.676442, 26285.878650, 26294.081133, 26302.283889, 26310.486919, 26318.690223, 26326.893801, 26335.097652, 
+   26343.301777, 26351.506176, 26359.710848, 26367.915793, 26376.121011, 26384.326503, 26392.532267, 26400.738305, 
+   26408.944616, 26417.151200, 26425.358056, 26433.565185, 26441.772587, 26449.980261, 26458.188208, 26466.396428, 
+   26474.604919, 26482.813684, 26491.022720, 26499.232028, 26507.441609, 26515.651461, 26523.861586, 26532.071982, 
+   26540.282650, 26548.493590, 26556.704801, 26564.916284, 26573.128038, 26581.340064, 26589.552361, 26597.764930, 
+   26605.977769, 26614.190880, 26622.404262, 26630.617914, 26638.831838, 26647.046032, 26655.260498, 26663.475233, 
+   26671.690240, 26679.905517, 26688.121064, 26696.336882, 26704.552970, 26712.769328, 26720.985957, 26729.202855, 
+   26737.420024, 26745.637463, 26753.855171, 26762.073149, 26770.291397, 26778.509915, 26786.728702, 26794.947759, 
+   26803.167085, 26811.386680, 26819.606545, 26827.826679, 26836.047082, 26844.267754, 26852.488695, 26860.709905, 
+   26868.931384, 26877.153132, 26885.375148, 26893.597433, 26901.819987, 26910.042809, 26918.265900, 26926.489259, 
+   26934.712886, 26942.936781, 26951.160945, 26959.385376, 26967.610076, 26975.835043, 26984.060279, 26992.285782, 
+   27000.511553, 27008.737591, 27016.963897, 27025.190470, 27033.417311, 27041.644420, 27049.871795, 27058.099438, 
+   27066.327348, 27074.555525, 27082.783968, 27091.012679, 27099.241657, 27107.470901, 27115.700412, 27123.930190, 
+   27132.160234, 27140.390545, 27148.621123, 27156.851966, 27165.083076, 27173.314452, 27181.546094, 27189.778002, 
+   27198.010177, 27206.242617, 27214.475323, 27222.708295, 27230.941532, 27239.175035, 27247.408804, 27255.642838, 
+   27263.877138, 27272.111703, 27280.346533, 27288.581629, 27296.816989, 27305.052615, 27313.288506, 27321.524661, 
+   27329.761082, 27337.997767, 27346.234717, 27354.471932, 27362.709411, 27370.947155, 27379.185163, 27387.423436, 
+   27395.661973, 27403.900774, 27412.139839, 27420.379169, 27428.618762, 27436.858620, 27445.098741, 27453.339126, 
+   27461.579775, 27469.820687, 27478.061864, 27486.303303, 27494.545006, 27502.786973, 27511.029203, 27519.271696, 
+   27527.514452, 27535.757472, 27544.000754, 27552.244300, 27560.488108, 27568.732180, 27576.976514, 27585.221110, 
+   27593.465970, 27601.711092, 27609.956476, 27618.202123, 27626.448032, 27634.694204, 27642.940638, 27651.187334, 
+   27659.434292, 27667.681512, 27675.928994, 27684.176738, 27692.424743, 27700.673011, 27708.921540, 27717.170331, 
+   27725.419383, 27733.668697, 27741.918272, 27750.168108, 27758.418206, 27766.668565, 27774.919185, 27783.170066, 
+   27791.421208, 27799.672611, 27807.924275, 27816.176200, 27824.428385, 27832.680832, 27840.933538, 27849.186505, 
+   27857.439733, 27865.693221, 27873.946969, 27882.200978, 27890.455247, 27898.709776, 27906.964565, 27915.219614, 
+   27923.474922, 27931.730491, 27939.986319, 27948.242408, 27956.498755, 27964.755363, 27973.012230, 27981.269356, 
+   27989.526741, 27997.784386, 28006.042291, 28014.300454, 28022.558876, 28030.817558, 28039.076498, 28047.335698, 
+   28055.595156, 28063.854873, 28072.114849, 28080.375083, 28088.635576, 28096.896327, 28105.157337, 28113.418605, 
+   28121.680131, 28129.941916, 28138.203959, 28146.466260, 28154.728819, 28162.991636, 28171.254711, 28179.518043, 
+   28187.781634, 28196.045482, 28204.309588, 28212.573951, 28220.838572, 28229.103450, 28237.368586, 28245.633979, 
+   28253.899629, 28262.165536, 28270.431701, 28278.698122, 28286.964801, 28295.231736, 28303.498928, 28311.766377, 
+   28320.034083, 28328.302045, 28336.570264, 28344.838739, 28353.107471, 28361.376459, 28369.645704, 28377.915205, 
+   28386.184962, 28394.454975, 28402.725244, 28410.995769, 28419.266550, 28427.537587, 28435.808879, 28444.080428, 
+   28452.352232, 28460.624291, 28468.896606, 28477.169177, 28485.442003, 28493.715084, 28501.988421, 28510.262013, 
+   28518.535860, 28526.809962, 28535.084319, 28543.358931, 28551.633798, 28559.908919, 28568.184296, 28576.459927, 
+   28584.735812, 28593.011952, 28601.288347, 28609.564996, 28617.841900, 28626.119058, 28634.396470, 28642.674136, 
+   28650.952056, 28659.230230, 28667.508659, 28675.787341, 28684.066277, 28692.345466, 28700.624910, 28708.904607, 
+   28717.184558, 28725.464762, 28733.745220, 28742.025931, 28750.306895, 28758.588113, 28766.869584, 28775.151308, 
+   28783.433285, 28791.715515, 28799.997998, 28808.280734, 28816.563722, 28824.846964, 28833.130458, 28841.414205, 
+   28849.698204, 28857.982456, 28866.266960, 28874.551717, 28882.836726, 28891.121987, 28899.407500, 28907.693265, 
+   28915.979283, 28924.265552, 28932.552074, 28940.838847, 28949.125872, 28957.413149, 28965.700677, 28973.988457, 
+   28982.276489, 28990.564772, 28998.853306, 29007.142092, 29015.431129, 29023.720417, 29032.009957, 29040.299748, 
+   29048.589789, 29056.880082, 29065.170625, 29073.461420, 29081.752465, 29090.043761, 29098.335307, 29106.627104, 
+   29114.919152, 29123.211450, 29131.503998, 29139.796797, 29148.089846, 29156.383146, 29164.676695, 29172.970495, 
+   29181.264545, 29189.558844, 29197.853394, 29206.148193, 29214.443242, 29222.738541, 29231.034090, 29239.329888, 
+   29247.625935, 29255.922232, 29264.218779, 29272.515575, 29280.812620, 29289.109914, 29297.407458, 29305.705251, 
+   29314.003292, 29322.301583, 29330.600122, 29338.898911, 29347.197948, 29355.497234, 29363.796768, 29372.096552, 
+   29380.396583, 29388.696863, 29396.997392, 29405.298169, 29413.599194, 29421.900468, 29430.201989, 29438.503759, 
+   29446.805777, 29455.108043, 29463.410557, 29471.713318, 29480.016327, 29488.319585, 29496.623089, 29504.926842, 
+   29513.230842, 29521.535089, 29529.839584, 29538.144326, 29546.449316, 29554.754553, 29563.060037, 29571.365768, 
+   29579.671746, 29587.977971, 29596.284444, 29604.591163, 29612.898129, 29621.205341, 29629.512800, 29637.820506, 
+   29646.128459, 29654.436658, 29662.745104, 29671.053795, 29679.362734, 29687.671918, 29695.981349, 29704.291026, 
+   29712.600949, 29720.911118, 29729.221533, 29737.532194, 29745.843101, 29754.154253, 29762.465651, 29770.777295, 
+   29779.089185, 29787.401320, 29795.713701, 29804.026327, 29812.339198, 29820.652315, 29828.965677, 29837.279284, 
+   29845.593136, 29853.907233, 29862.221576, 29870.536163, 29878.850995, 29887.166072, 29895.481394, 29903.796960, 
+   29912.112772, 29920.428827, 29928.745128, 29937.061672, 29945.378461, 29953.695495, 29962.012773, 29970.330295, 
+   29978.648061, 29986.966071, 29995.284325, 30003.602824, 30011.921566, 30020.240552, 30028.559782, 30036.879256, 
+   30045.198973, 30053.518934, 30061.839139, 30070.159587, 30078.480278, 30086.801213, 30095.122392, 30103.443813, 
+   30111.765478, 30120.087386, 30128.409537, 30136.731931, 30145.054568, 30153.377448, 30161.700571, 30170.023937, 
+   30178.347545, 30186.671397, 30194.995490, 30203.319827, 30211.644406, 30219.969227, 30228.294290, 30236.619597, 
+   30244.945145, 30253.270935, 30261.596968, 30269.923243, 30278.249760, 30286.576518, 30294.903519, 30303.230762, 
+   30311.558246, 30319.885972, 30328.213940, 30336.542150, 30344.870601, 30353.199293, 30361.528227, 30369.857403, 
+   30378.186820, 30386.516478, 30394.846377, 30403.176517, 30411.506899, 30419.837522, 30428.168385, 30436.499490, 
+   30444.830835, 30453.162422, 30461.494249, 30469.826316, 30478.158625, 30486.491174, 30494.823963, 30503.156993, 
+   30511.490263, 30519.823774, 30528.157525, 30536.491516, 30544.825748, 30553.160219, 30561.494931, 30569.829882, 
+   30578.165074, 30586.500506, 30594.836177, 30603.172088, 30611.508239, 30619.844629, 30628.181259, 30636.518129, 
+   30644.855238, 30653.192587, 30661.530175, 30669.868002, 30678.206068, 30686.544374, 30694.882919, 30703.221703, 
+   30711.560726, 30719.899988, 30728.239489, 30736.579229, 30744.919207, 30753.259425, 30761.599881, 30769.940575, 
+   30778.281508, 30786.622680, 30794.964090, 30803.305739, 30811.647626, 30819.989751, 30828.332115, 30836.674716, 
+   30845.017556, 30853.360634, 30861.703950, 30870.047504, 30878.391296, 30886.735325, 30895.079592, 30903.424098, 
+   30911.768840, 30920.113821, 30928.459039, 30936.804494, 30945.150187, 30953.496117, 30961.842285, 30970.188690, 
+   30978.535332, 30986.882211, 30995.229327, 31003.576681, 31011.924271, 31020.272098, 31028.620163, 31036.968464, 
+   31045.317002, 31053.665776, 31062.014787, 31070.364035, 31078.713519, 31087.063240, 31095.413198, 31103.763391, 
+   31112.113821, 31120.464487, 31128.815390, 31137.166529, 31145.517903, 31153.869514, 31162.221361, 31170.573443, 
+   31178.925762, 31187.278316, 31195.631106, 31203.984132, 31212.337394, 31220.690891, 31229.044624, 31237.398592, 
+   31245.752795, 31254.107234, 31262.461908, 31270.816818, 31279.171963, 31287.527343, 31295.882958, 31304.238808, 
+   31312.594893, 31320.951213, 31329.307767, 31337.664557, 31346.021582, 31354.378841, 31362.736335, 31371.094063, 
+   31379.452026, 31387.810223, 31396.168655, 31404.527322, 31412.886222, 31421.245357, 31429.604726, 31437.964329, 
+   31446.324167, 31454.684238, 31463.044544, 31471.405083, 31479.765856, 31488.126863, 31496.488104, 31504.849579, 
+   31513.211287, 31521.573229, 31529.935405, 31538.297814, 31546.660456, 31555.023332, 31563.386441, 31571.749784, 
+   31580.113359, 31588.477168, 31596.841210, 31605.205485, 31613.569993, 31621.934734, 31630.299708, 31638.664915, 
+   31647.030355, 31655.396027, 31663.761932, 31672.128070, 31680.494440, 31688.861043, 31697.227878, 31705.594946, 
+   31713.962246, 31722.329779, 31730.697543, 31739.065540, 31747.433769, 31755.802230, 31764.170924, 31772.539849, 
+   31780.909006, 31789.278395, 31797.648016, 31806.017868, 31814.387953, 31822.758269, 31831.128816, 31839.499595, 
+   31847.870606, 31856.241848, 31864.613322, 31872.985027, 31881.356963, 31889.729130, 31898.101529, 31906.474159, 
+   31914.847019, 31923.220111, 31931.593434, 31939.966988, 31948.340772, 31956.714788, 31965.089034, 31973.463511, 
+   31981.838218, 31990.213157, 31998.588325, 32006.963725, 32015.339354, 32023.715214, 32032.091305, 32040.467625, 
+   32048.844176, 32057.220957, 32065.597968, 32073.975209, 32082.352681, 32090.730382, 32099.108313, 32107.486474, 
+   32115.864865, 32124.243485, 32132.622336, 32141.001415, 32149.380725, 32157.760264, 32166.140032, 32174.520030, 
+   32182.900258, 32191.280714, 32199.661400, 32208.042316, 32216.423460, 32224.804833, 32233.186436, 32241.568267, 
+   32249.950328, 32258.332617, 32266.715136, 32275.097883, 32283.480859, 32291.864063, 32300.247496, 32308.631158, 
+   32317.015049, 32325.399167, 32333.783515, 32342.168090, 32350.552894, 32358.937927, 32367.323187, 32375.708676, 
+   32384.094393, 32392.480338, 32400.866510, 32409.252911, 32417.639540, 32426.026397, 32434.413481, 32442.800794, 
+   32451.188334, 32459.576101, 32467.964097, 32476.352319, 32484.740770, 32493.129447, 32501.518353, 32509.907485, 
+   32518.296845, 32526.686432, 32535.076246, 32543.466288, 32551.856556, 32560.247052, 32568.637774, 32577.028724, 
+   32585.419900, 32593.811303, 32602.202933, 32610.594790, 32618.986873, 32627.379183, 32635.771720, 32644.164483, 
+   32652.557473, 32660.950689, 32669.344131, 32677.737800, 32686.131695, 32694.525816, 32702.920163, 32711.314737, 
+   32719.709536, 32728.104562, 32736.499813, 32744.895291, 32753.290994, 32761.686923, 32770.083078, 32778.479459, 
+   32786.876065, 32795.272897, 32803.669954, 32812.067237, 32820.464745, 32828.862479, 32837.260438, 32845.658623, 
+   32854.057032, 32862.455667, 32870.854527, 32879.253612, 32887.652922, 32896.052457, 32904.452218, 32912.852203, 
+   32921.252412, 32929.652847, 32938.053506, 32946.454390, 32954.855499, 32963.256832, 32971.658390, 32980.060173, 
+   32988.462179, 32996.864411, 33005.266866, 33013.669546, 33022.072450, 33030.475578, 33038.878931, 33047.282507, 
+   33055.686308, 33064.090332, 33072.494581, 33080.899053, 33089.303749, 33097.708669, 33106.113813, 33114.519180, 
+   33122.924771, 33131.330586, 33139.736624, 33148.142885, 33156.549370, 33164.956079, 33173.363011, 33181.770166, 
+   33190.177544, 33198.585146, 33206.992970, 33215.401018, 33223.809289, 33232.217783, 33240.626499, 33249.035439, 
+   33257.444601, 33265.853987, 33274.263595, 33282.673425, 33291.083479, 33299.493754, 33307.904253, 33316.314974, 
+   33324.725917, 33333.137083, 33341.548471, 33349.960082, 33358.371914, 33366.783969, 33375.196246, 33383.608745, 
+   33392.021466, 33400.434410, 33408.847575, 33417.260962, 33425.674571, 33434.088401, 33442.502454, 33450.916728, 
+   33459.331224, 33467.745941, 33476.160880, 33484.576041, 33492.991422, 33501.407026, 33509.822850, 33518.238897, 
+   33526.655164, 33535.071652, 33543.488362, 33551.905293, 33560.322445, 33568.739817, 33577.157411, 33585.575226, 
+   33593.993262, 33602.411518, 33610.829995, 33619.248693, 33627.667612, 33636.086751, 33644.506111, 33652.925691, 
+   33661.345492, 33669.765513, 33678.185755, 33686.606217, 33695.026899, 33703.447802, 33711.868925, 33720.290267, 
+   33728.711830, 33737.133613, 33745.555616, 33753.977839, 33762.400282, 33770.822945, 33779.245827, 33787.668930, 
+   33796.092252, 33804.515793, 33812.939555, 33821.363535, 33829.787736, 33838.212156, 33846.636795, 33855.061653, 
+   33863.486731, 33871.912028, 33880.337545, 33888.763280, 33897.189235, 33905.615409, 33914.041802, 33922.468414, 
+   33930.895244, 33939.322294, 33947.749562, 33956.177050, 33964.604756, 33973.032680, 33981.460824, 33989.889186, 
+   33998.317766, 34006.746565, 34015.175583, 34023.604819, 34032.034273, 34040.463946, 34048.893836, 34057.323946, 
+   34065.754273, 34074.184818, 34082.615582, 34091.046563, 34099.477763, 34107.909180, 34116.340815, 34124.772669, 
+   34133.204739, 34141.637028, 34150.069535, 34158.502259, 34166.935200, 34175.368359, 34183.801736, 34192.235330, 
+   34200.669142, 34209.103171, 34217.537417, 34225.971881, 34234.406561, 34242.841459, 34251.276574, 34259.711907, 
+   34268.147456, 34276.583222, 34285.019205, 34293.455405, 34301.891822, 34310.328456, 34318.765306, 34327.202373, 
+   34335.639657, 34344.077158, 34352.514874, 34360.952808, 34369.390958, 34377.829324, 34386.267907, 34394.706706, 
+   34403.145722, 34411.584953, 34420.024401, 34428.464065, 34436.903945, 34445.344041, 34453.784354, 34462.224882, 
+   34470.665626, 34479.106586, 34487.547761, 34495.989153, 34504.430760, 34512.872583, 34521.314621, 34529.756875, 
+   34538.199345, 34546.642030, 34555.084931, 34563.528047, 34571.971378, 34580.414925, 34588.858687, 34597.302664, 
+   34605.746856, 34614.191264, 34622.635886, 34631.080724, 34639.525776, 34647.971044, 34656.416526, 34664.862223, 
+   34673.308135, 34681.754262, 34690.200603, 34698.647159, 34707.093930, 34715.540915, 34723.988115, 34732.435530, 
+   34740.883158, 34749.331001, 34757.779059, 34766.227331, 34774.675817, 34783.124517, 34791.573431, 34800.022560, 
+   34808.471902, 34816.921459, 34825.371229, 34833.821214, 34842.271412, 34850.721824, 34859.172450, 34867.623290, 
+   34876.074343, 34884.525610, 34892.977091, 34901.428785, 34909.880693, 34918.332814, 34926.785149, 34935.237697, 
+   34943.690458, 34952.143433, 34960.596620, 34969.050021, 34977.503636, 34985.957463, 34994.411503, 35002.865757, 
+   35011.320223, 35019.774902, 35028.229795, 35036.684900, 35045.140217, 35053.595748, 35062.051491, 35070.507447, 
+   35078.963615, 35087.419997, 35095.876590, 35104.333396, 35112.790415, 35121.247645, 35129.705089, 35138.162744, 
+   35146.620612, 35155.078692, 35163.536984, 35171.995488, 35180.454204, 35188.913133, 35197.372273, 35205.831625, 
+   35214.291189, 35222.750965, 35231.210953, 35239.671152, 35248.131563, 35256.592186, 35265.053021, 35273.514067, 
+   35281.975324, 35290.436793, 35298.898474, 35307.360366, 35315.822469, 35324.284783, 35332.747309, 35341.210046, 
+   35349.672994, 35358.136154, 35366.599524, 35375.063106, 35383.526898, 35391.990901, 35400.455116, 35408.919541, 
+   35417.384177, 35425.849023, 35434.314081, 35442.779349, 35451.244828, 35459.710517, 35468.176417, 35476.642527, 
+   35485.108848, 35493.575379, 35502.042121, 35510.509073, 35518.976235, 35527.443608, 35535.911191, 35544.378983, 
+   35552.846986, 35561.315199, 35569.783622, 35578.252255, 35586.721098, 35595.190151, 35603.659414, 35612.128886, 
+   35620.598568, 35629.068460, 35637.538562, 35646.008873, 35654.479394, 35662.950124, 35671.421064, 35679.892213, 
+   35688.363572, 35696.835140, 35705.306917, 35713.778904, 35722.251100, 35730.723505, 35739.196119, 35747.668942, 
+   35756.141974, 35764.615216, 35773.088666, 35781.562325, 35790.036193, 35798.510270, 35806.984556, 35815.459050, 
+   35823.933753, 35832.408665, 35840.883786, 35849.359115, 35857.834652, 35866.310398, 35874.786353, 35883.262515, 
+   35891.738887, 35900.215466, 35908.692254, 35917.169250, 35925.646454, 35934.123866, 35942.601487, 35951.079315, 
+   35959.557352, 35968.035596, 35976.514049, 35984.992709, 35993.471577, 36001.950653, 36010.429936, 36018.909428, 
+   36027.389127, 36035.869033, 36044.349147, 36052.829469, 36061.309998, 36069.790735, 36078.271679, 36086.752831, 
+   36095.234189, 36103.715755, 36112.197529, 36120.679509, 36129.161697, 36137.644091, 36146.126693, 36154.609502, 
+   36163.092517, 36171.575740, 36180.059170, 36188.542806, 36197.026649, 36205.510699, 36213.994956, 36222.479419, 
+   36230.964089, 36239.448966, 36247.934049, 36256.419339, 36264.904835, 36273.390537, 36281.876446, 36290.362561, 
+   36298.848883, 36307.335411, 36315.822145, 36324.309085, 36332.796231, 36341.283584, 36349.771142, 36358.258906, 
+   36366.746877, 36375.235053, 36383.723435, 36392.212023, 36400.700817, 36409.189816, 36417.679021, 36426.168432, 
+   36434.658048, 36443.147870, 36451.637898, 36460.128131, 36468.618569, 36477.109213, 36485.600063, 36494.091117, 
+   36502.582377, 36511.073842, 36519.565512, 36528.057388, 36536.549468, 36545.041754, 36553.534244, 36562.026940, 
+   36570.519840, 36579.012946, 36587.506256, 36595.999771, 36604.493491, 36612.987415, 36621.481545, 36629.975878, 
+   36638.470417, 36646.965160, 36655.460108, 36663.955260, 36672.450616, 36680.946177, 36689.441942, 36697.937912, 
+   36706.434086, 36714.930464, 36723.427046, 36731.923832, 36740.420823, 36748.918017, 36757.415416, 36765.913019, 
+   36774.410825, 36782.908835, 36791.407050, 36799.905468, 36808.404089, 36816.902915, 36825.401944, 36833.901177, 
+   36842.400614, 36850.900254, 36859.400097, 36867.900144, 36876.400395, 36884.900848, 36893.401506, 36901.902366, 
+   36910.403430, 36918.904697, 36927.406167, 36935.907841, 36944.409717, 36952.911797, 36961.414079, 36969.916565, 
+   36978.419253, 36986.922145, 36995.425239, 37003.928536, 37012.432036, 37020.935739, 37029.439644, 37037.943752, 
+   37046.448062, 37054.952576, 37063.457291, 37071.962209, 37080.467330, 37088.972653, 37097.478178, 37105.983906, 
+   37114.489836, 37122.995968, 37131.502303, 37140.008839, 37148.515578, 37157.022519, 37165.529662, 37174.037007, 
+   37182.544554, 37191.052302, 37199.560253, 37208.068405, 37216.576760, 37225.085316, 37233.594073, 37242.103033, 
+   37250.612194, 37259.121556, 37267.631120, 37276.140886, 37284.650853, 37293.161022, 37301.671392, 37310.181963, 
+   37318.692736, 37327.203710, 37335.714885, 37344.226261, 37352.737838, 37361.249617, 37369.761597, 37378.273777, 
+   37386.786159, 37395.298742, 37403.811525, 37412.324509, 37420.837695, 37429.351080, 37437.864667, 37446.378455, 
+   37454.892443, 37463.406631, 37471.921021, 37480.435610, 37488.950401, 37497.465391, 37505.980583, 37514.495974, 
+   37523.011566, 37531.527358, 37540.043351, 37548.559544, 37557.075936, 37565.592529, 37574.109323, 37582.626316, 
+   37591.143509, 37599.660902, 37608.178495, 37616.696288, 37625.214281, 37633.732474, 37642.250866, 37650.769458, 
+   37659.288250, 37667.807242, 37676.326433, 37684.845824, 37693.365414, 37701.885204, 37710.405193, 37718.925382, 
+   37727.445770, 37735.966357, 37744.487144, 37753.008130, 37761.529315, 37770.050700, 37778.572283, 37787.094066, 
+   37795.616048, 37804.138228, 37812.660608, 37821.183187, 37829.705964, 37838.228941, 37846.752116, 37855.275490, 
+   37863.799063, 37872.322834, 37880.846805, 37889.370973, 37897.895341, 37906.419907, 37914.944671, 37923.469634, 
+   37931.994796, 37940.520155, 37949.045713, 37957.571470, 37966.097424, 37974.623577, 37983.149929, 37991.676478, 
+   38000.203225, 38008.730171, 38017.257314, 38025.784656, 38034.312195, 38042.839933, 38051.367868, 38059.896001, 
+   38068.424332, 38076.952861, 38085.481587, 38094.010511, 38102.539633, 38111.068952, 38119.598469, 38128.128184, 
+   38136.658096, 38145.188205, 38153.718512, 38162.249016, 38170.779718, 38179.310617, 38187.841713, 38196.373006, 
+   38204.904497, 38213.436184, 38221.968069, 38230.500151, 38239.032430, 38247.564905, 38256.097578, 38264.630448, 
+   38273.163514, 38281.696778, 38290.230238, 38298.763895, 38307.297748, 38315.831799, 38324.366046, 38332.900489, 
+   38341.435129, 38349.969966, 38358.504999, 38367.040229, 38375.575655, 38384.111277, 38392.647096, 38401.183110, 
+   38409.719322, 38418.255729, 38426.792333, 38435.329132, 38443.866128, 38452.403320, 38460.940708, 38469.478292, 
+   38478.016072, 38486.554047, 38495.092219, 38503.630586, 38512.169150, 38520.707909, 38529.246863, 38537.786014, 
+   38546.325360, 38554.864901, 38563.404638, 38571.944571, 38580.484699, 38589.025023, 38597.565542, 38606.106256, 
+   38614.647166, 38623.188271, 38631.729571, 38640.271067, 38648.812757, 38657.354643, 38665.896724, 38674.439000, 
+   38682.981471, 38691.524137, 38700.066998, 38708.610054, 38717.153305, 38725.696750, 38734.240391, 38742.784226, 
+   38751.328256, 38759.872480, 38768.416899, 38776.961513, 38785.506321, 38794.051324, 38802.596522, 38811.141913, 
+   38819.687500, 38828.233280, 38836.779255, 38845.325425, 38853.871788, 38862.418346, 38870.965098, 38879.512044, 
+   38888.059184, 38896.606519, 38905.154047, 38913.701770, 38922.249686, 38930.797796, 38939.346100, 38947.894598, 
+   38956.443290, 38964.992176, 38973.541255, 38982.090528, 38990.639995, 38999.189656, 39007.739510, 39016.289557, 
+   39024.839798, 39033.390233, 39041.940861, 39050.491682, 39059.042697, 39067.593905, 39076.145306, 39084.696901, 
+   39093.248689, 39101.800670, 39110.352844, 39118.905211, 39127.457771, 39136.010525, 39144.563471, 39153.116610, 
+   39161.669943, 39170.223468, 39178.777186, 39187.331097, 39195.885200, 39204.439496, 39212.993985, 39221.548667, 
+   39230.103541, 39238.658608, 39247.213867, 39255.769319, 39264.324964, 39272.880801, 39281.436830, 39289.993051, 
+   39298.549465, 39307.106071, 39315.662870, 39324.219861, 39332.777043, 39341.334418, 39349.891985, 39358.449745, 
+   39367.007696, 39375.565839, 39384.124174, 39392.682701, 39401.241420, 39409.800331, 39418.359434, 39426.918728, 
+   39435.478214, 39444.037892, 39452.597761, 39461.157822, 39469.718075, 39478.278519, 39486.839155, 39495.399982, 
+   39503.961001, 39512.522211, 39521.083612, 39529.645205, 39538.206989, 39546.768965, 39555.331131, 39563.893489, 
+   39572.456038, 39581.018778, 39589.581709, 39598.144831, 39606.708144, 39615.271648, 39623.835343, 39632.399229, 
+   39640.963306, 39649.527574, 39658.092032, 39666.656681, 39675.221521, 39683.786551, 39692.351773, 39700.917184, 
+   39709.482787, 39718.048580, 39726.614563, 39735.180737, 39743.747101, 39752.313656, 39760.880401, 39769.447336, 
+   39778.014461, 39786.581777, 39795.149283, 39803.716979, 39812.284866, 39820.852942, 39829.421209, 39837.989665, 
+   39846.558311, 39855.127148, 39863.696174, 39872.265390, 39880.834797, 39889.404392, 39897.974178, 39906.544153, 
+   39915.114319, 39923.684673, 39932.255218, 39940.825952, 39949.396875, 39957.967988, 39966.539291, 39975.110783, 
+   39983.682464, 39992.254335, 40000.826395, 40009.398644, 40017.971083, 40026.543711, 40035.116528, 40043.689534, 
+   40052.262730, 40060.836114, 40069.409688, 40077.983450, 40086.557402, 40095.131542, 40103.705871, 40112.280390, 
+   40120.855097, 40129.429993, 40138.005077, 40146.580351, 40155.155813, 40163.731464, 40172.307303, 40180.883331, 
+   40189.459548, 40198.035953, 40206.612546, 40215.189328, 40223.766298, 40232.343457, 40240.920804, 40249.498340, 
+   40258.076063, 40266.653975, 40275.232076, 40283.810364, 40292.388840, 40300.967505, 40309.546357, 40318.125398, 
+   40326.704627, 40335.284043, 40343.863648, 40352.443440, 40361.023420, 40369.603588, 40378.183944, 40386.764487, 
+   40395.345218, 40403.926137, 40412.507244, 40421.088538, 40429.670020, 40438.251689, 40446.833546, 40455.415590, 
+   40463.997821, 40472.580240, 40481.162847, 40489.745640, 40498.328621, 40506.911789, 40515.495145, 40524.078687, 
+   40532.662417, 40541.246334, 40549.830438, 40558.414729, 40566.999207, 40575.583872, 40584.168723, 40592.753762, 
+   40601.338988, 40609.924400, 40618.509999, 40627.095785, 40635.681758, 40644.267918, 40652.854264, 40661.440796, 
+   40670.027515, 40678.614421, 40687.201514, 40695.788792, 40704.376258, 40712.963909, 40721.551747, 40730.139772, 
+   40738.727982, 40747.316379, 40755.904963, 40764.493732, 40773.082687, 40781.671829, 40790.261157, 40798.850671, 
+   40807.440371, 40816.030257, 40824.620328, 40833.210586, 40841.801030, 40850.391659, 40858.982475, 40867.573476, 
+   40876.164663, 40884.756035, 40893.347594, 40901.939337, 40910.531267, 40919.123382, 40927.715683, 40936.308169, 
+   40944.900841, 40953.493698, 40962.086740, 40970.679968, 40979.273381, 40987.866980, 40996.460764, 41005.054733, 
+   41013.648887, 41022.243226, 41030.837751, 41039.432460, 41048.027355, 41056.622435, 41065.217700, 41073.813149, 
+   41082.408784, 41091.004603, 41099.600608, 41108.196797, 41116.793171, 41125.389730, 41133.986473, 41142.583401, 
+   41151.180514, 41159.777812, 41168.375294, 41176.972960, 41185.570811, 41194.168847, 41202.767067, 41211.365471, 
+   41219.964060, 41228.562833, 41237.161791, 41245.760933, 41254.360259, 41262.959769, 41271.559463, 41280.159342, 
+   41288.759405, 41297.359651, 41305.960082, 41314.560697, 41323.161496, 41331.762478, 41340.363645, 41348.964995, 
+   41357.566530, 41366.168248, 41374.770150, 41383.372236, 41391.974505, 41400.576958, 41409.179595, 41417.782415, 
+   41426.385419, 41434.988606, 41443.591977, 41452.195531, 41460.799269, 41469.403190, 41478.007295, 41486.611583, 
+   41495.216054, 41503.820708, 41512.425546, 41521.030567, 41529.635771, 41538.241158, 41546.846729, 41555.452482, 
+   41564.058418, 41572.664538, 41581.270840, 41589.877325, 41598.483994, 41607.090845, 41615.697879, 41624.305095, 
+   41632.912495, 41641.520077, 41650.127842, 41658.735789, 41667.343920, 41675.952232, 41684.560728, 41693.169406, 
+   41701.778266, 41710.387309, 41718.996534, 41727.605942, 41736.215532, 41744.825304, 41753.435259, 41762.045396, 
+   41770.655715, 41779.266216, 41787.876900, 41796.487766, 41805.098813, 41813.710043, 41822.321455, 41830.933049, 
+   41839.544825, 41848.156783, 41856.768922, 41865.381244, 41873.993747, 41882.606432, 41891.219299, 41899.832348, 
+   41908.445578, 41917.058990, 41925.672584, 41934.286359, 41942.900316, 41951.514455, 41960.128774, 41968.743276, 
+   41977.357959, 41985.972823, 41994.587868, 42003.203095, 42011.818504, 42020.434093, 42029.049864, 42037.665816, 
+   42046.281949, 42054.898263, 42063.514759, 42072.131435, 42080.748293, 42089.365331, 42097.982551, 42106.599951, 
+   42115.217532, 42123.835295, 42132.453238, 42141.071362, 42149.689666, 42158.308152, 42166.926818, 42175.545665, 
+   42184.164692, 42192.783900, 42201.403289, 42210.022858, 42218.642608, 42227.262539, 42235.882649, 42244.502940, 
+   42253.123412, 42261.744064, 42270.364896, 42278.985909, 42287.607101, 42296.228474, 42304.850028, 42313.471761, 
+   42322.093674, 42330.715768, 42339.338042, 42347.960495, 42356.583129, 42365.205943, 42373.828936, 42382.452110, 
+   42391.075463, 42399.698997, 42408.322710, 42416.946602, 42425.570675, 42434.194927, 42442.819359, 42451.443971, 
+   42460.068762, 42468.693733, 42477.318883, 42485.944213, 42494.569722, 42503.195411, 42511.821279, 42520.447327, 
+   42529.073554, 42537.699960, 42546.326546, 42554.953310, 42563.580254, 42572.207378, 42580.834680, 42589.462162, 
+   42598.089822, 42606.717662, 42615.345681, 42623.973879, 42632.602255, 42641.230811, 42649.859545, 42658.488459, 
+   42667.117551, 42675.746822, 42684.376272, 42693.005901, 42701.635708, 42710.265694, 42718.895859, 42727.526202, 
+   42736.156724, 42744.787424, 42753.418303, 42762.049361, 42770.680597, 42779.312011, 42787.943604, 42796.575375, 
+   42805.207324, 42813.839452, 42822.471758, 42831.104242, 42839.736905, 42848.369745, 42857.002764, 42865.635961, 
+   42874.269336, 42882.902889, 42891.536620, 42900.170529, 42908.804616, 42917.438881, 42926.073323, 42934.707944, 
+   42943.342743, 42951.977719, 42960.612873, 42969.248204, 42977.883714, 42986.519401, 42995.155266, 43003.791308, 
+   43012.427528, 43021.063925, 43029.700500, 43038.337253, 43046.974183, 43055.611290, 43064.248575, 43072.886037, 
+   43081.523676, 43090.161493, 43098.799486, 43107.437658, 43116.076006, 43124.714531, 43133.353234, 43141.992114, 
+   43150.631170, 43159.270404, 43167.909815, 43176.549403, 43185.189168, 43193.829109, 43202.469228, 43211.109523, 
+   43219.749995, 43228.390644, 43237.031470, 43245.672473, 43254.313652, 43262.955008, 43271.596540, 43280.238249, 
+   43288.880135, 43297.522197, 43306.164436, 43314.806851, 43323.449442, 43332.092210, 43340.735155, 43349.378276, 
+   43358.021573, 43366.665046, 43375.308696, 43383.952521, 43392.596524, 43401.240702, 43409.885056, 43418.529586, 
+   43427.174293, 43435.819176, 43444.464234, 43453.109469, 43461.754879, 43470.400466, 43479.046228, 43487.692166, 
+   43496.338280, 43504.984570, 43513.631035, 43522.277677, 43530.924493, 43539.571486, 43548.218654, 43556.865998, 
+   43565.513518, 43574.161213, 43582.809083, 43591.457129, 43600.105351, 43608.753748, 43617.402320, 43626.051067, 
+   43634.699990, 43643.349089, 43651.998362, 43660.647811, 43669.297435, 43677.947234, 43686.597208, 43695.247358, 
+   43703.897682, 43712.548182, 43721.198856, 43729.849706, 43738.500731, 43747.151930, 43755.803304, 43764.454854, 
+   43773.106578, 43781.758477, 43790.410550, 43799.062799, 43807.715222, 43816.367820, 43825.020592, 43833.673539, 
+   43842.326661, 43850.979957, 43859.633428, 43868.287073, 43876.940893, 43885.594887, 43894.249056, 43902.903399, 
+   43911.557917, 43920.212608, 43928.867474, 43937.522514, 43946.177729, 43954.833118, 43963.488681, 43972.144418, 
+   43980.800329, 43989.456414, 43998.112673, 44006.769106, 44015.425714, 44024.082495, 44032.739450, 44041.396579, 
+   44050.053882, 44058.711359, 44067.369009, 44076.026833, 44084.684831, 44093.343003, 44102.001349, 44110.659868, 
+   44119.318561, 44127.977427, 44136.636467, 44145.295680, 44153.955067, 44162.614628, 44171.274362, 44179.934269, 
+   44188.594350, 44197.254604, 44205.915031, 44214.575632, 44223.236406, 44231.897353, 44240.558473, 44249.219767, 
+   44257.881233, 44266.542873, 44275.204686, 44283.866672, 44292.528831, 44301.191163, 44309.853668, 44318.516346, 
+   44327.179196, 44335.842220, 44344.505416, 44353.168786, 44361.832328, 44370.496043, 44379.159930, 44387.823991, 
+   44396.488223, 44405.152629, 44413.817207, 44422.481958, 44431.146881, 44439.811977, 44448.477245, 44457.142686, 
+   44465.808299, 44474.474085, 44483.140043, 44491.806173, 44500.472476, 44509.138951, 44517.805598, 44526.472417, 
+   44535.139409, 44543.806573, 44552.473908, 44561.141416, 44569.809096, 44578.476948, 44587.144973, 44595.813169, 
+   44604.481537, 44613.150077, 44621.818788, 44630.487672, 44639.156728, 44647.825955, 44656.495354, 44665.164925, 
+   44673.834668, 44682.504582, 44691.174668, 44699.844925, 44708.515355, 44717.185955, 44725.856728, 44734.527671, 
+   44743.198787, 44751.870073, 44760.541531, 44769.213161, 44777.884962, 44786.556934, 44795.229078, 44803.901393, 
+   44812.573879, 44821.246536, 44829.919364, 44838.592364, 44847.265535, 44855.938877, 44864.612390, 44873.286074, 
+   44881.959929, 44890.633955, 44899.308152, 44907.982519, 44916.657058, 44925.331768, 44934.006648, 44942.681700, 
+   44951.356922, 44960.032314, 44968.707878, 44977.383612, 44986.059517, 44994.735593, 45003.411839, 45012.088255, 
+   45020.764843, 45029.441600, 45038.118529, 45046.795627, 45055.472896, 45064.150336, 45072.827946, 45081.505726, 
+   45090.183677, 45098.861798, 45107.540089, 45116.218550, 45124.897182, 45133.575983, 45142.254955, 45150.934097, 
+   45159.613409, 45168.292891, 45176.972543, 45185.652366, 45194.332358, 45203.012520, 45211.692852, 45220.373353, 
+   45229.054025, 45237.734866, 45246.415878, 45255.097059, 45263.778410, 45272.459930, 45281.141620, 45289.823480, 
+   45298.505509, 45307.187709, 45315.870077, 45324.552615, 45333.235323, 45341.918200, 45350.601247, 45359.284462, 
+   45367.967848, 45376.651403, 45385.335127, 45394.019020, 45402.703083, 45411.387315, 45420.071716, 45428.756286, 
+   45437.441025, 45446.125934, 45454.811012, 45463.496258, 45472.181674, 45480.867259, 45489.553013, 45498.238936, 
+   45506.925028, 45515.611288, 45524.297718, 45532.984316, 45541.671083, 45550.358019, 45559.045124, 45567.732397, 
+   45576.419840, 45585.107450, 45593.795230, 45602.483178, 45611.171295, 45619.859580, 45628.548034, 45637.236656, 
+   45645.925447, 45654.614406, 45663.303534, 45671.992830, 45680.682294, 45689.371927, 45698.061728, 45706.751697, 
+   45715.441835, 45724.132141, 45732.822615, 45741.513257, 45750.204067, 45758.895046, 45767.586192, 45776.277507, 
+   45784.968989, 45793.660640, 45802.352458, 45811.044445, 45819.736599, 45828.428921, 45837.121412, 45845.814070, 
+   45854.506895, 45863.199889, 45871.893050, 45880.586379, 45889.279876, 45897.973540, 45906.667372, 45915.361372, 
+   45924.055539, 45932.749874, 45941.444376, 45950.139045, 45958.833883, 45967.528887, 45976.224059, 45984.919399, 
+   45993.614905, 46002.310579, 46011.006421, 46019.702429, 46028.398605, 46037.094948, 46045.791458, 46054.488136, 
+   46063.184980, 46071.881992, 46080.579171, 46089.276516, 46097.974029, 46106.671709, 46115.369556, 46124.067569, 
+   46132.765750, 46141.464097, 46150.162611, 46158.861292, 46167.560140, 46176.259155, 46184.958336, 46193.657684, 
+   46202.357199, 46211.056880, 46219.756728, 46228.456743, 46237.156924, 46245.857272, 46254.557786, 46263.258467, 
+   46271.959314, 46280.660328, 46289.361508, 46298.062854, 46306.764367, 46315.466046, 46324.167891, 46332.869903, 
+   46341.572081, 46350.274425, 46358.976935, 46367.679612, 46376.382454, 46385.085463, 46393.788638, 46402.491978, 
+   46411.195485, 46419.899158, 46428.602997, 46437.307001, 46446.011172, 46454.715508, 46463.420011, 46472.124679, 
+   46480.829513, 46489.534512, 46498.239678, 46506.945009, 46515.650506, 46524.356168, 46533.061996, 46541.767990, 
+   46550.474149, 46559.180474, 46567.886964, 46576.593620, 46585.300442, 46594.007428, 46602.714581, 46611.421898, 
+   46620.129381, 46628.837029, 46637.544843, 46646.252822, 46654.960966, 46663.669275, 46672.377749, 46681.086389, 
+   46689.795194, 46698.504164, 46707.213299, 46715.922599, 46724.632064, 46733.341694, 46742.051489, 46750.761449, 
+   46759.471574, 46768.181864, 46776.892319, 46785.602938, 46794.313722, 46803.024672, 46811.735785, 46820.447064, 
+   46829.158507, 46837.870115, 46846.581888, 46855.293825, 46864.005927, 46872.718194, 46881.430625, 46890.143220, 
+   46898.855980, 46907.568904, 46916.281993, 46924.995247, 46933.708664, 46942.422246, 46951.135993, 46959.849903, 
+   46968.563978, 46977.278217, 46985.992621, 46994.707188, 47003.421920, 47012.136816, 47020.851876, 47029.567100, 
+   47038.282488, 47046.998040, 47055.713756, 47064.429636, 47073.145680, 47081.861888, 47090.578260, 47099.294796, 
+   47108.011495, 47116.728359, 47125.445386, 47134.162577, 47142.879932, 47151.597450, 47160.315132, 47169.032978, 
+   47177.750987, 47186.469160, 47195.187496, 47203.905996, 47212.624660, 47221.343487, 47230.062478, 47238.781632, 
+   47247.500949, 47256.220430, 47264.940074, 47273.659881, 47282.379852, 47291.099986, 47299.820283, 47308.540744, 
+   47317.261368, 47325.982154, 47334.703104, 47343.424218, 47352.145494, 47360.866933, 47369.588536, 47378.310301, 
+   47387.032229, 47395.754321, 47404.476575, 47413.198992, 47421.921572, 47430.644315, 47439.367220, 47448.090289, 
+   47456.813520, 47465.536914, 47474.260471, 47482.984190, 47491.708073, 47500.432117, 47509.156325, 47517.880695, 
+   47526.605227, 47535.329922, 47544.054780, 47552.779800, 47561.504982, 47570.230327, 47578.955835, 47587.681504, 
+   47596.407336, 47605.133331, 47613.859487, 47622.585806, 47631.312288, 47640.038931, 47648.765737, 47657.492704, 
+   47666.219834, 47674.947126, 47683.674580, 47692.402197, 47701.129975, 47709.857915, 47718.586017, 47727.314281, 
+   47736.042707, 47744.771295, 47753.500045, 47762.228957, 47770.958031, 47779.687266, 47788.416663, 47797.146222, 
+   47805.875943, 47814.605825, 47823.335869, 47832.066074, 47840.796442, 47849.526970, 47858.257661, 47866.988513, 
+   47875.719526, 47884.450701, 47893.182037, 47901.913535, 47910.645194, 47919.377015, 47928.108997, 47936.841140, 
+   47945.573445, 47954.305911, 47963.038538, 47971.771326, 47980.504275, 47989.237386, 47997.970658, 48006.704091, 
+   48015.437685, 48024.171440, 48032.905356, 48041.639434, 48050.373672, 48059.108071, 48067.842631, 48076.577352, 
+   48085.312234, 48094.047277, 48102.782480, 48111.517845, 48120.253370, 48128.989056, 48137.724902, 48146.460910, 
+   48155.197078, 48163.933407, 48172.669896, 48181.406546, 48190.143356, 48198.880328, 48207.617459, 48216.354751, 
+   48225.092204, 48233.829817, 48242.567590, 48251.305524, 48260.043618, 48268.781873, 48277.520288, 48286.258863, 
+   48294.997599, 48303.736494, 48312.475550, 48321.214766, 48329.954143, 48338.693679, 48347.433376, 48356.173232, 
+   48364.913249, 48373.653426, 48382.393762, 48391.134259, 48399.874916, 48408.615732, 48417.356709, 48426.097845, 
+   48434.839142, 48443.580598, 48452.322214, 48461.063989, 48469.805925, 48478.548020, 48487.290275, 48496.032689, 
+   48504.775264, 48513.517998, 48522.260891, 48531.003944, 48539.747157, 48548.490529, 48557.234060, 48565.977752, 
+   48574.721602, 48583.465612, 48592.209782, 48600.954110, 48609.698598, 48618.443246, 48627.188053, 48635.933019, 
+   48644.678144, 48653.423428, 48662.168872, 48670.914475, 48679.660237, 48688.406158, 48697.152238, 48705.898477, 
+   48714.644876, 48723.391433, 48732.138150, 48740.885025, 48749.632059, 48758.379252, 48767.126604, 48775.874115, 
+   48784.621785, 48793.369614, 48802.117601, 48810.865747, 48819.614052, 48828.362516, 48837.111138, 48845.859919, 
+   48854.608859, 48863.357957, 48872.107214, 48880.856629, 48889.606203, 48898.355936, 48907.105827, 48915.855876, 
+   48924.606084, 48933.356450, 48942.106975, 48950.857658, 48959.608499, 48968.359499, 48977.110657, 48985.861973, 
+   48994.613448, 49003.365080, 49012.116871, 49020.868820, 49029.620928, 49038.373193, 49047.125616, 49055.878198, 
+   49064.630937, 49073.383835, 49082.136890, 49090.890104, 49099.643475, 49108.397005, 49117.150692, 49125.904537, 
+   49134.658540, 49143.412701, 49152.167019, 49160.921495, 49169.676129, 49178.430921, 49187.185871, 49195.940978, 
+   49204.696243, 49213.451665, 49222.207245, 49230.962982, 49239.718877, 49248.474930, 49257.231140, 49265.987508, 
+   49274.744033, 49283.500715, 49292.257555, 49301.014552, 49309.771707, 49318.529019, 49327.286488, 49336.044114, 
+   49344.801898, 49353.559839, 49362.317937, 49371.076192, 49379.834604, 49388.593174, 49397.351900, 49406.110784, 
+   49414.869825, 49423.629023, 49432.388377, 49441.147889, 49449.907558, 49458.667383, 49467.427366, 49476.187505, 
+   49484.947801, 49493.708254, 49502.468864, 49511.229631, 49519.990554, 49528.751634, 49537.512871, 49546.274265, 
+   49555.035815, 49563.797522, 49572.559385, 49581.321405, 49590.083581, 49598.845915, 49607.608404, 49616.371050, 
+   49625.133853, 49633.896811, 49642.659927, 49651.423199, 49660.186627, 49668.950211, 49677.713952, 49686.477849, 
+   49695.241902, 49704.006112, 49712.770477, 49721.534999, 49730.299677, 49739.064511, 49747.829502, 49756.594648, 
+   49765.359951, 49774.125409, 49782.891024, 49791.656794, 49800.422721, 49809.188803, 49817.955042, 49826.721436, 
+   49835.487986, 49844.254692, 49853.021554, 49861.788572, 49870.555745, 49879.323074, 49888.090559, 49896.858200, 
+   49905.625996, 49914.393948, 49923.162055, 49931.930318, 49940.698737, 49949.467311, 49958.236041, 49967.004927, 
+   49975.773967, 49984.543164, 49993.312515, 50002.082022, 50010.851685, 50019.621503, 50028.391476, 50037.161605, 
+   50045.931888, 50054.702327, 50063.472922, 50072.243671, 50081.014576, 50089.785636, 50098.556851, 50107.328221, 
+   50116.099747, 50124.871427, 50133.643262, 50142.415253, 50151.187398, 50159.959699, 50168.732154, 50177.504764, 
+   50186.277529, 50195.050450, 50203.823525, 50212.596754, 50221.370139, 50230.143678, 50238.917372, 50247.691221, 
+   50256.465225, 50265.239383, 50274.013696, 50282.788164, 50291.562786, 50300.337563, 50309.112494, 50317.887580, 
+   50326.662821, 50335.438216, 50344.213765, 50352.989469, 50361.765327, 50370.541340, 50379.317507, 50388.093828, 
+   50396.870304, 50405.646934, 50414.423719, 50423.200657, 50431.977750, 50440.754997, 50449.532399, 50458.309954, 
+   50467.087664, 50475.865527, 50484.643545, 50493.421717, 50502.200043, 50510.978523, 50519.757157, 50528.535945, 
+   50537.314887, 50546.093983, 50554.873232, 50563.652636, 50572.432193, 50581.211905, 50589.991770, 50598.771789, 
+   50607.551961, 50616.332288, 50625.112768, 50633.893402, 50642.674189, 50651.455130, 50660.236225, 50669.017473, 
+   50677.798875, 50686.580431, 50695.362140, 50704.144002, 50712.926018, 50721.708187, 50730.490510, 50739.272987, 
+   50748.055616, 50756.838399, 50765.621336, 50774.404425, 50783.187668, 50791.971064, 50800.754614, 50809.538317, 
+   50818.322173, 50827.106182, 50835.890344, 50844.674659, 50853.459128, 50862.243749, 50871.028524, 50879.813451, 
+   50888.598532, 50897.383766, 50906.169152, 50914.954692, 50923.740384, 50932.526230, 50941.312228, 50950.098379, 
+   50958.884683, 50967.671139, 50976.457749, 50985.244511, 50994.031426, 51002.818494, 51011.605714, 51020.393087, 
+   51029.180613, 51037.968291, 51046.756122, 51055.544105, 51064.332241, 51073.120529, 51081.908970, 51090.697564, 
+   51099.486310, 51108.275208, 51117.064259, 51125.853462, 51134.642817, 51143.432325, 51152.221985, 51161.011798, 
+   51169.801762, 51178.591879, 51187.382148, 51196.172569, 51204.963143, 51213.753869, 51222.544746, 51231.335776, 
+   51240.126958, 51248.918292, 51257.709778, 51266.501416, 51275.293206, 51284.085148, 51292.877242, 51301.669488, 
+   51310.461886, 51319.254435, 51328.047137, 51336.839990, 51345.632995, 51354.426152, 51363.219461, 51372.012921, 
+   51380.806533, 51389.600297, 51398.394212, 51407.188279, 51415.982498, 51424.776868, 51433.571390, 51442.366064, 
+   51451.160889, 51459.955865, 51468.750993, 51477.546272, 51486.341703, 51495.137285, 51503.933019, 51512.728904, 
+   51521.524940, 51530.321128, 51539.117467, 51547.913957, 51556.710598, 51565.507391, 51574.304335, 51583.101430, 
+   51591.898676, 51600.696074, 51609.493622, 51618.291322, 51627.089172, 51635.887174, 51644.685327, 51653.483631, 
+   51662.282085, 51671.080691, 51679.879447, 51688.678355, 51697.477413, 51706.276623, 51715.075983, 51723.875494, 
+   51732.675155, 51741.474968, 51750.274931, 51759.075045, 51767.875310, 51776.675725, 51785.476291, 51794.277007, 
+   51803.077875, 51811.878893, 51820.680061, 51829.481380, 51838.282849, 51847.084469, 51855.886240, 51864.688161, 
+   51873.490232, 51882.292454, 51891.094826, 51899.897348, 51908.700021, 51917.502844, 51926.305818, 51935.108942, 
+   51943.912216, 51952.715640, 51961.519214, 51970.322939, 51979.126814, 51987.930838, 51996.735013, 52005.539339, 
+   52014.343814, 52023.148439, 52031.953214, 52040.758140, 52049.563215, 52058.368440, 52067.173815, 52075.979340, 
+   52084.785015, 52093.590840, 52102.396815, 52111.202939, 52120.009213, 52128.815637, 52137.622211, 52146.428935, 
+   52155.235808, 52164.042831, 52172.850004, 52181.657326, 52190.464798, 52199.272419, 52208.080190, 52216.888111, 
+   52225.696181, 52234.504401, 52243.312770, 52252.121289, 52260.929957, 52269.738774, 52278.547741, 52287.356857, 
+   52296.166123, 52304.975538, 52313.785102, 52322.594816, 52331.404678, 52340.214690, 52349.024852, 52357.835162, 
+   52366.645622, 52375.456231, 52384.266989, 52393.077896, 52401.888952, 52410.700157, 52419.511511, 52428.323014, 
+   52437.134667, 52445.946468, 52454.758418, 52463.570517, 52472.382765, 52481.195162, 52490.007708, 52498.820402, 
+   52507.633246, 52516.446238, 52525.259379, 52534.072669, 52542.886107, 52551.699695, 52560.513430, 52569.327315, 
+   52578.141348, 52586.955530, 52595.769860, 52604.584339, 52613.398967, 52622.213743, 52631.028668, 52639.843741, 
+   52648.658962, 52657.474332, 52666.289851, 52675.105518, 52683.921333, 52692.737296, 52701.553408, 52710.369668, 
+   52719.186077, 52728.002634, 52736.819339, 52745.636192, 52754.453193, 52763.270343, 52772.087641, 52780.905087, 
+   52789.722681, 52798.540423, 52807.358313, 52816.176351, 52824.994538, 52833.812872, 52842.631354, 52851.449984, 
+   52860.268763, 52869.087689, 52877.906763, 52886.725985, 52895.545354, 52904.364872, 52913.184537, 52922.004350, 
+   52930.824311, 52939.644420, 52948.464676, 52957.285080, 52966.105632, 52974.926331, 52983.747178, 52992.568173, 
+   53001.389315, 53010.210605, 53019.032042, 53027.853627, 53036.675360, 53045.497240, 53054.319267, 53063.141442, 
+   53071.963764, 53080.786233, 53089.608850, 53098.431615, 53107.254526, 53116.077585, 53124.900791, 53133.724145, 
+   53142.547646, 53151.371294, 53160.195089, 53169.019031, 53177.843121, 53186.667357, 53195.491741, 53204.316272, 
+   53213.140950, 53221.965775, 53230.790747, 53239.615866, 53248.441131, 53257.266544, 53266.092104, 53274.917811, 
+   53283.743665, 53292.569665, 53301.395813, 53310.222107, 53319.048548, 53327.875136, 53336.701870, 53345.528752, 
+   53354.355780, 53363.182955, 53372.010276, 53380.837744, 53389.665359, 53398.493120, 53407.321028, 53416.149083, 
+   53424.977284, 53433.805631, 53442.634126, 53451.462766, 53460.291553, 53469.120487, 53477.949567, 53486.778793, 
+   53495.608166, 53504.437685, 53513.267350, 53522.097162, 53530.927120, 53539.757224, 53548.587475, 53557.417872, 
+   53566.248415, 53575.079104, 53583.909939, 53592.740921, 53601.572049, 53610.403322, 53619.234742, 53628.066308, 
+   53636.898020, 53645.729878, 53654.561882, 53663.394032, 53672.226328, 53681.058769, 53689.891357, 53698.724091, 
+   53707.556970, 53716.389995, 53725.223167, 53734.056483, 53742.889946, 53751.723555, 53760.557309, 53769.391209, 
+   53778.225254, 53787.059446, 53795.893783, 53804.728265, 53813.562894, 53822.397667, 53831.232587, 53840.067652, 
+   53848.902862, 53857.738218, 53866.573720, 53875.409367, 53884.245159, 53893.081097, 53901.917180, 53910.753408, 
+   53919.589782, 53928.426302, 53937.262966, 53946.099776, 53954.936731, 53963.773832, 53972.611077, 53981.448468, 
+   53990.286004, 53999.123685, 54007.961512, 54016.799483, 54025.637600, 54034.475862, 54043.314268, 54052.152820, 
+   54060.991517, 54069.830359, 54078.669346, 54087.508477, 54096.347754, 54105.187176, 54114.026742, 54122.866453, 
+   54131.706310, 54140.546311, 54149.386457, 54158.226747, 54167.067183, 54175.907763, 54184.748488, 54193.589357, 
+   54202.430372, 54211.271531, 54220.112834, 54228.954283, 54237.795875, 54246.637613, 54255.479495, 54264.321521, 
+   54273.163692, 54282.006008, 54290.848468, 54299.691073, 54308.533821, 54317.376715, 54326.219753, 54335.062935, 
+   54343.906261, 54352.749732, 54361.593347, 54370.437106, 54379.281010, 54388.125058, 54396.969250, 54405.813586, 
+   54414.658067, 54423.502692, 54432.347460, 54441.192373, 54450.037430, 54458.882631, 54467.727977, 54476.573466, 
+   54485.419099, 54494.264876, 54503.110798, 54511.956863, 54520.803072, 54529.649425, 54538.495922, 54547.342563, 
+   54556.189347, 54565.036276, 54573.883348, 54582.730564, 54591.577924, 54600.425428, 54609.273075, 54618.120866, 
+   54626.968801, 54635.816879, 54644.665102, 54653.513467, 54662.361977, 54671.210629, 54680.059426, 54688.908366, 
+   54697.757449, 54706.606676, 54715.456047, 54724.305561, 54733.155218, 54742.005019, 54750.854963, 54759.705051, 
+   54768.555282, 54777.405656, 54786.256174, 54795.106835, 54803.957639, 54812.808586, 54821.659677, 54830.510911, 
+   54839.362288, 54848.213808, 54857.065472, 54865.917278, 54874.769228, 54883.621321, 54892.473557, 54901.325936, 
+   54910.178457, 54919.031122, 54927.883930, 54936.736881, 54945.589975, 54954.443212, 54963.296591, 54972.150114, 
+   54981.003779, 54989.857588, 54998.711539, 55007.565633, 55016.419869, 55025.274249, 55034.128771, 55042.983436, 
+   55051.838244, 55060.693194, 55069.548287, 55078.403523, 55087.258901, 55096.114422, 55104.970085, 55113.825891, 
+   55122.681840, 55131.537931, 55140.394164, 55149.250540, 55158.107059, 55166.963720, 55175.820523, 55184.677469, 
+   55193.534557, 55202.391787, 55211.249160, 55220.106675, 55228.964333, 55237.822133, 55246.680075, 55255.538159, 
+   55264.396385, 55273.254754, 55282.113265, 55290.971918, 55299.830713, 55308.689650, 55317.548729, 55326.407951, 
+   55335.267314, 55344.126820, 55352.986467, 55361.846257, 55370.706188, 55379.566261, 55388.426477, 55397.286834, 
+   55406.147333, 55415.007974, 55423.868757, 55432.729682, 55441.590749, 55450.451957, 55459.313307, 55468.174799, 
+   55477.036432, 55485.898208, 55494.760125, 55503.622183, 55512.484384, 55521.346726, 55530.209209, 55539.071834, 
+   55547.934601, 55556.797509, 55565.660559, 55574.523751, 55583.387083, 55592.250558, 55601.114174, 55609.977931, 
+   55618.841829, 55627.705869, 55636.570051, 55645.434373, 55654.298837, 55663.163443, 55672.028190, 55680.893077, 
+   55689.758107, 55698.623277, 55707.488589, 55716.354042, 55725.219636, 55734.085371, 55742.951247, 55751.817264, 
+   55760.683423, 55769.549722, 55778.416163, 55787.282745, 55796.149467, 55805.016331, 55813.883336, 55822.750481, 
+   55831.617768, 55840.485195, 55849.352764, 55858.220473, 55867.088323, 55875.956314, 55884.824445, 55893.692718, 
+   55902.561131, 55911.429685, 55920.298380, 55929.167216, 55938.036192, 55946.905309, 55955.774566, 55964.643964, 
+   55973.513503, 55982.383182, 55991.253002, 56000.122963, 56008.993064, 56017.863305, 56026.733688, 56035.604210, 
+   56044.474873, 56053.345677, 56062.216620, 56071.087705, 56079.958929, 56088.830294, 56097.701800, 56106.573445, 
+   56115.445231, 56124.317158, 56133.189224, 56142.061431, 56150.933778, 56159.806265, 56168.678892, 56177.551660, 
+   56186.424568, 56195.297615, 56204.170803, 56213.044131, 56221.917599, 56230.791207, 56239.664956, 56248.538844, 
+   56257.412872, 56266.287040, 56275.161348, 56284.035796, 56292.910384, 56301.785112, 56310.659979, 56319.534987, 
+   56328.410134, 56337.285421, 56346.160848, 56355.036415, 56363.912121, 56372.787967, 56381.663953, 56390.540079, 
+   56399.416344, 56408.292749, 56417.169294, 56426.045978, 56434.922801, 56443.799765, 56452.676868, 56461.554110, 
+   56470.431492, 56479.309014, 56488.186674, 56497.064475, 56505.942415, 56514.820494, 56523.698713, 56532.577071, 
+   56541.455568, 56550.334205, 56559.212981, 56568.091896, 56576.970951, 56585.850145, 56594.729478, 56603.608950, 
+   56612.488562, 56621.368313, 56630.248203, 56639.128232, 56648.008400, 56656.888708, 56665.769154, 56674.649740, 
+   56683.530464, 56692.411328, 56701.292330, 56710.173472, 56719.054753, 56727.936172, 56736.817731, 56745.699428, 
+   56754.581264, 56763.463239, 56772.345354, 56781.227606, 56790.109998, 56798.992529, 56807.875198, 56816.758006, 
+   56825.640953, 56834.524038, 56843.407263, 56852.290625, 56861.174127, 56870.057767, 56878.941546, 56887.825464, 
+   56896.709520, 56905.593714, 56914.478047, 56923.362519, 56932.247129, 56941.131878, 56950.016765, 56958.901791, 
+   56967.786955, 56976.672258, 56985.557699, 56994.443278, 57003.328995, 57012.214851, 57021.100846, 57029.986978, 
+   57038.873249, 57047.759658, 57056.646206, 57065.532892, 57074.419715, 57083.306677, 57092.193778, 57101.081016, 
+   57109.968392, 57118.855907, 57127.743560, 57136.631350, 57145.519279, 57154.407346, 57163.295551, 57172.183894, 
+   57181.072375, 57189.960994, 57198.849750, 57207.738645, 57216.627678, 57225.516848, 57234.406156, 57243.295602, 
+   57252.185186, 57261.074908, 57269.964768, 57278.854765, 57287.744900, 57296.635173, 57305.525584, 57314.416132, 
+   57323.306818, 57332.197641, 57341.088603, 57349.979702, 57358.870938, 57367.762312, 57376.653824, 57385.545473, 
+   57394.437259, 57403.329183, 57412.221245, 57421.113444, 57430.005781, 57438.898255, 57447.790866, 57456.683615, 
+   57465.576501, 57474.469524, 57483.362685, 57492.255983, 57501.149419, 57510.042992, 57518.936702, 57527.830549, 
+   57536.724533, 57545.618655, 57554.512914, 57563.407310, 57572.301843, 57581.196513, 57590.091320, 57598.986265, 
+   57607.881346, 57616.776565, 57625.671921, 57634.567413, 57643.463043, 57652.358809, 57661.254713, 57670.150754, 
+   57679.046931, 57687.943245, 57696.839696, 57705.736285, 57714.633009, 57723.529871, 57732.426870, 57741.324005, 
+   57750.221277, 57759.118686, 57768.016232, 57776.913914, 57785.811733, 57794.709689, 57803.607781, 57812.506010, 
+   57821.404376, 57830.302878, 57839.201517, 57848.100292, 57856.999204, 57865.898252, 57874.797437, 57883.696759, 
+   57892.596217, 57901.495811, 57910.395542, 57919.295409, 57928.195413, 57937.095553, 57945.995829, 57954.896242, 
+   57963.796791, 57972.697476, 57981.598298, 57990.499255, 57999.400350, 58008.301580, 58017.202946, 58026.104449, 
+   58035.006088, 58043.907863, 58052.809774, 58061.711822, 58070.614005, 58079.516325, 58088.418780, 58097.321372, 
+   58106.224100, 58115.126963, 58124.029963, 58132.933099, 58141.836370, 58150.739778, 58159.643321, 58168.547001, 
+   58177.450816, 58186.354767, 58195.258854, 58204.163076, 58213.067435, 58221.971929, 58230.876559, 58239.781325, 
+   58248.686227, 58257.591264, 58266.496437, 58275.401746, 58284.307190, 58293.212770, 58302.118486, 58311.024337, 
+   58319.930324, 58328.836446, 58337.742704, 58346.649097, 58355.555626, 58364.462291, 58373.369090, 58382.276026, 
+   58391.183097, 58400.090303, 58408.997644, 58417.905121, 58426.812734, 58435.720481, 58444.628364, 58453.536383, 
+   58462.444536, 58471.352825, 58480.261249, 58489.169809, 58498.078503, 58506.987333, 58515.896298, 58524.805398, 
+   58533.714633, 58542.624004, 58551.533509, 58560.443150, 58569.352926, 58578.262836, 58587.172882, 58596.083063, 
+   58604.993379, 58613.903829, 58622.814415, 58631.725136, 58640.635991, 58649.546982, 58658.458107, 58667.369368, 
+   58676.280763, 58685.192293, 58694.103957, 58703.015757, 58711.927691, 58720.839760, 58729.751964, 58738.664303, 
+   58747.576776, 58756.489384, 58765.402127, 58774.315004, 58783.228016, 58792.141162, 58801.054444, 58809.967859, 
+   58818.881410, 58827.795094, 58836.708914, 58845.622868, 58854.536956, 58863.451179, 58872.365536, 58881.280028, 
+   58890.194654, 58899.109414, 58908.024309, 58916.939339, 58925.854502, 58934.769800, 58943.685232, 58952.600799, 
+   58961.516500, 58970.432335, 58979.348304, 58988.264408, 58997.180645, 59006.097017, 59015.013523, 59023.930164, 
+   59032.846938, 59041.763846, 59050.680889, 59059.598066, 59068.515376, 59077.432821, 59086.350400, 59095.268113, 
+   59104.185959, 59113.103940, 59122.022055, 59130.940303, 59139.858686, 59148.777202, 59157.695852, 59166.614637, 
+   59175.533555, 59184.452606, 59193.371792, 59202.291111, 59211.210565, 59220.130151, 59229.049872, 59237.969726, 
+   59246.889715, 59255.809836, 59264.730092, 59273.650481, 59282.571003, 59291.491660, 59300.412450, 59309.333373, 
+   59318.254430, 59327.175621, 59336.096945, 59345.018402, 59353.939993, 59362.861718, 59371.783576, 59380.705567, 
+   59389.627692, 59398.549950, 59407.472342, 59416.394867, 59425.317525, 59434.240317, 59443.163242, 59452.086300, 
+   59461.009491, 59469.932816, 59478.856274, 59487.779865, 59496.703590, 59505.627447, 59514.551438, 59523.475562, 
+   59532.399819, 59541.324209, 59550.248732, 59559.173389, 59568.098178, 59577.023100, 59585.948156, 59594.873344, 
+   59603.798666, 59612.724120, 59621.649707, 59630.575428, 59639.501281, 59648.427267, 59657.353386, 59666.279638, 
+   59675.206023, 59684.132540, 59693.059190, 59701.985973, 59710.912889, 59719.839938, 59728.767119, 59737.694433, 
+   59746.621880, 59755.549460, 59764.477172, 59773.405017, 59782.332994, 59791.261104, 59800.189347, 59809.117722, 
+   59818.046230, 59826.974870, 59835.903643, 59844.832549, 59853.761587, 59862.690757, 59871.620060, 59880.549495, 
+   59889.479063, 59898.408763, 59907.338596, 59916.268560, 59925.198658, 59934.128887, 59943.059249, 59951.989743, 
+   59960.920370, 59969.851128, 59978.782019, 59987.713043, 59996.644198, 60005.575486, 60014.506906, 60023.438458, 
+   60032.370142, 60041.301958, 60050.233906, 60059.165987, 60068.098199, 60077.030544, 60085.963020, 60094.895629, 
+   60103.828370, 60112.761242, 60121.694247, 60130.627383, 60139.560652, 60148.494052, 60157.427585, 60166.361249, 
+   60175.295045, 60184.228973, 60193.163032, 60202.097224, 60211.031547, 60219.966002, 60228.900589, 60237.835308, 
+   60246.770158, 60255.705140, 60264.640254, 60273.575499, 60282.510876, 60291.446385, 60300.382025, 60309.317797, 
+   60318.253701, 60327.189736, 60336.125903, 60345.062201, 60353.998631, 60362.935192, 60371.871884, 60380.808709, 
+   60389.745664, 60398.682751, 60407.619970, 60416.557320, 60425.494801, 60434.432413, 60443.370157, 60452.308033, 
+   60461.246039, 60470.184177, 60479.122446, 60488.060847, 60496.999378, 60505.938041, 60514.876835, 60523.815760, 
+   60532.754817, 60541.694005, 60550.633323, 60559.572773, 60568.512354, 60577.452066, 60586.391909, 60595.331883, 
+   60604.271989, 60613.212225, 60622.152592, 60631.093090, 60640.033720, 60648.974480, 60657.915371, 60666.856393, 
+   60675.797546, 60684.738829, 60693.680244, 60702.621789, 60711.563466, 60720.505273, 60729.447211, 60738.389279, 
+   60747.331479, 60756.273809, 60765.216270, 60774.158862, 60783.101584, 60792.044437, 60800.987421, 60809.930535, 
+   60818.873780, 60827.817155, 60836.760662, 60845.704298, 60854.648066, 60863.591963, 60872.535992, 60881.480151, 
+   60890.424440, 60899.368860, 60908.313410, 60917.258091, 60926.202902, 60935.147843, 60944.092915, 60953.038117, 
+   60961.983450, 60970.928913, 60979.874506, 60988.820230, 60997.766084, 61006.712068, 61015.658182, 61024.604427, 
+   61033.550802, 61042.497307, 61051.443942, 61060.390707, 61069.337603, 61078.284628, 61087.231784, 61096.179070, 
+   61105.126486, 61114.074032, 61123.021708, 61131.969514, 61140.917450, 61149.865516, 61158.813712, 61167.762038, 
+   61176.710494, 61185.659080, 61194.607796, 61203.556642, 61212.505618, 61221.454723, 61230.403958, 61239.353323, 
+   61248.302818, 61257.252443, 61266.202198, 61275.152082, 61284.102096, 61293.052240, 61302.002513, 61310.952916, 
+   61319.903449, 61328.854112, 61337.804904, 61346.755826, 61355.706877, 61364.658058, 61373.609369, 61382.560809, 
+   61391.512378, 61400.464077, 61409.415906, 61418.367864, 61427.319952, 61436.272169, 61445.224516, 61454.176992, 
+   61463.129597, 61472.082332, 61481.035196, 61489.988189, 61498.941312, 61507.894564, 61516.847946, 61525.801457, 
+   61534.755097, 61543.708866, 61552.662764, 61561.616792, 61570.570949, 61579.525235, 61588.479651, 61597.434195, 
+   61606.388869, 61615.343672, 61624.298603, 61633.253664, 61642.208854, 61651.164173, 61660.119622, 61669.075199, 
+   61678.030905, 61686.986740, 61695.942704, 61704.898797, 61713.855019, 61722.811370, 61731.767850, 61740.724459, 
+   61749.681196, 61758.638063, 61767.595058, 61776.552182, 61785.509435, 61794.466817, 61803.424327, 61812.381967, 
+   61821.339735, 61830.297631, 61839.255657, 61848.213811, 61857.172094, 61866.130505, 61875.089045, 61884.047714, 
+   61893.006512, 61901.965437, 61910.924492, 61919.883675, 61928.842987, 61937.802427, 61946.761995, 61955.721693, 
+   61964.681518, 61973.641472, 61982.601555, 61991.561766, 62000.522105, 62009.482573, 62018.443169, 62027.403894, 
+   62036.364746, 62045.325728, 62054.286837, 62063.248075, 62072.209441, 62081.170935, 62090.132558, 62099.094309, 
+   62108.056188, 62117.018195, 62125.980330, 62134.942594, 62143.904985, 62152.867505, 62161.830153, 62170.792929, 
+   62179.755833, 62188.718866, 62197.682026, 62206.645314, 62215.608730, 62224.572275, 62233.535947, 62242.499747, 
+   62251.463675, 62260.427732, 62269.391916, 62278.356228, 62287.320667, 62296.285235, 62305.249931, 62314.214754, 
+   62323.179705, 62332.144784, 62341.109991, 62350.075326, 62359.040788, 62368.006378, 62376.972096, 62385.937941, 
+   62394.903915, 62403.870015, 62412.836244, 62421.802600, 62430.769084, 62439.735695, 62448.702434, 62457.669301, 
+   62466.636295, 62475.603416, 62484.570666, 62493.538042, 62502.505547, 62511.473178, 62520.440937, 62529.408824, 
+   62538.376838, 62547.344979, 62556.313248, 62565.281644, 62574.250168, 62583.218819, 62592.187597, 62601.156503, 
+   62610.125535, 62619.094696, 62628.063983, 62637.033398, 62646.002940, 62654.972609, 62663.942405, 62672.912328, 
+   62681.882379, 62690.852557, 62699.822862, 62708.793294, 62717.763853, 62726.734539, 62735.705353, 62744.676293, 
+   62753.647361, 62762.618555, 62771.589876, 62780.561325, 62789.532900, 62798.504603, 62807.476432, 62816.448388, 
+   62825.420472, 62834.392682, 62843.365019, 62852.337482, 62861.310073, 62870.282791, 62879.255635, 62888.228606, 
+   62897.201704, 62906.174929, 62915.148280, 62924.121758, 62933.095363, 62942.069095, 62951.042953, 62960.016938, 
+   62968.991049, 62977.965288, 62986.939652, 62995.914144, 63004.888762, 63013.863507, 63022.838378, 63031.813375, 
+   63040.788500, 63049.763750, 63058.739128, 63067.714631, 63076.690262, 63085.666018, 63094.641901, 63103.617911, 
+   63112.594047, 63121.570309, 63130.546697, 63139.523212, 63148.499854, 63157.476621, 63166.453515, 63175.430535, 
+   63184.407682, 63193.384955, 63202.362354, 63211.339879, 63220.317530, 63229.295308, 63238.273212, 63247.251242, 
+   63256.229398, 63265.207680, 63274.186088, 63283.164623, 63292.143283, 63301.122070, 63310.100982, 63319.080021, 
+   63328.059186, 63337.038476, 63346.017893, 63354.997435, 63363.977104, 63372.956898, 63381.936819, 63390.916865, 
+   63399.897037, 63408.877335, 63417.857759, 63426.838309, 63435.818985, 63444.799786, 63453.780713, 63462.761766, 
+   63471.742945, 63480.724250, 63489.705680, 63498.687236, 63507.668917, 63516.650725, 63525.632658, 63534.614716, 
+   63543.596901, 63552.579211, 63561.561646, 63570.544207, 63579.526894, 63588.509706, 63597.492644, 63606.475707, 
+   63615.458896, 63624.442210, 63633.425650, 63642.409215, 63651.392906, 63660.376722, 63669.360664, 63678.344730, 
+   63687.328923, 63696.313240, 63705.297684, 63714.282252, 63723.266946, 63732.251765, 63741.236709, 63750.221778, 
+   63759.206973, 63768.192293, 63777.177739, 63786.163309, 63795.149005, 63804.134826, 63813.120772, 63822.106843, 
+   63831.093039, 63840.079361, 63849.065807, 63858.052379, 63867.039075, 63876.025897, 63885.012844, 63893.999916, 
+   63902.987113, 63911.974434, 63920.961881, 63929.949453, 63938.937150, 63947.924971, 63956.912918, 63965.900989, 
+   63974.889186, 63983.877507, 63992.865953, 64001.854524, 64010.843219, 64019.832040, 64028.820985, 64037.810055, 
+   64046.799250, 64055.788570, 64064.778014, 64073.767583, 64082.757277, 64091.747095, 64100.737038, 64109.727106, 
+   64118.717298, 64127.707615, 64136.698057, 64145.688623, 64154.679313, 64163.670129, 64172.661069, 64181.652133, 
+   64190.643322, 64199.634635, 64208.626073, 64217.617635, 64226.609322, 64235.601133, 64244.593069, 64253.585129, 
+   64262.577313, 64271.569622, 64280.562055, 64289.554612, 64298.547294, 64307.540100, 64316.533030, 64325.526085, 
+   64334.519264, 64343.512567, 64352.505994, 64361.499546, 64370.493222, 64379.487022, 64388.480946, 64397.474994, 
+   64406.469167, 64415.463463, 64424.457884, 64433.452429, 64442.447097, 64451.441890, 64460.436807, 64469.431848, 
+   64478.427013, 64487.422302, 64496.417715, 64505.413252, 64514.408913, 64523.404698, 64532.400607, 64541.396639, 
+   64550.392796, 64559.389076, 64568.385481, 64577.382009, 64586.378661, 64595.375437, 64604.372336, 64613.369360, 
+   64622.366507, 64631.363778, 64640.361172, 64649.358691, 64658.356333, 64667.354098, 64676.351988, 64685.350001, 
+   64694.348138, 64703.346398, 64712.344782, 64721.343290, 64730.341921, 64739.340676, 64748.339554, 64757.338556, 
+   64766.337681, 64775.336930, 64784.336303, 64793.335799, 64802.335418, 64811.335161, 64820.335027, 64829.335016, 
+   64838.335130, 64847.335366, 64856.335726, 64865.336209, 64874.336815, 64883.337545, 64892.338398, 64901.339375, 
+   64910.340475, 64919.341698, 64928.343044, 64937.344513, 64946.346106, 64955.347822, 64964.349661, 64973.351623, 
+   64982.353709, 64991.355917, 65000.358249, 65009.360704, 65018.363282, 65027.365983, 65036.368807, 65045.371754, 
+   65054.374824, 65063.378017, 65072.381334, 65081.384773, 65090.388335, 65099.392020, 65108.395828, 65117.399759, 
+   65126.403813, 65135.407990, 65144.412290, 65153.416712, 65162.421258, 65171.425926, 65180.430717, 65189.435631, 
+   65198.440668, 65207.445827, 65216.451110, 65225.456515, 65234.462042, 65243.467693, 65252.473466, 65261.479362, 
+   65270.485381, 65279.491522, 65288.497786, 65297.504172, 65306.510681, 65315.517313, 65324.524067, 65333.530944, 
+   65342.537944, 65351.545066, 65360.552310, 65369.559677, 65378.567167, 65387.574779, 65396.582513, 65405.590370, 
+   65414.598350, 65423.606451, 65432.614676, 65441.623022, 65450.631491, 65459.640082, 65468.648796, 65477.657632, 
+   65486.666590, 65495.675671, 65504.684874, 65513.694199, 65522.703647, 65531.713216, 65540.722908, 65549.732722, 
+   65558.742659, 65567.752717, 65576.762898, 65585.773200, 65594.783625, 65603.794172, 65612.804842, 65621.815633, 
+   65630.826546, 65639.837582, 65648.848739, 65657.860019, 65666.871420, 65675.882944, 65684.894589, 65693.906357, 
+   65702.918246, 65711.930257, 65720.942391, 65729.954646, 65738.967023, 65747.979522, 65756.992143, 65766.004886, 
+   65775.017750, 65784.030737, 65793.043845, 65802.057075, 65811.070427, 65820.083900, 65829.097495, 65838.111213, 
+   65847.125051, 65856.139012, 65865.153094, 65874.167298, 65883.181623, 65892.196070, 65901.210639, 65910.225329, 
+   65919.240141, 65928.255075, 65937.270130, 65946.285307, 65955.300605, 65964.316025, 65973.331566, 65982.347229, 
+   65991.363013, 66000.378919, 66009.394946, 66018.411095, 66027.427365, 66036.443756, 66045.460269, 66054.476904, 
+   66063.493659, 66072.510536, 66081.527534, 66090.544654, 66099.561895, 66108.579257, 66117.596741, 66126.614346, 
+   66135.632072, 66144.649919, 66153.667887, 66162.685977, 66171.704188, 66180.722520, 66189.740973, 66198.759548, 
+   66207.778243, 66216.797060, 66225.815997, 66234.835056, 66243.854236, 66252.873537, 66261.892959, 66270.912502, 
+   66279.932166, 66288.951951, 66297.971857, 66306.991884, 66316.012032, 66325.032301, 66334.052690, 66343.073201, 
+   66352.093833, 66361.114585, 66370.135459, 66379.156453, 66388.177568, 66397.198804, 66406.220160, 66415.241638, 
+   66424.263236, 66433.284955, 66442.306795, 66451.328755, 66460.350837, 66469.373038, 66478.395361, 66487.417804, 
+   66496.440368, 66505.463053, 66514.485858, 66523.508784, 66532.531831, 66541.554998, 66550.578285, 66559.601693, 
+   66568.625222, 66577.648871, 66586.672641, 66595.696532, 66604.720542, 66613.744674, 66622.768925, 66631.793298, 
+   66640.817790, 66649.842403, 66658.867137, 66667.891990, 66676.916965, 66685.942059, 66694.967274, 66703.992609, 
+   66713.018065, 66722.043641, 66731.069337, 66740.095153, 66749.121090, 66758.147147, 66767.173324, 66776.199621, 
+   66785.226039, 66794.252576, 66803.279234, 66812.306012, 66821.332911, 66830.359929, 66839.387067, 66848.414326, 
+   66857.441704, 66866.469203, 66875.496822, 66884.524561, 66893.552419, 66902.580398, 66911.608497, 66920.636716, 
+   66929.665055, 66938.693513, 66947.722092, 66956.750791, 66965.779609, 66974.808547, 66983.837606, 66992.866784, 
+   67001.896082, 67010.925500, 67019.955037, 67028.984695, 67038.014472, 67047.044369, 67056.074386, 67065.104522, 
+   67074.134779, 67083.165155, 67092.195651, 67101.226266, 67110.257001, 67119.287856, 67128.318830, 67137.349924, 
+   67146.381138, 67155.412471, 67164.443924, 67173.475497, 67182.507189, 67191.539001, 67200.570932, 67209.602982, 
+   67218.635153, 67227.667442, 67236.699851, 67245.732380, 67254.765028, 67263.797796, 67272.830683, 67281.863689, 
+   67290.896815, 67299.930060, 67308.963424, 67317.996908, 67327.030511, 67336.064234, 67345.098076, 67354.132037, 
+   67363.166117, 67372.200317, 67381.234636, 67390.269074, 67399.303631, 67408.338308, 67417.373104, 67426.408019, 
+   67435.443053, 67444.478206, 67453.513479, 67462.548870, 67471.584381, 67480.620011, 67489.655760, 67498.691628, 
+   67507.727615, 67516.763721, 67525.799946, 67534.836290, 67543.872753, 67552.909335, 67561.946036, 67570.982856, 
+   67580.019795, 67589.056853, 67598.094029, 67607.131325, 67616.168739, 67625.206273, 67634.243925, 67643.281696, 
+   67652.319586, 67661.357595, 67670.395722, 67679.433969, 67688.472334, 67697.510818, 67706.549420, 67715.588142, 
+   67724.626982, 67733.665941, 67742.705018, 67751.744214, 67760.783529, 67769.822962, 67778.862514, 67787.902185, 
+   67796.941974, 67805.981882, 67815.021909, 67824.062054, 67833.102317, 67842.142699, 67851.183200, 67860.223819, 
+   67869.264556, 67878.305413, 67887.346387, 67896.387480, 67905.428691, 67914.470021, 67923.511469, 67932.553036, 
+   67941.594721, 67950.636525, 67959.678446, 67968.720486, 67977.762645, 67986.804921, 67995.847316, 68004.889830, 
+   68013.932461, 68022.975211, 68032.018079, 68041.061065, 68050.104170, 68059.147392, 68068.190733, 68077.234192, 
+   68086.277769, 68095.321465, 68104.365278, 68113.409209, 68122.453259, 68131.497427, 68140.541713, 68149.586116, 
+   68158.630638, 68167.675278, 68176.720036, 68185.764912, 68194.809906, 68203.855018, 68212.900248, 68221.945596, 
+   68230.991061, 68240.036645, 68249.082347, 68258.128166, 68267.174103, 68276.220158, 68285.266331, 68294.312622, 
+   68303.359031, 68312.405558, 68321.452202, 68330.498964, 68339.545844, 68348.592841, 68357.639957, 68366.687190, 
+   68375.734540, 68384.782009, 68393.829595, 68402.877299, 68411.925120, 68420.973059, 68430.021116, 68439.069290, 
+   68448.117582, 68457.165992, 68466.214519, 68475.263163, 68484.311926, 68493.360805, 68502.409802, 68511.458917, 
+   68520.508149, 68529.557499, 68538.606966, 68547.656551, 68556.706253, 68565.756072, 68574.806009, 68583.856063, 
+   68592.906235, 68601.956524, 68611.006930, 68620.057454, 68629.108095, 68638.158853, 68647.209729, 68656.260722, 
+   68665.311832, 68674.363059, 68683.414404, 68692.465866, 68701.517445, 68710.569141, 68719.620955, 68728.672885, 
+   68737.724933, 68746.777098, 68755.829380, 68764.881779, 68773.934296, 68782.986929, 68792.039679, 68801.092547, 
+   68810.145531, 68819.198633, 68828.251852, 68837.305187, 68846.358640, 68855.412210, 68864.465896, 68873.519700, 
+   68882.573620, 68891.627657, 68900.681812, 68909.736083, 68918.790471, 68927.844976, 68936.899598, 68945.954336, 
+   68955.009192, 68964.064164, 68973.119253, 68982.174459, 68991.229782, 69000.285221, 69009.340777, 69018.396450, 
+   69027.452240, 69036.508146, 69045.564169, 69054.620309, 69063.676565, 69072.732938, 69081.789428, 69090.846034, 
+   69099.902757, 69108.959596, 69118.016553, 69127.073625, 69136.130814, 69145.188120, 69154.245542, 69163.303081, 
+   69172.360736, 69181.418508, 69190.476396, 69199.534401, 69208.592522, 69217.650760, 69226.709114, 69235.767584, 
+   69244.826171, 69253.884874, 69262.943694, 69272.002630, 69281.061682, 69290.120851, 69299.180136, 69308.239537, 
+   69317.299054, 69326.358688, 69335.418438, 69344.478304, 69353.538287, 69362.598385, 69371.658600, 69380.718931, 
+   69389.779379, 69398.839942, 69407.900622, 69416.961418, 69426.022329, 69435.083357, 69444.144501, 69453.205762, 
+   69462.267138, 69471.328630, 69480.390238, 69489.451963, 69498.513803, 69507.575759, 69516.637832, 69525.700020, 
+   69534.762324, 69543.824745, 69552.887281, 69561.949933, 69571.012701, 69580.075585, 69589.138585, 69598.201700, 
+   69607.264932, 69616.328279, 69625.391742, 69634.455321, 69643.519016, 69652.582827, 69661.646753, 69670.710795, 
+   69679.774953, 69688.839227, 69697.903616, 69706.968121, 69716.032742, 69725.097478, 69734.162330, 69743.227298, 
+   69752.292381, 69761.357580, 69770.422895, 69779.488325, 69788.553871, 69797.619532, 69806.685309, 69815.751202, 
+   69824.817210, 69833.883333, 69842.949572, 69852.015927, 69861.082397, 69870.148982, 69879.215683, 69888.282499, 
+   69897.349431, 69906.416478, 69915.483641, 69924.550919, 69933.618312, 69942.685821, 69951.753445, 69960.821185, 
+   69969.889039, 69978.957009, 69988.025095, 69997.093295, 70006.161611, 70015.230042, 70024.298589, 70033.367250, 
+   70042.436027, 70051.504919, 70060.573926, 70069.643049, 70078.712286, 70087.781639, 70096.851107, 70105.920690, 
+   70114.990388, 70124.060201, 70133.130129, 70142.200172, 70151.270331, 70160.340604, 70169.410992, 70178.481496, 
+   70187.552114, 70196.622848, 70205.693696, 70214.764659, 70223.835738, 70232.906931, 70241.978239, 70251.049662, 
+   70260.121200, 70269.192853, 70278.264621, 70287.336503, 70296.408501, 70305.480613, 70314.552840, 70323.625182, 
+   70332.697639, 70341.770210, 70350.842896, 70359.915697, 70368.988613, 70378.061643, 70387.134788, 70396.208048, 
+   70405.281423, 70414.354912, 70423.428516, 70432.502234, 70441.576067, 70450.650015, 70459.724078, 70468.798254, 
+   70477.872546, 70486.946952, 70496.021473, 70505.096108, 70514.170858, 70523.245722, 70532.320701, 70541.395794, 
+   70550.471002, 70559.546324, 70568.621760, 70577.697311, 70586.772977, 70595.848757, 70604.924651, 70614.000660, 
+   70623.076783, 70632.153020, 70641.229372, 70650.305838, 70659.382418, 70668.459113, 70677.535922, 70686.612845, 
+   70695.689883, 70704.767034, 70713.844300, 70722.921681, 70731.999175, 70741.076784, 70750.154507, 70759.232344, 
+   70768.310295, 70777.388360, 70786.466540, 70795.544833, 70804.623241, 70813.701763, 70822.780399, 70831.859149, 
+   70840.938013, 70850.016991, 70859.096083, 70868.175289, 70877.254609, 70886.334043, 70895.413591, 70904.493253, 
+   70913.573029, 70922.652919, 70931.732923, 70940.813041, 70949.893272, 70958.973618, 70968.054077, 70977.134651, 
+   70986.215338, 70995.296139, 71004.377054, 71013.458082, 71022.539225, 71031.620481, 71040.701851, 71049.783335, 
+   71058.864932, 71067.946644, 71077.028469, 71086.110407, 71095.192460, 71104.274626, 71113.356905, 71122.439299, 
+   71131.521806, 71140.604426, 71149.687160, 71158.770008, 71167.852970, 71176.936045, 71186.019233, 71195.102536, 
+   71204.185951, 71213.269480, 71222.353123, 71231.436879, 71240.520749, 71249.604732, 71258.688829, 71267.773039, 
+   71276.857363, 71285.941799, 71295.026350, 71304.111014, 71313.195791, 71322.280681, 71331.365685, 71340.450802, 
+   71349.536033, 71358.621377, 71367.706834, 71376.792404, 71385.878088, 71394.963885, 71404.049796, 71413.135819, 
+   71422.221956, 71431.308206, 71440.394569, 71449.481045, 71458.567635, 71467.654338, 71476.741154, 71485.828083, 
+   71494.915125, 71504.002280, 71513.089548, 71522.176930, 71531.264424, 71540.352032, 71549.439753, 71558.527586, 
+   71567.615533, 71576.703593, 71585.791766, 71594.880051, 71603.968450, 71613.056962, 71622.145586, 71631.234324, 
+   71640.323174, 71649.412138, 71658.501214, 71667.590403, 71676.679705, 71685.769120, 71694.858648, 71703.948288, 
+   71713.038042, 71722.127908, 71731.217887, 71740.307979, 71749.398184, 71758.488501, 71767.578931, 71776.669474, 
+   71785.760129, 71794.850897, 71803.941778, 71813.032772, 71822.123878, 71831.215097, 71840.306429, 71849.397873, 
+   71858.489430, 71867.581099, 71876.672881, 71885.764776, 71894.856783, 71903.948903, 71913.041135, 71922.133480, 
+   71931.225937, 71940.318507, 71949.411190, 71958.503984, 71967.596892, 71976.689911, 71985.783043, 71994.876288, 
+   72003.969645, 72013.063115, 72022.156696, 72031.250391, 72040.344197, 72049.438116, 72058.532147, 72067.626291, 
+   72076.720547, 72085.814915, 72094.909395, 72104.003988, 72113.098693, 72122.193510, 72131.288440, 72140.383482, 
+   72149.478636, 72158.573902, 72167.669280, 72176.764771, 72185.860373, 72194.956088, 72204.051915, 72213.147854, 
+   72222.243906, 72231.340069, 72240.436344, 72249.532732, 72258.629231, 72267.725843, 72276.822567, 72285.919402, 
+   72295.016350, 72304.113410, 72313.210581, 72322.307865, 72331.405261, 72340.502768, 72349.600388, 72358.698119, 
+   72367.795962, 72376.893918, 72385.991985, 72395.090164, 72404.188455, 72413.286857, 72422.385372, 72431.483998, 
+   72440.582737, 72449.681587, 72458.780548, 72467.879622, 72476.978807, 72486.078104, 72495.177513, 72504.277034, 
+   72513.376666, 72522.476410, 72531.576265, 72540.676233, 72549.776312, 72558.876502, 72567.976805, 72577.077219, 
+   72586.177744, 72595.278381, 72604.379130, 72613.479990, 72622.580962, 72631.682045, 72640.783240, 72649.884547, 
+   72658.985965, 72668.087494, 72677.189135, 72686.290888, 72695.392751, 72704.494727, 72713.596814, 72722.699012, 
+   72731.801321, 72740.903742, 72750.006275, 72759.108919, 72768.211674, 72777.314540, 72786.417518, 72795.520607, 
+   72804.623808, 72813.727120, 72822.830543, 72831.934077, 72841.037723, 72850.141480, 72859.245348, 72868.349327, 
+   72877.453418, 72886.557619, 72895.661932, 72904.766357, 72913.870892, 72922.975538, 72932.080296, 72941.185165, 
+   72950.290145, 72959.395236, 72968.500438, 72977.605751, 72986.711175, 72995.816710, 73004.922356, 73014.028114, 
+   73023.133982, 73032.239962, 73041.346052, 73050.452253, 73059.558566, 73068.664989, 73077.771523, 73086.878168, 
+   73095.984924, 73105.091791, 73114.198769, 73123.305858, 73132.413057, 73141.520368, 73150.627789, 73159.735321, 
+   73168.842964, 73177.950718, 73187.058583, 73196.166558, 73205.274644, 73214.382841, 73223.491149, 73232.599567, 
+   73241.708096, 73250.816736, 73259.925486, 73269.034348, 73278.143320, 73287.252402, 73296.361595, 73305.470899, 
+   73314.580314, 73323.689839, 73332.799474, 73341.909221, 73351.019077, 73360.129045, 73369.239123, 73378.349311, 
+   73387.459610, 73396.570020, 73405.680540, 73414.791170, 73423.901911, 73433.012763, 73442.123725, 73451.234797, 
+   73460.345980, 73469.457273, 73478.568677, 73487.680191, 73496.791815, 73505.903550, 73515.015395, 73524.127351, 
+   73533.239416, 73542.351592, 73551.463879, 73560.576276, 73569.688783, 73578.801400, 73587.914127, 73597.026965, 
+   73606.139913, 73615.252972, 73624.366140, 73633.479419, 73642.592808, 73651.706307, 73660.819916, 73669.933635, 
+   73679.047465, 73688.161404, 73697.275454, 73706.389614, 73715.503884, 73724.618264, 73733.732754, 73742.847354, 
+   73751.962064, 73761.076884, 73770.191814, 73779.306854, 73788.422005, 73797.537265, 73806.652635, 73815.768115, 
+   73824.883705, 73833.999405, 73843.115215, 73852.231135, 73861.347164, 73870.463304, 73879.579553, 73888.695913, 
+   73897.812382, 73906.928961, 73916.045650, 73925.162448, 73934.279357, 73943.396375, 73952.513503, 73961.630741, 
+   73970.748088, 73979.865545, 73988.983112, 73998.100789, 74007.218575, 74016.336472, 74025.454477, 74034.572593, 
+   74043.690818, 74052.809153, 74061.927597, 74071.046151, 74080.164814, 74089.283588, 74098.402470, 74107.521463, 
+   74116.640565, 74125.759776, 74134.879097, 74143.998528, 74153.118068, 74162.237717, 74171.357476, 74180.477344, 
+   74189.597322, 74198.717410, 74207.837607, 74216.957913, 74226.078329, 74235.198854, 74244.319488, 74253.440232, 
+   74262.561085, 74271.682048, 74280.803120, 74289.924301, 74299.045591, 74308.166991, 74317.288500, 74326.410119, 
+   74335.531847, 74344.653684, 74353.775630, 74362.897685, 74372.019850, 74381.142124, 74390.264507, 74399.386999, 
+   74408.509601, 74417.632311, 74426.755131, 74435.878060, 74445.001098, 74454.124245, 74463.247501, 74472.370867, 
+   74481.494341, 74490.617925, 74499.741617, 74508.865419, 74517.989330, 74527.113349, 74536.237478, 74545.361716, 
+   74554.486062, 74563.610518, 74572.735082, 74581.859756, 74590.984538, 74600.109430, 74609.234430, 74618.359539, 
+   74627.484758, 74636.610085, 74645.735520, 74654.861065, 74663.986719, 74673.112481, 74682.238352, 74691.364332, 
+   74700.490421, 74709.616619, 74718.742925, 74727.869340, 74736.995864, 74746.122497, 74755.249238, 74764.376088, 
+   74773.503047, 74782.630114, 74791.757290, 74800.884575, 74810.011969, 74819.139471, 74828.267082, 74837.394801, 
+   74846.522629, 74855.650565, 74864.778611, 74873.906764, 74883.035026, 74892.163397, 74901.291877, 74910.420465, 
+   74919.549161, 74928.677966, 74937.806879, 74946.935901, 74956.065031, 74965.194270, 74974.323617, 74983.453073, 
+   74992.582637, 75001.712309, 75010.842090, 75019.971980, 75029.101977, 75038.232083, 75047.362298, 75056.492620, 
+   75065.623051, 75074.753590, 75083.884238, 75093.014994, 75102.145858, 75111.276831, 75120.407911, 75129.539100, 
+   75138.670397, 75147.801803, 75156.933316, 75166.064938, 75175.196668, 75184.328506, 75193.460453, 75202.592507, 
+   75211.724670, 75220.856940, 75229.989319, 75239.121806, 75248.254401, 75257.387104, 75266.519915, 75275.652835, 
+   75284.785862, 75293.918997, 75303.052240, 75312.185592, 75321.319051, 75330.452618, 75339.586294, 75348.720077, 
+   75357.853968, 75366.987967, 75376.122074, 75385.256289, 75394.390612, 75403.525043, 75412.659582, 75421.794228, 
+   75430.928983, 75440.063845, 75449.198815, 75458.333893, 75467.469078, 75476.604372, 75485.739773, 75494.875282, 
+   75504.010899, 75513.146624, 75522.282456, 75531.418396, 75540.554444, 75549.690599, 75558.826863, 75567.963233, 
+   75577.099712, 75586.236298, 75595.372992, 75604.509793, 75613.646702, 75622.783719, 75631.920843, 75641.058075, 
+   75650.195415, 75659.332862, 75668.470417, 75677.608079, 75686.745848, 75695.883726, 75705.021710, 75714.159802, 
+   75723.298002, 75732.436309, 75741.574724, 75750.713246, 75759.851876, 75768.990613, 75778.129457, 75787.268409, 
+   75796.407468, 75805.546634, 75814.685908, 75823.825290, 75832.964778, 75842.104374, 75851.244077, 75860.383888, 
+   75869.523806, 75878.663831, 75887.803964, 75896.944203, 75906.084550, 75915.225005, 75924.365566, 75933.506235, 
+   75942.647011, 75951.787894, 75960.928884, 75970.069982, 75979.211186, 75988.352498, 75997.493917, 76006.635443, 
+   76015.777076, 76024.918816, 76034.060664, 76043.202618, 76052.344680, 76061.486848, 76070.629124, 76079.771507, 
+   76088.913996, 76098.056593, 76107.199297, 76116.342108, 76125.485025, 76134.628050, 76143.771182, 76152.914420, 
+   76162.057766, 76171.201218, 76180.344777, 76189.488444, 76198.632217, 76207.776097, 76216.920084, 76226.064177, 
+   76235.208378, 76244.352685, 76253.497100, 76262.641621, 76271.786248, 76280.930983, 76290.075824, 76299.220773, 
+   76308.365828, 76317.510989, 76326.656258, 76335.801633, 76344.947114, 76354.092703, 76363.238398, 76372.384200, 
+   76381.530108, 76390.676124, 76399.822245, 76408.968474, 76418.114809, 76427.261251, 76436.407799, 76445.554454, 
+   76454.701215, 76463.848083, 76472.995057, 76482.142138, 76491.289326, 76500.436620, 76509.584021, 76518.731528, 
+   76527.879141, 76537.026861, 76546.174688, 76555.322621, 76564.470660, 76573.618806, 76582.767058, 76591.915417, 
+   76601.063882, 76610.212453, 76619.361131, 76628.509915, 76637.658805, 76646.807802, 76655.956905, 76665.106114, 
+   76674.255430, 76683.404852, 76692.554380, 76701.704015, 76710.853755, 76720.003602, 76729.153556, 76738.303615, 
+   76747.453781, 76756.604052, 76765.754431, 76774.904915, 76784.055505, 76793.206202, 76802.357004, 76811.507913, 
+   76820.658928, 76829.810049, 76838.961276, 76848.112609, 76857.264049, 76866.415594, 76875.567245, 76884.719003, 
+   76893.870866, 76903.022836, 76912.174911, 76921.327092, 76930.479380, 76939.631773, 76948.784273, 76957.936878, 
+   76967.089589, 76976.242406, 76985.395330, 76994.548359, 77003.701493, 77012.854734, 77022.008081, 77031.161533, 
+   77040.315092, 77049.468756, 77058.622526, 77067.776402, 77076.930383, 77086.084471, 77095.238664, 77104.392963, 
+   77113.547368, 77122.701878, 77131.856495, 77141.011216, 77150.166044, 77159.320977, 77168.476017, 77177.631161, 
+   77186.786412, 77195.941768, 77205.097229, 77214.252797, 77223.408470, 77232.564248, 77241.720133, 77250.876122, 
+   77260.032218, 77269.188419, 77278.344725, 77287.501137, 77296.657655, 77305.814278, 77314.971006, 77324.127840, 
+   77333.284780, 77342.441825, 77351.598976, 77360.756232, 77369.913593, 77379.071060, 77388.228632, 77397.386310, 
+   77406.544093, 77415.701982, 77424.859976, 77434.018075, 77443.176279, 77452.334589, 77461.493005, 77470.651525, 
+   77479.810151, 77488.968883, 77498.127719, 77507.286661, 77516.445708, 77525.604860, 77534.764118, 77543.923481, 
+   77553.082949, 77562.242522, 77571.402200, 77580.561984, 77589.721873, 77598.881867, 77608.041966, 77617.202170, 
+   77626.362480, 77635.522894, 77644.683414, 77653.844039, 77663.004769, 77672.165604, 77681.326544, 77690.487589, 
+   77699.648739, 77708.809994, 77717.971354, 77727.132819, 77736.294390, 77745.456065, 77754.617845, 77763.779730, 
+   77772.941720, 77782.103815, 77791.266015, 77800.428320, 77809.590730, 77818.753245, 77827.915864, 77837.078589, 
+   77846.241418, 77855.404353, 77864.567392, 77873.730536, 77882.893784, 77892.057138, 77901.220596, 77910.384160, 
+   77919.547828, 77928.711600, 77937.875478, 77947.039460, 77956.203547, 77965.367739, 77974.532035, 77983.696436, 
+   77992.860942, 78002.025553, 78011.190268, 78020.355088, 78029.520012, 78038.685041, 78047.850175, 78057.015414, 
+   78066.180757, 78075.346204, 78084.511756, 78093.677413, 78102.843174, 78112.009040, 78121.175011, 78130.341086, 
+   78139.507265, 78148.673549, 78157.839938, 78167.006431, 78176.173028, 78185.339730, 78194.506536, 78203.673447, 
+   78212.840462, 78222.007582, 78231.174806, 78240.342135, 78249.509568, 78258.677105, 78267.844746, 78277.012492, 
+   78286.180343, 78295.348297, 78304.516356, 78313.684520, 78322.852787, 78332.021159, 78341.189635, 78350.358216, 
+   78359.526900, 78368.695689, 78377.864583, 78387.033580, 78396.202682, 78405.371887, 78414.541197, 78423.710612, 
+   78432.880130, 78442.049753, 78451.219479, 78460.389310, 78469.559245, 78478.729284, 78487.899427, 78497.069675, 
+   78506.240026, 78515.410481, 78524.581041, 78533.751704, 78542.922472, 78552.093344, 78561.264319, 78570.435399, 
+   78579.606583, 78588.777870, 78597.949262, 78607.120757, 78616.292357, 78625.464060, 78634.635868, 78643.807779, 
+   78652.979794, 78662.151914, 78671.324137, 78680.496464, 78689.668894, 78698.841429, 78708.014068, 78717.186810, 
+   78726.359656, 78735.532606, 78744.705660, 78753.878817, 78763.052079, 78772.225444, 78781.398913, 78790.572485, 
+   78799.746162, 78808.919942, 78818.093826, 78827.267813, 78836.441905, 78845.616100, 78854.790398, 78863.964800, 
+   78873.139306, 78882.313916, 78891.488629, 78900.663446, 78909.838366, 78919.013390, 78928.188518, 78937.363749, 
+   78946.539084, 78955.714522, 78964.890064, 78974.065710, 78983.241458, 78992.417311, 79001.593267, 79010.769326, 
+   79019.945489, 79029.121756, 79038.298125, 79047.474599, 79056.651175, 79065.827856, 79075.004639, 79084.181526, 
+   79093.358517, 79102.535610, 79111.712808, 79120.890108, 79130.067512, 79139.245019, 79148.422630, 79157.600344, 
+   79166.778161, 79175.956081, 79185.134105, 79194.312232, 79203.490462, 79212.668796, 79221.847233, 79231.025773, 
+   79240.204416, 79249.383163, 79258.562012, 79267.740965, 79276.920021, 79286.099181, 79295.278443, 79304.457809, 
+   79313.637277, 79322.816849, 79331.996524, 79341.176302, 79350.356183, 79359.536168, 79368.716255, 79377.896445, 
+   79387.076739, 79396.257135, 79405.437635, 79414.618237, 79423.798943, 79432.979751, 79442.160663, 79451.341678, 
+   79460.522795, 79469.704016, 79478.885339, 79488.066765, 79497.248295, 79506.429927, 79515.611662, 79524.793500, 
+   79533.975441, 79543.157485, 79552.339631, 79561.521881, 79570.704233, 79579.886688, 79589.069246, 79598.251907, 
+   79607.434671, 79616.617537, 79625.800506, 79634.983578, 79644.166753, 79653.350030, 79662.533410, 79671.716893, 
+   79680.900479, 79690.084167, 79699.267958, 79708.451852, 79717.635849, 79726.819948, 79736.004149, 79745.188454, 
+   79754.372861, 79763.557370, 79772.741982, 79781.926697, 79791.111515, 79800.296435, 79809.481457, 79818.666582, 
+   79827.851810, 79837.037140, 79846.222573, 79855.408108, 79864.593746, 79873.779486, 79882.965329, 79892.151274, 
+   79901.337322, 79910.523472, 79919.709725, 79928.896080, 79938.082537, 79947.269097, 79956.455759, 79965.642524, 
+   79974.829391, 79984.016360, 79993.203432, 80002.390606, 80011.577882, 80020.765261, 80029.952742, 80039.140326, 
+   80048.328011, 80057.515799, 80066.703690, 80075.891682, 80085.079777, 80094.267974, 80103.456273, 80112.644675, 
+   80121.833178, 80131.021784, 80140.210492, 80149.399302, 80158.588215, 80167.777229, 80176.966346, 80186.155565, 
+   80195.344886, 80204.534309, 80213.723834, 80222.913462, 80232.103191, 80241.293023, 80250.482956, 80259.672992, 
+   80268.863130, 80278.053369, 80287.243711, 80296.434155, 80305.624700, 80314.815348, 80324.006098, 80333.196950, 
+   80342.387903, 80351.578959, 80360.770116, 80369.961376, 80379.152737, 80388.344201, 80397.535766, 80406.727433, 
+   80415.919202, 80425.111073, 80434.303045, 80443.495120, 80452.687296, 80461.879575, 80471.071955, 80480.264437, 
+   80489.457020, 80498.649706, 80507.842493, 80517.035382, 80526.228373, 80535.421465, 80544.614659, 80553.807955, 
+   80563.001353, 80572.194852, 80581.388453, 80590.582156, 80599.775960, 80608.969866, 80618.163874, 80627.357984, 
+   80636.552195, 80645.746507, 80654.940921, 80664.135437, 80673.330055, 80682.524774, 80691.719594, 80700.914516, 
+   80710.109540, 80719.304665, 80728.499892, 80737.695220, 80746.890650, 80756.086181, 80765.281814, 80774.477548, 
+   80783.673384, 80792.869321, 80802.065360, 80811.261500, 80820.457741, 80829.654084, 80838.850528, 80848.047074, 
+   80857.243721, 80866.440469, 80875.637319, 80884.834270, 80894.031323, 80903.228476, 80912.425732, 80921.623088, 
+   80930.820546, 80940.018105, 80949.215765, 80958.413527, 80967.611390, 80976.809354, 80986.007419, 80995.205586, 
+   81004.403853, 81013.602222, 81022.800693, 81031.999264, 81041.197937, 81050.396710, 81059.595585, 81068.794561, 
+   81077.993638, 81087.192817, 81096.392096, 81105.591477, 81114.790958, 81123.990541, 81133.190225, 81142.390010, 
+   81151.589896, 81160.789883, 81169.989971, 81179.190160, 81188.390450, 81197.590841, 81206.791333, 81215.991926, 
+   81225.192620, 81234.393415, 81243.594311, 81252.795307, 81261.996405, 81271.197604, 81280.398904, 81289.600304, 
+   81298.801805, 81308.003408, 81317.205111, 81326.406915, 81335.608820, 81344.810826, 81354.012932, 81363.215140, 
+   81372.417448, 81381.619857, 81390.822367, 81400.024977, 81409.227689, 81418.430501, 81427.633413, 81436.836427, 
+   81446.039541, 81455.242756, 81464.446072, 81473.649489, 81482.853006, 81492.056624, 81501.260342, 81510.464161, 
+   81519.668081, 81528.872102, 81538.076223, 81547.280444, 81556.484767, 81565.689189, 81574.893713, 81584.098337, 
+   81593.303062, 81602.507887, 81611.712813, 81620.917839, 81630.122966, 81639.328193, 81648.533521, 81657.738949, 
+   81666.944478, 81676.150107, 81685.355837, 81694.561667, 81703.767598, 81712.973629, 81722.179761, 81731.385992, 
+   81740.592325, 81749.798758, 81759.005291, 81768.211924, 81777.418658, 81786.625492, 81795.832427, 81805.039462, 
+   81814.246597, 81823.453833, 81832.661168, 81841.868605, 81851.076141, 81860.283778, 81869.491515, 81878.699352, 
+   81887.907290, 81897.115327, 81906.323465, 81915.531703, 81924.740042, 81933.948480, 81943.157019, 81952.365658, 
+   81961.574397, 81970.783236, 81979.992176, 81989.201215, 81998.410355, 82007.619595, 82016.828935, 82026.038374, 
+   82035.247915, 82044.457555, 82053.667295, 82062.877135, 82072.087075, 82081.297116, 82090.507256, 82099.717496, 
+   82108.927837 
+  }; 
+
+
+const int kProtAlphabet = 2;   /**< identifies protein alphabet (FIXME: needed?). */
+
+
+
+/** Information about the alphabet used by seg.
+ *  For proteins this version of seg uses ncbistdaa,
+ *  This keeps track of those.
+ */
+typedef struct Alpha
+  {
+   int32_t alphabet;              /**< which alphabet, kProtAlphabet for proteins. */
+   int32_t alphasize;             /**< size of above alphabet. */
+   double lnalphasize;         /**< nat. log of size of above alphabet. */
+   int32_t* alphaindex;           /**< value in ncbistdaa. */
+   unsigned char* alphaflag;   /**< array of bools to indicate that letter is (not) valid?? */
+  } Alpha;
+
+
+/** General sequence information */
+typedef struct SSequence
+  {
+   struct SSequence* parent;   /**< SSequence window that encompasses the current one */
+   char* seq;                  /**< sequence in ncbistdaa. */
+   Alpha* palpha;              /**< alphabet information */
+   int32_t start;                 /**< starting offset to seg. */
+   int32_t length;                /**< Length of sequence to be segged. */
+   int32_t bogus;                 /**< tracks number of non-allowed residues (e.g., X) */
+   bool punctuation;        /**< FIXME: always false, never set to true? */
+   int32_t* composition;          /**< totals number of each type of residue */
+   int32_t* state;                /**< "state vector as described on pg. 151 of Wootton and Federhen
+                                  (Comput. Chem. 17, 149 (1993)).  Tracks number of each residue, 
+                                  like composition, but without gaps in array. */
+   double entropy;             /**< entropy of what this array refers to. */
+} SSequence;
+
+/** List of sequence segments (hits) */
+typedef struct SSeg
+  {
+   int begin;          /**< beginning of segment (hit). */
+   int end;            /**< end of segment (hit). */
+   struct SSeg *next;  /**< next object in linked list */
+  } SSeg;
+
+/** Initializes SSequence structure */
+static SSequence* 
+s_SSequenceNew(void)
+{
+   SSequence* seq;
+
+   seq = (SSequence*) calloc(1, sizeof(SSequence));
+   if (seq==NULL)
+     {
+      /* raise error flag and etc. */
+      return(seq);
+     }
+
+   seq->parent = (SSequence*) NULL;
+   seq->seq = (char*) NULL;
+   seq->palpha = (Alpha*) NULL;
+   seq->start = seq->length = 0;
+   seq->bogus = seq->punctuation = false;
+   seq->composition = seq->state = (int32_t*) NULL;
+   seq->entropy = (double) 0.0;
+
+   return(seq);
+}
+
+/*------------------------------------------------------------(AlphaFree)---*/
+
+/** Frees the Alpha structure and underlying structures.
+ * @param palpha the object to be freed [in]
+ */
+static void 
+s_AlphaFree (Alpha* palpha)
+
+  {
+   if (!palpha) return;
+
+   sfree (palpha->alphaindex);
+   sfree (palpha->alphaflag);
+   sfree (palpha);
+
+   return;
+ }
+
+/*--------------------------------------------------------------(SSequenceFree)---*/
+
+/** Frees the SSequence structure and the underlying structure
+ * @param seq the object to be freed [in]
+ */
+static void 
+s_SSequenceFree(SSequence* seq)
+{
+   if (seq==NULL) return;
+
+   sfree(seq->seq);
+   s_AlphaFree(seq->palpha);
+   sfree(seq->composition);
+   sfree(seq->state);
+   sfree(seq);
+   return;
+}
+
+/*--------------------------------------------------------------(SSegFree)---*/
+
+/** Frees the SSeg structure
+ * @param seg the object to be freed [in]
+ */
+static void 
+s_SegFree(SSeg* seg)
+{
+   SSeg* nextseg;
+
+   while (seg)
+     {
+      nextseg = seg->next;
+      sfree(seg);
+      seg = nextseg;
+     }
+
+   return;
+}
+
+/*--------------------------------------------------------------(hasdash)---*/
+
+/** Checks if sequence contains a dash.
+ * @param win SSequence structure for a piece of a sequence [in]
+ * @return true if dash is found in the sequence, otherwise false [in]
+ */
+static bool
+s_HasDash(SSequence* win)
+{
+	char	*seq, *seqmax;
+
+	seq = win->seq;
+	seqmax = seq + win->length;
+
+	while (seq < seqmax) {
+		if (*seq++ == '-')
+			return true;
+	}
+	return false;
+}
+
+/*------------------------------------------------------------(state_cmp)---*/
+
+/** State comparison function */
+static int 
+s_StateCmp(const void* s1, const void* s2)
+{
+	int *np1, *np2;
+
+	np1 = (int *) s1;
+	np2 = (int *) s2;
+
+	return (*np2 - *np1);
+}
+
+/*---------------------------------------------------------------(compon)---*/
+
+/** Calculates sequence composition array values. 
+ * @param win the object to be analyzed [in]
+ */
+static void 
+s_CompOn(SSequence* win)
+
+{
+	int32_t* comp;
+	int32_t letter;
+	char* seq,* seqmax;
+        int32_t* alphaindex;
+        unsigned char* alphaflag;
+        int32_t alphasize;
+
+        alphasize = win->palpha->alphasize;
+        alphaindex = win->palpha->alphaindex;
+        alphaflag = win->palpha->alphaflag;
+
+	win->composition = comp =
+                (int32_t*) calloc(alphasize, sizeof(int32_t));
+	seq = win->seq;
+	seqmax = seq + win->length;
+
+	while (seq < seqmax) {
+		letter = *seq++;
+		if (!alphaflag[letter])
+			comp[alphaindex[letter]]++;
+                else 
+                        win->bogus++;
+	}
+
+	return;
+}
+
+/*--------------------------------------------------------------(stateon)---*/
+
+/** Calculates state array values 
+ * @param win the object to be analyzed [in]
+ */
+static void 
+s_StateOn(SSequence* win)
+
+{
+	int32_t letter, nel, c;
+        int32_t alphasize;
+
+        alphasize = win->palpha->alphasize;
+
+	if (win->composition == NULL)
+		s_CompOn(win);
+
+	win->state = (int32_t*) calloc((alphasize+1), sizeof(win->state[0]));
+
+	for (letter = nel = 0; letter < alphasize; ++letter) {
+		if ((c = win->composition[letter]) == 0)
+			continue;
+		win->state[nel++] = c;
+	}
+	for (letter = nel; letter < alphasize+1; ++letter)
+		win->state[letter] = 0;
+
+	qsort(win->state, nel, sizeof(win->state[0]), s_StateCmp);
+
+	return;
+}
+
+/*--------------------------------------------------------------(s_OpenWin)---*/
+
+/** Initializes an SSequence structure for part of sequence contained in a
+ * window.
+ * @param parent Parent (whole) sequence [in]
+ * @param start Window start in parent [in]
+ * @param length Window length in parent [in]
+ * @return Pointer to the resulting SSequence structure.
+ */
+static SSequence* 
+s_OpenWin(SSequence* parent, int32_t start, int32_t length)
+{
+   SSequence* win;
+
+   if (start<0 || length<0 || start+length>parent->length)
+     {
+      return((SSequence*) NULL);
+     }
+
+      win = (SSequence*) calloc(1, sizeof(SSequence));
+
+/*---                                          ---[set links, up and down]---*/
+
+      win->parent = parent;
+      win->palpha = parent->palpha;
+
+/*---                          ---[install the local copy of the sequence]---*/
+
+      win->start = start;
+      win->length = length;
+	win->seq = parent->seq + start;
+
+        win->bogus = 0;
+	win->punctuation = false;
+
+	win->entropy = -2.;
+	win->state = (int32_t*) NULL;
+	win->composition = (int32_t*) NULL;
+
+	s_StateOn(win);
+
+	return win;
+}
+
+/*--------------------------------------------------------------(s_Entropy)---*/
+
+/** Calculates entropy of an integer array 
+ * @param sv array to be analyzed [in]
+ * @return the entropy
+ */
+static double 
+s_Entropy(int32_t* sv)
+{
+   double ent;
+   int32_t i, total;
+
+   total = 0;
+   for (i=0; sv[i]!=0; i++)
+     {
+      total += sv[i];
+     }
+   if (total==0) return(0.);
+
+   ent = 0.0;
+   for (i=0; sv[i]!=0; i++)
+     {
+      ent += ((double)sv[i])*log(((double)sv[i])/(double)total)/NCBIMATH_LN2;
+     }
+
+   ent = fabs(ent/(double)total);
+
+   return(ent);
+}
+
+/*----------------------------------------------------------(decrementsv)---*/
+
+
+
+/** Decrements the value in the int32_t array for every element that matches class.
+ * There is also another criteria that the next element must have a vlaue
+ * less than class.
+ * @param sv the array to be examined and decremented [in|out]
+ * @param class criteria for decrementing an element [in]
+ */
+static void 
+s_DecrementSV(int32_t* sv, int32_t cl)
+
+{
+	int32_t	svi;
+
+	while ((svi = *sv++) != 0) {
+		if (svi == cl && *sv < cl) {
+			sv[-1] = svi - 1;
+			break;
+		}
+	}
+}
+
+/** Increments the value in the int32_t array for every element that matches class.
+ * @param sv the array to be examined and incremented [in|out]
+ * @param class criteria for incrementing an element [in]
+ */
+static void 
+s_IncrementSV(int32_t* sv, int32_t cl)
+
+{
+	for (;;) {
+		if (*sv++ == cl) {
+			sv[-1]++;
+			break;
+		}
+	}
+}
+
+/** Moves over the "window" of sequence seg is currently working on.
+ *
+ * @param win object to be operated on [in]
+ * @return false if nothing done, true otherwise
+ */
+
+static bool
+s_ShiftWin1(SSequence* win)
+{
+	int32_t j, length;
+	int32_t* comp;
+        int32_t* alphaindex;
+        unsigned char* alphaflag;
+
+	length = win->length;
+	comp = win->composition;
+        alphaindex = win->palpha->alphaindex;
+        alphaflag = win->palpha->alphaflag;
+
+	if ((++win->start + length) > win->parent->length) {
+		--win->start;
+		return false;
+	}
+
+	if (!alphaflag[j = win->seq[0]])
+		s_DecrementSV(win->state, comp[alphaindex[j]]--);
+        else win->bogus--;
+
+	j = win->seq[length];
+	++win->seq;
+
+	if (!alphaflag[j])
+		s_IncrementSV(win->state, comp[alphaindex[j]]++);
+        else win->bogus++;
+
+	if (win->entropy > -2.)
+		win->entropy = s_Entropy(win->state);
+
+	return true;
+}
+
+/*-------------------------------------------------------------(closewin)---*/
+
+/** Frees the SSequence structure corresponding to a sequence window 
+ * Does not free palpha like s_SSequenceFree (two functions needed?).
+ * @param win object to be freed
+ */
+static void 
+s_CloseWin(SSequence* win)
+{
+   if (win==NULL) return;
+
+   if (win->state!=NULL)       sfree(win->state);
+   if (win->composition!=NULL) sfree(win->composition);
+
+   sfree(win);
+   return;
+}
+
+/*----------------------------------------------------------------(enton)---*/
+
+/** Calculates entropy of a sequence window 
+ * @param win object to be analyzed [in]
+ */
+static void 
+s_EntropyOn(SSequence* win)
+
+  {
+   if (win->state==NULL) {s_StateOn(win);}
+
+   win->entropy = s_Entropy(win->state);
+
+   return;
+  }
+
+/** Calculates entropy for a given sequence and window
+ * 
+ * @param seq Sequence to examine [in]
+ * @param window amount of sequence to examine at once [in]
+ * @param maxbogus limit on non-allowed (e.g., X) characters [in]
+ * @return calculated entropy
+ */
+static double* 
+s_SeqEntropy(SSequence* seq, int32_t window, int32_t maxbogus)
+{
+   SSequence* win;
+   double* H;
+   int32_t i, first, last, downset, upset;
+
+   downset = (window+1)/2 - 1;
+   upset = window - downset;
+
+   if (window>seq->length)
+     {
+      return((double*) NULL);
+     }
+
+   H = (double*) calloc(seq->length, sizeof(double));
+
+   for (i=0; i<seq->length; i++)
+     {
+      H[i] = -1.;
+     }
+
+   win = s_OpenWin(seq, 0, window);
+   s_EntropyOn(win);
+
+   first = downset;
+   last = seq->length - upset;
+
+   for (i=first; i<=last; i++)
+     {
+      if (seq->punctuation && s_HasDash(win))
+        {
+         H[i] = -1.;
+         s_ShiftWin1(win);
+         continue;
+        }
+      if (win->bogus > maxbogus)
+        {
+         H[i] = -1.;
+         s_ShiftWin1(win);
+         continue;
+        }
+      H[i] = win->entropy;
+      s_ShiftWin1(win);
+     }
+
+   s_CloseWin(win);
+   return(H);
+}
+
+/*---------------------------------------------------------------(s_FindLow)---*/
+
+/** Finds the first element above hicut, looks from i to limit.
+ * @param i first element to check [in]
+ * @param limit last element to check [in]
+ * @param hicut value to check for [in]
+ * @param H the array to check.
+ * @return index of last element with value below hicut
+ */
+
+static int32_t s_FindLow(int32_t i, int32_t limit, double hicut, double* H)
+
+  {
+   int32_t j;
+
+   for (j=i; j>=limit; j--)
+     {
+      if (H[j]==-1.0) break;
+      if (H[j]>hicut) break;
+     }
+
+   return(j+1);
+  }
+
+/*---------------------------------------------------------------(s_FindHigh)---*/
+
+/** Finds the last element below hicut, looks from i to limit.
+ * @param i first element to check [in]
+ * @param limit last element to check [in]
+ * @param hicut value to check for [in]
+ * @param H the array to check.
+ * @return index of last element with value below hicut
+ */
+static int32_t s_FindHigh(int32_t i, int32_t limit, double hicut, double* H)
+
+  {
+   int32_t j;
+
+   for (j=i; j<=limit; j++)
+     {
+      if (H[j]==-1.0) break;
+      if (H[j]>hicut) break;
+     }
+
+   return(j-1);
+  }
+
+/** calculate log(n!) using either tabulated data or Sterling's formula
+ * @param n [in]
+ * @return log(n!)
+ */
+static double
+s_lnfact(uint32_t n) {
+  if (n < sizeof(lnfact)/sizeof(*lnfact))
+     return lnfact[n];
+  else return ((n+0.5)*log(n) - n + 0.9189385332);
+}
+
+/** calculate "K2" entropy per equation 3 of Wootton and Federhen
+ * (Comput. Chem. 17, 149 (1993).
+ * @param sv state vector [in]
+ * @param window_length length of window being examined
+ * @return K2
+ */ 
+static double 
+s_LnPerm(const int32_t* sv, int32_t window_length)
+
+  {
+   double ans;
+   int32_t i;
+
+   ans = s_lnfact(window_length);
+
+   for (i=0; sv[i]!=0; i++) 
+     {
+      ans -= s_lnfact(sv[i]);
+     }
+
+   return(ans);
+  }
+
+
+/** Calculates natural log of "Farben" which is the number of compositions
+ * in any complexity state.  See equation 1 of Wootton and Federhen
+ * (Comput. Chem. 17, 149 (1993)).
+ * @param sv state vector [in]
+ * @param alphasize total letters in alphabet [in]
+ * @return number of compositions as described above
+ */
+static double 
+s_LnAss(const int32_t* sv, int32_t alphasize)
+
+{
+	double	ans;
+	int	svi, svim1;
+	int	cl, total;
+	int    i;
+
+	ans = lnfact[alphasize];
+	if (sv[0] == 0)
+		return ans;
+
+	total = alphasize;
+	cl = 1;
+	svi = *sv;
+	svim1 = sv[0];
+	for (i=0;; svim1 = svi) {
+	        if (++i==alphasize) {
+		        ans -= s_lnfact(cl);
+			break;
+		      }
+		else if ((svi = *++sv) == svim1) {
+			cl++;
+			continue;
+		}
+		else {
+			total -= cl;
+			ans -= s_lnfact(cl);
+			if (svi == 0) {
+				ans -= s_lnfact(total);
+				break;
+			}
+			else {
+				cl = 1;
+				continue;
+			}
+		}
+	}
+
+	return ans;
+}
+
+
+/** This function calculates the natural log of the value P sub 0 from 
+ * equation 3 of Wootton and Federhen (Methods Enzymol. 1996;266:554-71).
+ * @param sv state vector [in]
+ * @param total window length of area examined [in]
+ * @param palpha structure for alphabet information [in]
+ * @return log of P sub 0 as mentioned above
+ */
+static double 
+s_GetProb(const int32_t* sv, int32_t total, const Alpha* palpha)
+
+  {
+   double ans, ans1, ans2 = 0, totseq;
+
+   totseq = ((double) total) * palpha->lnalphasize;
+
+   ans1 = s_LnAss(sv, palpha->alphasize);
+   if (ans1 > -100000.0 && sv[0] != std::numeric_limits<int32_t>::min())
+   {
+	ans2 = s_LnPerm(sv, total);
+   }
+   else
+   {
+#ifdef ERR_POST_EX_DEFINED
+        ErrPostEx (SEV_ERROR, 0, 0, "Illegal value returned by s_LnAss");
+#endif
+   }
+   ans = ans1 + ans2 - totseq;
+
+   return ans;
+  }
+
+/** Trims view of sequence so as to minimize the probability returned by s_GetProb
+ * @param seq the part of sequence to be examined [in]
+ * @param leftend left-most end of sequence [in|out]
+ * @param rightend right-most end of sequence [in|out]
+ * @param sparamsp the SEG parameters [in]
+ */
+static int16_t
+s_Trim(SSequence* seq, int32_t* leftend, int32_t* rightend, const SegParameters* sparamsp)
+
+{
+   double prob, minprob;
+   int32_t len;
+   int32_t lend, rend;
+   int32_t minlen;
+   int32_t maxtrim;
+   int16_t status = 0;
+
+   lend = 0;
+   rend = seq->length - 1;
+   minlen = 1;
+   maxtrim = sparamsp->maxtrim;
+   if ((seq->length-maxtrim)>minlen) 
+        minlen = seq->length-maxtrim;
+
+   minprob = 1.;
+   for (len=seq->length; len>minlen; len--)
+   {
+      bool shift = true;
+      int32_t i = 0;
+      SSequence* win = s_OpenWin(seq, 0, len);
+
+      while (shift)
+      {
+         prob = s_GetProb(win->state, len, win->palpha);
+         if (prob<minprob)
+         {
+            minprob = prob;
+            lend = i;
+            rend = len + i - 1;
+         }
+         shift = s_ShiftWin1(win);
+         i++;
+      }
+      s_CloseWin(win);
+   }
+
+   *leftend = *leftend + lend;
+   *rightend = *rightend - (seq->length - rend - 1);
+
+   s_CloseWin(seq);
+   return status;
+}
+
+/** High-level function to perform calculations to find 
+ * low-complexity segments.  Thi function calls itself 
+ * recursively
+ * 
+ * @param seq sequence to be checked [in]
+ * @param sparamsp seg parameters [in]
+ * @param segs low-complexity segments found [out]
+ * @param offset offset of sequence passed in [in]
+ */
+static int16_t
+s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg **segs,
+                   int32_t offset)
+{
+   SSeg* seg = (SSeg*) NULL;
+   int32_t window;
+   double locut, hicut;
+   int32_t downset, upset;
+   int32_t first, last, lowlim;
+   int32_t i;
+   int32_t leftend, rightend;
+   double* H;
+   int16_t status = 0;
+
+   if (sparamsp->window<=0) return status;
+   if (sparamsp->locut<=0.) sparamsp->locut = 0.;
+   if (sparamsp->hicut<=0.) sparamsp->hicut = 0.;
+
+   window = sparamsp->window;
+   locut = sparamsp->locut;
+   hicut = sparamsp->hicut;
+   downset = (window+1)/2 - 1;
+   upset = window - downset;
+      
+   H = s_SeqEntropy(seq, window, sparamsp->maxbogus);
+
+   if (H == NULL) 
+      return status;
+
+   first = downset;
+   last = seq->length - upset;
+   lowlim = first;
+
+   for (i=first; i<=last; i++)
+   {
+      if (H[i] <= locut && H[i] != -1.0)
+        {
+         int32_t loi = s_FindLow(i, lowlim, hicut, H);
+         int32_t hii = s_FindHigh(i, last, hicut, H);
+         SSequence* temp_seq = NULL;
+
+         leftend = loi - downset;
+         rightend = hii + upset - 1;
+
+         temp_seq = s_OpenWin(seq, leftend, rightend-leftend+1);
+         status = s_Trim(temp_seq, &leftend, &rightend, sparamsp);
+
+         if (status < 0) {
+             s_CloseWin(temp_seq);
+             break;
+         }
+
+         if (i+upset-1<leftend)   /* check for trigger window in left trim */
+         {
+            int32_t lend = loi - downset;
+            int32_t rend = leftend - 1;
+
+            SSequence* leftseq = s_OpenWin(seq, lend, rend-lend+1);
+            SSeg *leftsegs = (SSeg*) NULL;
+            status = s_SegSeq(leftseq, sparamsp, &leftsegs, offset+lend);
+            if (status < 0)
+              return status;
+
+            /* prepend here, order will be restored in s_SegToSeqLoc */
+            if (leftsegs!=NULL)
+            {
+               leftsegs->next = *segs;
+               *segs = leftsegs;
+            }
+            s_CloseWin(leftseq);
+
+         }
+
+         seg = (SSeg*) calloc(1, sizeof(SSeg));
+         seg->begin = leftend + offset;
+         seg->end = rightend + offset;
+         seg->next = *segs;
+         *segs = seg;
+         i = std::min(hii, rightend+downset);
+         lowlim = i + 1;
+        }
+   }
+   sfree(H);
+   return status;
+}
+
+/*------------------------------------------------------------(mergesegs)---*/
+/** merge together overlapping segments, 
+ * hilenmin also does something, but we need to ask Scott Federhen what?
+ * @param seq information about sequence [in]
+ * @param segs segment information [in]
+*/
+static void 
+s_MergeSegs(SSequence* seq, SSeg* segs)
+{
+   SSeg* seg,* nextseg;
+   int32_t hilenmin;              /* hilenmin yet unset */
+
+   hilenmin = 0;               /* hilenmin - temporary default */
+
+   if (segs==NULL) return;
+
+   if (seq->length -1 - segs->end < hilenmin) 
+       segs->end = seq->length -1;
+
+   seg = segs;
+   nextseg = seg->next;
+
+   while (nextseg!=NULL) {
+      if (seg->begin - nextseg->end - 1 < hilenmin) {
+         if (seg->end < nextseg->end) seg->end = nextseg->end;
+         if (seg->begin > nextseg->begin) seg->begin = nextseg->begin;
+         seg->next = nextseg->next;
+         sfree(nextseg);
+      } else {
+         seg = nextseg;
+      }
+      nextseg = seg->next;
+   }
+
+   if (seg->begin < hilenmin) seg->begin = 0;
+
+   return;
+}
+
+/** Converts the internal representation used by seg to that used by BLAST
+ *
+ * @param segs internal representation [in]
+ * @param offset fixed value to add to offsets [in]
+ * @param seg_locs the new BLAST specific representation [out]
+ * @return 0 on success, -1 if memory allocation failed.
+ */
+static int16_t
+s_SegsToBlastSeqLoc(SSeg* segs, int32_t offset, BlastSeqLoc** seg_locs)
+{
+   for ( ; segs; segs = segs->next) {
+      BlastSeqLoc *loc = (BlastSeqLoc*) calloc(1, sizeof(BlastSeqLoc));
+      loc->ssr = (SSeqRange*) calloc(1,sizeof(SSeqRange));
+      loc->ssr->left = segs->begin + offset;
+      loc->ssr->right = segs->end  + offset;
+      loc->next = *seg_locs;
+      *seg_locs = loc;
+   }
+   /* If not all segs have been processed, it means that memory allocation 
+      failed, hence return error status. */
+   if (segs) {
+       *seg_locs = BlastSeqLocFree(*seg_locs);
+       return -1;
+   }
+
+   return 0;
+}
+
+/** Creats the Alphabet structure for standard protein alphabet. 
+ * @return pointer to the alphabet structure.
+ */
+static Alpha* 
+s_AA20alphaStd (void)
+{
+   Alpha* palpha;
+   int32_t* alphaindex;
+   unsigned char* alphaflag;
+   uint8_t c, i;
+   const int kCharSet = 128;
+   const double kLn20 = 2.9957322735539909;
+
+   palpha = (Alpha*) calloc(1, sizeof(Alpha));
+
+   palpha->alphabet = kProtAlphabet;
+   palpha->alphasize = 20;
+   palpha->lnalphasize = kLn20;
+
+   alphaindex = (int32_t*) calloc(kCharSet , sizeof(int32_t));
+   alphaflag = (unsigned char*) calloc(kCharSet , sizeof(char));
+
+   for (c=0, i=0; c<kCharSet; c++)
+     {
+        //if (c == 1 || (c >= 3 && c <= 20) || c == 22) {
+	   if (c < 20) {
+           alphaflag[c] = false;
+           alphaindex[c] = i; 
+           ++i;
+        } else {
+           alphaflag[c] = true; alphaindex[c] = 20;
+        }
+     }
+
+   palpha->alphaindex = alphaindex;
+   palpha->alphaflag = alphaflag;
+
+   return (palpha);
+}
+
+/* Comments in blast_seg.h */
+SegParameters* SegParametersNewAa (void)
+{
+   SegParameters* sparamsp;
+
+   sparamsp = (SegParameters*) calloc(1, sizeof(SegParameters));
+
+   sparamsp->window = kSegWindow;
+   sparamsp->locut = kSegLocut;
+   sparamsp->hicut = kSegHicut;
+   sparamsp->period = 1;
+   sparamsp->hilenmin = 0;
+   sparamsp->overlaps = false;
+   sparamsp->maxtrim = 50;
+   sparamsp->maxbogus = 2;
+
+   return (sparamsp);
+}
+
+/** Checks SeqParameter struct for proteins, sets default values if not set. 
+ * @param sparamsp parameters to check [in]
+ */
+static void 
+s_SegParametersCheck (SegParameters* sparamsp)
+{
+   if (!sparamsp) return;
+
+   if (sparamsp->window <= 0) sparamsp->window = 12;
+
+   if (sparamsp->locut < 0.0) sparamsp->locut = 0.0;
+
+   if (sparamsp->hicut < 0.0) sparamsp->hicut = 0.0;
+
+   if (sparamsp->locut > sparamsp->hicut)
+       sparamsp->hicut = sparamsp->locut;
+
+   if (sparamsp->maxbogus < 0)
+       sparamsp->maxbogus = 0;
+   if (sparamsp->maxbogus > sparamsp->window)
+       sparamsp->maxbogus = sparamsp->window;
+
+   if (sparamsp->period <= 0) sparamsp->period = 1;
+   if (sparamsp->maxtrim < 0) sparamsp->maxtrim = 0;
+
+   return;
+}
+
+/* Comments in blast_seg.h */
+void SegParametersFree(SegParameters* sparamsp)
+{
+   if (!sparamsp) 
+      return;
+   sfree(sparamsp);
+   return;
+}
+
+/* comments in blast_seg.h */
+int16_t SeqBufferSeg (uint8_t* sequence, uint32_t length, uint32_t offset,
+                     SegParameters* sparamsp, BlastSeqLoc** seg_locs)
+{
+   SSequence* seqwin;
+   SSeg* segs;
+   bool params_allocated = false;
+   int16_t status = 0;
+   
+   s_SegParametersCheck (sparamsp);
+   
+   /* check seg parameters */
+   if (!sparamsp) {
+      params_allocated = true;
+      sparamsp = SegParametersNewAa();
+      s_SegParametersCheck (sparamsp);
+      if (!sparamsp)
+         return -1;
+   }
+
+   /* make an old-style genwin sequence window object */
+    
+   seqwin = s_SSequenceNew();
+   seqwin->seq = (char*) sequence;
+   seqwin->length = length;
+   seqwin->palpha = s_AA20alphaStd();
+
+   *seg_locs = NULL;
+   
+   /* seg the sequence */
+   
+   segs = (SSeg*) NULL;
+   status = s_SegSeq (seqwin, sparamsp, &segs, 0);
+   if (status < 0)
+   {
+     seqwin->seq = NULL;
+     s_SSequenceFree (seqwin);
+     return status;
+   }
+
+   /* merge the segment if desired. */
+   if (sparamsp->overlaps)
+      s_MergeSegs(seqwin, segs);
+
+   /* convert segs to seqlocs */
+   s_SegsToBlastSeqLoc(segs, offset, seg_locs);   
+   
+   /* clean up & return */
+   seqwin->seq = NULL;
+   s_SSequenceFree (seqwin);
+   s_SegFree (segs);
+
+   if(params_allocated)
+       SegParametersFree(sparamsp);
+   
+   return 0;
+}
+
diff --git a/src/blast/blast_seg.h b/src/blast/blast_seg.h
new file mode 100644
index 0000000..a779d68
--- /dev/null
+++ b/src/blast/blast_seg.h
@@ -0,0 +1,77 @@
+/* $Id: blast_seg.h 114718 2007-11-28 15:52:56Z ivanov $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Ilya Dondoshansky
+ *
+ */
+
+/** @file blast_seg.h
+ * SEG filtering functions. @todo FIXME: should this be combined with
+ * blast_filter/dust? Needs doxygen documentation and comments
+ */
+
+#ifndef __BLAST_SEG__
+#define __BLAST_SEG__
+
+#include <stdint.h>
+#include "blast_def.h"
+
+/** Structure to hold parameters for seg search.
+ */
+typedef struct SegParameters
+  {
+   int32_t window;         /**< initial window size to trigger further work. */
+   double locut;        
+   double hicut;
+   int32_t period;
+   int32_t hilenmin;
+   bool overlaps;	/* merge overlapping pieces if TRUE. */
+   int32_t maxtrim;
+   int32_t maxbogus;
+  } SegParameters;
+
+/** Allocated SeqParameter struct for proteins and fills with default values.
+ * @return pointer to SegParameters
+ */
+SegParameters* SegParametersNewAa (void);
+
+/** Free SegParameters structure
+ * @param sparamsp object to be freed [in]
+ */
+void SegParametersFree(SegParameters* sparamsp);
+
+/** Runs seg on a protein sequence in ncbistdaa.
+ * @param sequence the protein residues in ncbistdaa [in]
+ * @param length number of redidues [in]
+ * @param offset amount to shift over resulting locations 
+ *    (if full sequence not passed in) [in]
+ * @param sparamsp the seg parameters created with SegParametersNewAa [in]
+ * @param seg_locs resulting locations for filtering [out]
+ * @return zero on success
+ */
+int16_t SeqBufferSeg (uint8_t* sequence, uint32_t length, uint32_t offset,
+                   SegParameters* sparamsp, BlastSeqLoc** seg_locs);
+
+#endif /* !__BLAST_FILTER__ */
diff --git a/src/blast/blast_stat.h b/src/blast/blast_stat.h
new file mode 100644
index 0000000..74b65d9
--- /dev/null
+++ b/src/blast/blast_stat.h
@@ -0,0 +1,861 @@
+/*  $Id: blast_stat.h 351770 2012-02-01 14:34:56Z maning $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Tom Madden
+ *
+ */
+
+/** @file blast_stat.h
+ * Definitions and prototypes used by blast_stat.c to calculate BLAST
+ * statistics. @todo FIXME: needs doxygen comments
+ */
+
+#ifndef ALGO_BLAST_CORE__BLAST_STAT__H
+#define ALGO_BLAST_CORE__BLAST_STAT__H
+
+#include "ncbitype.h"
+#include "ncbi_std.h"
+#include "raw_scoremat.h"
+#include "blast_message.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Defines for the matrix 'preferences' (as specified by S. Altschul).
+ * Used in arrays such as blosum45_prefs in blast_stat.c
+ */
+#define BLAST_MATRIX_NOMINAL 0   /**< acceptable values, not recommended. */
+#define BLAST_MATRIX_PREFERRED 1 /**< These value are preferred over others. */
+#define BLAST_MATRIX_BEST 2      /**< This is the best value, only one per matrix. */
+
+
+#define BLASTMAT_DIR "/usr/ncbi/blast/matrix" /**< Default location for blast databases. */
+
+/** callback to resolve the path to blast score matrices */
+typedef char* (*GET_MATRIX_PATH) (const char*, bool);
+
+/**
+  Structure to hold the Karlin-Altschul parameters.
+*/
+typedef struct Blast_KarlinBlk {
+      double   Lambda; /**< Lambda value used in statistics */
+      double   K; /**< K value used in statistics */
+      double   logK; /**< natural log of K value used in statistics */
+      double   H; /**< H value used in statistics */
+      double   paramC;  /**< for use in seed. */
+   } Blast_KarlinBlk;
+
+
+/**
+  Tabulated results for faster erfc(x) lookup.
+  erfc(x) = 1/2 + 1/sqrt(2*pi) * \int_0^x { exp(-y^2/2)} dy
+  erfc(-\inf) = 0.0
+  erfc(+\inf) = 1.0
+  The erfc(x) is tabulated in p with step h, starting from a to b
+*/
+typedef struct erfc_table {
+      double eps;
+      double a;  
+      double b;
+      Int4   N;
+      double h;
+      double *p;
+   } erfc_table;
+
+/**
+  Structure to hold the Gumbel parameters (for FSC).
+*/
+typedef struct Blast_GumbelBlk {
+      double  Lambda;    /**< the unscaled Lambda value */
+      double  C;
+      double  G;         /**< G is the total penalty for extension */
+      double  a;         /**< avg(L) = a     y + b    */
+      double  Alpha;     /**< var(L) = alpha y + beta */
+      double  Sigma;     /**< cov(L) = sigma y + tau  */
+      double  a_un;      /**< Ungapped a */
+      double  Alpha_un;  /**< Ungapped alpha */
+
+      double  b;         /**< 2*G*(a_un - a) */
+      double  Beta;      /**< 2*G*(alpha_un - alpha) */
+      double  Tau;       /**< 2*G*(alpha_un - Sigma) */
+
+      Int8 db_length;    /**< total length of database */
+
+      bool filled;    /**< flag indicate the values of gbp are prepared */
+      
+   } Blast_GumbelBlk;
+
+
+/********************************************************************
+
+   Structures relating to scoring or the BlastScoreBlk
+
+********************************************************************/
+
+#define BLAST_SCORE_MIN INT2_MIN   /**< minimum allowed score (for one letter comparison). */
+#define BLAST_SCORE_MAX INT2_MAX   /**< maximum allowed score (for one letter comparison). */
+
+
+/** Holds score frequencies used in calculation
+of Karlin-Altschul parameters for an ungapped search.
+*/
+typedef struct Blast_ScoreFreq {
+    Int4         score_min; /**< lowest allowed scores */
+    Int4         score_max; /**< highest allowed scores */
+    Int4         obs_min;   /**< lowest observed (actual) scores */
+    Int4         obs_max;   /**< highest observed (actual) scores */
+    double       score_avg; /**< average score, must be negative for local alignment. */
+    double*      sprob0;    /**< arrays for frequency of given score */
+    double*      sprob;     /**< arrays for frequency of given score, shifted down by score_min. */
+} Blast_ScoreFreq;
+
+/** Scoring matrix used in BLAST */
+typedef struct SBlastScoreMatrix {
+    int** data;         /**< actual scoring matrix data, stored in row-major
+                          form */
+    size_t ncols;       /**< number of columns */
+    size_t nrows;       /**< number of rows */
+    double* freqs;      /**< array of assumed matrix background frequencies -RMH-*/
+    double lambda;      /**< derived value of the matrix lambda -RMH- */
+} SBlastScoreMatrix;
+
+/** Scoring matrix data used in PSI-BLAST */
+typedef struct SPsiBlastScoreMatrix {
+    SBlastScoreMatrix* pssm;    /**< position-specific score matrix */
+    double** freq_ratios;       /**< PSSM's frequency ratios, dimensions are
+                                  specified in pssm data above */
+    Blast_KarlinBlk* kbp;       /**< Karlin-Altschul block associated with this
+                                  PSSM */
+} SPsiBlastScoreMatrix;
+
+/** Allocates a new SPsiBlastScoreMatrix structure of dimensions ncols by
+ * BLASTAA_SIZE.
+ * @param ncols number of columns (i.e.: query length) [in]
+ * @return NULL in case of memory allocation failure, else new
+ * SPsiBlastScoreMatrix structure
+ */
+NCBI_XBLAST_EXPORT
+SPsiBlastScoreMatrix*
+SPsiBlastScoreMatrixNew(size_t ncols);
+
+/** Deallocates a SPsiBlastScoreMatrix structure.
+ * @param matrix structure to deallocate [in]
+ * @return NULL
+ */
+NCBI_XBLAST_EXPORT
+SPsiBlastScoreMatrix*
+SPsiBlastScoreMatrixFree(SPsiBlastScoreMatrix* matrix);
+
+/** Structure used for scoring calculations.
+*/
+typedef struct BlastScoreBlk {
+   bool     protein_alphabet; /**< TRUE if alphabet_code is for a 
+protein alphabet (e.g., ncbistdaa etc.), FALSE for nt. alphabets. */
+   Uint1    alphabet_code; /**< NCBI alphabet code. */
+   Int2     alphabet_size;  /**< size of alphabet. */
+   Int2     alphabet_start;  /**< numerical value of 1st letter. */
+   char*    name;           /**< name of scoring matrix. */
+   ListNode*   comments;    /**< Comments about scoring matrix. */
+   SBlastScoreMatrix* matrix;   /**< scoring matrix data */
+   SPsiBlastScoreMatrix* psi_matrix;    /**< PSSM and associated data. If this
+                                         is not NULL, then the BLAST search is
+                                         position specific (i.e.: PSI-BLAST) */
+   bool  matrix_only_scoring;  /**< Score ungapped/gapped alignment only
+                                       using the matrix parameters and
+                                       with raw scores. Ignore 
+                                       penalty/reward and do not report 
+                                       Karlin-Altschul stats.  This is used
+                                       by the rmblastn program. -RMH- */
+   bool complexity_adjusted_scoring; /**< Use cross_match-like complexity
+                                           adjustment on raw scores. -RMH- */
+   Int4  loscore;   /**< Min.  substitution scores */
+   Int4  hiscore;   /**< Max. substitution scores */
+   Int4  penalty;   /**< penalty for mismatch in blastn. */
+   Int4  reward;    /**< reward for match in blastn. */
+        double  scale_factor; /**< multiplier for all cutoff and dropoff scores */
+   bool     read_in_matrix; /**< If TRUE, matrix is read in, otherwise
+               produce one from penalty and reward above. @todo should this be
+                an allowed way of specifying the matrix to use? */
+   Blast_ScoreFreq** sfp;  /**< score frequencies for scoring matrix. */
+   /* kbp & kbp_gap are ptrs that should be set to kbp_std, kbp_psi, etc. */
+   Blast_KarlinBlk** kbp;  /**< Karlin-Altschul parameters. Actually just a placeholder. */
+   Blast_KarlinBlk** kbp_gap; /**< K-A parameters for gapped alignments.  Actually just a placeholder. */
+   Blast_GumbelBlk* gbp;  /**< Gumbel parameters for FSC. */
+   /* Below are the Karlin-Altschul parameters for non-position based ('std')
+   and position based ('psi') searches. */
+   Blast_KarlinBlk **kbp_std,  /**< K-A parameters for ungapped alignments */
+                    **kbp_psi,       /**< K-A parameters for position-based alignments. */
+                    **kbp_gap_std,  /**< K-A parameters for std (not position-based) alignments */
+                    **kbp_gap_psi;  /**< K-A parameters for psi alignments. */
+   Blast_KarlinBlk*  kbp_ideal;  /**< Ideal values (for query with average database composition). */
+   Int4 number_of_contexts;   /**< Used by sfp and kbp, how large are these*/
+   Uint1*   ambiguous_res; /**< Array of ambiguous res. (e.g, 'X', 'N')*/
+   Int2     ambig_size, /**< size of array above. FIXME: not needed here? */
+         ambig_occupy;  /**< How many occupied? */
+   bool  round_down; /**< Score must be rounded down to nearest even score if odd. */
+} BlastScoreBlk;
+
+/** Scoring matrix data used for compressed protein alphabets */
+typedef struct SCompressedAlphabet {
+    Int4  compressed_alphabet_size;  /**< letters in the compressed alphabet */
+    SBlastScoreMatrix* matrix;    /**< score matrix */
+    Uint1* compress_table;  /**< translation table (AA->compressed)*/
+} SCompressedAlphabet;
+
+/** Allocate a new compressed alphabet and score matrix
+ * @param sbp Current score matrix information [in]
+ * @param compressed_alphabet_size Desired size of compressed
+ *                  alphabet (current choices are limited to 10 or 15) [in]
+ * @param scale_factor Score matrix entries are scaled by this value [in]
+ * @return the new alphabet, or NULL on failure
+ */
+NCBI_XBLAST_EXPORT
+SCompressedAlphabet*
+SCompressedAlphabetNew(BlastScoreBlk *sbp,
+                       Int4 compressed_alphabet_size, 
+                       double scale_factor);
+
+/** Free a compressed alphabet and score matrix
+ * @param alphabet The compressed alphabet structure
+ * @return Always NULL
+ */
+NCBI_XBLAST_EXPORT
+SCompressedAlphabet*
+SCompressedAlphabetFree(SCompressedAlphabet *alphabet);
+
+/** 
+Stores the letter frequency of a sequence or database.
+*/
+typedef struct Blast_ResFreq {
+    Uint1   alphabet_code;    /**< indicates alphabet. */
+    double* prob;       /**< letter probs, (possible) non-zero offset. */
+    double* prob0;            /**< probs, zero offset. */
+} Blast_ResFreq;
+
+/** 
+ * Check that score blk is valid, returns zero if it is.
+ * @param sbp ScoreBlk to check [in]
+ * @return zero if valid
+*/
+NCBI_XBLAST_EXPORT
+int BlastScoreBlkCheck(BlastScoreBlk* sbp);
+
+/**
+ *   Allocates and initializes BlastScoreBlk
+ * @param alphabet either BLASTAA_SEQ_CODE or BLASTNA_SEQ_CODE [in]
+ * @param number_of_contexts how many strands or sequences [in]
+ * @return BlastScoreBlk*
+*/
+NCBI_XBLAST_EXPORT
+BlastScoreBlk* BlastScoreBlkNew (Uint1 alphabet, Int4 number_of_contexts);
+
+/** Deallocates BlastScoreBlk as well as all associated structures.
+ * @param sbp BlastScoreBlk to be deallocated [in]
+ * @return NULL pointer.
+ */
+NCBI_XBLAST_EXPORT
+BlastScoreBlk* BlastScoreBlkFree (BlastScoreBlk* sbp);
+
+/** Set the ambiguous residue (e.g, 'N', 'X') in the BlastScoreBlk*.
+ *  Convert from ncbieaa to sbp->alphabet_code (i.e., ncbistdaa) first.
+ *
+ * @param sbp the object to be modified [in|out]
+ * @param ambiguous_res the residue to be set on the BlastScoreBlk
+ * @return zero on success, others on error
+ */
+NCBI_XBLAST_EXPORT
+Int2 BLAST_ScoreSetAmbigRes (BlastScoreBlk* sbp, char ambiguous_res);
+
+
+/** Calculate and fill the ungapped Karlin-Altschul parameters in the
+ * BlastScoreBlk structure (fields kbp_std, kbp_psi, and kbp of that structure).
+ * @param program BLAST program type, needed to decide whether to substitute
+ *                ideal values. [in]
+ * @param sbp Scoring block to work with [in] [out]
+ * @param query Buffer containing (concatenated) query sequence [in]
+ * @param query_info Information about offsets of concatenated queries [in]
+ * @param blast_message returns queries that could not be processed [out]
+ * @return 0 if ungapped Karlin-Altschul parameters could be calculated for 
+ *        all of the query sequence's contexts; 1 if any of the contexts 
+ *        failed (but all others will be populated).
+ */
+
+/** This function fills in the BlastScoreBlk structure.  
+ * Tasks are:
+ * -read in the matrix
+ * -set maxscore
+ * @param sbp Scoring block [in] [out]
+ * @param get_path pointer to function that will return path to matrix.  Only called
+ *  if built-in matrix not found [in]
+*/
+NCBI_XBLAST_EXPORT
+Int2 Blast_ScoreBlkMatrixFill (BlastScoreBlk* sbp, GET_MATRIX_PATH get_path);
+ 
+/** Callocs a Blast_KarlinBlk
+ * @return pointer to the Blast_KarlinBlk
+*/
+NCBI_XBLAST_EXPORT
+Blast_KarlinBlk* Blast_KarlinBlkNew (void);
+
+/** Copies contents of one Karlin block to another. Both must be allocated
+ * before this function is called.
+ * @param kbp_to Karlin block to copy values to [in] [out]
+ * @param kbp_from Karlin block to copy values from [in]
+ * @return 0 on success; -1 if either argument is NULL on input.
+ */ 
+NCBI_XBLAST_EXPORT
+Int2 Blast_KarlinBlkCopy(Blast_KarlinBlk* kbp_to, Blast_KarlinBlk* kbp_from);
+
+
+/** Deallocates the KarlinBlk
+ * @param kbp KarlinBlk to be deallocated [in]
+ * @return NULL
+*/
+NCBI_XBLAST_EXPORT
+Blast_KarlinBlk* Blast_KarlinBlkFree(Blast_KarlinBlk* kbp);
+
+/** Fills in lambda, H, and K values, as calculated by Stephen Altschul 
+ *  in Methods in Enzy. (vol 266, page 474).
+ * @param kbp object to be filled in [in|out]
+ * @param gap_open cost of gap existence [in]
+ * @param gap_extend cost to extend a gap one letter [in]
+ * @param matrix_name name of the matrix to be used [in]
+ * @param error_return filled in with error message if needed [out]
+ * @return zero on success
+ */
+NCBI_XBLAST_EXPORT
+Int2 Blast_KarlinBlkGappedCalc (Blast_KarlinBlk* kbp, Int4 gap_open, 
+     Int4 gap_extend, const char* matrix_name, Blast_Message** error_return);
+
+/** Retrieves Karlin-Altschul parameters from precomputed tables, given the
+ * substitution and gap scores. Gap cost values greater than any of those 
+ * listed in the tables ("greater" meaning that both values are greater than or
+ * equal, and at least one is strictly greater), are treated as infinite, and 
+ * parameters values are copied from the ungapped Karlin block.
+ * @param kbp Allocated Karlin block to fill [in] [out]
+ * @param gap_open Gap openening (existence) cost [in]
+ * @param gap_extend Gap extension cost [in]
+ * @param reward Match reward score [in]
+ * @param penalty Mismatch penalty score [in]
+ * @param kbp_ungap Karlin block with ungapped Karlin-Altschul parameters [in]
+ * @param round_down specifies that the score should be rounded down to nearest even
+ *      score in some cases [in|out]
+ * @param error_return Pointer to error message. [in] [out]
+ */
+NCBI_XBLAST_EXPORT
+Int2
+Blast_KarlinBlkNuclGappedCalc(Blast_KarlinBlk* kbp, Int4 gap_open, 
+                              Int4 gap_extend, Int4 reward, Int4 penalty,
+                              Blast_KarlinBlk* kbp_ungap,
+                              bool* round_down,
+                              Blast_Message** error_return);
+
+
+/** Calculates the Karlin-Altschul parameters assuming standard residue
+ * compositions for the query and subject sequences. It populates the kbp_ideal
+ * field of its sbp argument. This is used if the query is translated and the
+ * calculated (real) Karlin parameters are bad, as they're calculated for 
+ * non-coding regions.
+ * @param sbp ScoreBlk used to calculate "ideal" values. [in|out]
+ * @return 0 on success, 1 on failure
+*/
+NCBI_XBLAST_EXPORT
+Int2 Blast_ScoreBlkKbpIdealCalc(BlastScoreBlk* sbp);
+
+/** Attempts to fill KarlinBlk for given gap opening, extensions etc.
+ *
+ * @param kbp object to be filled in [in|out]
+ * @param gap_open gap existence cost [in]
+ * @param gap_extend gap extension cost [in]
+ * @param matrix_name name of the matrix used [in]
+ * @return  -1 if matrix_name is NULL;
+ *          1 if matrix not found
+ *           2 if matrix found, but open, extend etc. values not supported.
+*/
+NCBI_XBLAST_EXPORT
+Int2 Blast_KarlinBlkGappedLoadFromTables(Blast_KarlinBlk* kbp, Int4 gap_open, Int4 gap_extend, const char* matrix_name);
+
+/** Fills in gumbel parameters to estimate p-value using FSC
+ * @param gbp object to be filled in [in|out]
+ * @param gap_open cost of gap existence [in]
+ * @param gap_extend cost to extend a gap one letter [in]
+ * @param matrix_name name of the matrix to be used [in]
+ * @param error_return filled in with error message if needed [out]
+ * @return zero on success
+ */
+NCBI_XBLAST_EXPORT
+Int2 Blast_GumbelBlkCalc (Blast_GumbelBlk* gbp, Int4 gap_open, 
+     Int4 gap_extend, const char* matrix_name, Blast_Message** error_return);
+
+/** Attempts to fill GumbelBlk for given gap opening, extensions etc.
+ *
+ * @param gbp object to be filled in [in|out]
+ * @param gap_open gap existence cost [in]
+ * @param gap_extend gap extension cost [in]
+ * @param matrix_name name of the matrix used [in]
+ * @return  -1 if matrix_name is NULL;
+ *          1 if matrix not found
+ *           2 if matrix found, but open, extend etc. values not supported.
+*/
+NCBI_XBLAST_EXPORT
+Int2 Blast_GumbelBlkLoadFromTables(Blast_GumbelBlk* gbp, Int4 gap_open, 
+     Int4 gap_extend, const char* matrix_name);
+
+/** Prints a messages about the allowed matrices, BlastKarlinBlkGappedFill should return 1 before this is called. 
+ * @param matrix the matrix to print a message about [in]
+ * @return the message
+ */
+NCBI_XBLAST_EXPORT
+char* BLAST_PrintMatrixMessage(const char *matrix);
+
+/** Prints a messages about the allowed open etc values for the given matrix, 
+ * BlastKarlinBlkGappedFill should return 2 before this is called. 
+ * @param matrix name of the matrix [in]
+ * @param gap_open gap existence cost [in]
+ * @param gap_extend cost to extend a gap by one [in]
+ * @return message
+ */
+NCBI_XBLAST_EXPORT
+char* BLAST_PrintAllowedValues(const char *matrix, Int4 gap_open, Int4 gap_extend);
+
+/** Calculates the parameter Lambda given an initial guess for its value */
+NCBI_XBLAST_EXPORT
+double
+Blast_KarlinLambdaNR(Blast_ScoreFreq* sfp, double initialLambdaGuess);
+
+/** Calculates the Expect value based upon the search space and some Karlin-Altschul 
+ * parameters.  It is "simple" as it does not use sum-statistics.
+ * @param S the score of the alignment. [in]
+ * @param kbp the Karlin-Altschul parameters. [in]
+ * @param searchsp total search space to be used [in]
+ * @return the expect value
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_KarlinStoE_simple (Int4 S, Blast_KarlinBlk* kbp, Int8  searchsp);
+
+/** Calculates the Expect value based upon the Spouge's FSC method.
+ * @param S the score of the alignment. [in]
+ * @param gbp the Gumbel parameters. [in]
+ * @param qlen the query length. [in]
+ * @param slen the subject length. [in]
+ * @return the expect value
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_SpougeStoE (Int4 S, Blast_KarlinBlk* kbp, Blast_GumbelBlk* gbp, Int4 qlen, Int4 slen);
+
+/** Estimate the score for a specified expect value.
+ * @param E the expect value of the alignment. [in]
+ * @param gbp the Gumbel parameters. [in]
+ * @param qlen the query length. [in]
+ * @param slen the subject length. [in]
+ * @return the score
+ */
+NCBI_XBLAST_EXPORT
+Int4 BLAST_SpougeEtoS (double E, Blast_KarlinBlk* kbp, Blast_GumbelBlk* gbp, Int4 qlen, Int4 slen);
+
+/** Convert a P-value to an E-value.
+ *
+ * P-values and E-values may either represent statistics of a database
+ * search or represent statistics on the two sequences being compared.
+ * If given a database P-value, this routine will return a database
+ * E-value; if given a pairwise P-value, it will return a pairwise
+ * E-value.
+ *  
+ * In the context of a database search, the available P-value is often
+ * a pairwise P-value, whereas the desired E-value is a database
+ * E-value.  When this it the case, the value returned by this routine
+ * should be multiplied by the effective length of the database and
+ * divided by the effective length of the subject.
+ * 
+ * @param p the P-value to be converted [in] @return the corresponding
+ * expect value.
+ */
+NCBI_XBLAST_EXPORT double BLAST_KarlinPtoE(double p);
+
+/** Convert an E-value to a P-value.
+ * 
+ * E-values and P-values may either represent statistics of a database
+ * search or represent statistics on the two sequences being compared.
+ * If given a database E-value, this routine will return a database
+ * P-value; if given a pairwise E-value, it will return a pairwise
+ * P-value.
+ *
+ * In the context of a database search, the available E-value is
+ * typically a database E-value, whereas the desired P-value is a
+ * pairwise P-value.  When this is the case, the E-value should be
+ * divided by the effective length of the database and multiplied by
+ * the effective length of the subject, before BLAST_KarlinEtoP is
+ * called.
+ *
+ * @param x the expect value to be converted [in]
+ * @return the corresponding p-value.
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_KarlinEtoP(double x);
+
+/** Compute a divisor used to weight the evalue of a collection of
+ * "nsegs" distinct alignments.  These divisors are used to compensate
+ * for the effect of choosing the best among multiple collections of
+ * alignments.  See
+ *
+ * Stephen F. Altschul. Evaluating the statitical significance of
+ * multiple distinct local alignments. In Suhai, editior, Theoretical
+ * and Computational Methods in Genome Research, pages 1-14. Plenum
+ * Press, New York, 1997.
+ *
+ * The "decayrate" parameter of this routine is a value in the
+ * interval (0,1). Typical values of decayrate are .1 and .5.
+ * @param decayrate adjusts for (multiple) tests of number of HSP sum groups [in]
+ * @param nsegs the number of HSPs in the sum group [in]
+ * @return divisor used to compensate for multiple tests
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_GapDecayDivisor(double decayrate, unsigned nsegs );
+
+/** Calculate the cutoff score from the expected number of HSPs or vice versa.
+ * @param S The calculated score [in] [out]
+ * @param E The calculated e-value [in] [out]
+ * @param kbp The Karlin-Altschul statistical parameters [in]
+ * @param searchsp The effective search space [in]
+ * @param dodecay Use gap decay feature? [in]
+ * @param gap_decay_rate Gap decay rate to use, if dodecay is set [in]
+ */
+NCBI_XBLAST_EXPORT
+Int2 BLAST_Cutoffs (Int4 *S, double* E, Blast_KarlinBlk* kbp, 
+                    Int8 searchsp, bool dodecay, double gap_decay_rate);
+
+/** Calculates the e-value for alignments with "small" gaps (typically
+ *  under fifty residues/basepairs) following ideas of Stephen Altschul's.
+ * @param start_points the number of starting points permitted between
+ *    adjacent alignments; max_overlap + max_gap + 1 [in]
+ * @param num the number of distinct alignments in this collection [in]
+ * @param xsum the sum of the scores of these alignments each individually
+ *    normalized using an appropriate value of Lambda and logK [in]
+ * @param query_length effective len of the query seq [in]
+ * @param subject_length effective len of the subject seq [in]
+ * @param searchsp_eff effective size of the search space [in]
+ * @param weight_divisor a divisor used to weight the e-value
+ *    when multiple collections of alignments are being considered by 
+ *    the calling routine [in]
+ * @return the expect value 
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_SmallGapSumE (Int4 start_points, Int2 num,  double xsum,
+                           Int4 query_length, Int4 subject_length,
+                           Int8 searchsp_eff, double weight_divisor);
+
+/** Calculates the e-value of a collection multiple distinct
+ *   alignments with asymmetric gaps between the alignments. The gaps
+ *   in one (protein) sequence are typically small (like in
+ *   BLAST_SmallGapSumE) gap an the gaps in the other (translated DNA)
+ *   sequence are possibly large (up to 4000 bp.)  This routine is used
+ *   for linking HSPs representing exons in the DNA sequence that are
+ *   separated by introns.
+ * @param query_start_points the number of starting points in
+ *     the query sequence permitted between adjacent alignments;
+ *     max_overlap + max_gap + 1. [in]
+ * @param subject_start_points  the number of starting points in
+ *     the subject sequence permitted between adjacent alignments [in]
+ * @param num number of distinct alignments in one collection [in]
+ * @param xsum the sum of the scores of these alignments each individually
+ *    normalized using an appropriate value of Lambda and logK [in]
+ * @param query_length effective length of query [in]
+ * @param subject_length effective length of subject [in]
+ * @param searchsp_eff effective size of the search space [in]
+ * @param weight_divisor  a divisor used to weight the e-value
+ *    when multiple collections of alignments are being considered by
+ *    the calling routine [in]
+ * @return sum expect value.
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_UnevenGapSumE (Int4 query_start_points, Int4 subject_start_points,
+                            Int2 num, double xsum,
+                            Int4 query_length, Int4 subject_length,
+                            Int8 searchsp_eff, double weight_divisor);
+
+/** Calculates the e-value if a collection of distinct alignments with
+ *   arbitrarily large gaps between the alignments
+ * @param num number of distinct alignments in the collection [in]
+ * @param xsum the sum of the scores of these alignments each individually
+ *     normalized using an appropriate value of Lambda and logK [in]
+ * @param query_length effective length of query sequence [in]
+ * @param subject_length effective length of subject sequence [in]
+ * @param searchsp_eff effective size of the search space [in]
+ * @param weight_divisor  a divisor used to weight the e-value
+ *    when multiple collections of alignments are being considered by the
+ *    calling routine [in]
+ * @return sum expect value.
+ */
+NCBI_XBLAST_EXPORT
+double BLAST_LargeGapSumE (Int2 num,  double xsum,
+                           Int4 query_length, Int4 subject_length,
+                           Int8 searchsp_eff, double weight_divisor );
+
+/** Extract the recommended gap existence and extension values.
+ * Only to be used with protein matrices. 
+ * @param  matrixName name of the matrix [in]
+ * @param gap_existence returns recommended existence cost [in|out]
+ * @param gap_extension returns recommended extension cost [in|out]
+ * @return zero on success 
+ */
+NCBI_XBLAST_EXPORT
+Int2 BLAST_GetProteinGapExistenceExtendParams(const char* matrixName,
+                                       Int4* gap_existence,
+                                       Int4* gap_extension);
+
+/** Extract the recommended gap existence and extension values.
+ * Only to be used with blastn searches.
+ * @param reward match score [in]
+ * @param penalty mismatch score [in]
+ * @param gap_existence returns recommended existence cost [in|out]
+ * @param gap_extension returns recommended extension cost [in|out]
+ * @return zero on success 
+ */
+NCBI_XBLAST_EXPORT
+Int2 BLAST_GetNucleotideGapExistenceExtendParams(Int4 reward,
+                                       Int4 penalty,
+                                       Int4* gap_existence,
+                                       Int4* gap_extension);
+
+/** Check the validity of the reward and penalty scores.
+ * Only to be used with blastn searches.
+ * @param reward match score [in]
+ * @param penalty mismatch score [in]
+ * @return TRUE on success 
+ */
+NCBI_XBLAST_EXPORT
+bool BLAST_CheckRewardPenaltyScores(Int4 reward, Int4 penalty);
+
+/** Extract the alpha and beta settings for this matrixName, and these
+ *  gap open and gap extension costs
+ * @param matrixName name of the matrix used [in]
+ * @param alpha Karlin-Altschul parameter to be set [out]
+ * @param beta Karlin-Altschul parameter to be set [out]
+ * @param gapped TRUE if a gapped search [in]
+ * @param gap_open existence cost of a gap [in]
+ * @param gap_extend extension cost of a gap [in]
+ * @param kbp_ungapped Karlin block with ungapped values of the parameters [in]
+*/
+NCBI_XBLAST_EXPORT
+void BLAST_GetAlphaBeta (const char* matrixName, double *alpha,
+                         double *beta, bool gapped, Int4 gap_open, 
+                         Int4 gap_extend, const Blast_KarlinBlk* kbp_ungapped);
+
+/** Extract the alpha and beta settings for these substitution and gap scores. 
+ * If substitution or gap costs are not found in the tables, assume an ungapped
+ * search. Then alpha is computed using the formula Alpha = Lambda/H, and beta
+ * is equal to 0 except for some special cases.
+ * @param reward Match reward score [in]
+ * @param penalty Mismatch penalty score [in]
+ * @param gap_open Gap opening (existence) cost [in]
+ * @param gap_extend Gap extension cost [in]
+ * @param kbp Karlin block containing already computed Lambda, K and H 
+ *            parameters.
+ * @param gapped_calculation Is this a gapped search? [in]
+ * @param alpha Alpha parameter for this scoring system [out]
+ * @param beta Beta parameter for this scoring system [out]
+ */
+NCBI_XBLAST_EXPORT
+Int2 Blast_GetNuclAlphaBeta(Int4 reward, Int4 penalty, Int4 gap_open, 
+                            Int4 gap_extend, Blast_KarlinBlk* kbp,
+                            bool gapped_calculation,
+                            double *alpha, double *beta);
+
+/** Rescale the PSSM, using composition-based statistics, for use
+ *  with RPS BLAST. This function produces a PSSM for a single RPS DB
+ *  sequence (of size db_seq_length) and incorporates information from 
+ *  the RPS blast query. Each individual database sequence must call this
+ *  function to retrieve its own PSSM. The matrix is returned (and must
+ *  be freed elsewhere). posMatrix is the portion of the complete 
+ *  concatenated PSSM that is specific to this DB sequence 
+ * @todo revise to use existing code
+ * @param scalingFactor used to rescale Lambda [in]
+ * @param rps_query_length length of query sequence [in]
+ * @param rps_query_seq the query sequence [in]
+ * @param db_seq_length Length of the database sequence [in]
+ * @param posMatrix matrix (actual) values to be used [in]
+ * @param sbp Structure with score matrix parameters [in][out]
+ * @return rescaled pssm 
+ */
+NCBI_XBLAST_EXPORT
+Int4 ** RPSRescalePssm(double scalingFactor, Int4 rps_query_length, 
+                   const Uint1 * rps_query_seq, Int4 db_seq_length, 
+                   Int4 **posMatrix, BlastScoreBlk *sbp);
+
+
+/** 
+ * Computes the adjustment to the lengths of the query and database sequences
+ * that is used to compensate for edge effects when computing evalues. 
+ *
+ * The length adjustment is an integer-valued approximation to the fixed
+ * point of the function
+ *
+ *    f(ell) = beta + 
+ *               (alpha/lambda) * (log K + log((m - ell)*(n - N ell)))
+ *
+ * where m is the query length n is the length of the database and N is the
+ * number of sequences in the database. The values beta, alpha, lambda and
+ * K are statistical, Karlin-Altschul parameters.
+ * 
+ * The value of the length adjustment computed by this routine, A, 
+ * will always be an integer smaller than the fixed point of
+ * f(ell). Usually, it will be the largest such integer.  However, the
+ * computed length adjustment, A, will also be so small that 
+ *
+ *    K * (m - A) * (n - N * A) > MAX(m,n).
+ *
+ * Moreover, an iterative method is used to compute A, and under
+ * unusual circumstances the iterative method may not converge. 
+ *
+ * @param K      the statistical parameter K [in]
+ * @param logK   the natural logarithm of K [in]
+ * @param alpha_d_lambda    the ratio of the statistical parameters 
+ *                          alpha and lambda (for ungapped alignments, the
+ *                          value 1/H should be used) [in]
+ * @param beta              the statistical parameter beta (for ungapped
+ *                          alignments, beta == 0) [in]
+ * @param query_length      the length of the query sequence [in]
+ * @param db_length         the length of the database [in]
+ * @param db_num_seqs       the number of sequences in the database [in]
+ * @param length_adjustment the computed value of the length adjustment [out]
+ *
+ * @return   0 if length_adjustment is known to be the largest integer less
+ *           than the fixed point of f(ell); 1 otherwise.
+ */
+NCBI_XBLAST_EXPORT
+Int4
+BLAST_ComputeLengthAdjustment(double K,
+                              double logK,
+                              double alpha_d_lambda,
+                              double beta,
+                              Int4 query_length,
+                              Int8 db_length,
+                              Int4 db_num_seqs,
+                              Int4 * length_adjustment);
+
+
+/** Allocates a new Blast_ResFreq structure and fills in the prob element
+    based upon the contents of sbp.
+ * @param sbp The BlastScoreBlk* used to init prob [in]
+*/
+NCBI_XBLAST_EXPORT
+Blast_ResFreq* Blast_ResFreqNew(const BlastScoreBlk* sbp);
+
+/** Deallocates Blast_ResFreq and prob0 element.
+ * @param rfp the Blast_ResFreq to be deallocated.
+*/
+NCBI_XBLAST_EXPORT
+Blast_ResFreq* Blast_ResFreqFree(Blast_ResFreq* rfp);
+
+
+/** Calculates residues frequencies given a standard distribution.
+ * @param sbp the BlastScoreBlk provides information on alphabet.
+ * @param rfp the prob element on this Blast_ResFreq is used.
+ * @return zero on success
+*/
+NCBI_XBLAST_EXPORT
+Int2 Blast_ResFreqStdComp(const BlastScoreBlk* sbp, Blast_ResFreq* rfp);
+
+/** Creates a new structure to keep track of score frequencies for a scoring
+ * system.
+ * @param score_min Minimum score [in]
+ * @param score_max Maximum score [in]
+ * @return allocated and initialized pointer to Blast_ScoreFreq
+ */
+NCBI_XBLAST_EXPORT
+Blast_ScoreFreq*
+Blast_ScoreFreqNew(Int4 score_min, Int4 score_max);
+
+/** Deallocates the score frequencies structure 
+ * @param sfp the structure to deallocate [in]
+ * @return NULL
+ */
+NCBI_XBLAST_EXPORT
+Blast_ScoreFreq*
+Blast_ScoreFreqFree(Blast_ScoreFreq* sfp);
+
+/** Fills a buffer with the 'standard' alphabet 
+ * (given by STD_AMINO_ACID_FREQS[index].ch).
+ *
+ * @param alphabet_code specifies alphabet [in]
+ * @param residues buffer to be filled in [in|out]
+ * @param residue_size size of "residues" buffer [in]
+ * @return Number of residues in alphabet or negative returns upon error.
+ */
+NCBI_XBLAST_EXPORT
+Int2
+Blast_GetStdAlphabet(Uint1 alphabet_code, Uint1* residues, 
+                     Uint4 residue_size);
+
+/** Computes the parameters lambda, H K for use in calculating the
+ * statistical significance of high-scoring segments or subalignments (see
+ * comment on blast_stat.c for more details).
+ * @param kbp object containing Lambda, H, and K as well as scoring information [in|out]
+ * @param sfp array of probabilities for all scores [in]
+ * @return zero on success, 1 on error.
+ */
+NCBI_XBLAST_EXPORT
+Int2
+Blast_KarlinBlkUngappedCalc(Blast_KarlinBlk* kbp, Blast_ScoreFreq* sfp);
+
+/**  Given a sequence of 'length' amino acid residues, compute the
+ *   probability of each residue and put that in the array resProb
+ *   Excludes ambiguity characters.
+ *
+ * @param sequence the sequence to be computed upon [in]
+ * @param length the length of the sequence [in]
+ * @param resProb the object to be filled in [in|out]
+ */
+NCBI_XBLAST_EXPORT
+void
+Blast_FillResidueProbability(const Uint1* sequence, Int4 length, double * resProb);
+
+/** Fill in the matrix for blastn using the penaly and rewards
+ * The query sequence alphabet is blastna, the subject sequence
+ * is ncbi2na.  The alphabet blastna is defined in blast_stat.h
+ * and the first four elements of blastna are identical to ncbi2na.
+ * if sbp->matrix==NULL, it is allocated.
+ * @param sbp the BlastScoreBlk on which reward, penalty, and matrix will be set
+ [in|out]
+ * @return zero on success.
+*/
+NCBI_XBLAST_EXPORT
+Int2 BlastScoreBlkNuclMatrixCreate(BlastScoreBlk* sbp);
+
+/** Returns a pointer to the static compiled in version of the 
+ * matrix.  If name is NULL or the matrix is not compiled in
+ * NULL is returned.
+ * @param name matrix name [in]
+ * @return pointer to matrix or NULL if not supported.
+ */
+NCBI_XBLAST_EXPORT 
+SNCBIPackedScoreMatrix* BlastScoreBlkGetCompiledInMatrix(const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !ALGO_BLAST_CORE__BLAST_STAT__H */
diff --git a/src/blast/ncbi_math.h b/src/blast/ncbi_math.h
new file mode 100644
index 0000000..bf2edc7
--- /dev/null
+++ b/src/blast/ncbi_math.h
@@ -0,0 +1,146 @@
+/* $Id: ncbi_math.h 351792 2012-02-01 16:20:19Z ucko $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Authors:  Gish, Kans, Ostell, Schuler
+ *
+ * Version Creation Date:   10/23/91
+ *
+ * ==========================================================================
+ */
+
+/** @file ncbi_math.h
+ * Prototypes for portable math library (ported from C Toolkit)
+ */
+
+#ifndef ALGO_BLAST_CORE__NCBIMATH
+#define ALGO_BLAST_CORE__NCBIMATH
+
+/** Natural logarithm with shifted input
+ *  @param x input operand (x > -1)
+ *  @return log(x+1)
+ */
+double BLAST_Log1p (double x);
+
+/** Exponentional with base e 
+ *  @param x input operand
+ *  @return exp(x) - 1
+ */
+double BLAST_Expm1 (double x);
+
+/** Factorial function
+ *  @param n input operand
+ *  @return (double)(1 * 2 * 3 * ... * n)
+ */
+double BLAST_Factorial(int32_t n);
+
+/** Logarithm of the factorial 
+ *  @param x input operand
+ *  @return log(1 * 2 * 3 * ... * x)
+ */
+double BLAST_LnFactorial (double x);
+
+/** log(gamma(n)), integral n 
+ *  @param n input operand
+ *  @return log(1 * 2 * 3 * ... (n-1))
+ */
+double BLAST_LnGammaInt (int32_t n);
+
+/** Romberg numerical integrator 
+ *  @param f Pointer to the function to integrate; the first argument
+ *               is the variable to integrate over, the second is a pointer
+ *               to a list of additional arguments that f may need
+ *  @param fargs Pointer to an array of extra arguments or parameters
+ *               needed to compute the function to be integrated. None
+ *               of the items in this list may vary over the region
+ *               of integration
+ *  @param p Left-hand endpoint of the integration interval
+ *  @param q Right-hand endpoint of the integration interval
+ *           (q is assumed > p)
+ *  @param eps The relative error tolerance that indicates convergence
+ *  @param epsit The number of consecutive diagonal entries in the 
+ *               Romberg array whose relative difference must be less than
+ *               eps before convergence is assumed. This is presently 
+ *               limited to 1, 2, or 3
+ *  @param itmin The minimum number of diagnonal Romberg entries that
+ *               will be computed
+ *  @return The computed integral of f() between p and q
+ */
+double BLAST_RombergIntegrate (double (*f) (double, void*), 
+                               void* fargs, double p, double q, 
+                               double eps, int32_t epsit, int32_t itmin);
+
+/** Greatest common divisor 
+ *  @param a First operand (any integer)
+ *  @param b Second operand (any integer)
+ *  @return The largest integer that evenly divides a and b
+ */
+int32_t BLAST_Gcd (int32_t a, int32_t b);
+
+/** Divide 3 numbers by their greatest common divisor
+ * @param a First integer [in] [out]
+ * @param b Second integer [in] [out]
+ * @param c Third integer [in] [out]
+ * @return The greatest common divisor
+ */
+int32_t BLAST_Gdb3(int32_t* a, int32_t* b, int32_t* c);
+
+/** Nearest integer 
+ *  @param x Input to round (rounded value must be representable
+ *           as a 32-bit signed integer)
+ *  @return floor(x + 0.5);
+ */
+long BLAST_Nint (double x);
+
+/** Integral power of x 
+ * @param x floating-point base of the exponential
+ * @param n (integer) exponent
+ * @return x multiplied by itself n times
+ */
+double BLAST_Powi (double x, int32_t n);
+
+/** The error function of x: the integral from 0 to x of e(-t*t) dt,
+ *  scaled by 2/sqrt(pi) to fall within the range (-1,1). */
+double BLAST_Erf (double x);
+
+/** The complementary error function of x: 1 - erf(x), but calculated
+ *  more accurately for large x (where erf(x) approaches unity). */
+double BLAST_ErfC (double x);
+
+/** Number of derivatives of log(x) to carry in gamma-related 
+    computations */
+#define LOGDERIV_ORDER_MAX	4  
+/** Number of derivatives of polygamma(x) to carry in gamma-related 
+    computations for non-integral values of x */
+#define POLYGAMMA_ORDER_MAX	LOGDERIV_ORDER_MAX
+
+/** value of pi is only used in gamma-related computations */
+#define NCBIMATH_PI	3.1415926535897932384626433832795
+
+/** Natural log(2) */
+#define NCBIMATH_LN2	0.69314718055994530941723212145818
+/** Natural log(PI) */
+#define NCBIMATH_LNPI	1.1447298858494001741434273513531
+
+#endif /* !ALGO_BLAST_CORE__NCBIMATH */
diff --git a/src/blast/ncbi_std.h b/src/blast/ncbi_std.h
new file mode 100644
index 0000000..fbac29a
--- /dev/null
+++ b/src/blast/ncbi_std.h
@@ -0,0 +1,270 @@
+/* $Id: ncbi_std.h 417725 2013-11-08 18:44:19Z rafanovi $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ *
+ */
+
+/** @file ncbi_std.h
+ * Type and macro definitions from C toolkit that are not defined in C++ 
+ * toolkit.
+ */
+
+
+
+#ifndef ALGO_BLAST_CORE__NCBI_STD
+#define ALGO_BLAST_CORE__NCBI_STD
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <math.h>
+#include <ctype.h>
+#include <assert.h>
+
+#define NCBI_XBLAST_EXPORT
+
+/* which toolkit are we using? */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef NCBI_RESTRICT /* now defined in the C++ Toolkit */
+/** For some reason, ICC claims a suitable __STDC_VERSION__ but then
+   barfs on restrict. Added ECC per Haruna Cofer */
+#if defined(__ICC) || defined(__ECC)
+#define NCBI_RESTRICT __restrict
+#elif __STDC_VERSION__ >= 199901  &&  (!defined(__IBMC__) || defined(__C99_RESTRICT))
+#define NCBI_RESTRICT restrict
+#else
+#define NCBI_RESTRICT
+#endif
+#endif
+
+/* inlining support -- compiler dependent */
+#if defined(__cplusplus)  ||  __STDC_VERSION__ >= 199901
+/** C++ and C99 both guarantee "inline" */
+#define NCBI_INLINE inline
+#elif defined(__GNUC__)
+/* So does GCC, normally, but it may be running with strict options
+   that require the extra underscores */
+#define NCBI_INLINE __inline__
+#elif defined(_MSC_VER)  ||  defined(__sgi) || defined(HPUX)
+/* MSVC and (older) MIPSpro always require leading underscores */
+#define NCBI_INLINE __inline
+#else
+/** "inline" seems to work on our remaining in-house compilers
+   (WorkShop, Compaq, ICC, MPW) */
+#define NCBI_INLINE inline
+#endif
+
+#ifdef _MSC_VER
+#define strcasecmp _stricmp
+#define strdup _strdup
+#define snprintf _snprintf
+#endif
+
+#ifndef _NCBISTD_ /* if we're not in the C toolkit... */
+/** bool replacment for C */
+#ifndef TRUE
+/** bool replacment for C indicating true. */
+#define TRUE 1
+#endif
+#ifndef FALSE
+/** bool replacment for C indicating false. */
+#define FALSE 0
+#endif
+#endif
+
+/** macro for assert. */
+#ifndef ASSERT
+#define ASSERT assert
+#endif
+
+#ifndef MIN
+/** returns smaller of a and b. */
+#define MIN(a,b)	((a)>(b)?(b):(a))
+#endif
+
+#ifndef MAX
+/** returns larger of a and b. */
+#define MAX(a,b)	((a)>=(b)?(a):(b))
+#endif
+
+#ifndef ABS
+/** returns absolute value of a (|a|) */
+#define ABS(a)	((a)>=0?(a):-(a))
+#endif
+
+#ifndef SIGN
+/** return +1 for a > 0, -1 for a < 0 */
+#define SIGN(a)	((a)>0?1:((a)<0?-1:0))
+#endif
+
+/* low-level ANSI-style functions */
+
+#ifndef _NCBISTD_ /* if we're not in the C toolkit ... */
+
+#ifndef UINT4_MAX
+/** largest number represented by unsigned int. */
+#define UINT4_MAX     4294967295U
+#endif
+
+#ifndef INT4_MAX
+/** largest nubmer represented by signed int */
+#define INT4_MAX    2147483647
+#endif 
+
+#ifndef INT4_MIN
+/** Smallest (most negative) number represented by signed int */
+#define INT4_MIN    (-2147483647-1)
+#endif
+
+#ifndef NCBIMATH_LN2
+/** natural log of 2. */
+#define NCBIMATH_LN2      0.69314718055994530941723212145818
+#endif
+
+#ifndef INT2_MAX
+/** largest number represented by signed (two byte) short */
+#define INT2_MAX    32767
+#endif
+
+#ifndef INT2_MIN
+/** smallest (most negative) number represented by signed (two byte) short */
+#define INT2_MIN    (-32768)
+#endif
+
+#ifndef INT1_MAX
+/** largest number represented by signed short (one byte) */
+#define INT1_MAX    127
+#endif
+
+#ifndef INT1_MIN
+/** smallest (most negative) number represented by signed short (one byte) */
+#define INT1_MIN    (-128)
+#endif
+
+#ifndef DIM
+/** dimension of an array. */
+#define DIM(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#ifndef NULLB
+/** terminating byte of a char* string. */
+#define NULLB '\0'
+#endif
+
+#endif /* _NCBISTD_ */
+
+/** 64-bit integers */
+#ifndef NCBI_CONST_INT8 /* C Toolkit */
+#  ifdef INT64_C /* stdint.h should have this */
+#    define NCBI_CONST_INT8(v)   INT64_C(v)
+#    define NCBI_CONST_UINT8(v)  UINT64_C(v)
+#  elif defined(_MSC_VER)
+#    define NCBI_CONST_INT8(v)   v##i64
+#    define NCBI_CONST_UINT8(v)  v##ui64
+#  else /* Try treating as (unsigned) long long */
+#    define NCBI_CONST_INT8(v)   v##LL
+#    define NCBI_CONST_UINT8(v)  v##ULL
+#  endif
+#endif
+
+/** Copies memory using memcpy and malloc
+ * @param orig memory to be copied [in]
+ * @param size amount to be copied [in]
+ * @return pointer to newly allocated memory. NULL if orig NULL, size is zero,
+ *   or allocation fails.
+ */
+NCBI_XBLAST_EXPORT
+void* BlastMemDup (const void *orig, size_t size);
+
+
+/******************************************************************************/
+
+/** A generic linked list node structure */
+typedef struct ListNode {
+	Uint1 choice;   /**< to pick a choice */
+	void *ptr;              /**< attached data */
+	struct ListNode *next;  /**< next in linked list */
+} ListNode;
+
+/** Create a new list node  
+ * @param vnp Pointer to the start of the list, may be NULL [in]
+ * @return newly allocated node 
+ */
+NCBI_XBLAST_EXPORT
+ListNode* ListNodeNew (ListNode* vnp);
+
+/** Add a node to the list.
+ * @param head Pointer to the start of the list, if *head is NULL will
+ *  be Pointer to new node. [in] [out]
+ * @return New node
+ */
+NCBI_XBLAST_EXPORT
+ListNode* ListNodeAdd (ListNode** head);
+
+/** Add a node to the list with a given choice and data pointer.
+ * @param head Pointer to the start of the list, if *head is NULL will
+ *  be Pointer to new node. [in] [out]
+ * @param choice Choice value for the new node. [in]
+ * @param value Data pointer for the new node. [in]
+ * @return New node
+ */
+NCBI_XBLAST_EXPORT
+ListNode* ListNodeAddPointer (ListNode** head, Uint1 choice, void *value);
+
+/** Free all list's nodes, does not attempt to free data. 
+ * @param vnp objects to be freed [in]
+ * @return NULL
+ */
+NCBI_XBLAST_EXPORT
+ListNode* ListNodeFree (ListNode* vnp);
+
+/** Free nodes as well as data (vnp->ptr) assuming it is one contiguous chunk.
+ * @param vnp objects to be freed [in] 
+ * @return NULL
+ */
+NCBI_XBLAST_EXPORT
+ListNode* ListNodeFreeData (ListNode* vnp);
+
+/** Add a node to the list with a provided choice, and attached data 
+ * pointing to a provided string.
+ * @param head Pointer to the start of the list, if *head is NULL will
+ *  be Pointer to new node. [in] [out]
+ * @param choice sets the "choice" field in ListNode [in]
+ * @param str char* buffer to be copied [in]
+ * @return newly allocated node 
+ */
+NCBI_XBLAST_EXPORT
+ListNode* ListNodeCopyStr (ListNode** head, Uint1 choice, const char* str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ALGO_BLAST_CORE__NCBI_STD */
diff --git a/src/blast/ncbitype.h b/src/blast/ncbitype.h
new file mode 100644
index 0000000..be66d84
--- /dev/null
+++ b/src/blast/ncbitype.h
@@ -0,0 +1,174 @@
+#ifndef CORELIB___NCBITYPE__H
+#define CORELIB___NCBITYPE__H
+
+/*  $Id: ncbitype.h 375760 2012-09-24 14:15:47Z ucko $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Denis Vakatov
+ *
+ *
+ */
+
+/**
+ * @file ncbitype.h
+ *
+ * Defines NCBI C/C++ fixed-size types.
+ *
+ *   -  Char, Uchar
+ *   -  Int1, Uint1
+ *   -  Int2, Uint2
+ *   -  Int4, Uint4
+ *   -  Int8, Uint8
+ *   -  Ncbi_BigScalar
+ *   -  Macros for constant values definition.
+ *
+ */
+
+/** @addtogroup Portability
+ *
+ * @{
+ */
+
+#  ifndef   __STDC_CONSTANT_MACROS
+#    define __STDC_CONSTANT_MACROS
+#  endif /*!__STDC_CONSTANT_MACROS*/
+#  ifndef   __STDC_FORMAT_MACROS
+#    define __STDC_FORMAT_MACROS
+#  endif /*!__STDC_FORMAT_MACROS*/
+#  include <inttypes.h>
+
+/* Char, Uchar, Int[1,2,4], Uint[1,2,4]
+ */
+
+#ifdef Int1
+#  undef Int1
+#  undef Uint1
+#  undef Int2
+#  undef Uint2
+#  undef Int4
+#  undef Uint4
+#endif
+#ifdef Int8
+#  undef Int8
+#  undef Uint8
+#endif
+
+typedef          char  Char;    /**< Alias for char */
+typedef signed   char  Schar;   /**< Alias for signed char */
+typedef unsigned char  Uchar;   /**< Alias for unsigned char */
+
+
+typedef int8_t   Int1;  /**< 1-byte  (8-bit)   signed integer */
+typedef uint8_t  Uint1; /**< 1-byte  (8-bit) unsigned integer */
+typedef int16_t  Int2;  /**< 2-byte (16-bit)   signed integer */
+typedef uint16_t Uint2; /**< 2-byte (16-bit) unsigned integer */
+typedef int32_t  Int4;  /**< 4-byte (32-bit)   signed integer */
+typedef uint32_t Uint4; /**< 4-byte (32-bit) unsigned integer */
+typedef int64_t  Int8;  /**< 8-byte (64-bit)   signed integer */
+typedef uint64_t Uint8; /**< 8-byte (64-bit) unsigned integer */
+/* We still need to know (u)int64_t's ultimate type when defining functions
+ * or operators with one variant per distinct integral type. :-/ */
+#  if SIZEOF_LONG == 8  &&  !defined(NCBI_OS_DARWIN)
+#    define NCBI_INT8_IS_LONG      1
+#  elif SIZEOF_LONG_LONG == 8
+#    define NCBI_INT8_IS_LONG_LONG 1
+#  elif SIZEOF___INT64 == 8
+#    define NCBI_INT8_IS_INT64     1
+#  endif
+
+/* BigScalar
+ */
+
+#define NCBI_BIG_TYPE Int8
+#define SIZEOF_NCBI_BIG 8
+#if (SIZEOF_LONG_DOUBLE > SIZEOF_NCBI_BIG)
+#  undef  NCBI_BIG_TYPE
+#  undef  SIZEOF_NCBI_BIG
+#  define NCBI_BIG_TYPE   long double 
+#  define SIZEOF_NCBI_BIG SIZEOF_LONG_DOUBLE
+#endif
+#if (SIZEOF_DOUBLE > SIZEOF_NCBI_BIG)
+#  undef  NCBI_BIG_TYPE
+#  undef  SIZEOF_NCBI_BIG
+#  define NCBI_BIG_TYPE   double
+#  define SIZEOF_NCBI_BIG SIZEOF_DOUBLE
+#endif
+#if (SIZEOF_VOIDP > SIZEOF_NCBI_BIG)
+#  undef  NCBI_BIG_TYPE
+#  undef  SIZEOF_NCBI_BIG
+#  define NCBI_BIG_TYPE   void*
+#  define SIZEOF_NCBI_BIG SIZEOF_VOIDP
+#endif
+
+/**
+ * Define large scalar type.
+ *
+ * This is platform dependent. It could be an Int8, long double, double
+ * or void*.
+ */
+typedef NCBI_BIG_TYPE Ncbi_BigScalar;
+
+/* Macros for constant values definition 
+ */
+
+#  define NCBI_CONST_INT8(v)     INT64_C(v)
+#  define NCBI_CONST_UINT8(v)   UINT64_C(v)
+#  define NCBI_INT8_FORMAT_SPEC  PRId64
+#  define NCBI_UINT8_FORMAT_SPEC PRIu64
+#elif (SIZEOF_LONG == 8)
+#  define NCBI_CONST_INT8(v)   v##L
+#  define NCBI_CONST_UINT8(v)  v##UL
+#  define NCBI_INT8_FORMAT_SPEC   "ld"
+#  define NCBI_UINT8_FORMAT_SPEC  "lu"
+#elif (SIZEOF_LONG_LONG == 8)
+#  define NCBI_CONST_INT8(v)   v##LL
+#  define NCBI_CONST_UINT8(v)  v##ULL
+#  if defined(__MINGW32__)  ||  defined(__MINGW64__)
+#    define NCBI_INT8_FORMAT_SPEC   "I64d"
+#    define NCBI_UINT8_FORMAT_SPEC  "I64u"
+#  else
+#    define NCBI_INT8_FORMAT_SPEC   "lld"
+#    define NCBI_UINT8_FORMAT_SPEC  "llu"
+#  endif
+#elif defined(NCBI_USE_INT64)
+#  define NCBI_CONST_INT8(v)   v##i64
+#  define NCBI_CONST_UINT8(v)  v##ui64
+#  define NCBI_INT8_FORMAT_SPEC   "I64d"
+#  define NCBI_UINT8_FORMAT_SPEC  "I64u"
+
+
+
+/* Undef auxiliaries
+ */
+
+#undef SIZEOF_NCBI_BIG
+#undef NCBI_BIG_TYPE
+#undef NCBI_INT8_TYPE
+
+
+#endif  /* CORELIB___NCBITYPE__H */
+
+
+/* @} */
diff --git a/src/blast/raw_scoremat.h b/src/blast/raw_scoremat.h
new file mode 100644
index 0000000..87a268b
--- /dev/null
+++ b/src/blast/raw_scoremat.h
@@ -0,0 +1,121 @@
+#ifndef UTIL_TABLES___SCOREMAT__H
+#define UTIL_TABLES___SCOREMAT__H
+
+/*  $Id: raw_scoremat.h 255842 2011-02-28 18:39:03Z ucko $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Aaron Ucko
+ *
+ */
+
+/** @file scoremat.h
+ ** Protein alignment score matrices; shared between the two toolkits.
+ **/
+
+#define NCBI_TABLES_EXPORT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** data types */
+
+typedef signed char TNCBIScore;
+typedef struct SNCBIPackedScoreMatrix {
+    const char*       symbols;  /**< order of residues */
+    const TNCBIScore* scores;   /**< strlen(symbols) x strlen(symbols) */
+    TNCBIScore        defscore; /**< score for unknown residues */
+} SNCBIPackedScoreMatrix;
+
+/** Map a standard residue code into an index suitable for a particular
+ ** packed score matrix.  Calling this function is not as fast as working
+ ** with unpacked matrices, but avoids the overhead of producing them.
+ ** @param sm
+ **   Packed score matrix of interest.
+ ** @param aa
+ **   Standard amino acid code; may be either NCBIstdaa or case-insensitive
+ **   NCBIeaa (which are conveniently disjoint), modulo gaps in coverage.
+ **   (The standard built-in matrices don't cover O or U.)
+ ** @return
+ **   The corresponding index into sm, or -1 if it doesn't cover AA.
+ **/
+extern NCBI_TABLES_EXPORT
+int        NCBISM_GetIndex(const SNCBIPackedScoreMatrix* sm, int aa);
+
+/** Look up an entry in a packed score matrix.  Calling this function is
+ ** not as fast as working with unpacked matrices, but avoids the overhead
+ ** of producing them.
+ ** @param sm
+ **   Packed score matrix of interest.
+ ** @param aa1, aa2
+ **   Standard amino acid code; may be either NCBIstdaa or case-insensitive
+ **   NCBIeaa (which are conveniently disjoint), modulo gaps in coverage.
+ **   (The standard built-in matrices don't cover O or U.)
+ ** @return
+ **   The corresponding score (or the matrix's default if it doesn't cover
+ **   both residues).
+ **/
+extern NCBI_TABLES_EXPORT
+TNCBIScore NCBISM_GetScore(const SNCBIPackedScoreMatrix* sm,
+                           int aa1, int aa2);
+
+/** Recommended approach: unpack and index directly. */
+#define NCBI_FSM_DIM 128
+typedef struct SNCBIFullScoreMatrix {
+    TNCBIScore s[NCBI_FSM_DIM][NCBI_FSM_DIM];
+} SNCBIFullScoreMatrix;
+
+/** Expand a packed score matrix into an unpacked one, which callers can
+ ** proceed to index directly by standard residue values (NCBIstdaa or
+ ** case-insensitive NCBIeaa, which are conveniently disjoint) modulo gaps
+ ** in coverage, for which the unpacked matrix will hold the packed one's
+ ** default score. (The standard built-in matrices don't cover O or U.)
+ ** @param sm
+ **   Packed score matrix to expand.
+ ** @param fsm
+ **   Storage for the resulting full score matrix.
+ **/
+extern NCBI_TABLES_EXPORT
+void NCBISM_Unpack(const SNCBIPackedScoreMatrix* psm,
+                   SNCBIFullScoreMatrix* fsm);
+
+/** The standard matrices. */
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Blosum45;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Blosum50;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Blosum62;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Blosum80;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Blosum90;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Pam30;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Pam70;
+extern NCBI_TABLES_EXPORT const SNCBIPackedScoreMatrix NCBISM_Pam250;
+
+extern NCBI_TABLES_EXPORT
+const SNCBIPackedScoreMatrix* NCBISM_GetStandardMatrix(const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* UTIL_TABLES___SCOREMAT__H */
diff --git a/src/blast/sm_blosum45.c b/src/blast/sm_blosum45.c
new file mode 100644
index 0000000..cf6b43b
--- /dev/null
+++ b/src/blast/sm_blosum45.c
@@ -0,0 +1,97 @@
+/*  $Id: sm_blosum45.c 90506 2006-09-25 19:30:59Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+
+#include "raw_scoremat.h"
+
+/** Entries for the BLOSUM45 matrix at a scale of ln(2)/3.0. */
+
+static const TNCBIScore s_Blosum45PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    5, -2, -1, -2, -1, -1, -1,  0, -2, -1, -1, -1, -1,
+            -2, -1,  1,  0, -2, -2,  0, -1, -1, -1, -1, -5,
+    /*R*/   -2,  7,  0, -1, -3,  1,  0, -2,  0, -3, -2,  3, -1,
+            -2, -2, -1, -1, -2, -1, -2, -1, -3,  1, -1, -5,
+    /*N*/   -1,  0,  6,  2, -2,  0,  0,  0,  1, -2, -3,  0, -2,
+            -2, -2,  1,  0, -4, -2, -3,  5, -3,  0, -1, -5,
+    /*D*/   -2, -1,  2,  7, -3,  0,  2, -1,  0, -4, -3,  0, -3,
+            -4, -1,  0, -1, -4, -2, -3,  6, -3,  1, -1, -5,
+    /*C*/   -1, -3, -2, -3, 12, -3, -3, -3, -3, -3, -2, -3, -2,
+            -2, -4, -1, -1, -5, -3, -1, -2, -2, -3, -1, -5,
+    /*Q*/   -1,  1,  0,  0, -3,  6,  2, -2,  1, -2, -2,  1,  0,
+            -4, -1,  0, -1, -2, -1, -3,  0, -2,  4, -1, -5,
+    /*E*/   -1,  0,  0,  2, -3,  2,  6, -2,  0, -3, -2,  1, -2,
+            -3,  0,  0, -1, -3, -2, -3,  1, -3,  5, -1, -5,
+    /*G*/    0, -2,  0, -1, -3, -2, -2,  7, -2, -4, -3, -2, -2,
+            -3, -2,  0, -2, -2, -3, -3, -1, -4, -2, -1, -5,
+    /*H*/   -2,  0,  1,  0, -3,  1,  0, -2, 10, -3, -2, -1,  0,
+            -2, -2, -1, -2, -3,  2, -3,  0, -2,  0, -1, -5,
+    /*I*/   -1, -3, -2, -4, -3, -2, -3, -4, -3,  5,  2, -3,  2,
+             0, -2, -2, -1, -2,  0,  3, -3,  4, -3, -1, -5,
+    /*L*/   -1, -2, -3, -3, -2, -2, -2, -3, -2,  2,  5, -3,  2,
+             1, -3, -3, -1, -2,  0,  1, -3,  4, -2, -1, -5,
+    /*K*/   -1,  3,  0,  0, -3,  1,  1, -2, -1, -3, -3,  5, -1,
+            -3, -1, -1, -1, -2, -1, -2,  0, -3,  1, -1, -5,
+    /*M*/   -1, -1, -2, -3, -2,  0, -2, -2,  0,  2,  2, -1,  6,
+             0, -2, -2, -1, -2,  0,  1, -2,  2, -1, -1, -5,
+    /*F*/   -2, -2, -2, -4, -2, -4, -3, -3, -2,  0,  1, -3,  0,
+             8, -3, -2, -1,  1,  3,  0, -3,  1, -3, -1, -5,
+    /*P*/   -1, -2, -2, -1, -4, -1,  0, -2, -2, -2, -3, -1, -2,
+            -3,  9, -1, -1, -3, -3, -3, -2, -3, -1, -1, -5,
+    /*S*/    1, -1,  1,  0, -1,  0,  0,  0, -1, -2, -3, -1, -2,
+            -2, -1,  4,  2, -4, -2, -1,  0, -2,  0, -1, -5,
+    /*T*/    0, -1,  0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1,
+            -1, -1,  2,  5, -3, -1,  0,  0, -1, -1, -1, -5,
+    /*W*/   -2, -2, -4, -4, -5, -2, -3, -2, -3, -2, -2, -2, -2,
+             1, -3, -4, -3, 15,  3, -3, -4, -2, -2, -1, -5,
+    /*Y*/   -2, -1, -2, -2, -3, -1, -2, -3,  2,  0,  0, -1,  0,
+             3, -3, -2, -1,  3,  8, -1, -2,  0, -2, -1, -5,
+    /*V*/    0, -2, -3, -3, -1, -3, -3, -3, -3,  3,  1, -2,  1,
+             0, -3, -1,  0, -3, -1,  5, -3,  2, -3, -1, -5,
+    /*B*/   -1, -1,  5,  6, -2,  0,  1, -1,  0, -3, -3,  0, -2,
+            -3, -2,  0,  0, -4, -2, -3,  5, -3,  1, -1, -5,
+    /*J*/   -1, -3, -3, -3, -2, -2, -3, -4, -2,  4,  4, -3,  2,
+             1, -3, -2, -1, -2,  0,  2, -3,  4, -2, -1, -5,
+    /*Z*/   -1,  1,  0,  1, -3,  4,  5, -2,  0, -3, -2,  1, -1,
+            -3, -1,  0, -1, -2, -2, -3,  1, -2,  5, -1, -5,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -5,
+    /***/   -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5,
+            -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Blosum45 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Blosum45PSM,
+    -5
+};
+
diff --git a/src/blast/sm_blosum50.c b/src/blast/sm_blosum50.c
new file mode 100644
index 0000000..219a38b
--- /dev/null
+++ b/src/blast/sm_blosum50.c
@@ -0,0 +1,97 @@
+/*  $Id: sm_blosum50.c 90507 2006-09-25 19:31:51Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+
+#include "raw_scoremat.h"
+
+/** Entries for the BLOSUM50 matrix at a scale of ln(2)/3.0. */
+
+static const TNCBIScore s_Blosum50PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    5, -2, -1, -2, -1, -1, -1,  0, -2, -1, -2, -1, -1,
+            -3, -1,  1,  0, -3, -2,  0, -2, -2, -1, -1, -5,
+    /*R*/   -2,  7, -1, -2, -4,  1,  0, -3,  0, -4, -3,  3, -2,
+            -3, -3, -1, -1, -3, -1, -3, -1, -3,  0, -1, -5,
+    /*N*/   -1, -1,  7,  2, -2,  0,  0,  0,  1, -3, -4,  0, -2,
+            -4, -2,  1,  0, -4, -2, -3,  5, -4,  0, -1, -5,
+    /*D*/   -2, -2,  2,  8, -4,  0,  2, -1, -1, -4, -4, -1, -4,
+            -5, -1,  0, -1, -5, -3, -4,  6, -4,  1, -1, -5,
+    /*C*/   -1, -4, -2, -4, 13, -3, -3, -3, -3, -2, -2, -3, -2,
+            -2, -4, -1, -1, -5, -3, -1, -3, -2, -3, -1, -5,
+    /*Q*/   -1,  1,  0,  0, -3,  7,  2, -2,  1, -3, -2,  2,  0,
+            -4, -1,  0, -1, -1, -1, -3,  0, -3,  4, -1, -5,
+    /*E*/   -1,  0,  0,  2, -3,  2,  6, -3,  0, -4, -3,  1, -2,
+            -3, -1, -1, -1, -3, -2, -3,  1, -3,  5, -1, -5,
+    /*G*/    0, -3,  0, -1, -3, -2, -3,  8, -2, -4, -4, -2, -3,
+            -4, -2,  0, -2, -3, -3, -4, -1, -4, -2, -1, -5,
+    /*H*/   -2,  0,  1, -1, -3,  1,  0, -2, 10, -4, -3,  0, -1,
+            -1, -2, -1, -2, -3,  2, -4,  0, -3,  0, -1, -5,
+    /*I*/   -1, -4, -3, -4, -2, -3, -4, -4, -4,  5,  2, -3,  2,
+             0, -3, -3, -1, -3, -1,  4, -4,  4, -3, -1, -5,
+    /*L*/   -2, -3, -4, -4, -2, -2, -3, -4, -3,  2,  5, -3,  3,
+             1, -4, -3, -1, -2, -1,  1, -4,  4, -3, -1, -5,
+    /*K*/   -1,  3,  0, -1, -3,  2,  1, -2,  0, -3, -3,  6, -2,
+            -4, -1,  0, -1, -3, -2, -3,  0, -3,  1, -1, -5,
+    /*M*/   -1, -2, -2, -4, -2,  0, -2, -3, -1,  2,  3, -2,  7,
+             0, -3, -2, -1, -1,  0,  1, -3,  2, -1, -1, -5,
+    /*F*/   -3, -3, -4, -5, -2, -4, -3, -4, -1,  0,  1, -4,  0,
+             8, -4, -3, -2,  1,  4, -1, -4,  1, -4, -1, -5,
+    /*P*/   -1, -3, -2, -1, -4, -1, -1, -2, -2, -3, -4, -1, -3,
+            -4, 10, -1, -1, -4, -3, -3, -2, -3, -1, -1, -5,
+    /*S*/    1, -1,  1,  0, -1,  0, -1,  0, -1, -3, -3,  0, -2,
+            -3, -1,  5,  2, -4, -2, -2,  0, -3,  0, -1, -5,
+    /*T*/    0, -1,  0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1,
+            -2, -1,  2,  5, -3, -2,  0,  0, -1, -1, -1, -5,
+    /*W*/   -3, -3, -4, -5, -5, -1, -3, -3, -3, -3, -2, -3, -1,
+             1, -4, -4, -3, 15,  2, -3, -5, -2, -2, -1, -5,
+    /*Y*/   -2, -1, -2, -3, -3, -1, -2, -3,  2, -1, -1, -2,  0,
+             4, -3, -2, -2,  2,  8, -1, -3, -1, -2, -1, -5,
+    /*V*/    0, -3, -3, -4, -1, -3, -3, -4, -4,  4,  1, -3,  1,
+            -1, -3, -2,  0, -3, -1,  5, -3,  2, -3, -1, -5,
+    /*B*/   -2, -1,  5,  6, -3,  0,  1, -1,  0, -4, -4,  0, -3,
+            -4, -2,  0,  0, -5, -3, -3,  6, -4,  1, -1, -5,
+    /*J*/   -2, -3, -4, -4, -2, -3, -3, -4, -3,  4,  4, -3,  2,
+             1, -3, -3, -1, -2, -1,  2, -4,  4, -3, -1, -5,
+    /*Z*/   -1,  0,  0,  1, -3,  4,  5, -2,  0, -3, -3,  1, -1,
+            -4, -1,  0, -1, -2, -2, -3,  1, -3,  5, -1, -5,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -5,
+    /***/   -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5,
+            -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Blosum50 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Blosum50PSM,
+    -5
+};
+
diff --git a/src/blast/sm_blosum62.c b/src/blast/sm_blosum62.c
new file mode 100644
index 0000000..3d9e87e
--- /dev/null
+++ b/src/blast/sm_blosum62.c
@@ -0,0 +1,96 @@
+/*  $Id: sm_blosum62.c 90506 2006-09-25 19:30:59Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+
+#include "raw_scoremat.h"
+
+/** Entries for the BLOSUM62 matrix at a scale of ln(2)/2.0. */
+static const TNCBIScore s_Blosum62PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    4, -1, -2, -2,  0, -1, -1,  0, -2, -1, -1, -1, -1,
+            -2, -1,  1,  0, -3, -2,  0, -2, -1, -1, -1, -4,
+    /*R*/   -1,  5,  0, -2, -3,  1,  0, -2,  0, -3, -2,  2, -1,
+            -3, -2, -1, -1, -3, -2, -3, -1, -2,  0, -1, -4,
+    /*N*/   -2,  0,  6,  1, -3,  0,  0,  0,  1, -3, -3,  0, -2,
+            -3, -2,  1,  0, -4, -2, -3,  4, -3,  0, -1, -4,
+    /*D*/   -2, -2,  1,  6, -3,  0,  2, -1, -1, -3, -4, -1, -3,
+            -3, -1,  0, -1, -4, -3, -3,  4, -3,  1, -1, -4,
+    /*C*/    0, -3, -3, -3,  9, -3, -4, -3, -3, -1, -1, -3, -1,
+            -2, -3, -1, -1, -2, -2, -1, -3, -1, -3, -1, -4,
+    /*Q*/   -1,  1,  0,  0, -3,  5,  2, -2,  0, -3, -2,  1,  0,
+            -3, -1,  0, -1, -2, -1, -2,  0, -2,  4, -1, -4,
+    /*E*/   -1,  0,  0,  2, -4,  2,  5, -2,  0, -3, -3,  1, -2,
+            -3, -1,  0, -1, -3, -2, -2,  1, -3,  4, -1, -4,
+    /*G*/    0, -2,  0, -1, -3, -2, -2,  6, -2, -4, -4, -2, -3,
+            -3, -2,  0, -2, -2, -3, -3, -1, -4, -2, -1, -4,
+    /*H*/   -2,  0,  1, -1, -3,  0,  0, -2,  8, -3, -3, -1, -2,
+            -1, -2, -1, -2, -2,  2, -3,  0, -3,  0, -1, -4,
+    /*I*/   -1, -3, -3, -3, -1, -3, -3, -4, -3,  4,  2, -3,  1,
+             0, -3, -2, -1, -3, -1,  3, -3,  3, -3, -1, -4,
+    /*L*/   -1, -2, -3, -4, -1, -2, -3, -4, -3,  2,  4, -2,  2,
+             0, -3, -2, -1, -2, -1,  1, -4,  3, -3, -1, -4,
+    /*K*/   -1,  2,  0, -1, -3,  1,  1, -2, -1, -3, -2,  5, -1,
+            -3, -1,  0, -1, -3, -2, -2,  0, -3,  1, -1, -4,
+    /*M*/   -1, -1, -2, -3, -1,  0, -2, -3, -2,  1,  2, -1,  5,
+             0, -2, -1, -1, -1, -1,  1, -3,  2, -1, -1, -4,
+    /*F*/   -2, -3, -3, -3, -2, -3, -3, -3, -1,  0,  0, -3,  0,
+             6, -4, -2, -2,  1,  3, -1, -3,  0, -3, -1, -4,
+    /*P*/   -1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2,
+            -4,  7, -1, -1, -4, -3, -2, -2, -3, -1, -1, -4,
+    /*S*/    1, -1,  1,  0, -1,  0,  0,  0, -1, -2, -2,  0, -1,
+            -2, -1,  4,  1, -3, -2, -2,  0, -2,  0, -1, -4,
+    /*T*/    0, -1,  0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1,
+            -2, -1,  1,  5, -2, -2,  0, -1, -1, -1, -1, -4,
+    /*W*/   -3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1,
+             1, -4, -3, -2, 11,  2, -3, -4, -2, -2, -1, -4,
+    /*Y*/   -2, -2, -2, -3, -2, -1, -2, -3,  2, -1, -1, -2, -1,
+             3, -3, -2, -2,  2,  7, -1, -3, -1, -2, -1, -4,
+    /*V*/    0, -3, -3, -3, -1, -2, -2, -3, -3,  3,  1, -2,  1,
+            -1, -2, -2,  0, -3, -1,  4, -3,  2, -2, -1, -4,
+    /*B*/   -2, -1,  4,  4, -3,  0,  1, -1,  0, -3, -4,  0, -3,
+            -3, -2,  0, -1, -4, -3, -3,  4, -3,  0, -1, -4,
+    /*J*/   -1, -2, -3, -3, -1, -2, -3, -4, -3,  3,  3, -3,  2,
+             0, -3, -2, -1, -2, -1,  2, -3,  3, -3, -1, -4,
+    /*Z*/   -1,  0,  0,  1, -3,  4,  4, -2,  0, -3, -3,  1, -1,
+            -3, -1,  0, -1, -2, -2, -2,  0, -3,  4, -1, -4,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4,
+    /***/   -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
+            -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Blosum62 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Blosum62PSM,
+    -4
+};
+
diff --git a/src/blast/sm_blosum80.c b/src/blast/sm_blosum80.c
new file mode 100644
index 0000000..80aaf8e
--- /dev/null
+++ b/src/blast/sm_blosum80.c
@@ -0,0 +1,97 @@
+/*  $Id: sm_blosum80.c 90506 2006-09-25 19:30:59Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+
+#include "raw_scoremat.h"
+
+/** Entries for the BLOSUM80 matrix at a scale of ln(2)/2.0. */
+
+static const TNCBIScore s_Blosum80PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    5, -2, -2, -2, -1, -1, -1,  0, -2, -2, -2, -1, -1,
+            -3, -1,  1,  0, -3, -2,  0, -2, -2, -1, -1, -6,
+    /*R*/   -2,  6, -1, -2, -4,  1, -1, -3,  0, -3, -3,  2, -2,
+            -4, -2, -1, -1, -4, -3, -3, -1, -3,  0, -1, -6,
+    /*N*/   -2, -1,  6,  1, -3,  0, -1, -1,  0, -4, -4,  0, -3,
+            -4, -3,  0,  0, -4, -3, -4,  5, -4,  0, -1, -6,
+    /*D*/   -2, -2,  1,  6, -4, -1,  1, -2, -2, -4, -5, -1, -4,
+            -4, -2, -1, -1, -6, -4, -4,  5, -5,  1, -1, -6,
+    /*C*/   -1, -4, -3, -4,  9, -4, -5, -4, -4, -2, -2, -4, -2,
+            -3, -4, -2, -1, -3, -3, -1, -4, -2, -4, -1, -6,
+    /*Q*/   -1,  1,  0, -1, -4,  6,  2, -2,  1, -3, -3,  1,  0,
+            -4, -2,  0, -1, -3, -2, -3,  0, -3,  4, -1, -6,
+    /*E*/   -1, -1, -1,  1, -5,  2,  6, -3,  0, -4, -4,  1, -2,
+            -4, -2,  0, -1, -4, -3, -3,  1, -4,  5, -1, -6,
+    /*G*/    0, -3, -1, -2, -4, -2, -3,  6, -3, -5, -4, -2, -4,
+            -4, -3, -1, -2, -4, -4, -4, -1, -5, -3, -1, -6,
+    /*H*/   -2,  0,  0, -2, -4,  1,  0, -3,  8, -4, -3, -1, -2,
+            -2, -3, -1, -2, -3,  2, -4, -1, -4,  0, -1, -6,
+    /*I*/   -2, -3, -4, -4, -2, -3, -4, -5, -4,  5,  1, -3,  1,
+            -1, -4, -3, -1, -3, -2,  3, -4,  3, -4, -1, -6,
+    /*L*/   -2, -3, -4, -5, -2, -3, -4, -4, -3,  1,  4, -3,  2,
+             0, -3, -3, -2, -2, -2,  1, -4,  3, -3, -1, -6,
+    /*K*/   -1,  2,  0, -1, -4,  1,  1, -2, -1, -3, -3,  5, -2,
+            -4, -1, -1, -1, -4, -3, -3, -1, -3,  1, -1, -6,
+    /*M*/   -1, -2, -3, -4, -2,  0, -2, -4, -2,  1,  2, -2,  6,
+             0, -3, -2, -1, -2, -2,  1, -3,  2, -1, -1, -6,
+    /*F*/   -3, -4, -4, -4, -3, -4, -4, -4, -2, -1,  0, -4,  0,
+             6, -4, -3, -2,  0,  3, -1, -4,  0, -4, -1, -6,
+    /*P*/   -1, -2, -3, -2, -4, -2, -2, -3, -3, -4, -3, -1, -3,
+            -4,  8, -1, -2, -5, -4, -3, -2, -4, -2, -1, -6,
+    /*S*/    1, -1,  0, -1, -2,  0,  0, -1, -1, -3, -3, -1, -2,
+            -3, -1,  5,  1, -4, -2, -2,  0, -3,  0, -1, -6,
+    /*T*/    0, -1,  0, -1, -1, -1, -1, -2, -2, -1, -2, -1, -1,
+            -2, -2,  1,  5, -4, -2,  0, -1, -1, -1, -1, -6,
+    /*W*/   -3, -4, -4, -6, -3, -3, -4, -4, -3, -3, -2, -4, -2,
+             0, -5, -4, -4, 11,  2, -3, -5, -3, -3, -1, -6,
+    /*Y*/   -2, -3, -3, -4, -3, -2, -3, -4,  2, -2, -2, -3, -2,
+             3, -4, -2, -2,  2,  7, -2, -3, -2, -3, -1, -6,
+    /*V*/    0, -3, -4, -4, -1, -3, -3, -4, -4,  3,  1, -3,  1,
+            -1, -3, -2,  0, -3, -2,  4, -4,  2, -3, -1, -6,
+    /*B*/   -2, -1,  5,  5, -4,  0,  1, -1, -1, -4, -4, -1, -3,
+            -4, -2,  0, -1, -5, -3, -4,  5, -4,  0, -1, -6,
+    /*J*/   -2, -3, -4, -5, -2, -3, -4, -5, -4,  3,  3, -3,  2,
+             0, -4, -3, -1, -3, -2,  2, -4,  3, -3, -1, -6,
+    /*Z*/   -1,  0,  0,  1, -4,  4,  5, -3,  0, -4, -3,  1, -1,
+            -4, -2,  0, -1, -3, -3, -3,  0, -3,  5, -1, -6,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -6,
+    /***/   -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6,
+            -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Blosum80 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Blosum80PSM,
+    -6
+};
+
diff --git a/src/blast/sm_blosum90.c b/src/blast/sm_blosum90.c
new file mode 100644
index 0000000..8889e4a
--- /dev/null
+++ b/src/blast/sm_blosum90.c
@@ -0,0 +1,96 @@
+/*  $Id: sm_blosum90.c 90507 2006-09-25 19:31:51Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+#include "raw_scoremat.h"
+
+/** Entries for the BLOSUM90 matrix at a scale of ln(2)/2.0. */
+
+static const TNCBIScore s_Blosum90PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    5, -2, -2, -3, -1, -1, -1,  0, -2, -2, -2, -1, -2,
+            -3, -1,  1,  0, -4, -3, -1, -2, -2, -1, -1, -6,
+    /*R*/   -2,  6, -1, -3, -5,  1, -1, -3,  0, -4, -3,  2, -2,
+            -4, -3, -1, -2, -4, -3, -3, -2, -3,  0, -1, -6,
+    /*N*/   -2, -1,  7,  1, -4,  0, -1, -1,  0, -4, -4,  0, -3,
+            -4, -3,  0,  0, -5, -3, -4,  5, -4, -1, -1, -6,
+    /*D*/   -3, -3,  1,  7, -5, -1,  1, -2, -2, -5, -5, -1, -4,
+            -5, -3, -1, -2, -6, -4, -5,  5, -5,  1, -1, -6,
+    /*C*/   -1, -5, -4, -5,  9, -4, -6, -4, -5, -2, -2, -4, -2,
+            -3, -4, -2, -2, -4, -4, -2, -4, -2, -5, -1, -6,
+    /*Q*/   -1,  1,  0, -1, -4,  7,  2, -3,  1, -4, -3,  1,  0,
+            -4, -2, -1, -1, -3, -3, -3, -1, -3,  5, -1, -6,
+    /*E*/   -1, -1, -1,  1, -6,  2,  6, -3, -1, -4, -4,  0, -3,
+            -5, -2, -1, -1, -5, -4, -3,  1, -4,  5, -1, -6,
+    /*G*/    0, -3, -1, -2, -4, -3, -3,  6, -3, -5, -5, -2, -4,
+            -5, -3, -1, -3, -4, -5, -5, -2, -5, -3, -1, -6,
+    /*H*/   -2,  0,  0, -2, -5,  1, -1, -3,  8, -4, -4, -1, -3,
+            -2, -3, -2, -2, -3,  1, -4, -1, -4,  0, -1, -6,
+    /*I*/   -2, -4, -4, -5, -2, -4, -4, -5, -4,  5,  1, -4,  1,
+            -1, -4, -3, -1, -4, -2,  3, -5,  3, -4, -1, -6,
+    /*L*/   -2, -3, -4, -5, -2, -3, -4, -5, -4,  1,  5, -3,  2,
+             0, -4, -3, -2, -3, -2,  0, -5,  4, -4, -1, -6,
+    /*K*/   -1,  2,  0, -1, -4,  1,  0, -2, -1, -4, -3,  6, -2,
+            -4, -2, -1, -1, -5, -3, -3, -1, -3,  1, -1, -6,
+    /*M*/   -2, -2, -3, -4, -2,  0, -3, -4, -3,  1,  2, -2,  7,
+            -1, -3, -2, -1, -2, -2,  0, -4,  2, -2, -1, -6,
+    /*F*/   -3, -4, -4, -5, -3, -4, -5, -5, -2, -1,  0, -4, -1,
+             7, -4, -3, -3,  0,  3, -2, -4,  0, -4, -1, -6,
+    /*P*/   -1, -3, -3, -3, -4, -2, -2, -3, -3, -4, -4, -2, -3,
+            -4,  8, -2, -2, -5, -4, -3, -3, -4, -2, -1, -6,
+    /*S*/    1, -1,  0, -1, -2, -1, -1, -1, -2, -3, -3, -1, -2,
+            -3, -2,  5,  1, -4, -3, -2,  0, -3, -1, -1, -6,
+    /*T*/    0, -2,  0, -2, -2, -1, -1, -3, -2, -1, -2, -1, -1,
+            -3, -2,  1,  6, -4, -2, -1, -1, -2, -1, -1, -6,
+    /*W*/   -4, -4, -5, -6, -4, -3, -5, -4, -3, -4, -3, -5, -2,
+             0, -5, -4, -4, 11,  2, -3, -6, -3, -4, -1, -6,
+    /*Y*/   -3, -3, -3, -4, -4, -3, -4, -5,  1, -2, -2, -3, -2,
+             3, -4, -3, -2,  2,  8, -3, -4, -2, -3, -1, -6,
+    /*V*/   -1, -3, -4, -5, -2, -3, -3, -5, -4,  3,  0, -3,  0,
+            -2, -3, -2, -1, -3, -3,  5, -4,  1, -3, -1, -6,
+    /*B*/   -2, -2,  5,  5, -4, -1,  1, -2, -1, -5, -5, -1, -4,
+            -4, -3,  0, -1, -6, -4, -4,  5, -5,  0, -1, -6,
+    /*J*/   -2, -3, -4, -5, -2, -3, -4, -5, -4,  3,  4, -3,  2,
+             0, -4, -3, -2, -3, -2,  1, -5,  4, -4, -1, -6,
+    /*Z*/   -1,  0, -1,  1, -5,  5,  5, -3,  0, -4, -4,  1, -2,
+            -4, -2, -1, -1, -4, -3, -3,  0, -4,  5, -1, -6,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -6,
+    /***/   -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6,
+            -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Blosum90 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Blosum90PSM,
+    -6
+};
+
diff --git a/src/blast/sm_pam250.c b/src/blast/sm_pam250.c
new file mode 100644
index 0000000..d23a1bc
--- /dev/null
+++ b/src/blast/sm_pam250.c
@@ -0,0 +1,96 @@
+/*  $Id: sm_pam250.c 90506 2006-09-25 19:30:59Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+#include "raw_scoremat.h"
+
+/** Entries for the PAM250 matrix at a scale of ln(2)/3.0. */
+
+static const TNCBIScore s_Pam250PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    2, -2,  0,  0, -2,  0,  0,  1, -1, -1, -2, -1, -1,
+            -3,  1,  1,  1, -6, -3,  0,  0, -1,  0, -1, -8,
+    /*R*/   -2,  6,  0, -1, -4,  1, -1, -3,  2, -2, -3,  3,  0,
+            -4,  0,  0, -1,  2, -4, -2, -1, -3,  0, -1, -8,
+    /*N*/    0,  0,  2,  2, -4,  1,  1,  0,  2, -2, -3,  1, -2,
+            -3,  0,  1,  0, -4, -2, -2,  2, -3,  1, -1, -8,
+    /*D*/    0, -1,  2,  4, -5,  2,  3,  1,  1, -2, -4,  0, -3,
+            -6, -1,  0,  0, -7, -4, -2,  3, -3,  3, -1, -8,
+    /*C*/   -2, -4, -4, -5, 12, -5, -5, -3, -3, -2, -6, -5, -5,
+            -4, -3,  0, -2, -8,  0, -2, -4, -5, -5, -1, -8,
+    /*Q*/    0,  1,  1,  2, -5,  4,  2, -1,  3, -2, -2,  1, -1,
+            -5,  0, -1, -1, -5, -4, -2,  1, -2,  3, -1, -8,
+    /*E*/    0, -1,  1,  3, -5,  2,  4,  0,  1, -2, -3,  0, -2,
+            -5, -1,  0,  0, -7, -4, -2,  3, -3,  3, -1, -8,
+    /*G*/    1, -3,  0,  1, -3, -1,  0,  5, -2, -3, -4, -2, -3,
+            -5,  0,  1,  0, -7, -5, -1,  0, -4,  0, -1, -8,
+    /*H*/   -1,  2,  2,  1, -3,  3,  1, -2,  6, -2, -2,  0, -2,
+            -2,  0, -1, -1, -3,  0, -2,  1, -2,  2, -1, -8,
+    /*I*/   -1, -2, -2, -2, -2, -2, -2, -3, -2,  5,  2, -2,  2,
+             1, -2, -1,  0, -5, -1,  4, -2,  3, -2, -1, -8,
+    /*L*/   -2, -3, -3, -4, -6, -2, -3, -4, -2,  2,  6, -3,  4,
+             2, -3, -3, -2, -2, -1,  2, -3,  5, -3, -1, -8,
+    /*K*/   -1,  3,  1,  0, -5,  1,  0, -2,  0, -2, -3,  5,  0,
+            -5, -1,  0,  0, -3, -4, -2,  1, -3,  0, -1, -8,
+    /*M*/   -1,  0, -2, -3, -5, -1, -2, -3, -2,  2,  4,  0,  6,
+             0, -2, -2, -1, -4, -2,  2, -2,  3, -2, -1, -8,
+    /*F*/   -3, -4, -3, -6, -4, -5, -5, -5, -2,  1,  2, -5,  0,
+             9, -5, -3, -3,  0,  7, -1, -4,  2, -5, -1, -8,
+    /*P*/    1,  0,  0, -1, -3,  0, -1,  0,  0, -2, -3, -1, -2,
+            -5,  6,  1,  0, -6, -5, -1, -1, -2,  0, -1, -8,
+    /*S*/    1,  0,  1,  0,  0, -1,  0,  1, -1, -1, -3,  0, -2,
+            -3,  1,  2,  1, -2, -3, -1,  0, -2,  0, -1, -8,
+    /*T*/    1, -1,  0,  0, -2, -1,  0,  0, -1,  0, -2,  0, -1,
+            -3,  0,  1,  3, -5, -3,  0,  0, -1, -1, -1, -8,
+    /*W*/   -6,  2, -4, -7, -8, -5, -7, -7, -3, -5, -2, -3, -4,
+             0, -6, -2, -5, 17,  0, -6, -5, -3, -6, -1, -8,
+    /*Y*/   -3, -4, -2, -4,  0, -4, -4, -5,  0, -1, -1, -4, -2,
+             7, -5, -3, -3,  0, 10, -2, -3, -1, -4, -1, -8,
+    /*V*/    0, -2, -2, -2, -2, -2, -2, -1, -2,  4,  2, -2,  2,
+            -1, -1, -1,  0, -6, -2,  4, -2,  2, -2, -1, -8,
+    /*B*/    0, -1,  2,  3, -4,  1,  3,  0,  1, -2, -3,  1, -2,
+            -4, -1,  0,  0, -5, -3, -2,  3, -3,  2, -1, -8,
+    /*J*/   -1, -3, -3, -3, -5, -2, -3, -4, -2,  3,  5, -3,  3,
+             2, -2, -2, -1, -3, -1,  2, -3,  5, -2, -1, -8,
+    /*Z*/    0,  0,  1,  3, -5,  3,  3,  0,  2, -2, -3,  0, -2,
+            -5,  0,  0, -1, -6, -4, -2,  2, -2,  3, -1, -8,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -8,
+    /***/   -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
+            -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Pam250 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Pam250PSM,
+    -8
+};
+
diff --git a/src/blast/sm_pam30.c b/src/blast/sm_pam30.c
new file mode 100644
index 0000000..53d791a
--- /dev/null
+++ b/src/blast/sm_pam30.c
@@ -0,0 +1,96 @@
+/*  $Id: sm_pam30.c 90506 2006-09-25 19:30:59Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+#include "raw_scoremat.h"
+
+/** Entries for the PAM30 matrix at a scale of ln(2)/2.0. */
+
+static const TNCBIScore s_Pam30PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    6, -7, -4, -3, -6, -4, -2, -2, -7, -5, -6, -7, -5,
+            -8, -2,  0, -1,-13, -8, -2, -3, -6, -3, -1,-17,
+    /*R*/   -7,  8, -6,-10, -8, -2, -9, -9, -2, -5, -8,  0, -4,
+            -9, -4, -3, -6, -2,-10, -8, -7, -7, -4, -1,-17,
+    /*N*/   -4, -6,  8,  2,-11, -3, -2, -3,  0, -5, -7, -1, -9,
+            -9, -6,  0, -2, -8, -4, -8,  6, -6, -3, -1,-17,
+    /*D*/   -3,-10,  2,  8,-14, -2,  2, -3, -4, -7,-12, -4,-11,
+           -15, -8, -4, -5,-15,-11, -8,  6,-10,  1, -1,-17,
+    /*C*/   -6, -8,-11,-14, 10,-14,-14, -9, -7, -6,-15,-14,-13,
+           -13, -8, -3, -8,-15, -4, -6,-12, -9,-14, -1,-17,
+    /*Q*/   -4, -2, -3, -2,-14,  8,  1, -7,  1, -8, -5, -3, -4,
+           -13, -3, -5, -5,-13,-12, -7, -3, -5,  6, -1,-17,
+    /*E*/   -2, -9, -2,  2,-14,  1,  8, -4, -5, -5, -9, -4, -7,
+           -14, -5, -4, -6,-17, -8, -6,  1, -7,  6, -1,-17,
+    /*G*/   -2, -9, -3, -3, -9, -7, -4,  6, -9,-11,-10, -7, -8,
+            -9, -6, -2, -6,-15,-14, -5, -3,-10, -5, -1,-17,
+    /*H*/   -7, -2,  0, -4, -7,  1, -5, -9,  9, -9, -6, -6,-10,
+            -6, -4, -6, -7, -7, -3, -6, -1, -7, -1, -1,-17,
+    /*I*/   -5, -5, -5, -7, -6, -8, -5,-11, -9,  8, -1, -6, -1,
+            -2, -8, -7, -2,-14, -6,  2, -6,  5, -6, -1,-17,
+    /*L*/   -6, -8, -7,-12,-15, -5, -9,-10, -6, -1,  7, -8,  1,
+            -3, -7, -8, -7, -6, -7, -2, -9,  6, -7, -1,-17,
+    /*K*/   -7,  0, -1, -4,-14, -3, -4, -7, -6, -6, -8,  7, -2,
+           -14, -6, -4, -3,-12, -9, -9, -2, -7, -4, -1,-17,
+    /*M*/   -5, -4, -9,-11,-13, -4, -7, -8,-10, -1,  1, -2, 11,
+            -4, -8, -5, -4,-13,-11, -1,-10,  0, -5, -1,-17,
+    /*F*/   -8, -9, -9,-15,-13,-13,-14, -9, -6, -2, -3,-14, -4,
+             9,-10, -6, -9, -4,  2, -8,-10, -2,-13, -1,-17,
+    /*P*/   -2, -4, -6, -8, -8, -3, -5, -6, -4, -8, -7, -6, -8,
+           -10,  8, -2, -4,-14,-13, -6, -7, -7, -4, -1,-17,
+    /*S*/    0, -3,  0, -4, -3, -5, -4, -2, -6, -7, -8, -4, -5,
+            -6, -2,  6,  0, -5, -7, -6, -1, -8, -5, -1,-17,
+    /*T*/   -1, -6, -2, -5, -8, -5, -6, -6, -7, -2, -7, -3, -4,
+            -9, -4,  0,  7,-13, -6, -3, -3, -5, -6, -1,-17,
+    /*W*/  -13, -2, -8,-15,-15,-13,-17,-15, -7,-14, -6,-12,-13,
+            -4,-14, -5,-13, 13, -5,-15,-10, -7,-14, -1,-17,
+    /*Y*/   -8,-10, -4,-11, -4,-12, -8,-14, -3, -6, -7, -9,-11,
+             2,-13, -7, -6, -5, 10, -7, -6, -7, -9, -1,-17,
+    /*V*/   -2, -8, -8, -8, -6, -7, -6, -5, -6,  2, -2, -9, -1,
+            -8, -6, -6, -3,-15, -7,  7, -8,  0, -6, -1,-17,
+    /*B*/   -3, -7,  6,  6,-12, -3,  1, -3, -1, -6, -9, -2,-10,
+           -10, -7, -1, -3,-10, -6, -8,  6, -8,  0, -1,-17,
+    /*J*/   -6, -7, -6,-10, -9, -5, -7,-10, -7,  5,  6, -7,  0,
+            -2, -7, -8, -5, -7, -7,  0, -8,  6, -6, -1,-17,
+    /*Z*/   -3, -4, -3,  1,-14,  6,  6, -5, -1, -6, -7, -4, -5,
+           -13, -4, -5, -6,-14, -9, -6,  0, -6,  6, -1,-17,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-17,
+    /***/  -17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,
+           -17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Pam30 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Pam30PSM,
+    -17
+};
+
diff --git a/src/blast/sm_pam70.c b/src/blast/sm_pam70.c
new file mode 100644
index 0000000..57f9de8
--- /dev/null
+++ b/src/blast/sm_pam70.c
@@ -0,0 +1,96 @@
+/*  $Id: sm_pam70.c 90506 2006-09-25 19:30:59Z madden $
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*               National Center for Biotechnology Information
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government have not placed any restriction on its use or reproduction.
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+*  Please cite the author in any work or product based on this material.
+*
+* ===========================================================================
+*
+* Author:  Aaron Ucko, Mike Gertz
+*
+* File Description:
+*   Protein alignment score matrices; shared between the two toolkits.
+*
+* ===========================================================================
+*/
+#include "raw_scoremat.h"
+
+/** Entries for the PAM70 matrix at a scale of ln(2)/2.0. */
+
+static const TNCBIScore s_Pam70PSM[25 * 25] = {
+    /*       A,  R,  N,  D,  C,  Q,  E,  G,  H,  I,  L,  K,  M,
+             F,  P,  S,  T,  W,  Y,  V,  B,  J,  Z,  X,  *        */ 
+    /*A*/    5, -4, -2, -1, -4, -2, -1,  0, -4, -2, -4, -4, -3,
+            -6,  0,  1,  1, -9, -5, -1, -1, -3, -1, -1,-11,
+    /*R*/   -4,  8, -3, -6, -5,  0, -5, -6,  0, -3, -6,  2, -2,
+            -7, -2, -1, -4,  0, -7, -5, -4, -5, -2, -1,-11,
+    /*N*/   -2, -3,  6,  3, -7, -1,  0, -1,  1, -3, -5,  0, -5,
+            -6, -3,  1,  0, -6, -3, -5,  5, -4, -1, -1,-11,
+    /*D*/   -1, -6,  3,  6, -9,  0,  3, -1, -1, -5, -8, -2, -7,
+           -10, -4, -1, -2,-10, -7, -5,  5, -7,  2, -1,-11,
+    /*C*/   -4, -5, -7, -9,  9, -9, -9, -6, -5, -4,-10, -9, -9,
+            -8, -5, -1, -5,-11, -2, -4, -8, -7, -9, -1,-11,
+    /*Q*/   -2,  0, -1,  0, -9,  7,  2, -4,  2, -5, -3, -1, -2,
+            -9, -1, -3, -3, -8, -8, -4, -1, -3,  5, -1,-11,
+    /*E*/   -1, -5,  0,  3, -9,  2,  6, -2, -2, -4, -6, -2, -4,
+            -9, -3, -2, -3,-11, -6, -4,  2, -5,  5, -1,-11,
+    /*G*/    0, -6, -1, -1, -6, -4, -2,  6, -6, -6, -7, -5, -6,
+            -7, -3,  0, -3,-10, -9, -3, -1, -7, -3, -1,-11,
+    /*H*/   -4,  0,  1, -1, -5,  2, -2, -6,  8, -6, -4, -3, -6,
+            -4, -2, -3, -4, -5, -1, -4,  0, -4,  1, -1,-11,
+    /*I*/   -2, -3, -3, -5, -4, -5, -4, -6, -6,  7,  1, -4,  1,
+             0, -5, -4, -1, -9, -4,  3, -4,  4, -4, -1,-11,
+    /*L*/   -4, -6, -5, -8,-10, -3, -6, -7, -4,  1,  6, -5,  2,
+            -1, -5, -6, -4, -4, -4,  0, -6,  5, -4, -1,-11,
+    /*K*/   -4,  2,  0, -2, -9, -1, -2, -5, -3, -4, -5,  6,  0,
+            -9, -4, -2, -1, -7, -7, -6, -1, -5, -2, -1,-11,
+    /*M*/   -3, -2, -5, -7, -9, -2, -4, -6, -6,  1,  2,  0, 10,
+            -2, -5, -3, -2, -8, -7,  0, -6,  2, -3, -1,-11,
+    /*F*/   -6, -7, -6,-10, -8, -9, -9, -7, -4,  0, -1, -9, -2,
+             8, -7, -4, -6, -2,  4, -5, -7, -1, -9, -1,-11,
+    /*P*/    0, -2, -3, -4, -5, -1, -3, -3, -2, -5, -5, -4, -5,
+            -7,  7,  0, -2, -9, -9, -3, -4, -5, -2, -1,-11,
+    /*S*/    1, -1,  1, -1, -1, -3, -2,  0, -3, -4, -6, -2, -3,
+            -4,  0,  5,  2, -3, -5, -3,  0, -5, -2, -1,-11,
+    /*T*/    1, -4,  0, -2, -5, -3, -3, -3, -4, -1, -4, -1, -2,
+            -6, -2,  2,  6, -8, -4, -1, -1, -3, -3, -1,-11,
+    /*W*/   -9,  0, -6,-10,-11, -8,-11,-10, -5, -9, -4, -7, -8,
+            -2, -9, -3, -8, 13, -3,-10, -7, -5,-10, -1,-11,
+    /*Y*/   -5, -7, -3, -7, -2, -8, -6, -9, -1, -4, -4, -7, -7,
+             4, -9, -5, -4, -3,  9, -5, -4, -4, -7, -1,-11,
+    /*V*/   -1, -5, -5, -5, -4, -4, -4, -3, -4,  3,  0, -6,  0,
+            -5, -3, -3, -1,-10, -5,  6, -5,  1, -4, -1,-11,
+    /*B*/   -1, -4,  5,  5, -8, -1,  2, -1,  0, -4, -6, -1, -6,
+            -7, -4,  0, -1, -7, -4, -5,  5, -5,  1, -1,-11,
+    /*J*/   -3, -5, -4, -7, -7, -3, -5, -7, -4,  4,  5, -5,  2,
+            -1, -5, -5, -3, -5, -4,  1, -5,  5, -4, -1,-11,
+    /*Z*/   -1, -2, -1,  2, -9,  5,  5, -3,  1, -4, -4, -2, -3,
+            -9, -2, -2, -3,-10, -7, -4,  1, -4,  5, -1,-11,
+    /*X*/   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-11,
+    /***/  -11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,
+           -11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,  1
+};
+const SNCBIPackedScoreMatrix NCBISM_Pam70 = {
+    "ARNDCQEGHILKMFPSTWYVBJZX*",
+    s_Pam70PSM,
+    -11
+};
+
diff --git a/src/data/count_approximate.cpp b/src/data/count_approximate.cpp
new file mode 100644
index 0000000..dcff5dc
--- /dev/null
+++ b/src/data/count_approximate.cpp
@@ -0,0 +1,110 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <set>
+#include "index.h"
+#include "../basic/shape_config.h"
+
+template<unsigned PartitionBits> struct Flajolet_Martin_counter
+{
+	static const unsigned N = 1 << PartitionBits;
+	static const uint64_t MASK = N - 1;
+	static const uint64_t HIGH = MASK << (64 - PartitionBits);
+	static const double PHI;
+	uint64_t buckets[N];
+
+	Flajolet_Martin_counter()
+	{
+		clear();
+	}
+
+	void clear()
+	{
+		for (unsigned i = 0; i<N; ++i)
+			buckets[i] = 0;
+	}
+
+	void add(uint64_t hash)
+	{
+		buckets[hash & MASK] |= 1LL << ctz(HIGH | (hash >> PartitionBits));
+	}
+
+	double get()
+	{
+		int n = 0;
+		for (unsigned i = 0; i<N; ++i)
+			n += ctz(~buckets[i]);
+		return double(N) / PHI * pow(2, double(n) / N);
+	}
+
+};
+
+template<unsigned PartitionBits> const double Flajolet_Martin_counter<PartitionBits>::PHI = 0.77351;
+
+struct Exact_counter
+{
+	Exact_counter():
+		seeds(shape_to-shape_from)
+	{}
+	void operator()(Hashed_seed seed, size_t pos, unsigned shape_id)
+	{
+		seeds[shape_id - shape_from][seed.partition()].insert(seed);
+	}
+	void finish()
+	{}
+	vector<Array<std::set<uint64_t>, Hashed_seed::p> > seeds;
+};
+
+struct Approximate_counter
+{
+	Approximate_counter() :
+		data(shape_to - shape_from)
+	{}
+	void operator()(Hashed_seed seed, size_t pos, unsigned shape_id)
+	{
+		data[shape_id - shape_from].add(seed);
+	}
+	void finish()
+	{}
+	enum { counter_pbits = 8 };
+	vector<Flajolet_Martin_counter<counter_pbits> > data;
+};
+
+vector<Array<unsigned, Hashed_seed::p> > count_exact(const Sequence_set &seqs)
+{
+	vector<Exact_counter> counters(config.threads_);
+	seqs.enum_seeds(counters);
+	vector<Array<unsigned, Hashed_seed::p> > out(shape_to - shape_from);
+	memset(out.data(), 0, (shape_to - shape_from)*Hashed_seed::p*sizeof(unsigned));
+	for (unsigned s = 0; s < shape_to - shape_from; ++s)
+		for (unsigned p = 0; p < Hashed_seed::p; ++p)
+			for (unsigned t = 0; t < config.threads_; ++t)
+				out[s][p] += (unsigned)counters[t].seeds[s][p].size();
+	return out;	
+}
+
+vector<size_t> count_approximate(const Sequence_set &seqs)
+{
+	vector<Approximate_counter> counters(config.threads_);
+	seqs.enum_seeds(counters);
+	vector<size_t> out(shape_to - shape_from);
+	for (unsigned s = 0; s < shape_to - shape_from; ++s)
+		for (unsigned t = 0; t < config.threads_; ++t)
+			out[s] += (size_t)counters[t].data[s].get();
+	return out;
+}
\ No newline at end of file
diff --git a/src/data/frequent_seeds.cpp b/src/data/frequent_seeds.cpp
new file mode 100644
index 0000000..31c6831
--- /dev/null
+++ b/src/data/frequent_seeds.cpp
@@ -0,0 +1,109 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <numeric>
+#include "frequent_seeds.h"
+#include "sorted_list.h"
+
+const double Frequent_seeds::hash_table_factor = 1.3;
+Frequent_seeds frequent_seeds;
+
+void Frequent_seeds::compute_sd(Atomic<unsigned> *seedp, const sorted_list *ref_idx, const sorted_list *query_idx, vector<Sd> *ref_out, vector<Sd> *query_out)
+{
+	unsigned p;
+	while ((p = (*seedp)++) < current_range.end()) {
+		Sd ref_sd;
+		sorted_list::const_iterator it = ref_idx->get_partition_cbegin(p);
+		while (!it.at_end()) {
+			ref_sd.add((double)it.n);
+			++it;
+		}
+		(*ref_out)[p - current_range.begin()] = ref_sd;
+
+		Sd query_sd;
+		it = query_idx->get_partition_cbegin(p);
+		while (!it.at_end()) {
+			query_sd.add((double)it.n);
+			++it;
+		}
+		(*query_out)[p - current_range.begin()] = query_sd;
+	}
+}
+
+struct Frequent_seeds::Build_context
+{
+	Build_context(const sorted_list &ref_idx, const sorted_list &query_idx, const seedp_range &range, unsigned sid, unsigned ref_max_n, unsigned query_max_n, vector<unsigned> &counts) :
+		ref_idx(ref_idx),
+		query_idx(query_idx),
+		range(range),
+		sid(sid),
+		ref_max_n(ref_max_n),
+		query_max_n(query_max_n),
+		counts(counts)
+	{ }
+	void operator()(unsigned thread_id, unsigned seedp)
+	{
+		if (!range.contains(seedp))
+			return;
+		
+		vector<uint32_t> buf;
+		size_t n = 0;
+		Merge_iterator<sorted_list::iterator> merge_it(ref_idx.get_partition_begin(seedp), query_idx.get_partition_begin(seedp));
+		while (merge_it.next()) {
+			if (merge_it.i.n > ref_max_n || merge_it.j.n > query_max_n) {
+				merge_it.i.get(0)->value = 0;
+				n += (unsigned)merge_it.i.n;
+				buf.push_back(merge_it.i.key());
+			}
+			++merge_it;
+		}
+
+		const size_t ht_size = std::max((size_t)(buf.size() * hash_table_factor), buf.size() + 1);
+		PHash_set hash_set(ht_size);
+
+		for (vector<uint32_t>::const_iterator i = buf.begin(); i != buf.end(); ++i)
+			hash_set.insert(*i);
+
+		frequent_seeds.tables_[sid][seedp] = hash_set;
+		counts[seedp] = (unsigned)n;
+	}
+	const sorted_list &ref_idx;
+	const sorted_list &query_idx;
+	const seedp_range range;
+	const unsigned sid, ref_max_n, query_max_n;
+	vector<unsigned> &counts;
+};
+
+void Frequent_seeds::build(unsigned sid, const seedp_range &range, sorted_list &ref_idx, const sorted_list &query_idx)
+{
+	vector<Sd> ref_sds(range.size()), query_sds(range.size());
+	Atomic<unsigned> seedp (range.begin());
+	Thread_pool threads;
+	for (unsigned i = 0; i < config.threads_; ++i)
+		threads.push_back(launch_thread(compute_sd, &seedp, &ref_idx, &query_idx, &ref_sds, &query_sds));
+	threads.join_all();
+
+	Sd ref_sd(ref_sds), query_sd(query_sds);
+	const unsigned ref_max_n = (unsigned)(ref_sd.mean() + config.freq_sd*ref_sd.sd()), query_max_n = (unsigned)(query_sd.mean() + config.freq_sd*query_sd.sd());
+	log_stream << "Seed frequency mean (reference) = " << ref_sd.mean() << ", SD = " << ref_sd.sd() << endl;
+	log_stream << "Seed frequency mean (query) = " << query_sd.mean() << ", SD = " << query_sd.sd() << endl;
+	vector<unsigned> counts(Const::seedp);
+	Build_context build_context(ref_idx, query_idx, range, sid, ref_max_n, query_max_n, counts);
+	launch_scheduled_thread_pool(build_context, Const::seedp, config.threads_);
+	log_stream << "Masked positions = " << std::accumulate(counts.begin(), counts.end(), 0) << std::endl;
+}
\ No newline at end of file
diff --git a/src/data/frequent_seeds.h b/src/data/frequent_seeds.h
new file mode 100644
index 0000000..522651f
--- /dev/null
+++ b/src/data/frequent_seeds.h
@@ -0,0 +1,53 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef FREQUENT_SEEDS_H_
+#define FREQUENT_SEEDS_H_
+
+#include "../basic/const.h"
+#include "../util/hash_table.h"
+#include "sorted_list.h"
+
+struct Frequent_seeds
+{
+
+	void build(unsigned sid, const seedp_range &range, sorted_list &ref_idx, const sorted_list &query_idx);
+
+	bool get(const Letter *pos, unsigned sid) const
+	{
+		Packed_seed seed;
+		if (!shapes[sid].set_seed(seed, pos))
+			return true;
+		return tables_[sid][seed_partition(seed)].contains(seed_partition_offset(seed));
+	}
+
+private:
+
+	static const double hash_table_factor;
+
+	struct Build_context;
+
+	static void compute_sd(Atomic<unsigned> *seedp, const sorted_list *ref_idx, const sorted_list *query_idx, vector<Sd> *ref_out, vector<Sd> *query_out);
+
+	PHash_set tables_[Const::max_shapes][Const::seedp];
+
+};
+
+extern Frequent_seeds frequent_seeds;
+
+#endif
\ No newline at end of file
diff --git a/src/data/index.cpp b/src/data/index.cpp
new file mode 100644
index 0000000..22aecb0
--- /dev/null
+++ b/src/data/index.cpp
@@ -0,0 +1,86 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <numeric>
+#include "index.h"
+#include "queries.h"
+#include "../util/log_stream.h"
+
+const double Seed_index::hash_table_factor = 1.3;
+Seed_index seed_index[Const::max_shapes];
+
+Seed_index::Seed_index(const Partitioned_histogram &hst, const Sequence_set &seqs, unsigned sid):
+	list_buffer(sorted_list::alloc_buffer(hst)),
+	list(list_buffer.get(), seqs, shapes[sid], hst.get(sid), seedp_range::all(), hst.partition())
+{
+	task_timer timer("Counting seeds", 3);
+	Thread_pool threads;
+	vector<size_t> counts(Const::seedp);
+	Atomic<unsigned> seedp(0);
+	for (unsigned i = 0; i < config.threads_; ++i)
+		threads.push_back(launch_thread(count_seeds, &seedp, &counts, &list));
+	threads.join_all();
+
+	timer.go("Allocating hash tables");
+	for (unsigned p = 0; p < Hashed_seed::p; ++p)
+		assign_ptr(tables[p], new PHash_table<Entry>(counts[p], hash_table_factor));
+	
+	timer.go("Filling hash tables");
+	seedp = 0;
+	for (unsigned i = 0; i < config.threads_; ++i)
+		threads.push_back(launch_thread(fill_tables, &seedp, this));
+	threads.join_all();
+}
+
+void Seed_index::count_seeds(Atomic<unsigned> *seedp, vector<size_t> *counts, sorted_list *list)
+{
+	unsigned p;
+	while ((p = (*seedp)++) < Const::seedp) {
+		sorted_list::const_iterator i = list->get_partition_cbegin(p);
+		size_t n = 0;
+		while (!i.at_end()) {
+			++n;
+			++i;
+		}
+		(*counts)[p] = n;
+	}
+}
+
+void Seed_index::fill_tables(Atomic<unsigned> *seedp, Seed_index *idx)
+{
+	unsigned p;
+	while ((p = (*seedp)++) < Const::seedp) {
+		sorted_list::const_iterator i = idx->list.get_partition_cbegin(p);
+		while (!i.at_end()) {
+			PHash_table<Entry>::entry *e = idx->tables[p].insert(murmur_hash()(i.key()));
+			e->value.n = (unsigned)idx->list.iterator_offset(i, p);
+			++i;
+		}
+	}
+}
+
+void build_index(const Sequence_set &seqs)
+{
+	task_timer timer("Building histograms", 3);
+	const pair<size_t, size_t> len_bounds = seqs.len_bounds(shapes[0].length_);
+	const Partitioned_histogram hst(seqs, (unsigned)len_bounds.second);
+	timer.finish();
+
+	for (unsigned i = 0; i < shapes.count();++i)
+		assign_ptr(seed_index[i], new Seed_index(hst, seqs, i));
+}
\ No newline at end of file
diff --git a/src/data/index.h b/src/data/index.h
new file mode 100644
index 0000000..9d174ac
--- /dev/null
+++ b/src/data/index.h
@@ -0,0 +1,75 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef INDEX_H_
+#define INDEX_H_
+
+#include <vector>
+#include "sequence_set.h"
+#include "../util/hash_table.h"
+#include "seed_histogram.h"
+#include "sorted_list.h"
+
+using std::vector;
+
+struct Seed_index
+{
+
+	Seed_index()
+	{}
+	Seed_index(const Partitioned_histogram &hst, const Sequence_set &seqs, unsigned sh);
+
+	sorted_list::Random_access_iterator operator[](uint64_t seed) const
+	{
+		const unsigned p = seed_partition(seed);
+		PHash_table<Entry>::entry *e = tables[p][murmur_hash()(seed_partition_offset(seed))];
+		if (e == 0)
+			return sorted_list::Random_access_iterator(0, 0);
+		else
+			return list.random_access(p, e->value.n);
+	}
+	
+private:
+
+	static const double hash_table_factor;
+	
+	struct Entry
+	{
+		uint32_t n;
+		operator unsigned() const
+		{
+			return n;
+		}
+	};
+
+	static void fill_tables(Atomic<unsigned> *seedp, Seed_index *idx);
+	static void count_seeds(Atomic<unsigned> *seedp, vector<size_t> *counts, sorted_list *list);
+
+	auto_ptr<char> list_buffer;
+	sorted_list list;
+	PHash_table<Entry> tables[Const::seedp];
+
+};
+
+extern Seed_index seed_index[Const::max_shapes];
+
+vector<Array<unsigned, Hashed_seed::p> > count_exact(const Sequence_set &seqs);
+vector<size_t> count_approximate(const Sequence_set &seqs);
+void build_index(const Sequence_set &seqs);
+
+#endif
\ No newline at end of file
diff --git a/src/data/load_seqs.h b/src/data/load_seqs.h
new file mode 100644
index 0000000..29be206
--- /dev/null
+++ b/src/data/load_seqs.h
@@ -0,0 +1,90 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef LOAD_SEQS_H_
+#define LOAD_SEQS_H_
+
+#include <iostream>
+#include "sequence_set.h"
+#include "../basic/translate.h"
+#include "../util/seq_file_format.h"
+
+inline size_t push_seq(Sequence_set &ss, Sequence_set& source_seqs, const vector<Letter> &seq)
+{
+	if (config.command == Config::blastp || config.command == Config::makedb || config.command == Config::random_seqs) {
+		ss.push_back(seq);
+		return seq.size();
+	}
+	else {
+		source_seqs.push_back(seq);
+		if (seq.size() < 2) {
+			for (unsigned j = 0; j<6; ++j)
+				ss.fill(0, value_traits.mask_char);
+			return 0;
+		}
+		vector<Letter> proteins[6];
+		size_t n = Translator::translate(seq, proteins);
+
+		unsigned bestFrames(Translator::computeGoodFrames(proteins, config.get_run_len((unsigned)seq.size() / 3)));
+		for (unsigned j = 0; j < 6; ++j) {
+			if (bestFrames & (1 << j))
+				ss.push_back(proteins[j]);
+			else
+				ss.fill(proteins[j].size(), value_traits.mask_char);
+		}
+		return n;
+	}
+}
+
+inline size_t load_seqs(Input_stream &file,
+		const Sequence_file_format &format,
+		Sequence_set** seqs,
+		String_set<0>*& ids,
+		Sequence_set*& source_seqs,
+		size_t max_letters)
+{
+	*seqs = new Sequence_set ();
+	ids = new String_set<0> ();
+	source_seqs = new Sequence_set ();
+	size_t letters = 0, n = 0;
+	vector<Letter> seq;
+	vector<char> id;
+	try {
+		while(letters < max_letters && format.get_seq(id, seq, file)) {
+			ids->push_back(id);
+			letters += push_seq(**seqs, *source_seqs, seq);
+			++n;
+		}
+	} catch(invalid_sequence_char_exception &e) {
+		std::cerr << n << endl;
+		throw e;
+	}
+	ids->finish_reserve();
+	(*seqs)->finish_reserve();
+	source_seqs->finish_reserve();
+	if(n == 0) {
+		delete *seqs;
+		delete ids;
+		delete source_seqs;
+	}
+	return n;
+}
+
+#endif /* LOAD_SEQS_H_ */
diff --git a/src/data/queries.cpp b/src/data/queries.cpp
new file mode 100644
index 0000000..2ebc115
--- /dev/null
+++ b/src/data/queries.cpp
@@ -0,0 +1,42 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "queries.h"
+
+unsigned current_query_chunk;
+Sequence_set* query_source_seqs::data_ = 0;
+Sequence_set* query_seqs::data_ = 0;
+String_set<0>* query_ids::data_ = 0;
+Partitioned_histogram query_hst;
+vector<bool> query_aligned;
+
+void write_unaligned(Output_stream *file)
+{
+	const size_t n = query_ids::get().get_length();
+	string s;
+	for (size_t i = 0; i < n; ++i) {
+		if (!query_aligned[i]) {
+			std::stringstream ss;
+			ss << '>' << query_ids::get()[i].c_str() << endl;
+			(align_mode.query_translated ? query_source_seqs::get()[i] : query_seqs::get()[i]).print(ss, input_value_traits);
+			ss << endl;
+			s = ss.str();
+			file->write(s.data(), s.length());
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/data/queries.h b/src/data/queries.h
new file mode 100644
index 0000000..a59841a
--- /dev/null
+++ b/src/data/queries.h
@@ -0,0 +1,63 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef QUERIES_H_
+#define QUERIES_H_
+
+#include "../basic/translate.h"
+#include "../util/complexity_filter.h"
+#include "sorted_list.h"
+#include "../basic/statistics.h"
+#include "sequence_set.h"
+
+extern Partitioned_histogram query_hst;
+extern unsigned current_query_chunk;
+
+struct query_source_seqs
+{
+	static const Sequence_set& get()
+	{ return *data_; }
+	static Sequence_set *data_;
+};
+
+struct query_seqs
+{
+	static const Sequence_set& get()
+	{ return *data_; }
+	static Sequence_set *data_;
+};
+
+struct query_ids
+{
+	static const String_set<0>& get()
+	{ return *data_; }
+	static String_set<0> *data_;
+};
+
+extern vector<bool> query_aligned;
+
+void write_unaligned(Output_stream *file);
+
+inline unsigned get_source_query_len(unsigned query_id)
+{
+	return align_mode.query_translated ? (unsigned)query_seqs::get().reverse_translated_len(query_id*align_mode.query_contexts) : (unsigned)query_seqs::get().length(query_id);
+}
+
+#endif /* QUERIES_H_ */
diff --git a/src/data/reference.cpp b/src/data/reference.cpp
new file mode 100644
index 0000000..090fcd9
--- /dev/null
+++ b/src/data/reference.cpp
@@ -0,0 +1,186 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <limits>
+#include <iostream>
+#include <sstream>
+#include <set>
+#include "../basic/config.h"
+#include "reference.h"
+#include "../basic/statistics.h"
+#include "load_seqs.h"
+#include "../util/seq_file_format.h"
+#include "../util/log_stream.h"
+
+String_set<0>* ref_ids::data_ = 0;
+Ref_map ref_map;
+Partitioned_histogram ref_hst;
+unsigned current_ref_block;
+Reference_header ref_header;
+Sequence_set* ref_seqs::data_ = 0;
+bool blocked_processing;
+
+using std::cout;
+using std::endl;
+
+struct Pos_record
+{
+	Pos_record()
+	{}
+	Pos_record(uint64_t pos, size_t len):
+		pos(pos),
+		seq_len(uint32_t(len))
+	{}
+	uint64_t pos;
+	uint32_t seq_len;
+};
+
+void make_db()
+{
+	message_stream << "Database file: " << config.input_ref_file << endl;
+	
+	Timer total;
+	total.start();
+	task_timer timer("Opening the database file", true);
+	auto_ptr<Input_stream> db_file (Compressed_istream::auto_detect(config.input_ref_file));
+	
+	Output_stream out(config.database);
+	out.typed_write(&ref_header, 1);
+
+	size_t letters = 0, n = 0;
+	uint64_t offset = sizeof(ref_header);
+
+	vector<Letter> seq;
+	vector<char> id;
+	vector<Pos_record> pos_array;
+	FASTA_format format;
+
+	while (format.get_seq(id, seq, *db_file)) {
+		if (seq.size() == 0)
+			throw std::runtime_error("File format error: sequence of length 0 at line " + to_string(db_file->line_count));
+		if (n % 100000llu == 0llu) {
+			std::stringstream ss;
+			ss << "Loading sequence data (" << n << " sequences processed)";
+			timer.go(ss.str().c_str());
+		}
+		pos_array.push_back(Pos_record(offset, seq.size()));
+		out.write("\xff", 1);
+		out.write(seq, false);
+		out.write("\xff", 1);
+		out.write(id, false);
+		out.write("\0", 1);
+		letters += seq.size();
+		++n;
+		offset += seq.size() + id.size() + 3;
+	}
+
+	timer.go("Writing trailer");
+	ref_header.pos_array_offset = offset;
+	pos_array.push_back(Pos_record(offset, 0));
+	out.write(pos_array, false);
+
+	timer.go("Closing the input file");
+	db_file->close();
+	
+	timer.go("Closing the database file");
+	ref_header.letters = letters;
+	ref_header.sequences = n;
+	out.seekp(0);
+	out.typed_write(&ref_header, 1);
+	out.close();
+
+	timer.finish();
+	message_stream << "Processed " << n << " sequences, " << letters << " letters." << endl;
+	message_stream << "Total time = " << total.getElapsedTimeInSec() << "s" << endl;
+}
+
+bool Database_file::load_seqs()
+{
+	task_timer timer("Loading reference sequences");
+	const size_t max_letters = (size_t)(config.chunk_size*1e9);
+	seek(pos_array_offset);
+	size_t letters = 0, seqs = 0, id_letters = 0;
+
+	ref_seqs::data_ = new Sequence_set;
+	ref_ids::data_ = new String_set<0>;
+
+	Pos_record r;
+	read(&r, 1);
+	size_t start_offset = r.pos;
+
+	while (r.seq_len > 0 && letters < max_letters) {
+		Pos_record r_next;
+		read(&r_next, 1);
+		letters += r.seq_len;
+		ref_seqs::data_->reserve(r.seq_len);
+		const size_t id = r_next.pos - r.pos - r.seq_len - 3;
+		id_letters += id;
+		ref_ids::data_->reserve(id);
+		pos_array_offset += sizeof(Pos_record);
+		++seqs;
+		r = r_next;
+	}
+
+	if (seqs == 0) {
+		delete ref_seqs::data_;
+		delete ref_ids::data_;
+		return false;
+	}
+
+	ref_seqs::data_->finish_reserve();
+	ref_ids::data_->finish_reserve();
+	seek(start_offset);
+
+	for (size_t n = 0; n < seqs; ++n) {
+		read(ref_seqs::data_->ptr(n) - 1, ref_seqs::data_->length(n) + 2);
+		read(ref_ids::data_->ptr(n), ref_ids::data_->length(n) + 1);
+	}
+
+	blocked_processing = seqs < ref_header.sequences;
+	return true;
+}
+
+void Database_file::get_seq()
+{
+	vector<Letter> seq;
+	string id;
+	char c;
+	bool all = config.seq_no.size() == 0;
+	std::set<size_t> seqs;
+	if (!all)
+		for (vector<string>::const_iterator i = config.seq_no.begin(); i != config.seq_no.end(); ++i)
+			seqs.insert(atoi(i->c_str()) - 1);
+	for (size_t n = 0; n < ref_header.sequences; ++n) {
+		read(&c, 1);
+		while (read(&c, 1), c != '\xff')
+			seq.push_back(c);
+		while (read(&c, 1), c != '\0')
+			id.push_back(c);
+		if (all || seqs.find(n) != seqs.end()) {
+			cout << '>' << id << endl;
+			if (config.reverse) {
+				sequence(seq).print(cout, value_traits, sequence::Reversed());
+				cout << endl;
+			}
+			else
+				cout << sequence(seq) << endl;
+		}
+		seq.clear();
+		id.clear();
+	}
+}
\ No newline at end of file
diff --git a/src/data/reference.h b/src/data/reference.h
new file mode 100644
index 0000000..e215ba7
--- /dev/null
+++ b/src/data/reference.h
@@ -0,0 +1,202 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef REFERENCE_H_
+#define REFERENCE_H_
+
+#include <memory>
+#include <string>
+#include <numeric>
+#include <limits>
+#include "../util/binary_file.h"
+#include "sorted_list.h"
+#include "../basic/statistics.h"
+#include "../data/seed_histogram.h"
+#include "../util/hash_table.h"
+#include "../util/hash_function.h"
+#include "../basic/packed_loc.h"
+#include "sequence_set.h"
+#include "../util/ptr_vector.h"
+
+using std::auto_ptr;
+
+struct invalid_database_version_exception : public std::exception
+{
+	virtual const char* what() const throw()
+	{
+		return "Incompatible database version";
+	}
+};
+
+struct Reference_header
+{
+	Reference_header():
+		unique_id (0x24af8a415ee186dllu),
+		build (Const::build_version),
+		db_version(current_db_version),
+		sequences (0),
+		letters (0)
+	{ }
+	uint64_t unique_id;
+	uint32_t build, db_version;
+	uint64_t sequences, letters, pos_array_offset;
+#ifdef EXTRA
+	Sequence_type sequence_type;
+#endif
+	enum { current_db_version = 0 };
+};
+
+extern Reference_header ref_header;
+
+struct Database_format_exception : public std::exception
+{
+	virtual const char* what() const throw()
+	{ return "Database file is not a DIAMOND database."; }
+};
+
+struct Database_file : public Input_stream
+{
+	Database_file():
+		Input_stream (config.database)
+	{
+		if(this->read(&ref_header, 1) != 1)
+			throw Database_format_exception ();
+		if(ref_header.unique_id != Reference_header ().unique_id)
+			throw Database_format_exception ();
+		if(ref_header.build < min_build_required || ref_header.db_version != Reference_header::current_db_version)
+			throw invalid_database_version_exception();
+#ifdef EXTRA
+		if(sequence_type(_val()) != ref_header.sequence_type)
+			throw std::runtime_error("Database has incorrect sequence type for current alignment mode.");
+#endif
+		pos_array_offset = ref_header.pos_array_offset;
+	}
+	void rewind()
+	{
+		pos_array_offset = ref_header.pos_array_offset;
+	}
+	bool load_seqs();
+	void get_seq();
+	enum { min_build_required = 74 };
+
+	size_t pos_array_offset;
+};
+
+void make_db();
+
+struct ref_seqs
+{
+	static const Sequence_set& get()
+	{ return *data_; }
+	static Sequence_set& get_nc()
+	{ return *data_; }
+	static Sequence_set *data_;
+};
+
+struct ref_ids
+{
+	static const String_set<0>& get()
+	{ return *data_; }
+	static String_set<0> *data_;
+};
+
+extern Partitioned_histogram ref_hst;
+extern unsigned current_ref_block;
+extern bool blocked_processing;
+
+inline size_t max_id_len(const String_set<0> &ids)
+{
+	size_t max (0);
+	for(size_t i=0;i<ids.get_length(); ++i)
+		max = std::max(max, find_first_of(ids[i].c_str(), Const::id_delimiters));
+	return max;
+}
+
+struct Ref_map
+{
+	Ref_map():
+		next_ (0)
+	{ }
+	void init(unsigned ref_count)
+	{
+		const unsigned block = current_ref_block;
+		if(data_.size() < block+1) {
+			data_.resize(block+1);
+			data_[block].insert(data_[block].end(), ref_count, std::numeric_limits<unsigned>::max());
+		}
+	}
+	uint32_t get(unsigned block, unsigned i)
+	{
+		uint32_t n = data_[block][i];
+		if(n != std::numeric_limits<unsigned>::max())
+			return n;
+		{
+			mtx_.lock();
+			n = data_[block][i];
+			if (n != std::numeric_limits<uint32_t>::max()) {
+				mtx_.unlock();
+				return n;
+			}
+			n = next_++;
+			data_[block][i] = n;
+			len_.push_back((uint32_t)ref_seqs::get().length(i));
+			if (config.salltitles)
+				name_.push_back(new string(ref_ids::get()[i].c_str()));
+			else
+				name_.push_back(get_str(ref_ids::get()[i].c_str(), Const::id_delimiters));
+			mtx_.unlock();
+		}
+		return n;
+	}
+
+	unsigned length(uint32_t i) const
+	{
+		return len_[i];
+	}
+	const char* name(uint32_t i) const
+	{
+		return name_[i].c_str();
+	}
+	void init_rev_map()
+	{
+		rev_map_.resize(next_);
+		unsigned n = 0;
+		for (unsigned i = 0; i < data_.size(); ++i) {
+			for (unsigned j = 0; j < data_[i].size(); ++j)
+				if (data_[i][j] != std::numeric_limits<uint32_t>::max())
+					rev_map_[data_[i][j]] = n + j;
+			n += (unsigned)data_[i].size();
+		}
+	}
+	unsigned original_id(unsigned i) const
+	{
+		return rev_map_[i];
+	}
+private:
+	tthread::mutex mtx_;
+	vector<vector<uint32_t> > data_;
+	vector<uint32_t> len_;
+	Ptr_vector<string> name_;
+	vector<uint32_t> rev_map_;
+	uint32_t next_;
+	friend void finish_daa(Output_stream&);
+};
+
+extern Ref_map ref_map;
+
+#endif /* REFERENCE_H_ */
diff --git a/src/data/seed_histogram.cpp b/src/data/seed_histogram.cpp
new file mode 100644
index 0000000..22c6b97
--- /dev/null
+++ b/src/data/seed_histogram.cpp
@@ -0,0 +1,21 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "seed_histogram.h"
+
+seedp_range current_range;
\ No newline at end of file
diff --git a/src/data/seed_histogram.h b/src/data/seed_histogram.h
new file mode 100644
index 0000000..f6063a9
--- /dev/null
+++ b/src/data/seed_histogram.h
@@ -0,0 +1,168 @@
+/****
+Copyright (c) 2014-16, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SEED_HISTOGRAM_H_
+#define SEED_HISTOGRAM_H_
+
+#include <limits>
+#include "../basic/seed.h"
+#include "sequence_set.h"
+#include "../basic/shape_config.h"
+#include "../util/thread.h"
+#include "../basic/seed_iterator.h"
+
+using std::vector;
+
+typedef vector<Array<unsigned,Const::seedp> > shape_histogram;
+
+struct seedp_range
+{
+	seedp_range():
+		begin_ (0),
+		end_ (0)
+	{ }
+	seedp_range(unsigned begin, unsigned end):
+		begin_ (begin),
+		end_ (end)
+	{ }
+	bool contains(unsigned i) const
+	{ return i >= begin_ && i < end_; }
+	unsigned begin() const
+	{ return begin_; }
+	unsigned end() const
+	{ return end_; }
+	bool lower(unsigned i) const
+	{ return i < begin_; }
+	bool lower_or_equal(unsigned i) const
+	{ return i < end_; }
+	unsigned size() const
+	{
+		return end_ - begin_;
+	}
+	static seedp_range all()
+	{
+		return seedp_range(0, Const::seedp);
+	}
+private:
+	unsigned begin_, end_;
+};
+
+extern seedp_range current_range;
+
+inline size_t partition_size(const shape_histogram &hst, unsigned p)
+{
+	size_t s = 0;
+	for(unsigned i=0;i<hst.size();++i)
+		s += hst[i][p];
+	return s;
+}
+
+inline size_t hst_size(const shape_histogram &hst, const seedp_range &range)
+{
+	size_t s = 0;
+	for(unsigned i=range.begin();i<range.end();++i)
+		s += partition_size(hst, i);
+	return s;
+}
+
+struct Partitioned_histogram
+{
+
+	Partitioned_histogram()
+	{ }
+
+	Partitioned_histogram(const Sequence_set &seqs, unsigned longest):
+		data_(shapes.count()),
+		p_(seqs.partition(config.threads_*4))
+	{
+		for (unsigned s = 0; s < shapes.count(); ++s) {
+			data_[s].resize(p_.size() - 1);
+			memset(data_[s].data(), 0, (p_.size() - 1)*sizeof(unsigned)*Const::seedp);
+		}
+		Build_context context (seqs, *this, longest);
+		launch_scheduled_thread_pool(context, (unsigned)(p_.size() - 1), (unsigned)(p_.size() - 1));
+	}
+
+	const shape_histogram& get(unsigned sid) const
+	{ return data_[sid]; }
+
+	size_t max_chunk_size() const
+	{
+		size_t max = 0;
+		::partition<unsigned> p(Const::seedp, config.lowmem);
+		for (unsigned shape = 0; shape < shapes.count(); ++shape)
+			for (unsigned chunk = 0; chunk < p.parts; ++chunk)
+				max = std::max(max, hst_size(data_[shape], seedp_range(p.getMin(chunk), p.getMax(chunk))));
+		return max;
+	}
+
+	const vector<size_t>& partition() const
+	{
+		return p_;
+	}
+
+private:
+
+	struct Build_context
+	{
+		Build_context(const Sequence_set &seqs, Partitioned_histogram &hst, unsigned longest):
+			seqs (seqs),
+			hst (hst),
+			longest(longest)
+		{ }
+		void operator()(unsigned thread_id, unsigned seqp) const
+		{
+			vector<char> buf(longest);
+			hst.build_seq_partition(seqs, seqp, hst.p_[seqp], hst.p_[seqp+1], buf);
+		}
+		const Sequence_set &seqs;
+		Partitioned_histogram &hst;
+		unsigned longest;
+	};
+
+	void build_seq_partition(const Sequence_set &seqs,
+			const unsigned seqp,
+			const size_t begin,
+			const size_t end,
+		vector<char> &buf)
+	{
+		for (size_t i = begin; i < end; ++i) {
+
+			assert(i < seqs.get_length());
+			if (seqs[i].length() == 0)
+				continue;
+			Reduction::reduce_seq(seqs[i], buf);
+
+			for (unsigned s = 0; s < shapes.count(); ++s) {
+				Seed_iterator it(buf, shapes[s]);
+				unsigned *ptr = data_[s][seqp].begin();
+				uint64_t seed;
+				while (it.good())
+					if (it.get(seed, shapes[s]))
+						++ptr[seed_partition(seed)];
+			}
+
+		}
+	}
+
+	vector<shape_histogram> data_;
+	vector<size_t> p_;
+
+};
+
+#endif /* SEED_HISTOGRAM_H_ */
diff --git a/src/data/sequence_set.h b/src/data/sequence_set.h
new file mode 100644
index 0000000..5f99f4c
--- /dev/null
+++ b/src/data/sequence_set.h
@@ -0,0 +1,244 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SEQUENCE_SET_H_
+#define SEQUENCE_SET_H_
+
+#include <iostream>
+#include <string>
+#include <algorithm>
+#include <queue>
+#include "../basic/sequence.h"
+#include "string_set.h"
+#include "../util/thread.h"
+#include "../basic/shape_config.h"
+
+using std::cout;
+using std::endl;
+using std::pair;
+
+struct Sequence_set : public String_set<'\xff', 1>
+{
+
+	Sequence_set()
+	{ }
+
+	Sequence_set(Input_stream &file) :
+		String_set<'\xff',1>(file)
+	{ }
+
+	void print_stats() const
+	{
+		verbose_stream << "Sequences = " << this->get_length() << ", letters = " << this->letters() << ", average length = " << this->avg_len() << endl;
+	}
+
+	pair<size_t, size_t> len_bounds(size_t min_len) const
+	{
+		const size_t l(this->get_length());
+		size_t max = 0, min = std::numeric_limits<size_t>::max();
+		for (size_t i = 0; i < l; ++i) {
+			max = std::max(this->length(i), max);
+			min = this->length(i) >= min_len ? std::min(this->length(i), min) : min;
+		}
+		return pair<size_t, size_t>(min, max);
+	}
+
+	sequence window_infix(size_t offset, unsigned &left) const
+	{
+		const Letter* begin(this->data(offset));
+		unsigned n(0);
+		while (*begin != '\xff' && n <= config.window) {
+			--begin;
+			++n;
+		}
+		++begin;
+		left = config.window + 1 - n;
+		const Letter* end(this->data(offset));
+		n = 0;
+		while (*end != '\xff' && n < config.window) {
+			++end;
+			++n;
+		}
+		return sequence(begin, end - begin);
+	}
+
+	sequence fixed_window_infix(size_t offset) const
+	{
+		const Letter* begin(this->data(offset));
+		unsigned n(0);
+		while (*begin != '\xff' && n <= config.window) {
+			--begin;
+			++n;
+		}
+		++begin;
+		const Letter* s(this->data(offset - config.window));
+		return sequence(s, 2 * config.window, (int)(begin - s));
+	}
+
+	vector<size_t> partition(unsigned n_part) const
+	{
+		vector<size_t> v;
+		const size_t l = (this->letters() + n_part - 1) / n_part;
+		v.push_back(0);
+		for (unsigned i = 0; i < this->get_length();) {
+			size_t n = 0;
+			while (i < this->get_length() && n < l)
+				n += this->length(i++);
+			v.push_back(i);
+		}
+		for (size_t i = v.size(); i < n_part + 1; ++i)
+			v.push_back(this->get_length());
+		return v;
+	}
+
+	size_t reverse_translated_len(size_t i) const
+	{
+		const size_t j(i - i % 6);
+		const size_t l(this->length(j));
+		if (this->length(j + 2) == l)
+			return l * 3 + 2;
+		else if (this->length(j + 1) == l)
+			return l * 3 + 1;
+		else
+			return l * 3;
+	}
+
+	size_t avg_len() const
+	{
+		return this->letters() / this->get_length();
+	}
+
+	template <typename _f>
+	void enum_seeds(vector<_f> &f) const
+	{
+		const vector<size_t> p = this->partition((unsigned)f.size());
+		Thread_pool threads;
+		for (unsigned i = 0; i < f.size(); ++i)
+			threads.push_back(launch_thread(enum_seeds_worker<_f>, &f[i], this, (unsigned)p[i], (unsigned)p[i + 1]));
+		threads.join_all();
+	}
+
+	template<typename _f, typename _entry>
+	void enum_seeds_partitioned() const
+	{
+		vector<Enum_partitioned_callback<_f, _entry> > v;
+		v.reserve(config.threads_);
+		::partition<unsigned> p(Hashed_seed::p, config.threads_);
+		for (unsigned i = 0; i < config.threads_; ++i) {
+			Enum_partitioned_callback<_f, _entry> * tmp = new Enum_partitioned_callback<_f, _entry>(p.getMin(i), p.getMax(i));
+			v.push_back(*tmp);
+			delete tmp;
+		}
+		enum_seeds(v);
+		/*for (unsigned i = 0; i < config.threads_; ++i)
+			v[i].flush_queues();*/
+	}
+
+	virtual ~Sequence_set()
+	{ }
+
+private:
+
+	template<typename _f>
+	static void enum_seeds_worker(_f *f, const Sequence_set *seqs, unsigned begin, unsigned end)
+	{
+		uint64_t key;
+		for (unsigned i = begin; i < end; ++i) {
+			const sequence seq = (*seqs)[i];
+			for (unsigned shape_id = shape_from; shape_id < shape_to; ++shape_id) {
+				const shape& sh = shapes[shape_id];
+				if (seq.length() < sh.length_) continue;
+				for (unsigned j = 0; j < seq.length() - sh.length_ + 1; ++j) {
+					if (sh.set_seed(key, &seq[j]))
+						(*f)(Hashed_seed(key), seqs->position(i, j), shape_id);
+				}
+			}
+		}
+		f->finish();
+	}
+
+	template<typename _f, typename _entry>
+	struct Enum_partitioned_callback
+	{
+		Enum_partitioned_callback(unsigned p_begin, unsigned p_end) :
+			p_begin(p_begin),
+			p_end(p_end)
+		{
+			memset(counts, 0, sizeof(counts));
+		}
+		void operator()(Hashed_seed seed, size_t pos, unsigned shape_id)
+		{
+			const unsigned p = seed.partition();
+			buffers[shape_id][p][counts[shape_id][p]++] = _entry(seed, pos);
+			if (counts[shape_id][p] == buffer_size)
+				flush_buffer(shape_id, p);
+			if ((pos & flush_mask) == 0 && shape_id == shape_from)
+				flush_queues();
+		}
+		void flush_buffer(unsigned shape_id, unsigned p)
+		{
+			mtx[shape_id][p].lock();
+			vector<_entry> &q = queues[shape_id][p];
+			unsigned &count = counts[shape_id][p];
+			const size_t s = q.size();
+			q.resize(s + sizeof(_entry)*count);
+			memcpy(q.data() + s, buffers[shape_id][p].begin(), sizeof(_entry)*count);
+			mtx[shape_id][p].unlock();
+			count = 0;
+		}
+		void finish()
+		{
+			for (unsigned shape_id = shape_from; shape_id < shape_to; ++shape_id)
+				for (unsigned p = 0; p < Hashed_seed::p; ++p)
+					flush_buffer(shape_id, p);
+		}
+		void flush_queues()
+		{
+			for (unsigned shape_id = shape_from; shape_id < shape_to; ++shape_id)
+				for (unsigned p = p_begin; p < p_end; ++p) {
+					mtx[shape_id][p].lock();
+					vector<_entry> &q = queues[shape_id][p];
+					const size_t size = q.size();
+					if (size == 0) {
+						mtx[shape_id][p].unlock();
+						continue;
+					}
+					out_buf.resize(size);
+					memcpy(out_buf.data(), q.data(), size * sizeof(_entry));
+					q.clear();
+					mtx[shape_id][p].unlock();
+					for (typename vector<_entry>::const_iterator i = out_buf.begin(); i != out_buf.end(); ++i)
+						_f()(shape_id, *i);
+				}
+		}
+		enum { buffer_size = 16, flush_mask = 1023 };
+		Array<_entry, buffer_size> buffers[Const::max_shapes][Hashed_seed::p];
+		unsigned counts[Const::max_shapes][Hashed_seed::p], p_begin, p_end;
+		vector<_entry> out_buf;
+		static tthread::mutex mtx[Const::max_shapes][Hashed_seed::p];
+		static vector<_entry> queues[Const::max_shapes][Hashed_seed::p];
+	};
+
+};
+
+template<typename _f, typename _entry>
+tthread::mutex Sequence_set::Enum_partitioned_callback<_f, _entry>::mtx[Const::max_shapes][Hashed_seed::p];
+template<typename _f, typename _entry>
+vector<_entry> Sequence_set::Enum_partitioned_callback<_f, _entry>::queues[Const::max_shapes][Hashed_seed::p];
+
+#endif /* SEQUENCE_SET_H_ */
\ No newline at end of file
diff --git a/src/data/sorted_list.h b/src/data/sorted_list.h
new file mode 100644
index 0000000..665acce
--- /dev/null
+++ b/src/data/sorted_list.h
@@ -0,0 +1,310 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SORTED_LIST_H_
+#define SORTED_LIST_H_
+
+#include "../util/util.h"
+#include "seed_histogram.h"
+#include "../basic/packed_loc.h"
+#include "../util/system.h"
+
+#pragma pack(1)
+
+struct sorted_list
+{
+
+	typedef Packed_loc _pos;
+
+	struct entry
+	{
+		entry():
+			key (),
+			value ()
+		{ }
+		entry(unsigned key, _pos value):
+			key (key),
+			value (value)
+		{ }
+		bool operator<(const entry &rhs) const
+		{ return key < rhs.key; }
+		unsigned	key;
+		_pos		value;
+	} PACKED_ATTRIBUTE ;
+
+	static char* alloc_buffer(const Partitioned_histogram &hst)
+	{ return new char[sizeof(entry) * hst.max_chunk_size()]; }
+
+	sorted_list()
+	{}
+
+	sorted_list(char *buffer, const Sequence_set &seqs, const shape &sh, const shape_histogram &hst, const seedp_range &range, const vector<size_t> seq_partition):
+		limits_ (hst, range),
+		data_ (reinterpret_cast<entry*>(buffer))
+	{
+		task_timer timer ("Building seed list", 3);
+		Build_context build_context (seqs, sh, range, build_iterators(hst), seq_partition);
+		launch_scheduled_thread_pool(build_context, unsigned(seq_partition.size() - 1), config.threads_);
+		timer.go("Sorting seed list");
+		Sort_context sort_context (*this);
+		launch_scheduled_thread_pool(sort_context, Const::seedp, config.threads_);
+	}
+
+	template<typename _t>
+	struct Iterator_base
+	{
+		Iterator_base(_t *i, _t *end):
+			i (i),
+			end (end),
+			n (count())
+		{ }
+		size_t count() const
+		{
+			_t *k (i);
+			size_t n (0);
+			while(k < end && (k++)->key == i->key)
+				++n;
+			return n;
+		}
+		void operator++()
+		{ i += n; n = count(); }
+		Loc operator[](unsigned k) const
+		{ return (Loc)((i+k)->value); }
+		_t* get(unsigned k)
+		{ return i+k; }
+		bool at_end() const
+		{ return i >= end; }
+		unsigned key() const
+		{ return i->key; }
+		_t *i, *end;
+		size_t n;
+	};
+
+	typedef Iterator_base<entry> iterator;
+	typedef Iterator_base<const entry> const_iterator;
+
+	const_iterator get_partition_cbegin(unsigned p) const
+	{ return const_iterator (cptr_begin(p), cptr_end(p)); }
+
+	iterator get_partition_begin(unsigned p) const
+	{ return iterator (ptr_begin(p), ptr_end(p)); }
+
+	struct Random_access_iterator
+	{
+		Random_access_iterator(const entry *i, const entry *end) :
+			i(i),
+			end(end),
+			key_(i ? i->key : 0)
+		{ }
+		void operator++()
+		{
+			++i;
+		}
+		Loc operator*() const
+		{
+			return (Loc)i->value;
+		}
+		bool good() const
+		{
+			return i < end && i->key == key_;
+		}
+		unsigned key() const
+		{
+			return key_;
+		}
+		const entry *i, *end;
+		unsigned key_;
+	};
+
+	size_t iterator_offset(const const_iterator &i, unsigned p) const
+	{
+		return i.i - cptr_begin(p);
+	}
+
+	Random_access_iterator random_access(unsigned p, size_t offset) const
+	{
+		return Random_access_iterator(cptr_begin(p) + offset, cptr_end(p));
+	}
+
+private:
+
+	typedef vector<Array<entry*, Const::seedp> > Ptr_set;
+
+	struct buffered_iterator
+	{
+		static const unsigned BUFFER_SIZE = 16;
+		buffered_iterator(entry* const* ptr)
+		{
+			memset(n, 0, sizeof(n));
+			memcpy(this->ptr, ptr, sizeof(this->ptr));
+		}
+		void push(Packed_seed key, Loc value, const seedp_range &range)
+		{
+			const unsigned p(seed_partition(key));
+			if(range.contains(p)) {
+				assert(n[p] < BUFFER_SIZE);
+				buf[p][n[p]++] = entry (seed_partition_offset(key), value);
+				if(n[p] == BUFFER_SIZE)
+					flush(p);
+			}
+		}
+		void flush(unsigned p)
+		{
+			memcpy(ptr[p], buf[p], n[p] * sizeof(entry));
+			ptr[p] += n[p];
+			n[p] = 0;
+		}
+		void flush()
+		{
+			for(unsigned p=0;p<Const::seedp;++p)
+				if(n[p] > 0)
+					flush(p);
+		}
+		entry* ptr[Const::seedp];
+		entry  	 buf[Const::seedp][BUFFER_SIZE];
+		uint8_t  n[Const::seedp];
+	};
+
+	entry* ptr_begin(unsigned i) const
+	{ return &data_[limits_[i]]; }
+
+	entry* ptr_end(unsigned i) const
+	{ return &data_[limits_[i+1]]; }
+
+	const entry* cptr_begin(unsigned i) const
+	{ return &data_[limits_[i]]; }
+
+	const entry* cptr_end(unsigned i) const
+	{ return &data_[limits_[i+1]]; }
+
+	struct Build_context
+	{
+		Build_context(const Sequence_set &seqs, const shape &sh, const seedp_range &range, const Ptr_set &iterators, const vector<size_t> &seq_partition):
+			seqs (seqs),
+			sh (sh),
+			range (range),
+			iterators (iterators),
+			seq_partition (seq_partition)
+		{ }
+		void operator()(unsigned thread_id, unsigned seqp) const
+		{
+			build_seqp(seqs,
+				seq_partition[seqp],
+				seq_partition[seqp + 1],
+				iterators[seqp].begin(),
+				sh,
+				range);
+		}
+		const Sequence_set &seqs;
+		const shape &sh;
+		const seedp_range ⦥
+		const Ptr_set iterators;
+		const vector<size_t> &seq_partition;
+	};
+
+	static void build_seqp(const Sequence_set &seqs, size_t begin, size_t end, entry* const* ptr, const shape &sh, const seedp_range &range)
+	{
+		uint64_t key;
+		auto_ptr<buffered_iterator> it (new buffered_iterator(ptr));
+		for(size_t i=begin;i<end;++i) {
+			const sequence seq = seqs[i];
+			if(seq.length()<sh.length_) continue;
+			for (unsigned j = 0; j < seq.length() - sh.length_ + 1; ++j) {
+				if (sh.set_seed(key, &seq[j]))
+					it->push(key, seqs.position(i, j), range);
+			}
+		}
+		it->flush();
+	}
+
+	Ptr_set build_iterators(const shape_histogram &hst) const
+	{
+		Ptr_set iterators (hst.size());
+		for (unsigned i = 0; i < Const::seedp; ++i)
+			iterators[0][i] = ptr_begin(i);
+
+		for (unsigned i = 1; i < hst.size(); ++i)
+			for (unsigned j = 0; j < Const::seedp; ++j)
+				iterators[i][j] = iterators[i - 1][j] + hst[i - 1][j];
+		return iterators;
+	}
+
+	struct Sort_context
+	{
+		Sort_context(sorted_list &sl):
+			sl (sl)
+		{ }
+		void operator()(unsigned thread_id ,unsigned seedp) const
+		{ std::sort(sl.ptr_begin(seedp), sl.ptr_end(seedp)); }
+		sorted_list &sl;
+	};
+
+	struct Limits : vector<size_t>
+	{
+		Limits()
+		{}
+		Limits(const shape_histogram &hst, const seedp_range &range)
+		{
+			task_timer timer ("Computing limits", 3);
+			this->push_back(0);
+			for(unsigned i=0;i<Const::seedp;++i) {
+#ifdef EXTRA
+				log_stream << i << ' ' << partition_size(hst, i) << endl;
+#endif
+				this->push_back(this->operator[](i) + (range.contains(i) ? partition_size(hst, i) : 0));
+			}
+		}
+	};
+
+	Limits limits_;
+	entry *data_;
+
+};
+
+template<typename _it>
+struct Merge_iterator
+{
+	Merge_iterator(const _it &i, const _it& j):
+		i(i),
+		j(j)
+	{}
+	bool next()
+	{		
+		while (!i.at_end() && !j.at_end()) {
+			if (i.key() < j.key()) {
+				++i;
+			}
+			else if (j.key() < i.key()) {
+				++j;
+			}
+			else
+				return true;
+		}
+		return false;
+	}
+	void operator++()
+	{
+		++i;
+		++j;
+	}
+	_it i, j;
+};
+
+#pragma pack()
+
+#endif /* SORTED_LIST_H_ */
diff --git a/src/data/string_set.h b/src/data/string_set.h
new file mode 100644
index 0000000..62ab8f3
--- /dev/null
+++ b/src/data/string_set.h
@@ -0,0 +1,133 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef STRING_SET_H_
+#define STRING_SET_H_
+
+#include <vector>
+#include <stddef.h>
+#include "../util/binary_file.h"
+
+using std::vector;
+
+template<char _pchar = '\xff', size_t _padding = 1lu>
+struct String_set
+{
+
+	typedef char _t;
+	static const unsigned PERIMETER_PADDING = 256;
+
+	String_set():
+		data_ (PERIMETER_PADDING)
+	{ limits_.push_back(PERIMETER_PADDING); }
+
+	void finish_reserve()
+	{
+		data_.resize(raw_len() + PERIMETER_PADDING);
+		for(unsigned i=0;i<PERIMETER_PADDING;++i) {
+			data_[i] = _pchar;
+			data_[raw_len()+i] = _pchar;
+		}
+	}
+
+	void reserve(size_t n)
+	{
+		limits_.push_back(raw_len() + n + _padding);
+	}
+
+	void push_back(const vector<_t> &v)
+	{
+		limits_.push_back(raw_len() + v.size() + _padding);
+		data_.insert(data_.end(), v.begin(), v.end());
+		data_.insert(data_.end(), _padding, _pchar);
+	}
+
+	void fill(size_t n, _t v)
+	{
+		limits_.push_back(raw_len() + n + _padding);
+		data_.insert(data_.end(), n, v);
+		data_.insert(data_.end(), _padding, _pchar);
+	}
+
+	_t* ptr(size_t i)
+	{ return &data_[limits_[i]]; }
+
+	const _t* ptr(size_t i) const
+	{ return &data_[limits_[i]]; }
+
+	size_t length(size_t i) const
+	{ return limits_[i+1] - limits_[i] - _padding; }
+
+	size_t get_length() const
+	{ return limits_.size() - 1; }
+
+	void save(Output_stream &file) const
+	{
+		file.write(limits_);
+		file.write(data_);
+	}
+
+	String_set(Input_stream &file)
+	{
+		file.read(limits_);
+		file.read(data_);
+	}
+
+	static void skip(Input_stream &file)
+	{
+		file.skip_vector<size_t>();
+		file.skip_vector<_t>();
+	}
+
+	size_t raw_len() const
+	{ return limits_.back(); }
+
+	size_t letters() const
+	{ return raw_len() - get_length() - PERIMETER_PADDING; }
+
+	_t* data(ptrdiff_t p = 0)
+	{ return &data_[p]; }
+
+	const _t* data(ptrdiff_t p = 0) const
+	{ return &data_[p]; }
+
+	size_t position(const _t* p) const
+	{ return p - data(); }
+
+	size_t position(size_t i, size_t j) const
+	{ return limits_[i] + j; }
+
+	std::pair<size_t,size_t> local_position(size_t p) const
+	{
+		size_t i = std::upper_bound(limits_.begin(), limits_.end(), p) - limits_.begin() - 1;
+		return std::pair<size_t,size_t> (i, p - limits_[i]);
+	}
+
+	sequence operator[](size_t i) const
+	{ return sequence (ptr(i), length(i)); }
+
+private:
+
+	vector<_t> data_;
+	vector<size_t> limits_;
+
+};
+
+#endif /* STRING_SET_H_ */
diff --git a/src/dp/comp_based_stats.cpp b/src/dp/comp_based_stats.cpp
new file mode 100644
index 0000000..a65c36b
--- /dev/null
+++ b/src/dp/comp_based_stats.cpp
@@ -0,0 +1,116 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "dp.h"
+
+double background_scores[20];
+const double background_freq[] = { 0.0844581,0.0581912,0.0421072,0.0546748,0.0146359,0.040118,0.0621211,0.0669379,0.0225159,0.0547866,0.0957934,0.0523275,0.0218629,0.038769,0.0505311,
+0.0760908,0.0573267,0.0127314,0.0295317,0.0644889 };
+
+void init_cbs()
+{	
+	for (unsigned i = 0; i < 20; ++i) {
+		background_scores[i] = 0;
+		for (unsigned j = 0; j < 20; ++j)
+			background_scores[i] += background_freq[j] * score_matrix(i, j);
+	}
+}
+
+struct Vector_scores
+{
+	Vector_scores()
+	{
+		memset(scores, 0, sizeof(scores));
+	}
+	Vector_scores& operator+=(Letter l)
+	{
+		for (unsigned i = 0; i < 20; ++i)
+			scores[i] += score_matrix(l, i);
+		return *this;
+	}
+	Vector_scores& operator-=(Letter l)
+	{
+		for (unsigned i = 0; i < 20; ++i)
+			scores[i] -= score_matrix(l, i);
+		return *this;
+	}
+	int scores[20];
+};
+
+Bias_correction::Bias_correction(const sequence &seq):
+	vector<float>(seq.length())
+{
+	Vector_scores scores;
+	const unsigned window_half = std::min(20u, (unsigned)seq.length() - 1);
+	unsigned n = 0;
+	unsigned h = 0, m = 0, t = 0, l = (unsigned)seq.length();
+	while (n < window_half && h < l) {
+		++n;
+		scores += seq[h];
+		++h;
+	}
+	while (n < 41 && h < l) {
+		++n;
+		scores += seq[h];
+		const Letter r = seq[m];
+		if (r < 20)
+			this->operator[](m) = (float)background_scores[(int)r] - float(scores.scores[(int)r] - score_matrix(r, r)) / (n - 1);
+		++h;
+		++m;
+	}
+	while (h < l) {
+		scores += seq[h];
+		scores -= seq[t];
+		const Letter r = seq[m];
+		if (r < 20)
+			this->operator[](m) = (float)background_scores[(int)r] - float(scores.scores[(int)r] - score_matrix(r, r)) / (n - 1);
+		++h;
+		++t;
+		++m;
+	}
+	while (m < l && n>21) {
+		--n;
+		scores -= seq[t];
+		const Letter r = seq[m];
+		if (r < 20)
+			this->operator[](m) = (float)background_scores[(int)r] - float(scores.scores[(int)r] - score_matrix(r, r)) / (n - 1);
+		++t;
+		++m;
+	}
+	while (m < l) {
+		const Letter r = seq[m];
+		if (r < 20)
+			this->operator[](m) = (float)background_scores[(int)r] - float(scores.scores[(int)r] - score_matrix(r, r)) / (n - 1);
+		++m;
+	}
+}
+
+int Bias_correction::operator()(const Hsp_data &hsp) const
+{
+	float s = 0;
+	for (Hsp_data::Iterator i = hsp.begin(); i.good(); ++i) {
+		switch (i.op()) {
+		case op_match:
+		case op_substitution:
+			s += (*this)[i.query_pos];
+		default:
+			;
+		}
+	}
+	return (int)s;
+}
\ No newline at end of file
diff --git a/src/dp/dp.h b/src/dp/dp.h
new file mode 100644
index 0000000..f01ca80
--- /dev/null
+++ b/src/dp/dp.h
@@ -0,0 +1,144 @@
+/****
+Copyright (c) 2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef DP_H_
+#define DP_H_
+
+#include <utility>
+#include "../basic/match.h"
+#include "../align/align.h"
+#include "score_profile.h"
+
+void init_cbs();
+
+struct No_score_correction
+{
+	void operator()(int &score, int i, int query_anchor, int mult) const
+	{}
+};
+
+struct Bias_correction : public vector<float>
+{
+	Bias_correction(const sequence &seq);
+	void operator()(float &score, int i, int query_anchor, int mult) const
+	{
+		score += (*this)[query_anchor + i*mult];
+	}
+	int operator()(const Hsp_data &hsp) const;
+};
+
+template<typename _score>
+void smith_waterman(const Letter *query, local_match &segment, _score gap_open, _score gap_extend, vector<char> &transcript_buf, const _score& = int());
+int smith_waterman(const sequence &query, const sequence &subject, unsigned band, unsigned padding, int op, int ep);
+
+int xdrop_ungapped(const Letter *query, const Letter *subject, unsigned seed_len, unsigned &delta, unsigned &len);
+int xdrop_ungapped(const Letter *query, const Letter *subject, unsigned &delta, unsigned &len);
+int xdrop_ungapped_right(const Letter *query, const Letter *subject, int &len);
+
+void greedy_align(sequence query, sequence subject, const vector<Diagonal_segment> &sh, bool log);
+void greedy_align(sequence query, sequence subject, const Diagonal_segment &sh, bool log);
+void greedy_align(sequence query, const Long_score_profile &qp, sequence subject, const Diagonal_segment &sh, bool log);
+void greedy_align2(sequence query, const Long_score_profile &qp, sequence subject, const vector<Diagonal_segment> &sh, bool log, Hsp_data &out);
+void greedy_align(sequence query, const Long_score_profile &qp, sequence subject, int qa, int sa, bool log);
+
+template<typename _t>
+struct Fixed_score_buffer
+{
+
+	inline void init(size_t col_size, size_t cols, _t init)
+	{
+		col_size_ = col_size;
+		data_.reserve(col_size * cols);
+		data_.resize(col_size);
+		for (size_t i = 0; i<col_size; ++i)
+			data_[i] = init;
+	}
+
+	inline std::pair<_t*, _t*> get()
+	{
+		data_.resize(data_.size() + col_size_);
+		_t* ptr = last();
+		return std::pair<_t*, _t*>(ptr - col_size_, ptr);
+	}
+
+	inline _t* last()
+	{
+		return &*(data_.end() - col_size_);
+	}
+
+	const _t* column(int col) const
+	{
+		return &data_[col_size_*col];
+	}
+
+	_t operator()(int i, int j) const
+	{
+		return data_[j*col_size_ + i];
+	}
+
+private:
+	vector<_t> data_;
+	size_t col_size_;
+
+};
+
+struct Diagonal_node : public Diagonal_segment
+{
+
+	struct Edge
+	{
+		Edge() :
+			prefix_score(0),
+			node(),
+			exact(true)
+		{}
+		Edge(int prefix_score, int j, unsigned node, bool exact) :
+			prefix_score(prefix_score),
+			j(j),
+			node(node),
+			exact(exact)
+		{}
+		operator int() const
+		{
+			return prefix_score;
+		}
+		int prefix_score, j;
+		unsigned node;
+		bool exact;
+	};
+
+	Diagonal_node() :
+		Diagonal_segment(),
+		diff(std::numeric_limits<int>::min())
+	{}
+	Diagonal_node(int query_pos, int subject_pos, int len, int score) :
+		Diagonal_segment(query_pos, subject_pos, len, score),
+		diff(std::numeric_limits<int>::min())
+	{}
+	Diagonal_node(const Diagonal_segment &d) :
+		Diagonal_segment(d),
+		diff(std::numeric_limits<int>::min())
+	{}
+	enum { n_path = 2 };
+	Top_list<Edge, n_path> edges;
+	int diff;
+};
+
+int needleman_wunsch(sequence query, sequence subject, int qbegin, int qend, int sbegin, int send, unsigned node, unsigned edge, vector<Diagonal_node> &diags, bool log);
+
+#endif /* FLOATING_SW_H_ */
diff --git a/src/dp/dp_matrix.h b/src/dp/dp_matrix.h
new file mode 100644
index 0000000..1d7ea0e
--- /dev/null
+++ b/src/dp/dp_matrix.h
@@ -0,0 +1,149 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef DP_MATRIX_H_
+#define DP_MATRIX_H_
+
+#include <vector>
+#include "score_vector.h"
+
+using std::vector;
+
+template<typename _score>
+void array_clear(score_vector<_score> *v, unsigned n)
+{
+	score_vector<_score> *end (v+n);
+	while(v < end)
+		*(v++) = score_vector<_score> ();
+}
+
+template<typename _score>
+struct DP_matrix
+{
+
+	typedef score_vector<_score> sv;
+
+	struct Column_iterator
+	{
+		Column_iterator(unsigned column, sv* hgap_front, sv* score_front, unsigned row_pos, unsigned row_end, unsigned delta):
+			row_pos_ (row_pos),
+			row_end_ (row_end),
+			delta_ (delta),
+			hgap_ptr_ (hgap_front),
+			score_ptr_ (score_front),
+			d_ (delta > 0 ? *score_front : sv ())
+		{ }
+		inline bool at_end() const
+		{ return row_pos_ >= row_end_; }
+		inline void operator++()
+		{ ++row_pos_; ++hgap_ptr_; ++score_ptr_; }
+		inline sv hgap() const
+		{ return *(hgap_ptr_+delta_); }
+		inline sv diag() const
+		{ return d_; }
+		inline void set_hgap(const sv& x)
+		{ *hgap_ptr_ = x; }
+		inline void set_score(const sv& x)
+		{ d_ = *(score_ptr_+delta_); *score_ptr_ = x; }
+		unsigned row_pos_, row_end_, delta_;
+		sv *hgap_ptr_, *score_ptr_, d_;
+	};
+
+	DP_matrix(unsigned columns, unsigned rows, unsigned band, unsigned padding):
+		rows_ (rows),
+		band_ (band),
+		padding_ (padding),
+		scores_ (TLS::get(scores_ptr)),
+		hgap_ (TLS::get(hgap_ptr))
+	{
+		scores_.resize(2*band+1);
+		hgap_.resize(2*band+2);
+		hgap_front_ = &hgap_.front();
+		score_front_ = &scores_.front();
+	}
+
+	inline void clear()
+	{
+		array_clear(hgap_front_, 2*band_+2);
+		array_clear(score_front_, 2*band_+1);
+	}
+
+	inline void band_range(unsigned column, unsigned& begin, unsigned& end)
+	{
+		if(column >= rows_ + padding_) {
+			begin = 0;
+			end = band_;
+		} else if(column >= padding_) {
+			unsigned pj (column - padding_);
+			unsigned top_delta (pj >= band_ ? 0 : band_ - pj);
+			unsigned query_start (pj >= band_ ? pj - band_ : 0);
+			unsigned query_end (std::min(pj+band_+1, rows_));
+			begin = top_delta;
+			end = begin + query_end - query_start;
+		} else {
+			begin = band_ + 1;
+			end = begin + band_;
+		}
+	}
+
+	inline Column_iterator begin(unsigned column)
+	{
+		if(column >= rows_ + padding_) {
+			return Column_iterator (column, hgap_front_, score_front_, rows_-band_, rows_, 0);
+		} else if(column >= padding_) {
+			unsigned pj (column - padding_);
+			unsigned top_delta (pj >= band_ ? 0 : band_ - pj);
+			unsigned query_start (pj >= band_ ? pj - band_ : 0);
+			unsigned query_end (std::min(pj+band_+1, rows_));
+			return Column_iterator (column, hgap_front_+top_delta, score_front_+top_delta, query_start, query_end, 1);
+		} else {
+			return Column_iterator (column, hgap_front_+band_+1, score_front_+band_+1, 0, band_, 0);
+		}
+	}
+
+	inline void sub_all(sv *ptr, const sv *end, const sv& x)
+	{
+		while(ptr < end)
+			*(ptr++) -= x;
+	}
+
+	inline sv get_min(const sv *ptr, const sv *end) const
+	{
+		sv x (*(ptr++));
+		while(ptr < end)
+			x = x.min(*(ptr++));
+		return x;
+	}
+
+private:
+
+	static TLS_PTR vector<sv> *scores_ptr;
+	static TLS_PTR vector<sv> *hgap_ptr;
+
+	const unsigned rows_, band_, padding_;
+	sv *hgap_front_, *score_front_;
+	vector<sv> &scores_, &hgap_;
+
+};
+
+template<typename _score> TLS_PTR vector<score_vector<_score> >* DP_matrix<_score>::scores_ptr;
+template<typename _score> TLS_PTR vector<score_vector<_score> >* DP_matrix<_score>::hgap_ptr;
+
+#endif /* DP_MATRIX_H_ */
diff --git a/src/dp/floating_sw.cpp b/src/dp/floating_sw.cpp
new file mode 100644
index 0000000..045da25
--- /dev/null
+++ b/src/dp/floating_sw.cpp
@@ -0,0 +1,130 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <limits>
+#include "../basic/match.h"
+#include "../dp/scalar_dp_matrix.h"
+#include "../util/direction.h"
+#include "scalar_traceback.h"
+#include "scalar_dp_matrix.h"
+#include "../basic/score_matrix.h"
+#include "../align/align.h"
+#include "dp.h"
+
+template<typename _score, typename _traceback> TLS_PTR typename Score_buffer<_score,_traceback>::Type* Scalar_dp_matrix<_score,_traceback>::score_ptr = 0;
+template<typename _score, typename _traceback> TLS_PTR Double_buffer<_score>* Scalar_dp_matrix<_score,_traceback>::hgap_ptr = 0;
+
+template struct Scalar_dp_matrix<int, Traceback>;
+
+template<typename _dir, typename _score, typename _score_correction>
+Hsp_data get_traceback(const Letter *query,
+	const Letter *subject,
+	const Growing_buffer<_score> &scores,
+	int band,
+	_score gap_open,
+	_score gap_extend,
+	int i,
+	int j,
+	int query_anchor,
+	_score score,
+	const Traceback&,
+	const _score_correction &score_correction)
+{
+	return traceback<_dir, _score, _score_correction>(query, subject, scores, band, gap_open, gap_extend, i, j, query_anchor, score, score_correction);
+}
+
+template<typename _dir, typename _score, typename _score_correction>
+Hsp_data get_traceback(const Letter *query,
+	const Letter *subject,
+	const Double_buffer<_score> &scores,
+	int band,
+	_score gap_open,
+	_score gap_extend,
+	int i,
+	int j,
+	int query_anchor,
+	_score score,
+	const Score_only&,
+	const _score_correction &score_correction)
+{
+	return Hsp_data((int)score);
+}
+
+template<typename _dir, typename _score, typename _traceback, typename _score_correction>
+Hsp_data floating_sw_dir(const Letter *query, const Letter* subject, int band, _score xdrop, _score gap_open, _score gap_extend, uint64_t &cell_updates, const _score_correction &score_correction, int query_anchor)
+{
+	using std::max;
+
+	_score max_score = 0, column_max = 0;
+	int j = 0, i_max = -1, j_best = -1, i_best = -1;
+	Scalar_dp_matrix<_score, _traceback> mtx(band);
+	const Letter *x = query, *y = subject;
+
+	while (*y != '\xff' && max_score - column_max < xdrop) {
+		typename Scalar_dp_matrix<_score, _traceback>::Column_iterator it = mtx.column(j, i_max);
+		if (get_dir(x, it.row(), _dir()) == '\xff')
+			break;
+		_score vgap = Scalar_dp_matrix<_score, _traceback>::minus_inf;
+		if (get_dir(x, i_max + 1, _dir()) == '\xff') {
+			column_max = std::numeric_limits<_score>::min();
+		}
+		else {
+			++i_max;
+			_score match_score = (_score)score_matrix(*y, get_dir(x, i_max, _dir()));
+			score_correction(match_score, i_max, query_anchor, _dir::mult);
+			column_max += match_score;
+		}
+
+		for (; it.valid() && get_dir(x, it.row(), _dir()) != '\xff'; ++it) {
+			_score match_score = (_score)score_matrix(*y, get_dir(x, it.row(), _dir()));
+			score_correction(match_score, it.row(), query_anchor, _dir::mult);
+			const _score s = max(max(it.diag() + match_score, vgap), it.hgap_in());
+			if (s > column_max) {
+				column_max = s;
+				i_max = it.row();
+			}
+			const _score open = s - gap_open;
+			vgap = max(vgap - gap_extend, open);
+			it.hgap_out() = max(it.hgap_in() - gap_extend, open);
+			it.score() = s;
+			++cell_updates;
+		}
+
+		if (column_max > max_score) {
+			max_score = column_max;
+			j_best = j;
+			i_best = i_max;
+		}
+		y = inc_dir(y, _dir());
+		++j;
+	}
+	
+	return get_traceback<_dir, _score, _score_correction>(query, subject, mtx.score_buffer(), band, gap_open, gap_extend, j_best, i_best, query_anchor, max_score, _traceback(), score_correction);
+}
+
+template<typename _score, typename _traceback, typename _score_correction>
+void floating_sw(const Letter *query, const Letter *subject, Hsp_data &segment, int band, _score xdrop, _score gap_open, _score gap_extend, uint64_t &cell_updates, unsigned query_anchor, unsigned subject_anchor, const _score_correction &score_correction, const _traceback&, const _score&)
+{
+	segment.merge(floating_sw_dir<Right, _score, _traceback, _score_correction>(query + 1, subject + 1, band, xdrop, gap_open, gap_extend, cell_updates, score_correction, query_anchor+1),
+		floating_sw_dir<Left, _score, _traceback, _score_correction>(query, subject, band, xdrop, gap_open, gap_extend, cell_updates, score_correction, query_anchor), query_anchor, subject_anchor);
+}
+
+template void floating_sw<int, Traceback, No_score_correction>(const Letter *query, const Letter *subject, Hsp_data &segment, int band, int xdrop, int gap_open, int gap_extend, uint64_t &cell_updates, unsigned query_anchor, unsigned subject_anchor, const No_score_correction&, const Traceback&, const int&);
+template void floating_sw<int, Score_only, No_score_correction>(const Letter *query, const Letter *subject, Hsp_data &segment, int band, int xdrop, int gap_open, int gap_extend, uint64_t &cell_updates, unsigned query_anchor, unsigned subject_anchor, const No_score_correction&, const Score_only&, const int&);
+template void floating_sw<float, Traceback, Bias_correction>(const Letter *query, const Letter *subject, Hsp_data &segment, int band, float xdrop, float gap_open, float gap_extend, uint64_t &cell_updates, unsigned query_anchor, unsigned subject_anchor, const Bias_correction&, const Traceback&, const float&);
+template void floating_sw<float, Score_only, Bias_correction>(const Letter *query, const Letter *subject, Hsp_data &segment, int band, float xdrop, float gap_open, float gap_extend, uint64_t &cell_updates, unsigned query_anchor, unsigned subject_anchor, const Bias_correction&, const Score_only&, const float&);
\ No newline at end of file
diff --git a/src/dp/floating_sw.h b/src/dp/floating_sw.h
new file mode 100644
index 0000000..566edbf
--- /dev/null
+++ b/src/dp/floating_sw.h
@@ -0,0 +1,43 @@
+/****
+Copyright (c) 2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef FLOATING_SW_H_
+#define FLOATING_SW_H_
+
+#include "../basic/match.h"
+#include "../align/align.h"
+
+struct Score_only { };
+struct Traceback { };
+
+template<typename _score, typename _traceback, typename _score_correction>
+void floating_sw(const Letter *query,
+	const Letter *subject,
+	Hsp_data &segment,
+	int band,
+	_score xdrop,
+	_score gap_open,
+	_score gap_extend,
+	uint64_t &cell_updates,
+	unsigned query_anchor,
+	unsigned subject_anchor,
+	const _score_correction &score_correction,
+	const _traceback& = Score_only(),
+	const _score& = int());
+
+#endif /* FLOATING_SW_H_ */
diff --git a/src/dp/greedy_align.cpp b/src/dp/greedy_align.cpp
new file mode 100644
index 0000000..5e2de2d
--- /dev/null
+++ b/src/dp/greedy_align.cpp
@@ -0,0 +1,589 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+// #define _ITERATOR_DEBUG_LEVEL 0
+
+#include "../basic/sequence.h"
+#include "../basic/match.h"
+#include "../basic/score_matrix.h"
+#include "../search/sse_dist.h"
+#include "../align/extend_ungapped.h"
+#include "../dp/score_profile.h"
+
+struct Link
+{
+	Link():
+		subject_pos1(-1)
+	{}
+	Link(unsigned target, int query_pos, int subject_pos, int score1, int score2) :
+		subject_pos1(subject_pos),
+		query_pos1(query_pos),
+		score1(score1),
+		score2(score2)
+	{}
+	int subject_pos1, query_pos1, subject_pos2, query_pos2, score1, score2;
+	Link& transpose()
+	{
+		std::swap(subject_pos1, query_pos1);
+		std::swap(subject_pos2, query_pos2);
+		return *this;
+	}
+	void reset()
+	{
+		subject_pos1 = -1;
+		score1 = 0;
+		score2 = 0;
+	}
+};
+
+Diagonal_segment score_diagonal(const Letter *query, const Letter *subject, int qbegin, int jbegin)
+{
+	int i = 0, j = 0, max_score = 0, score = 0, begin = 0, end = 0;
+	while (query[i] != '\xff' && subject[i] != '\xff') {
+		score += score_matrix(query[i], subject[i]);
+		if (score <= 0) {
+			score = 0;
+			j = i + 1;
+		}
+		if (score > max_score) {
+			max_score = score;
+			begin = j;
+			end = i + 1;
+		}
+		++i;
+	}
+	return Diagonal_segment(qbegin + begin, jbegin + begin, end - begin, max_score);
+}
+
+Diagonal_segment score_diagonal(const Letter *query, const Letter *subject, int n, int qbegin, int jbegin)
+{
+	int i = 0, j = 0, max_score = 0, score = 0, begin = 0, end = 0;
+	while (i < n) {
+		score += score_matrix(query[i], subject[i]);
+		if (score <= 0) {
+			score = 0;
+			j = i + 1;
+		}
+		if (score > max_score) {
+			max_score = score;
+			begin = j;
+			end = i + 1;
+		}
+		++i;
+	}
+	return Diagonal_segment(qbegin + begin, jbegin + begin, end - begin, max_score);
+}
+
+int score_range(sequence query, sequence subject, int i, int j, int j_end)
+{
+	int score = 0;
+	while (j < j_end) {
+		score += score_matrix(query[i], subject[j]);
+		++i;
+		++j;
+	}
+	return score;
+}
+
+int get_hgap_link(const Diagonal_segment &d1, const Diagonal_segment &d2, sequence query, sequence subject, Link &l)
+{
+	const int d = d1.diag() - d2.diag(),
+		j2_end = std::min(std::max((int)d2.j, d1.subject_last() + d + 1), d2.subject_last());
+	int j1;
+	bool space;
+	if (d1.subject_last() < d2.j - d - 1) {
+		j1 = d1.subject_last();
+		space = true;
+	}
+	else {
+		j1 = std::max(d2.j - d - 1, d1.j);
+		space = false;
+	}
+	int j2 = j1 + d + 1,
+		i1 = d1.i + (j1 - d1.j),
+		i2 = i1 + 1;
+	if (j2 > d2.subject_last()) {
+		l.reset();
+		return std::numeric_limits<int>::min();
+	}
+	int score1 = 0,
+		//score2 = score_range(query, subject, i2, j2, d2.j + d2.len);
+		score2 = score_range(query, subject, i2, j2, d2.j) + d2.score - score_range(query, subject, d2.i, d2.j, j2);
+	int max_score = std::numeric_limits<int>::min();
+	while (true) {
+		if (score1 + score2 > max_score) {
+			max_score = score1 + score2;
+			l.query_pos1 = i1;
+			l.subject_pos1 = j1;
+			l.query_pos2 = i2;
+			l.subject_pos2 = j2;
+			l.score1 = score1;
+			l.score2 = score2;
+		}
+		score2 -= score_matrix(query[i2], subject[j2]);
+		++i1; ++i2; ++j1; ++j2;
+		if (j2 > j2_end)
+			break;
+		score1 += score_matrix(query[i1], subject[j1]);
+	}
+	const int j1_end = j2_end - d;
+	if (space)
+		l.score1 = d1.score + l.score1;
+	else
+		l.score1 = d1.score - score_range(query, subject, d1.diag() + j1_end, j1_end, d1.subject_end()) - score1 + l.score1;
+	return max_score;
+}
+
+int get_vgap_link(const Diagonal_segment &d1, const Diagonal_segment &d2, sequence query, sequence subject, Link &l)
+{
+	int s = get_hgap_link(d1.transpose(), d2.transpose(), subject, query, l);
+	l.transpose();
+	return s;
+}
+
+int get_link(const Diagonal_segment &d1, const Diagonal_segment &d2, sequence query, sequence subject, Link &l)
+{
+	if (d1.diag() < d2.diag())
+		return get_vgap_link(d1, d2, query, subject, l);
+	else
+		return get_hgap_link(d1, d2, query, subject, l);
+}
+
+void set_global_max(score_vector<uint8_t> *max, score_vector<uint8_t> *global_max, uint8_t *&local_max)
+{
+#ifdef __SSE2__
+	global_max[0].max(max[0]);
+	max[0].store(local_max);
+	max[0] = score_vector<uint8_t>();
+	local_max += 16;
+	global_max[1].max(max[1]);
+	max[1].store(local_max);
+	max[1] = score_vector<uint8_t>();
+	local_max += 16;
+	global_max[2].max(max[2]);
+	max[2].store(local_max);
+	max[2] = score_vector<uint8_t>();
+	local_max += 16;
+	global_max[3].max(max[3]);
+	max[3].store(local_max);
+	max[3] = score_vector<uint8_t>();
+	local_max += 16;
+#endif
+}
+
+void scan_cols(const Long_score_profile &qp, sequence s, int i, int j, int j_end, uint8_t *sv_max, bool log, uint8_t *buf, uint8_t *local_max, int block_len)
+{
+#ifdef __SSE2__
+	typedef score_vector<uint8_t> Sv;
+	const Sv vbias(score_matrix.bias());
+	Sv v[4], max[4], global_max[4];
+	int n = 0;
+	for (; j < j_end; ++j) {
+		const uint8_t *q = qp.get(s[j], i);
+		v[0] = v[0] + score_vector<uint8_t>(q);
+		v[0] -= vbias;
+		max[0].max(v[0]);
+		_mm_storeu_si128((__m128i*)buf, v[0].data_);
+		q += 16;
+		buf += 16;
+		v[1] = v[1] + score_vector<uint8_t>(q);
+		v[1] -= vbias;
+		max[1].max(v[1]);
+		_mm_storeu_si128((__m128i*)buf, v[1].data_);
+		q += 16;
+		buf += 16;
+		v[2] = v[2] + score_vector<uint8_t>(q);
+		v[2] -= vbias;
+		max[2].max(v[2]);
+		_mm_storeu_si128((__m128i*)buf, v[2].data_);
+		q += 16;
+		buf += 16;
+		v[3] = v[3] + score_vector<uint8_t>(q);
+		v[3] -= vbias;
+		max[3].max(v[3]);
+		_mm_storeu_si128((__m128i*)buf, v[3].data_);
+		buf += 16;
+		//cout << 's' << v[0] << v[1] << v[2] << v[3] << endl;
+		if ((n & 15) == 15) {
+			//cout << 'l' << max[0] << max[1] << max[2] << max[3] << endl;
+			set_global_max(max, global_max, local_max);
+		}
+		++i;
+		++n;
+	}
+	if(n % block_len != 0)
+		set_global_max(max, global_max, local_max);
+	global_max[0].store(sv_max);
+	global_max[1].store(sv_max + 16);
+	global_max[2].store(sv_max + 32);
+	global_max[3].store(sv_max + 48);
+	//cout << 'g' << global_max[0] << global_max[1] << global_max[2] << global_max[3] << endl;
+#endif
+}
+
+struct Greedy_aligner2
+{
+
+	enum { band = 64, block_len = 16 };
+
+	struct Node_ref
+	{
+		Node_ref():
+			node(0),
+			score(0)
+		{}
+		Node_ref(unsigned node, int score) :
+			node(node),
+			score(score)
+		{}
+		unsigned node;
+		int score;
+		bool operator<(const Node_ref &rhs) const
+		{
+			return score > rhs.score;
+		}
+	};
+
+	int correct_left(unsigned node, int j)
+	{
+		const Diagonal_segment &d = diags[node];
+		const int shift = j - d.j;
+		return shift < 0 ? score_range(query, subject, d.i + shift, j, d.j) : -score_range(query, subject, d.i, d.j, j);
+	}
+	
+	int correct_right(unsigned node, int j)
+	{
+		const Diagonal_segment &d = diags[node];
+		const int end = d.subject_end(), shift = j - end;
+		return shift < 0 ? -score_range(query, subject, d.query_end() + shift, j, d.subject_end()) : score_range(query, subject, d.query_end(), d.subject_end(), j);
+	}
+
+	void get_diag(int i, int j, int o, int begin, int end, int max_score)
+	{
+		const uint8_t *p = score_buf.data() + o + begin*band,
+			*p_end = p + block_len*band,
+			*b0 = p - band,
+			*b = b0;
+		for (; p < p_end; p += band) {
+			if (*p == 0)
+				b = p;
+			if (*p == max_score)
+				break;
+		}
+		if (b == b0) {
+			b0 = score_buf.data() + o;
+			for (; b >= b0; b -= band)
+				if (*b == 0)
+					break;
+		}
+
+		p = score_buf.data() + o + end*band;
+		p_end = p + block_len*band;
+		for (; p < p_end; p += band) {
+			if (*p == max_score)
+				break;
+		}
+
+		const int b2 = int(b - (score_buf.data() + o)) / band + 1;
+		diags.push_back(Diagonal_segment(i + b2, j + b2, int(p - b) / band, max_score));
+	}
+
+	void get_diag(int i, int j, int o)
+	{
+		const uint8_t *p = local_max.data() + o, *p_end = local_max.data() + local_max.size();
+		int n = 0, begin = -1, best = -1, best_score = -1, second_best_score = -1, second_best = -1, second_best_begin = -1;
+		for (; p < p_end; p += band) {
+			if (*p >= config.min_diag_raw_score) {
+				if (begin == -1) {
+					begin = n;
+					best = n;
+					best_score = *p;
+				} 
+				else if (*p > best_score) {
+					best = n;
+					best_score = *p;
+				}
+				else if (*p > *(p - band)) {
+					if (second_best_begin == -1) {
+						second_best_begin = n;
+						second_best = n;
+						second_best_score = *p;
+					}
+					else {
+						if (*p > second_best_score) {
+							second_best_score = *p;
+							second_best = n;
+						}
+					}
+				}
+			}
+			else if (begin >= 0) {
+				get_diag(i, j, o, begin * 16, best * 16, best_score);
+				if (second_best_begin >= 0) {
+					second_best_begin -= 1;
+					const Diagonal_segment second = score_diagonal(&query[i + second_best_begin * 16],
+						&subject[j + second_best_begin * 16],
+						(second_best - second_best_begin + 1) * 16,
+						i + second_best_begin * 16,
+						j + second_best_begin * 16);
+					if (second.score >= config.min_diag_raw_score)
+						diags.push_back(second);
+					second_best_begin = -1;
+				}
+				begin = -1;
+				best = -1;
+				best_score = -1;
+			}
+			++n;
+		}
+		if (begin >= 0) {
+			get_diag(i, j, o, begin * 16, best * 16, best_score);
+			if (second_best_begin >= 0) {
+				second_best_begin -= 1;
+				const Diagonal_segment second = score_diagonal(&query[i + second_best_begin * 16],
+					&subject[j + second_best_begin * 16],
+					(second_best - second_best_begin + 1) * 16,
+					i + second_best_begin * 16,
+					j + second_best_begin * 16);
+				if (second.score >= config.min_diag_raw_score)
+					diags.push_back(second);
+			}
+		}
+	}
+	
+	void scan_diags(const Diagonal_segment &diag)
+	{
+		const int d = diag.diag() - band / 2,
+			d1 = d + band - 1,
+			i = std::max(0, d1) - band + 1,
+			j = i - d,
+			j1 = std::min((int)query.length() - d, (int)subject.length());
+		uint8_t sv_max[band];
+		memset(sv_max, 0, band);
+		const size_t cells = band * (j1 - j);
+		score_buf.resize(cells);
+		local_max.resize((j1 - j + block_len - 1) / block_len * band);
+		scan_cols(qp, subject, i, j, j1, sv_max, log, score_buf.data(), local_max.data(), block_len);
+		for (int o = 0; o < band; ++o)
+			if (sv_max[o] >= config.min_diag_raw_score) {
+				//get_diag(i + o, j, sv_max[o], o);
+				get_diag(i + o, j, o);
+			}
+	}
+
+	int follow_path(unsigned level, unsigned node, int score, int subject_pos)
+	{
+		static const int max_dist = 32, min_nw_space = 7;
+		static const float space_penalty = -0.5;
+		Diagonal_node& d = diags[node];
+		if (log) cout << "Node " << node << " Score=" << d.edges[0].prefix_score << endl;
+		if (d.diff != std::numeric_limits<int>::min()) {
+			if (log)
+				cout << "Visited node final_score=" << d.edges[0].prefix_score << endl;
+			return d.diff;
+		}
+		int max_score = d.edges[0].prefix_score, diff = 0, max_edge = 0;
+		for (unsigned k = 0; k < Diagonal_node::n_path; ++k) {
+			Diagonal_node::Edge &f = d.edges[k];
+			if (f.prefix_score == 0)
+				break;
+			if (f.node == node)
+				continue;
+			unsigned next = f.node;
+			const Diagonal_node &e = diags[next];
+			if (!f.exact) {
+				const int shift = d.diag() - e.diag();
+				int gap_score = -config.gap_open - abs(shift)*config.gap_extend;
+				const int space = shift > 0 ? d.j - e.subject_last() : d.i - e.query_last();
+				f.prefix_score += int(config.raw_space_penalty*std::max(space - 1, 0));
+				if (space >= min_nw_space && abs(shift) > 1) {
+					if (log) {
+						const sequence q1 = sequence(query, e.query_last() + 1, d.i - 1),
+							s1 = sequence(subject, e.subject_last() + 1, d.j - 1);
+						cout << q1 << endl << s1 << endl;
+					}
+					gap_score = needleman_wunsch(query, subject, e.query_last() + 1, d.i, e.subject_last() + 1, d.j, node, k, diags, log);
+					f.prefix_score -= -config.gap_open - abs(shift)*config.gap_extend;
+					f.prefix_score += gap_score;
+				}
+				else {
+					Link l;
+					int link_score = get_link(e, d, query, subject, l);
+					f.prefix_score += (l.score1 - e.score) + (l.score2 - d.score);
+					f.j = l.subject_pos2;
+				}
+			}
+			if (log)
+				cout << "Node=" << node << " Link n=" << next << " prefix_score=" << f.prefix_score << endl;
+			f.prefix_score += follow_path(level + 1, next, 0, 0);
+			if (diff < f.prefix_score - max_score) {
+				diff = f.prefix_score - max_score;
+				max_edge = k;
+			}
+		}
+		if (max_edge != 0) {
+			memcpy(&d.edges[0], &d.edges[max_edge], sizeof(Diagonal_node::Edge));
+		}
+		d.diff = diff;
+		top_node = std::min(top_node, Node_ref(node, d.edges[0].prefix_score));
+		if(log) cout << "Node " << node << " diff=" << diff << " final_score=" << d.edges[0].prefix_score << endl;
+		return diff;
+	}
+
+	unsigned follow_path_approximate()
+	{
+		static const int max_dist = 32;
+		static const float space_penalty = -0.5;
+		int max_score = 0;
+		unsigned max_node;
+		for (unsigned node = 0; node < diags.size(); ++node) {
+			Diagonal_node& d = diags[node];
+			if (log) cout << "Node " << node << " Score=" << d.score << endl;
+			d.edges.add(Diagonal_node::Edge(d.score, d.j, node, true));
+			for (int k = node - 1; k >= 0; --k) {
+				const Diagonal_node &e = diags[k];
+				if (d.j - e.subject_last() < max_dist) {
+					if (abs(d.i - e.query_last()) >= max_dist)
+						continue;
+					const int shift = d.diag() - e.diag();
+					int gap_score = -config.gap_open - abs(shift)*config.gap_extend;
+					const int space = shift > 0 ? d.j - e.subject_last() : d.i - e.query_last();
+					int prefix_score = 0, link_score = 0, link_j;
+					bool exact;
+					if (space <= 0) {
+						Link link;
+						if (get_link(e, d, query, subject, link) > 0) {
+							prefix_score = e.edges[0].prefix_score - (e.score - link.score1) + gap_score + link.score2;
+							link_score = link.score1 + link.score2 + gap_score;
+							exact = true;
+							link_j = link.subject_pos2;
+						}
+					}
+					else {
+						prefix_score = e.edges[0].prefix_score + gap_score - int(config.raw_space_penalty*std::max(space - 1, 0)) + d.score;
+						link_score = e.score + d.score + gap_score;
+						exact = false;
+						link_j = d.j;
+					}
+
+					if (log)
+						cout << "Link n=" << k << " shift=" << shift << " space=" << space << " prefix_score=" << prefix_score << " link_score=" << link_score << endl;
+					if (prefix_score > 0)
+						d.edges.add(Diagonal_node::Edge(prefix_score, link_j, k, exact));
+				}
+				else
+					break;
+			}
+			if (log) {
+				cout << "Final score=" << d.edges[0].prefix_score << endl << endl;
+			}
+			top_nodes.push_back(Node_ref(node, d.edges[0].prefix_score));
+			if (d.edges[0].prefix_score > max_score) {
+				max_score = d.edges[0].prefix_score;
+				max_node = node;
+			}
+		}
+		return max_node;
+	}
+
+	void backtrace(unsigned node, int j_end, Hsp_data &out)
+	{
+		const Diagonal_node &d = diags[node];
+		const Diagonal_node::Edge &f = d.edges[0];
+		const Diagonal_node &e = diags[f.node];
+		const int shift = d.diag() - e.diag();
+		int j = f.j;
+		if (f.node != node) {
+			backtrace(f.node, shift > 0 ? j : j + shift, out);
+			if (shift > 0) {
+				out.transcript.push_back(op_insertion, (unsigned)shift);
+			}
+			else {
+				for (int j2 = j + shift; j2 < j; ++j2)
+					out.transcript.push_back(op_deletion, subject[j2]);
+			}
+		}
+		else {
+			out.query_range.begin_ = d.i;
+			out.subject_range.begin_ = d.j;
+		}
+		const int d2 = d.diag();
+		for (; j < j_end; ++j) {
+			const Letter s = subject[j], q = query[d2 + j];
+			if (s == q)
+				out.transcript.push_back(op_match);
+			else
+				out.transcript.push_back(op_substitution, s);
+		}
+	}
+
+	Greedy_aligner2(const sequence &query, const Long_score_profile &qp, const sequence &subject, const vector<Diagonal_segment> &sh, bool log, Hsp_data &out) :
+		query(query),
+		subject(subject),
+		qp(qp),
+		log(log),
+		score_buf(TLS::get(score_buf_ptr)),
+		local_max(TLS::get(local_max_ptr)),
+		diags(TLS::get(diags_ptr)),
+		top_nodes(TLS::get(top_nodes_ptr))
+	{
+		config.min_diag_raw_score = 15;
+		diags.clear();
+		local_max.clear();
+		top_nodes.clear();
+		scan_diags(sh[0]);
+		std::sort(diags.begin(), diags.end(), Diagonal_segment::cmp_subject_end);
+		if (log)
+			for (int k = 0; k < (int)diags.size(); ++k) {
+				const Diagonal_segment &d = diags[k];
+				cout << "Diag n=" << k << " i=" << d.i << " j=" << d.j << " score=" << d.score << " len=" << d.len << endl;
+				cout << sequence(query, d.i, d.query_last()) << endl;
+				cout << sequence(subject, d.j, d.subject_last()) << endl;
+			}
+		if(log) cout << endl;
+		unsigned max_node = follow_path_approximate();
+		follow_path(0, max_node, 0, 0);
+		out.transcript.clear();
+		out.length = 1;
+		backtrace(top_node.node, diags[top_node.node].subject_end(), out);
+		out.transcript.push_terminator();
+	}
+
+	static TLS_PTR vector<uint8_t> *score_buf_ptr;
+	static TLS_PTR vector<uint8_t> *local_max_ptr;
+	static TLS_PTR vector<Diagonal_node> *diags_ptr;
+	static TLS_PTR vector<Node_ref> *top_nodes_ptr;
+	const sequence query, subject;
+	const Long_score_profile &qp;
+	const bool log;
+	vector<uint8_t> &score_buf, &local_max;
+	vector<Diagonal_node> &diags;
+	vector<Node_ref> &top_nodes;
+	Node_ref top_node;
+
+};
+
+TLS_PTR vector<uint8_t> *Greedy_aligner2::score_buf_ptr;
+TLS_PTR vector<uint8_t> *Greedy_aligner2::local_max_ptr;
+TLS_PTR vector<Diagonal_node> *Greedy_aligner2::diags_ptr;
+TLS_PTR vector<Greedy_aligner2::Node_ref> *Greedy_aligner2::top_nodes_ptr;
+
+void greedy_align2(sequence query, const Long_score_profile &qp, sequence subject, const vector<Diagonal_segment> &sh, bool log, Hsp_data &out)
+{
+	Greedy_aligner2(query, qp, subject, sh, log, out);
+}
\ No newline at end of file
diff --git a/src/dp/growing_buffer.h b/src/dp/growing_buffer.h
new file mode 100644
index 0000000..7efc748
--- /dev/null
+++ b/src/dp/growing_buffer.h
@@ -0,0 +1,71 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+Author: Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef GROWING_BUFFER_H_
+#define GROWING_BUFFER_H_
+
+#include <vector>
+
+using std::vector;
+using std::pair;
+
+template<typename _t>
+struct Growing_buffer
+{
+
+	inline void init(size_t size, size_t padding, size_t padding_front, _t init)
+	{
+		const size_t total = size + padding;
+		data_.resize(total);
+		col_size_ = total;
+		for(size_t i=0;i<total;++i)
+			data_[i] = init;
+		init_ = init;
+		center_.clear();
+		center_.push_back(-1);
+	}
+
+	inline pair<_t*,_t*> get(int center)
+	{
+		data_.resize(data_.size() + col_size_);
+		_t* ptr = last();
+		for(size_t i=0;i<col_size_;++i)
+			ptr[i] = init_;
+		center_.push_back(center);
+		return pair<_t*,_t*> (ptr-col_size_, ptr);
+	}
+
+	inline _t* last()
+	{ return &*(data_.end() - col_size_); }
+
+	const _t* column(int col) const
+	{ return &data_[col_size_*col]; }
+
+	int center(int col) const
+	{ return center_[col]; }
+
+private:
+	vector<_t> data_;
+	vector<int> center_;
+	size_t col_size_;
+	_t init_;
+
+};
+
+#endif
diff --git a/src/dp/needleman_wunsch.cpp b/src/dp/needleman_wunsch.cpp
new file mode 100644
index 0000000..1fd6e0f
--- /dev/null
+++ b/src/dp/needleman_wunsch.cpp
@@ -0,0 +1,192 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <vector>
+#include "dp.h"
+#include "../util/double_buffer.h"
+#include "growing_buffer.h"
+#include "../util/util.h"
+#include "traceback.h"
+
+using std::vector;
+using std::pair;
+
+template<typename _score>
+struct Dp_matrix
+{
+
+	struct Column_iterator
+	{
+
+		inline Column_iterator(const pair<_score*, _score*> &score, _score* hgap, int query_len, int col) :
+			score_(score),
+			hgap_(hgap),
+			end_(score_.second + query_len + 1),
+			i_(0)
+		{
+			*score_.first = col == 0 ? 0 : -config.gap_open - col*config.gap_extend;
+			++score_.second;
+		}
+
+		inline int row() const
+		{
+			return i_;
+		}
+
+		inline bool valid() const
+		{
+			return score_.second < end_;
+		}
+
+		inline _score& score()
+		{
+			return *score_.second;
+		}
+
+		inline _score diag() const
+		{
+			return *score_.first;
+		}
+
+		inline _score& hgap()
+		{
+			return *hgap_;
+		}
+
+		inline void operator++()
+		{
+			++i_;
+			++score_.first;
+			++score_.second;
+			++hgap_;
+		}
+
+	private:
+		pair<_score*, _score*> score_;
+		_score* hgap_;
+		const _score* const end_;
+		int i_;
+
+	};
+
+	inline Column_iterator column(int j)
+	{
+		return Column_iterator(score_.get(), hgap_.data(), query_len_, j);
+	}
+
+	inline Dp_matrix(int query_len, int subject_len) :
+		query_len_(query_len),
+		score_(TLS::get(score_ptr)),
+		hgap_(TLS::get(hgap_ptr))
+	{
+		score_.init(query_len + 1, subject_len + 1, 0);
+		hgap_.clear();
+		hgap_.insert(hgap_.end(), query_len, std::numeric_limits<int>::min() + 1);
+		int *score = score_.last();
+		int g = -config.gap_open - config.gap_extend;
+		for (int i = 1; i <= query_len; ++i)
+			score[i] = g--;
+	}
+
+	const Fixed_score_buffer<_score>& score_buffer() const
+	{
+		return score_;
+	}
+
+private:
+
+	const int query_len_;
+	Fixed_score_buffer<_score> &score_;
+	vector<_score> &hgap_;
+	static TLS_PTR Fixed_score_buffer<_score> *score_ptr;
+	static TLS_PTR vector<_score> *hgap_ptr;
+
+};
+
+template<typename _score> TLS_PTR Fixed_score_buffer<_score>* Dp_matrix<_score>::score_ptr;
+template<typename _score> TLS_PTR vector<_score>* Dp_matrix<_score>::hgap_ptr;
+
+template<typename _score>
+const Fixed_score_buffer<_score>& needleman_wunsch(sequence query, sequence subject, const _score& = int())
+{
+	using std::max;
+	const int gap_open = config.gap_open + config.gap_extend, gap_extend = config.gap_extend;
+
+	Dp_matrix<_score> mtx((unsigned)query.length(), (unsigned)subject.length());
+
+	for (int j = 0; j < (int)subject.length(); ++j) {
+		typename Dp_matrix<_score>::Column_iterator it = mtx.column(j);
+		_score vgap = std::numeric_limits<int>::min() + 1;
+		for (; it.valid(); ++it) {
+			const _score match_score = score_matrix(subject[j], query[it.row()]);
+			const _score s = max(max(it.diag() + match_score, vgap), it.hgap());
+			const _score open = s - gap_open;
+			vgap = max(vgap - gap_extend, open);
+			it.hgap() = max(it.hgap() - gap_extend, open);
+			it.score() = s;
+		}
+	}
+
+	return mtx.score_buffer();
+}
+
+int needleman_wunsch(sequence query, sequence subject, int qbegin, int qend, int sbegin, int send, unsigned node, unsigned edge, vector<Diagonal_node> &diags, bool log)
+{
+	const sequence q = query.subseq(qbegin, qend), s = subject.subseq(sbegin, send);
+	const Fixed_score_buffer<int> &dp = needleman_wunsch(q, s, int());
+	Diagonal_node *d = &diags[node];
+	unsigned start_node = d->edges[edge].node;
+	Diagonal_node::Edge *f = &d->edges[edge];
+
+	const int gap_open = config.gap_open, gap_extend = config.gap_extend;
+	int l, i = qend - qbegin, j = send - sbegin;
+	const int score = dp(i, j);
+
+	l = have_diag(dp, i, j, q, s, log);
+	if (l > 0) {
+		i -= l;
+		j -= l;
+		f->exact = true;
+		f->j = j;
+	}
+
+	while (i > 0 && j > 0) {
+		if ((l = have_diag(dp, i, j, q, s, log)) > 0) {
+			i -= l;
+			j -= l;
+			if (i != 0 || j != 0) {
+				f->node = (unsigned)diags.size();
+				diags.push_back(Diagonal_node(qbegin + i, sbegin + j, l, 0));
+				f = &diags.back().edges[0];
+				f->exact = true;
+				f->j = sbegin + j;
+			}
+		}
+		else if (have_hgap(dp, i, j, gap_open, gap_extend, l)) {
+			j -= l;
+		}
+		else if (have_vgap(dp, i, j, gap_open, gap_extend, l)) {
+			i -= l;
+		}
+		else
+			throw std::runtime_error("Traceback error.");
+	}
+
+	f->node = start_node;
+	return score;
+}
\ No newline at end of file
diff --git a/src/dp/padded_banded_sw.cpp b/src/dp/padded_banded_sw.cpp
new file mode 100644
index 0000000..3c67607
--- /dev/null
+++ b/src/dp/padded_banded_sw.cpp
@@ -0,0 +1,147 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "dp.h"
+
+struct Padded_banded_DP_matrix
+{
+
+	struct Column_iterator
+	{
+		Column_iterator(unsigned column, int* hgap_front, int* score_front, unsigned row_pos, unsigned row_end, unsigned delta) :
+			row_pos_(row_pos),
+			row_end_(row_end),
+			delta_(delta),
+			hgap_ptr_(hgap_front),
+			score_ptr_(score_front),
+			d_(delta > 0 ? *score_front : 0)
+		{ }
+		inline bool at_end() const
+		{
+			return row_pos_ >= row_end_;
+		}
+		inline void operator++()
+		{
+			++row_pos_; ++hgap_ptr_; ++score_ptr_;
+		}
+		inline int hgap() const
+		{
+			return *(hgap_ptr_ + delta_);
+		}
+		inline int diag() const
+		{
+			return d_;
+		}
+		inline void set_hgap(int x)
+		{
+			*hgap_ptr_ = x;
+		}
+		inline void set_score(int x)
+		{
+			d_ = *(score_ptr_ + delta_); *score_ptr_ = x;
+		}
+		unsigned row_pos_, row_end_, delta_;
+		int *hgap_ptr_, *score_ptr_, d_;
+	};
+
+	Padded_banded_DP_matrix(unsigned columns, unsigned rows, unsigned band, unsigned padding) :
+		rows_(rows),
+		band_(band),
+		padding_(padding),
+		scores_(TLS::get(scores_ptr)),
+		hgap_(TLS::get(hgap_ptr))
+	{
+		scores_.resize(2 * band + 1);
+		hgap_.resize(2 * band + 2);
+		hgap_front_ = &hgap_.front();
+		score_front_ = &scores_.front();
+	}
+
+	inline void clear()
+	{
+		memset(hgap_front_, 0, (2 * band_ + 2) * sizeof(int));
+		memset(score_front_, 0, (2 * band_ + 1) * sizeof(int));
+	}
+
+	inline Column_iterator begin(unsigned column)
+	{
+		if (column >= rows_ + padding_) {
+			return Column_iterator(column, hgap_front_, score_front_, rows_ - band_, rows_, 0);
+		}
+		else if (column >= padding_) {
+			unsigned pj(column - padding_);
+			unsigned top_delta(pj >= band_ ? 0 : band_ - pj);
+			unsigned query_start(pj >= band_ ? pj - band_ : 0);
+			unsigned query_end(std::min(pj + band_ + 1, rows_));
+			return Column_iterator(column, hgap_front_ + top_delta, score_front_ + top_delta, query_start, query_end, 1);
+		}
+		else {
+			return Column_iterator(column, hgap_front_ + band_ + 1, score_front_ + band_ + 1, 0, band_, 0);
+		}
+	}
+
+private:
+
+	static TLS_PTR vector<int> *scores_ptr;
+	static TLS_PTR vector<int> *hgap_ptr;
+
+	const unsigned rows_, band_, padding_;
+	int *hgap_front_, *score_front_;
+	vector<int> &scores_, &hgap_;
+
+};
+
+TLS_PTR vector<int>* Padded_banded_DP_matrix::scores_ptr;
+TLS_PTR vector<int>* Padded_banded_DP_matrix::hgap_ptr;
+
+int smith_waterman(const sequence &query, const sequence &subject, unsigned band, unsigned padding, int op, int ep)
+{
+	unsigned qlen((unsigned)query.length());
+	unsigned slen((unsigned)subject.length());
+	Padded_banded_DP_matrix dp(slen, qlen, band, padding);
+
+	int best = 0;
+	dp.clear();
+
+	for (unsigned j = 0; j < slen; ++j) {
+		if (j < (unsigned)subject.clipping_offset_)
+			continue;
+		if (subject[j] == '\xff')
+			break;
+		Padded_banded_DP_matrix::Column_iterator it(dp.begin(j));
+		int vgap = 0, hgap;
+		while (!it.at_end()) {
+			hgap = it.hgap();
+			int current_cell = it.diag() + score_matrix(query[it.row_pos_], subject[j]);
+			current_cell = std::max(current_cell, vgap);
+			current_cell = std::max(current_cell, hgap);
+			current_cell = std::max(current_cell, 0);
+			best = std::max(best, current_cell);
+			vgap -= ep;
+			hgap -= ep;
+			int open = current_cell - op;
+			vgap = std::max(vgap, open);
+			hgap = std::max(hgap, open);
+			it.set_hgap(hgap);
+			it.set_score(current_cell);
+			++it;
+		}
+	}
+	
+	return best;
+}
\ No newline at end of file
diff --git a/src/dp/scalar_dp_matrix.h b/src/dp/scalar_dp_matrix.h
new file mode 100644
index 0000000..788176d
--- /dev/null
+++ b/src/dp/scalar_dp_matrix.h
@@ -0,0 +1,140 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+Author: Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SCALAR_DP_MATRIX_H_
+#define SCALAR_DP_MATRIX_H_
+
+#include <vector>
+#include "../util/double_buffer.h"
+#include "growing_buffer.h"
+#include "../util/util.h"
+#include "floating_sw.h"
+
+using std::vector;
+using std::pair;
+
+template<typename _score, typename _traceback>
+struct Score_buffer { };
+
+template<typename _score>
+struct Score_buffer<_score,Score_only>
+{
+	typedef Double_buffer<_score> Type;
+};
+
+template<typename _score>
+struct Score_buffer<_score,Traceback>
+{
+	typedef Growing_buffer<_score> Type;
+};
+
+template<typename _score, typename _traceback>
+struct Scalar_dp_matrix
+{
+
+	struct Column_iterator
+	{
+
+		inline Column_iterator(const pair<_score*,_score*> &score, const pair<_score*,_score*> &hgap, int j, int i, int delta, int band):
+			score_ (score),
+			hgap_ (hgap),
+			end_ (score_.second + 2*band + 1),
+			i_ (std::max(i - band, 0))
+		{
+			assert(delta >= 0 && j >= 0 && i >= 0 && band >= 0);
+			if(j == 0)
+				score_.first[band] = 0;
+			const int offset = i_ - i + band;
+			score_.second += offset;
+			hgap_.second += offset;
+			hgap_.first += offset + delta;
+			score_.first += offset + delta - 1;
+		}
+
+		inline int row() const
+		{ return i_; }
+
+		inline bool valid() const
+		{ return score_.second < end_; }
+
+		inline _score& score()
+		{ return *score_.second; }
+
+		inline _score diag() const
+		{ return *score_.first; }
+
+		inline _score hgap_in() const
+		{ return *hgap_.first; }
+
+		inline _score& hgap_out()
+		{ return *hgap_.second; }
+
+		inline void operator++()
+		{
+			++i_;
+			++score_.first;
+			++score_.second;
+			++hgap_.first;
+			++hgap_.second;
+		}
+
+	private:
+		pair<_score*,_score*> score_, hgap_;
+		const _score* const end_;
+		int i_;
+
+	};
+
+	inline Column_iterator column(int j, int i_max)
+	{
+		int i = std::max(current_i_, i_max+1), delta = i - current_i_;
+		current_i_ = i;
+		return Column_iterator (score_.get(i), hgap_.get(int ()), j, i, delta, band_);
+	}
+
+	inline Scalar_dp_matrix(int band):
+		band_ (band),
+		band_max_ (2*band+1),
+		current_i_ (-1),
+		score_ (TLS::get(score_ptr)),
+		hgap_ (TLS::get(hgap_ptr))
+	{
+		score_.init(band_max_, band_+1, 1, minus_inf);
+		hgap_.init(band_max_, band_+1, 1, minus_inf);
+	}
+
+	const typename Score_buffer<_score,_traceback>::Type& score_buffer() const
+	{ return score_; }
+
+	enum {
+		minus_inf = -65536
+	};
+
+private:
+
+	const int band_, band_max_;
+	int current_i_;
+	typename Score_buffer<_score,_traceback>::Type &score_;
+	Double_buffer<_score> &hgap_;
+	static TLS_PTR typename Score_buffer<_score,_traceback>::Type *score_ptr;
+	static TLS_PTR Double_buffer<_score> *hgap_ptr;
+
+};
+
+#endif /* SCALAR_DP_MATRIX_H_ */
diff --git a/src/dp/scalar_traceback.h b/src/dp/scalar_traceback.h
new file mode 100644
index 0000000..5fc940f
--- /dev/null
+++ b/src/dp/scalar_traceback.h
@@ -0,0 +1,194 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SCALAR_TRACEBACK_H_
+#define SCALAR_TRACEBACK_H_
+
+#include <exception>
+#include "../basic/score_matrix.h"
+
+template<typename _t>
+inline bool almost_equal(_t x, _t y)
+{
+	return x == y;
+}
+
+template<>
+inline bool almost_equal<float>(float x, float y)
+{
+	return abs(x - y) < 0.001f;
+}
+
+template<typename _score>
+struct Scalar_traceback_matrix
+{
+	Scalar_traceback_matrix(const Growing_buffer<_score> &data, int band):
+		data_ (data),
+		band_ (band)
+	{ }
+	_score operator()(int col, int row) const
+	{ return data_.column(col+1)[row - (data_.center(col+1)-band_)]; }
+	bool in_band(int col, int row) const
+	{ return row >= data_.center(col+1)-band_ && row <= data_.center(col+1)+band_ && row >= 0 && col >= 0; }
+	void print(int col, int row) const
+	{
+		for(unsigned j=0;j<=row;++j) {
+			for(unsigned i=0;i<=col;++i)
+				printf("%4i", in_band(i, j) ? this->operator()(i, j) : 0);
+			printf("\n");
+		}
+	}
+private:
+	const Growing_buffer<_score> &data_;
+	const int band_;
+};
+
+template<typename _score>
+bool have_vgap(const Scalar_traceback_matrix<_score> &dp,
+		int i,
+		int j,
+		_score gap_open,
+		_score gap_extend,
+		int &l)
+{
+	_score score = dp(i, j);
+	l = 1;
+	--j;
+	while(dp.in_band(i, j)) {
+		if (almost_equal(score, dp(i, j) - gap_open - (l - 1)*gap_extend))
+			return true;
+		--j;
+		++l;
+	}
+	return false;
+}
+
+template<typename _score>
+bool have_hgap(const Scalar_traceback_matrix<_score> &dp,
+	int i,
+	int j,
+	_score gap_open,
+	_score gap_extend,
+	int &l)
+{
+	_score score = dp(i, j);
+	l = 1;
+	--i;
+	while(dp.in_band(i, j)) {
+		if (almost_equal(score, dp(i, j) - gap_open - (l - 1)*gap_extend))
+			return true;
+		--i;
+		++l;
+	}
+	return false;
+}
+
+template<typename _dir, typename _score, typename _score_correction>
+local_match traceback(const Letter *query,
+	const Letter *subject,
+	const Growing_buffer<_score> &scores,
+	int band,
+	_score gap_open,
+	_score gap_extend,
+	int i,
+	int j,
+	int query_anchor,
+	_score score,
+	const _score_correction &score_correction)
+{
+	if(i == -1)
+		return local_match (0);
+	Scalar_traceback_matrix<_score> dp (scores, band);
+	//dp.print(i, j);
+
+	local_match l;
+	l.query_range.begin_ = 0;
+	l.query_range.end_ = j + 1;
+	l.subject_range.begin_ = 0;
+	l.subject_range.end_ = i + 1;
+	l.score = (unsigned)score;
+
+	int gap_len;
+
+	while(i>0 || j>0) {
+		const Letter lq = get_dir(query, j, _dir()), ls = get_dir(subject, i, _dir());
+		_score match_score = (_score)score_matrix(lq, ls);
+		score_correction(match_score, j, query_anchor, _dir::mult);
+		//printf("i=%i j=%i score=%i subject=%c query=%c\n",i,j,dp(i, j),Value_traits<_val>::ALPHABET[ls],Value_traits<_val>::ALPHABET[lq]);
+
+		if (almost_equal(dp(i, j), match_score + dp(i - 1, j - 1))) { // || dp(i, j) == score_matrix(ls, lq) + dp(i - 1, j - 1)) {		// i==0, j==0 ?
+			if (lq == ls) {
+				l.transcript.push_back(op_match);
+				++l.identities;
+				++l.positives;
+			}
+			else {
+				l.transcript.push_back(op_substitution, ls);
+				++l.mismatches;
+				if (match_score > 0)
+					++l.positives;
+			}
+			--i;
+			--j;
+			++l.length;			
+		} else if (have_hgap(dp, i, j, gap_open, gap_extend, gap_len)) {
+			++l.gap_openings;
+			l.length += gap_len;
+			l.gaps += gap_len;
+			for (; gap_len > 0; gap_len--)
+				l.transcript.push_back(op_deletion, get_dir(subject, i--, _dir()));
+		} else if (have_vgap(dp, i, j, gap_open, gap_extend, gap_len)) {
+			++l.gap_openings;
+			l.length += gap_len;
+			l.gaps += gap_len;
+			j -= gap_len;
+			l.transcript.push_back(op_insertion, (unsigned)gap_len);
+		} else {
+			throw std::runtime_error("Traceback error.");
+		}
+	}
+
+	const Letter lq = get_dir(query, 0, _dir()), ls = get_dir(subject, 0, _dir());
+	if (lq == ls) {
+		l.transcript.push_back(op_match);
+		++l.identities;
+		++l.positives;
+	}
+	else {
+		l.transcript.push_back(op_substitution, ls);
+		++l.mismatches;
+		if (score_matrix(lq, ls) > 0)
+			++l.positives;
+	}
+	++l.length;
+	return l;
+}
+
+template<typename _dir, typename _score>
+local_match traceback(const Letter *query,
+		const Letter *subject,
+		const Double_buffer<_score> &scores,
+		int band,
+		_score gap_open,
+		_score gap_extend,
+		int i,
+		int j,
+		_score score)
+{ return local_match (score); }
+
+#endif /* SCALAR_TRACEBACK_H_ */
diff --git a/src/dp/score_profile.h b/src/dp/score_profile.h
new file mode 100644
index 0000000..1ea8794
--- /dev/null
+++ b/src/dp/score_profile.h
@@ -0,0 +1,160 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef SCORE_PROFILE_H_
+#define SCORE_PROFILE_H_
+
+#include <vector>
+#include "../basic/sequence.h"
+#include "score_vector.h"
+
+using std::vector;
+
+#ifdef __SSE2__
+
+struct sequence_stream
+{
+	sequence_stream():
+		next (buffer_len),
+		mask (0)
+	{ }
+	inline void reset()
+	{
+		next = buffer_len;
+		mask = 0;
+	}
+	template<typename _score>
+	inline const __m128i& get(const typename vector<sequence>::const_iterator &begin,
+					   const typename vector<sequence>::const_iterator &end,
+					   unsigned pos,
+					   const _score&)
+	{
+		if(next == buffer_len)
+			fill<_score>(begin, end, pos);
+		return data_[next++];
+	}
+	template<typename _score>
+	inline void fill(const typename vector<sequence>::const_iterator &begin,
+		  	  const typename vector<sequence>::const_iterator &end,
+		 	  unsigned pos)
+	{
+		memset(data_, value_traits.mask_char, buffer_len*16);
+		unsigned n = 0;
+		typename vector<sequence>::const_iterator it (begin);
+		assert(pos < it->length());
+		const unsigned read_len (std::min(unsigned(buffer_len), static_cast<unsigned>(it->length())-pos));
+		while(it < end) {
+			const uint8_t *src (reinterpret_cast<const uint8_t*>(it->data()) + pos);
+			_score *dest (reinterpret_cast<_score*>(data_) + n);
+			int clip (int(pos) - it->clipping_offset_);
+			if((mask & (1 << n)) == 0) {
+				if(copy_char(src, dest, mask, n, clip))
+				if(read_len > 1 && copy_char(src, dest, mask, n, clip))
+				if(read_len > 2 && copy_char(src, dest, mask, n, clip))
+				if(read_len > 3) copy_char(src, dest, mask, n, clip);
+			}
+			++it;
+			++n;
+		}
+		next = 0;
+	}
+	template<typename _score>
+	static inline bool copy_char(const uint8_t*& src, _score*& dest, unsigned &mask, unsigned n, int &clip)
+	{
+		if(clip++ < 0) {
+			dest += 16/sizeof(_score);
+			++src;
+			return true;
+		}
+		if(*src == 0xff) {
+			mask |= 1 << n;
+			return false;
+		}
+		*dest = *(src++) & 0x7f;
+		dest += 16/sizeof(_score);
+		return true;
+	}
+	static const unsigned buffer_len = 4;
+	__m128i data_[buffer_len];
+	unsigned next;
+	unsigned mask;
+};
+
+template<typename _score>
+struct score_profile
+{
+
+	inline void set(const __m128i &seq)
+	{
+		assert(sizeof(data_)/sizeof(score_vector<_score>) >= value_traits.alphabet_size);
+		/*unsigned j = 0;
+		do {
+			data_[j] = score_vector<_score> (j, seq);
+			++j;
+			data_[j] = score_vector<_score> (j, seq);
+			++j;
+			data_[j] = score_vector<_score> (j, seq);
+			++j;
+			data_[j] = score_vector<_score> (j, seq);
+			++j;
+		} while(j<24);
+		data_[j] = score_vector<_score> (j, seq);
+		assert(j+1 == Value_traits<_val>::ALPHABET_SIZE);*/
+		for (unsigned j = 0; j < value_traits.alphabet_size; ++j)
+			data_[j] = score_vector<_score> (j, seq);
+	}
+
+	inline const score_vector<_score>& get(Letter i) const
+	{
+		return data_[(int)i];
+	}
+
+	score_vector<_score> data_[25];
+
+};
+
+#endif
+
+struct Long_score_profile
+{
+	Long_score_profile(sequence seq)
+	{
+		for (unsigned l = 0; l < 25; ++l) {
+			const uint8_t *scores = &score_matrix.matrix8u()[l << 5];
+			data[l].reserve(seq.length() + 2*padding);
+			data[l].insert(data[l].end(), padding, 0);
+			for (unsigned i = 0; i < seq.length(); ++i)
+				data[l].push_back(scores[(int)seq[i]]);
+			data[l].insert(data[l].end(), padding, 0);
+		}
+	}
+	size_t length() const
+	{
+		return data[0].size() - 2 * padding;
+	}
+	const uint8_t* get(Letter l, int i) const
+	{
+		return &data[(int)l][i + padding];
+	}
+	vector<uint8_t> data[25];
+	enum { padding = 256 };
+};
+
+#endif /* SCORE_PROFILE_H_ */
diff --git a/src/dp/score_vector.h b/src/dp/score_vector.h
new file mode 100644
index 0000000..f8c8d0c
--- /dev/null
+++ b/src/dp/score_vector.h
@@ -0,0 +1,213 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SCORE_VECTOR_H_
+#define SCORE_VECTOR_H_
+
+#include "../util/simd.h"
+
+template<typename _score>
+struct score_traits
+{
+	static const unsigned channels = 1;
+	enum { zero = 0, byte_size = 4 };
+	typedef bool Mask;
+};
+
+template<>
+struct score_traits<uint8_t>
+{
+	//static const unsigned channels = 16;
+	enum { channels = 16, zero = 0x00, byte_size = 1 };
+	typedef uint16_t Mask;
+};
+
+template<typename _score>
+struct score_vector
+{ };
+
+#ifdef __SSE2__
+
+template<>
+struct score_vector<uint8_t>
+{
+
+	score_vector()
+	{
+		//data_ = _mm_set1_epi8(score_traits<uint8_t>::zero);
+		data_ = _mm_setzero_si128();
+	}
+
+	explicit score_vector(char x):
+		data_ (_mm_set(x))
+	{ }
+
+	explicit score_vector(__m128i data):
+		data_ (data)
+	{ }
+
+	explicit score_vector(unsigned a, const __m128i &seq)
+	{
+		if(config.have_ssse3) {
+#ifdef __SSSE3__
+			set_ssse3(a, seq);
+#else
+			set_generic(a, seq);
+#endif
+		} else
+			set_generic(a, seq);
+	}
+
+	void set_ssse3(unsigned a, const __m128i &seq)
+	{
+#ifdef __SSSE3__
+		const __m128i *row = reinterpret_cast<const __m128i*>(&score_matrix.matrix8u()[a << 5]);
+
+		__m128i high_mask = _mm_slli_epi16(_mm_and_si128(seq, _mm_set1_epi8('\x10')), 3);
+		__m128i seq_low = _mm_or_si128(seq, high_mask);
+		__m128i seq_high = _mm_or_si128(seq, _mm_xor_si128(high_mask, _mm_set1_epi8('\x80')));
+
+		__m128i r1 = _mm_load_si128(row);
+		__m128i r2 = _mm_load_si128(row+1);
+		__m128i s1 = _mm_shuffle_epi8(r1, seq_low);
+		__m128i s2 = _mm_shuffle_epi8(r2, seq_high);
+		data_ = _mm_or_si128(s1, s2);
+#endif
+	}
+
+	void set_generic(unsigned a, const __m128i &seq)
+	{
+		const uint8_t* row (&score_matrix.matrix8u()[a<<5]);
+		const uint8_t* seq_ptr (reinterpret_cast<const uint8_t*>(&seq));
+		uint8_t* dest (reinterpret_cast<uint8_t*>(&data_));
+		for(unsigned i=0;i<16;i++)
+			*(dest++) = row[*(seq_ptr++)];
+	}
+
+	score_vector(const uint8_t* s):
+		data_ (_mm_loadu_si128(reinterpret_cast<const __m128i*>(s)))
+	{ }
+
+	score_vector operator+(const score_vector &rhs) const
+	{
+		return score_vector (_mm_adds_epu8(data_, rhs.data_));
+	}
+
+	score_vector operator-(const score_vector &rhs) const
+	{
+		return score_vector (_mm_subs_epu8(data_, rhs.data_));
+	}
+
+	score_vector& operator-=(const score_vector &rhs)
+	{
+		data_ = _mm_subs_epu8(data_, rhs.data_);
+		return *this;
+	}
+
+	score_vector& operator++()
+	{
+		data_ = _mm_adds_epu8(data_, _mm_set(1));
+		return *this;
+	}
+
+	__m128i operator==(const score_vector &rhs) const
+	{
+		return _mm_cmpeq_epi8(data_, rhs.data_);
+	}
+
+	void unbias(const score_vector &bias)
+	{ this->operator -=(bias); }
+
+	int operator [](unsigned i) const
+	{
+		return *(((uint8_t*)&data_)+i);
+	}
+
+	void set(unsigned i, uint8_t v)
+	{
+		*(((uint8_t*)&data_)+i) = v;
+	}
+
+	score_vector& max(const score_vector &rhs)
+	{
+		data_ = _mm_max_epu8(data_, rhs.data_);
+		return *this;
+	}
+
+	score_vector& min(const score_vector &rhs)
+	{
+		data_ = _mm_min_epu8(data_, rhs.data_);
+		return *this;
+	}
+
+	friend score_vector max(const score_vector& lhs, const score_vector &rhs)
+	{
+		return score_vector (_mm_max_epu8(lhs.data_, rhs.data_));
+	}
+
+	friend score_vector min(const score_vector& lhs, const score_vector &rhs)
+	{
+		return score_vector (_mm_min_epu8(lhs.data_, rhs.data_));
+	}
+
+	uint16_t cmpeq(const score_vector &rhs) const
+	{
+		return _mm_movemask_epi8(_mm_cmpeq_epi8(data_, rhs.data_));
+	}
+
+	__m128i cmpeq2(const score_vector &rhs) const
+	{
+		return _mm_cmpeq_epi8(data_, rhs.data_);
+	}
+
+	uint16_t cmpgt(const score_vector &rhs) const
+	{
+		return _mm_movemask_epi8(_mm_cmpgt_epi8(data_, rhs.data_));
+	}
+
+	void store(uint8_t *ptr) const
+	{
+		_mm_storeu_si128((__m128i*)ptr, data_);
+	}
+
+	bool operator>(score_vector<uint8_t> cmp) const
+	{
+		const score_vector<uint8_t> s = *this - cmp;
+#ifdef __SSE4_1__
+		return _mm_testz_si128(s.data_, s.data_) == 0;
+#else
+		return _mm_movemask_epi8(_mm_cmpeq_epi8(s.data_, _mm_setzero_si128())) == 0xFFFF;
+#endif
+	}
+
+	friend std::ostream& operator<<(std::ostream &s, score_vector v)
+	{
+		uint8_t x[16];
+		v.store(x);
+		for (unsigned i = 0; i < 16; ++i)
+			printf("%3i ", (int)x[i]);
+		return s;
+	}
+
+	__m128i data_;
+
+};
+
+#endif
+
+#endif /* SCORE_VECTOR_H_ */
diff --git a/src/dp/smith_waterman.cpp b/src/dp/smith_waterman.cpp
new file mode 100644
index 0000000..af19b99
--- /dev/null
+++ b/src/dp/smith_waterman.cpp
@@ -0,0 +1,157 @@
+/****
+Copyright (c) 2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <vector>
+#include "dp.h"
+#include "../util/double_buffer.h"
+#include "growing_buffer.h"
+#include "../util/util.h"
+
+using std::vector;
+using std::pair;
+
+template<typename _score>
+struct Dp_matrix
+{
+
+	struct Column_iterator
+	{
+
+		inline Column_iterator(const pair<_score*, _score*> &score, const pair<_score*, _score*> &hgap, int query_len):
+			score_(score),
+			hgap_(hgap),
+			end_(score_.second + query_len),
+			i_(0)
+		{
+			*score_.first = 0;
+			++score_.second;
+		}
+
+		inline int row() const
+		{
+			return i_;
+		}
+
+		inline bool valid() const
+		{
+			return score_.second < end_;
+		}
+
+		inline _score& score()
+		{
+			return *score_.second;
+		}
+
+		inline _score diag() const
+		{
+			return *score_.first;
+		}
+
+		inline _score hgap_in() const
+		{
+			return *hgap_.first;
+		}
+
+		inline _score& hgap_out()
+		{
+			return *hgap_.second;
+		}
+
+		inline void operator++()
+		{
+			++i_;
+			++score_.first;
+			++score_.second;
+			++hgap_.first;
+			++hgap_.second;
+		}
+
+	private:
+		pair<_score*, _score*> score_, hgap_;
+		const _score* const end_;
+		int i_;
+
+	};
+
+	inline Column_iterator column(int j)
+	{
+		return Column_iterator(score_.get(), hgap_.get(int()), query_len_);
+	}
+
+	inline Dp_matrix(int query_len, int subject_len):
+		query_len_(query_len),
+		score_(TLS::get(score_ptr)),
+		hgap_(TLS::get(hgap_ptr))
+	{
+		score_.init(query_len+1, subject_len+1, 0);
+		hgap_.init(query_len, 0, 0, 0);
+	}
+
+	const Fixed_score_buffer<_score>& score_buffer() const
+	{
+		return score_;
+	}
+	
+private:
+
+	const int query_len_;
+	Fixed_score_buffer<_score> &score_;
+	Double_buffer<_score> &hgap_;
+	static TLS_PTR Fixed_score_buffer<_score> *score_ptr;
+	static TLS_PTR Double_buffer<_score> *hgap_ptr;
+
+};
+
+template<typename _score>
+void smith_waterman(const Letter *query, unsigned query_len, local_match &hssp, _score gap_open, _score gap_extend, vector<char> &transcript_buf, const _score& = int())
+{
+	using std::max;
+
+	_score max_score = 0, column_max = 0;
+	int j = 0, i_max = -1, j_best = -1, i_best = -1;
+	Dp_matrix<_score> mtx(query_len, hssp.total_subject_len_);
+	const Letter *subject = hssp.subject_;
+
+	while (*subject != '\xff') {
+		typename Dp_matrix<_score>::Column_iterator it = mtx.column(j);
+		_score vgap = 0;		
+		for (; it.valid(); ++it) {
+			const _score match_score = score_matrix(mask_critical(*subject), query[it.row()]);
+			const _score s = max(max(it.diag() + match_score, vgap), it.hgap_in());
+			s = max(s, 0);
+			if (s > column_max) {
+				column_max = s;
+				i_max = it.row();
+			}
+			const _score open = s - gap_open;
+			vgap = max(vgap - gap_extend, open);
+			it.hgap_out() = max(it.hgap_in() - gap_extend, open);
+			it.score() = s;
+		}
+
+		if (column_max > max_score) {
+			max_score = column_max;
+			j_best = j;
+			i_best = i_max;
+		}
+		++subject;
+		++j;
+	}
+
+	return traceback<_dir, _score>(query, subject, mtx.score_buffer(), band, gap_open, gap_extend, j_best, i_best, max_score, transcript_buf);
+}
diff --git a/src/dp/smith_waterman.h b/src/dp/smith_waterman.h
new file mode 100644
index 0000000..157c7b1
--- /dev/null
+++ b/src/dp/smith_waterman.h
@@ -0,0 +1,126 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef SSE_SW_H_
+#define SSE_SW_H_
+
+#include <algorithm>
+#include <stddef.h>
+#include "score_profile.h"
+#include "dp_matrix.h"
+
+#ifdef __SSE2__
+
+template<typename _score>
+inline score_vector<_score> cell_update(const score_vector<_score> &diagonal_cell,
+						 const score_vector<_score> &scores,
+						 const score_vector<_score> &gap_extension,
+						 const score_vector<_score> &gap_open,
+						 score_vector<_score> &horizontal_gap,
+						 score_vector<_score> &vertical_gap,
+						 score_vector<_score> &best,
+						 const score_vector<_score> &vbias)
+{
+	score_vector<_score> current_cell = diagonal_cell + scores;
+	current_cell.unbias(vbias);
+	current_cell.max(vertical_gap).max(horizontal_gap);
+	best.max(current_cell);
+	vertical_gap -= gap_extension;
+	horizontal_gap -=  gap_extension;
+	score_vector<_score> open = current_cell - gap_open;
+	vertical_gap.max(open);
+	horizontal_gap.max(open);
+	return current_cell;
+}
+
+template<typename _score, typename _callback>
+void smith_waterman(const sequence &query,
+			const vector<sequence> &subjects,
+			unsigned band,
+			unsigned padding,
+			int op,
+			int ep,
+			int filter_score,
+			_callback &f,
+			const _score&,
+			Statistics &stats)
+{
+	#ifdef SW_ENABLE_DEBUG
+	int v[1024][1024];
+	#endif
+
+	typedef score_vector<_score> sv;
+
+	unsigned qlen ((unsigned)query.length());
+	unsigned slen ((unsigned)subjects[0].length());
+	DP_matrix<_score> dp (slen, qlen, band, padding);
+
+	sv open_penalty (static_cast<char>(op));
+	sv extend_penalty (static_cast<char>(ep));
+	sv vbias (score_matrix.bias());
+	sequence_stream dseq;
+	score_profile<_score> profile;
+
+	typename vector<sequence>::const_iterator subject_it (subjects.begin());
+	while(subject_it < subjects.end()) {
+
+		const unsigned n_subject (std::min((unsigned)score_traits<_score>::channels, (unsigned)(subjects.end() - subject_it)));
+		typename vector<sequence>::const_iterator subject_end (subject_it + n_subject);
+		sv best;
+		dseq.reset();
+		dp.clear();
+
+		for(unsigned j=0;j<slen;++j) {
+			typename DP_matrix<_score>::Column_iterator it (dp.begin(j));
+			sv vgap, hgap, column_best;
+			profile.set(dseq.get(subject_it, subject_end, j, _score()));
+
+			while(!it.at_end()) {
+				hgap = it.hgap();
+				sv next = cell_update<_score>(it.diag(), profile.get(query[it.row_pos_]), extend_penalty, open_penalty, hgap, vgap, column_best, vbias);
+				it.set_hgap(hgap);
+				it.set_score(next);
+				#ifdef SW_ENABLE_DEBUG
+				v[j][it.row_pos_] = next[0];
+				#endif
+				++it;
+			}
+			best.max(column_best);
+		}
+
+		for(unsigned i=0;i<n_subject;++i)
+			if(best[i] >= filter_score)
+				f(i + unsigned(subject_it - subjects.begin()), *(subject_it + i), best[i]);
+		subject_it += std::min((ptrdiff_t)score_traits<_score>::channels, subjects.end()-subject_it);
+	}
+
+	#ifdef SW_ENABLE_DEBUG
+	for(unsigned j=0;j<qlen;++j) {
+		for(unsigned i=0;i<subjects[0].length();++i)
+			printf("%4i", v[i][j]);
+		printf("\n");
+	}
+	printf("\n");
+	#endif
+}
+
+#endif
+
+#endif /* SSE_SW_H_ */
diff --git a/src/dp/traceback.h b/src/dp/traceback.h
new file mode 100644
index 0000000..3ec6621
--- /dev/null
+++ b/src/dp/traceback.h
@@ -0,0 +1,89 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef TRACEBACK_H_
+#define TRACEBACK_H_
+
+#include "../basic/match.h"
+
+template<typename _matrix>
+bool have_vgap(const _matrix &dp,
+	int i,
+	int j,
+	int gap_open,
+	int gap_extend,
+	int &l)
+{
+	int score = dp(i, j);
+	l = 1;
+	--i;
+	while (i > 0) {
+		if (score == dp(i, j) - gap_open - l*gap_extend)
+			return true;
+		--i;
+		++l;
+	}
+	return false;
+}
+
+template<typename _matrix>
+bool have_hgap(const _matrix &dp,
+	int i,
+	int j,
+	int gap_open,
+	int gap_extend,
+	int &l)
+{
+	int score = dp(i, j);
+	l = 1;
+	--j;
+	while (j > 0) {
+		if (score == dp(i, j) - gap_open - l*gap_extend)
+			return true;
+		--j;
+		++l;
+	}
+	return false;
+}
+
+template<typename _matrix>
+int have_diag(const _matrix &dp,
+	int i,
+	int j,
+	const sequence &query,
+	const sequence &subject,
+	bool log)
+{
+	int l = 0;
+	while (i > 0 && j > 0) {
+		const int match_score = score_matrix(query[i - 1], subject[j - 1]);
+
+		if (dp(i, j) == match_score + dp(i - 1, j - 1)) {
+			if (log)
+				printf("i=%i j=%i score=%i subject=%c query=%c\n", i, j, dp(i, j), value_traits.alphabet[(int)subject[j - 1]], value_traits.alphabet[(int)query[i - 1]]);
+			++l;
+			--i;
+			--j;
+		}
+		else
+			break;
+	}
+	return l;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/dp/ungapped_align.cpp b/src/dp/ungapped_align.cpp
new file mode 100644
index 0000000..8c83c1f
--- /dev/null
+++ b/src/dp/ungapped_align.cpp
@@ -0,0 +1,130 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "dp.h"
+#include "../basic/score_matrix.h"
+
+int xdrop_ungapped(const Letter *query, const Letter *subject, unsigned seed_len, unsigned &delta, unsigned &len)
+{
+	int score(0), st(0);
+	unsigned n(0);
+	delta = 0;
+
+	const Letter *q(query - 1), *s(subject - 1);
+	const unsigned window_left = std::max(config.window, (unsigned)config.seed_anchor) - config.seed_anchor;
+	while (score - st < config.raw_ungapped_xdrop
+		&& delta < window_left
+		&& *q != '\xff'
+		&& *s != '\xff')
+	{
+		st += score_matrix(*q, *s);
+		score = std::max(score, st);
+		--q;
+		--s;
+		++delta;
+	}
+
+	q = query + seed_len;
+	s = subject + seed_len;
+	st = score;
+	assert(seed_len >= config.seed_anchor);
+	const unsigned window_right = std::max(config.window, seed_len - config.seed_anchor) - (seed_len - config.seed_anchor);
+	while (score - st < config.raw_ungapped_xdrop
+		&& n < window_right
+		&& *q != '\xff'
+		&& *s != '\xff')
+	{
+		st += score_matrix(*q, *s);
+		score = std::max(score, st);
+		++q;
+		++s;
+		++n;
+	}
+
+	for (unsigned i = 0; i<seed_len; ++i)
+		score += score_matrix(query[i], subject[i]);
+
+	len = delta + n + seed_len;
+	return score;
+}
+
+int xdrop_ungapped(const Letter *query, const Letter *subject, unsigned &delta, unsigned &len)
+{
+	int score(0), st(0), n=1;
+	delta = 0;
+	
+	const Letter *q(query - 1), *s(subject - 1);
+	while (score - st < config.raw_ungapped_xdrop
+		&& *q != '\xff'
+		&& *s != '\xff')
+	{
+		st += score_matrix(*q, *s);
+		if (st > score) {
+			score = st;
+			delta = n;
+		}
+		--q;
+		--s;
+		++n;
+	}
+
+	q = query;
+	s = subject;
+	st = score;
+	n = 1;
+	len = 0;
+	while (score - st < config.raw_ungapped_xdrop
+		&& *q != '\xff'
+		&& *s != '\xff')
+	{
+		st += score_matrix(*q, *s);
+		if (st > score) {
+			score = st;
+			len = n;
+		}
+		++q;
+		++s;
+		++n;
+	}
+	len += delta;
+	return score;
+}
+
+int xdrop_ungapped_right(const Letter *query, const Letter *subject, int &len)
+{
+	int score(0), st(0), n = 1;
+	len = 0;
+	
+	const Letter *q = query;
+	const Letter *s = subject;
+	
+	while (score - st < config.raw_ungapped_xdrop
+		&& *q != '\xff'
+		&& *s != '\xff')
+	{
+		st += score_matrix(*q, *s);
+		if (st > score) {
+			score = st;
+			len = n;
+		}
+		++q;
+		++s;
+		++n;
+	}
+	return score;
+}
\ No newline at end of file
diff --git a/src/extra/blast_record.h b/src/extra/blast_record.h
new file mode 100644
index 0000000..4cdf2a6
--- /dev/null
+++ b/src/extra/blast_record.h
@@ -0,0 +1,33 @@
+#ifndef BLAST_RECORD_H_
+#define BLAST_RECORD_H_
+
+#include <stdint.h>
+
+using std::string;
+
+struct blast_match {
+
+	string query;
+	string subject;
+	double expect, bitscore, id;
+	bool hit, stop;
+	unsigned len, rid, ungapped_len, n, raw_score;
+
+	bool empty() const
+	{
+		return query.length() == 0;
+	}
+
+	void set_empty()
+	{
+		query.resize(0);
+	}
+
+	bool operator<(const blast_match &rhs) const
+	{
+		return subject < rhs.subject;
+	}
+
+};
+
+#endif /* BLAST_RECORD_H_ */
diff --git a/src/extra/compare.h b/src/extra/compare.h
new file mode 100644
index 0000000..1cf016c
--- /dev/null
+++ b/src/extra/compare.h
@@ -0,0 +1,188 @@
+#ifndef COMPARE_H_
+#define COMPARE_H_
+
+#include "../basic/config.h"
+#include "match_file.h"
+#include "../util/compressed_stream.h"
+#include "../util/seq_file_format.h"
+
+struct Cmp_stats
+{
+	Cmp_stats():
+		queries(0), queries1(0), queries2(0), unique1(0), unique2(0), queries1_sc(0), unique1_sc(0),
+		matches1(0), matches1_hit(0), matches1_badscore(0), query_sens (0)
+	{}
+	size_t queries, queries1, queries2, unique1, unique2, queries1_sc, unique1_sc, matches1, matches1_hit, matches1_badscore;
+	double query_sens;
+};
+
+void trim(string &s, const vector<char> &in)
+{
+	s.clear();
+	for(size_t i=0;i<in.size();++i)
+		s += in[i];
+	s = s.substr(0, s.find(' '));
+}
+
+bool unique_match(const match_file::mcont::const_iterator &i, const match_file::mcont::const_iterator &begin)
+{
+	return i == begin || i->subject != (i-1)->subject;
+}
+
+bool consider_match(const blast_match &match)
+{
+	return match.n < config.max_alignments && match.bitscore >= config.min_bit_score && match.expect <= config.max_evalue;
+}
+
+void get_target_seq(vector<blast_match>::const_iterator& i,
+		vector<blast_match>::const_iterator& j,
+		const vector<blast_match>::const_iterator& end_i,
+		const vector<blast_match>::const_iterator& end_j,
+		Cmp_stats &stat)
+{
+	unsigned v2_matches = config.run_len != 0 ? config.run_len : 0xffffffffu;
+	vector<blast_match>::const_iterator i_begin = i, j_begin = j;
+	double sc_i=0,sc_j=0;
+	unsigned rs_i = 0, rs_j = 0;
+
+	while(i < end_i && i->subject == i_begin->subject) {
+		sc_i = std::max(sc_i, i->bitscore);
+		rs_i = std::max(rs_i, i->raw_score);
+		++i;
+	}
+
+	while(j< end_j && j->subject == j_begin->subject) {
+		sc_j = std::max(sc_j, j->bitscore);
+		rs_j = std::max(rs_j, j->raw_score);
+		++j;
+	}
+	if(consider_match(*i_begin)) {
+		++stat.matches1;
+		if(j_begin->n < v2_matches) ++stat.matches1_hit;
+		double q = sc_j / sc_i;
+		//if(q >= 0.95 && q <=1.05) ++matches_hit;
+		//if(q < 0.95) ++matches_badscore;
+		if (rs_i != rs_j) ++stat.matches1_badscore;
+	}
+
+}
+
+void query_sens(match_file::mcont &v1,
+		match_file::mcont &v2,
+		Cmp_stats &stat)
+{
+	std::stable_sort(v1.begin(), v1.end());
+	std::stable_sort(v2.begin(), v2.end());
+	vector<blast_match>::const_iterator i = v1.begin(), j = v2.begin();
+	size_t matches = stat.matches1, matches_hit = stat.matches1_hit;
+
+	while(i < v1.end() && j < v2.end())
+	{
+		int c = i->subject.compare(j->subject);
+		if(c < 0) {
+			if(consider_match(*i) && unique_match(i, v1.begin())) ++stat.matches1;
+			++i;
+		} else if(c > 0) {
+			++j;
+		} else {
+			get_target_seq(i, j, v1.end(), v2.end(), stat);
+		}
+	}
+	if (stat.matches1 - matches > 0)
+		stat.query_sens += double(stat.matches1_hit - matches_hit) / (stat.matches1 - matches);
+}
+
+void lone_query(match_file::mcont &v1,
+		Cmp_stats &stat)
+{
+	vector<blast_match>::const_iterator i = v1.begin();
+	while(i != v1.end()) {
+		if(consider_match(*i) && unique_match(i, v1.begin()))
+			++stat.matches1;
+		++i;
+	}
+}
+
+void print_out(Cmp_stats &stat)
+{
+	printf("queries=%zu queries(1)=%zu queries(2)=%zu\n", stat.queries, stat.queries1, stat.queries2);
+	printf("unique(1)=%zu unique(2)=%zu\n", stat.unique1, stat.unique2);
+	printf("queries(1)>sc=%zu unique(1)>sc=%zu hit(2)=%zu (%1.f%%)\n", stat.queries1_sc, stat.unique1_sc, stat.queries1_sc-stat.unique1_sc, (double)(stat.queries1_sc-stat.unique1_sc)*100/stat.queries1_sc);
+	printf("matches(1)>sc=%zu hit(2)=%zu (%.1lf%%) bad score=%zu\n", stat.matches1, stat.matches1_hit, double(stat.matches1_hit)*100/stat.matches1, stat.matches1_badscore);
+	printf("query_sens=%.1lf\n", stat.query_sens * 100 / stat.queries1_sc);
+	printf("\n");
+}
+
+void compare()
+{
+	typedef blast_tab_format_with_rawscore Format1;
+	typedef blast_tab_format Format2;
+
+	vector<char> id;
+	vector<Letter> seq;
+
+	Input_stream seqStream(config.query_file);
+	match_file file1 (config.match_file1.c_str());
+	match_file::mcont v1;
+	file1.get_read(v1, Format1());
+	match_file file2 (config.match_file2.c_str());
+	match_file::mcont v2;
+	file2.get_read(v2, Format2());
+	bool do_out = config.output_file.length() > 0;
+	FILE *out = 0;
+	if(do_out) out = fopen(config.output_file.c_str(), "wt");
+
+	Cmp_stats stat;
+	string q;
+	size_t read = 0;
+	FASTA_format format;
+	while(format.get_seq(id, seq, seqStream)) {
+		trim(q, id);
+		++stat.queries;
+		//printf("%lu ", queries);
+		if (stat.queries % 1000 == 0) {
+			printf("n = %zu\n", stat.queries);
+			print_out(stat);
+		}
+
+		bool have1 = false, have2 = false, have1_sc = false;
+		if(v1.size() > 0 && q == v1[0].query) {
+			++stat.queries1;
+			if(v1[0].bitscore >= config.min_bit_score && v1[0].expect <= config.max_evalue) {
+				have1_sc = true;
+				++stat.queries1_sc;
+			}
+			have1 = true;
+		}
+
+		if(v2.size() > 0 && q == v2[0].query) {
+			++stat.queries2;
+			have2 = true;
+		} else if(have1_sc) {
+			++stat.unique1_sc;
+		}
+
+		if(have1_sc && !have2)
+			lone_query(v1, stat);
+		else if(have1_sc && have2)
+			query_sens(v1, v2, stat);
+
+		if(have1 && !have2) {
+			++stat.unique1;
+			if(do_out) fprintf(out, "1 %s\n", q.c_str());
+		} else if(have2 && !have1) {
+			++stat.unique2;
+			if(do_out) fprintf(out, "2 %s\n", q.c_str());
+		}
+		if(have1) file1.get_read(v1, Format1());
+		if(have2) file2.get_read(v2, Format2());
+
+		++read;
+	}
+
+	print_out(stat);
+
+	if(do_out) fclose(out);
+}
+
+#endif /* COMPARE_H_ */
diff --git a/src/extra/match_file.h b/src/extra/match_file.h
new file mode 100644
index 0000000..c1ec693
--- /dev/null
+++ b/src/extra/match_file.h
@@ -0,0 +1,337 @@
+#ifndef MATCH_FILE_H_
+#define MATCH_FILE_H_
+
+#include <vector>
+#include "blast_record.h"
+#include "../util/util.h"
+#include "../basic/reduction.h"
+#include "../basic/shape_config.h"
+
+struct file_parse_exception : public std::runtime_error
+{
+	file_parse_exception(size_t l):
+		std::runtime_error (string("File parse error line ") + to_string((unsigned)l) + "\n")
+	{ }
+};
+
+struct blast_format { };
+struct blast_tab_format { };
+struct blast_tab_format_with_rawscore {};
+
+using std::vector;
+
+inline void alline(const char *buffer, char *dest)
+{
+	buffer += 7;
+	const char *begin = strstr(buffer, " ") + 1;
+	while(*begin == ' ')
+		++begin;
+	const char *end = strstr(begin, " ");
+	strncpy(dest, begin, end - begin);
+	dest[end-begin] = 0;
+}
+
+inline bool seq_letter(char x)
+{
+	return x >= 'A' && x <= 'Z';
+}
+
+/*int64_t match_scores[32];
+int64_t match_counts[32];*/
+
+inline unsigned char_match(char query, char subject, const Reduction &red)
+{
+	Letter ql = query;
+	Letter sl = subject;
+	if(red(ql) == red(sl)) {
+		//int sc = score_matrix::get().letter_score(ql, sl);
+		//match_scores[(int)ql] += sc;
+		//++match_counts[(int)ql];
+		//match_scores[(int)sl] += sc;
+		//++match_counts[(int)sl];
+		return 1;
+	} else
+		return 0;
+}
+
+inline void get_match(unsigned &mask, const char *queryl, const char *subjectl, bool &hit, unsigned &len, unsigned &rid, unsigned &current_len, unsigned &ungapped_len, Letter* q, Letter* s, bool &stop)
+{
+	unsigned l ((unsigned)strlen(queryl));
+	for(unsigned i=0;i<l;++i) {
+		mask <<= 1;
+		if(seq_letter(queryl[i]) && seq_letter(subjectl[i])) {
+			unsigned x = char_match(queryl[i], subjectl[i], Reduction::reduction);
+			rid += x;
+			++len;
+			++current_len;
+			ungapped_len = std::max(ungapped_len, current_len);
+			mask |= x;
+		} else if(queryl[i] == '-' || subjectl[i] == '-') {
+			mask = 0;
+			current_len = 0;
+		} else if(queryl[i] == '*') {
+			stop = true;
+		}
+		*(q++) = queryl[i];
+		*(s++) = subjectl[i];
+		for(unsigned j=0;j<shapes.count();++j) {
+			if(((mask & shapes[j].rev_mask_) == shapes[j].rev_mask_))
+				hit = true;
+		}
+	}
+}
+
+class match_file : public Input_stream
+{
+
+public:
+
+	typedef std::vector<blast_match> mcont;
+
+	match_file(const char* fileName) : Input_stream(fileName), currentQueryCount(0), queryCount(0), matchCount(0)
+	{
+		currentQuery[0] = 0;
+		currentSubject[0] = 0;
+		memset(subst_p, 0, sizeof(subst_p));
+		memset(subst_n, 0, sizeof(subst_n));
+	}
+
+	void set_subst(const char* q, const char *s)
+	{
+		while (*q) {
+			if (*q != '-' && *s != '-' && *q != *s) {
+				const Letter lq = value_traits.from_char(*q), ls = value_traits.from_char(*s);
+				if (lq < 20 && ls < 20 && lq != ls) {
+					++subst_p[(size_t)lq][(size_t)ls];
+					++subst_n[(size_t)lq];
+				}
+			}
+			++q;
+			++s;
+		}
+	}
+
+	void get_subst() const
+	{
+		for (unsigned i = 0; i < 20; ++i) {
+			cout << "{";
+			for (unsigned j = 0; j < 20; ++j)
+				cout << (double)subst_p[i][j] / subst_n[i] << ',';
+			cout << "}," << endl;
+		}
+	}
+
+	bool get(blast_match &record, const blast_format&)
+	{
+
+		enum State { begin = 0, end = 1, queryStart = 2, subjectStart = 3, matchStart = 4, queryLine = 5, subjectLine = 6, separator = 7, between = 8, haveid = 9 } state = begin;
+		unsigned expect_i, id1, id2;
+		char queryl[128], subjectl[128];
+		Letter queryseq[4096], subjectseq[4096];
+		Letter *q = queryseq, *s = subjectseq;
+		unsigned match_mask = 0, current_len = 0;
+		record.hit = false;
+		record.ungapped_len = 0;
+		record.rid = 0;
+		record.len = 0;
+		record.stop = false;
+
+		while(state != end && (this->getline(), !this->eof())) {
+
+			//printf("%lu %u %s\n", line_count, state, line.c_str());
+
+			if(!strncmp(line.c_str(), "Query= ", 7)) {
+				if(state == begin || state == queryStart) {
+					state = queryStart;
+					if(sscanf(line.c_str(), "Query= %s", currentQuery) != 1)
+						throw file_parse_exception(this->line_count);
+				} else
+					throw file_parse_exception(this->line_count);
+			} else if(line.c_str()[0] == '>') {
+				if(state == begin || state == queryStart) {
+					state = subjectStart;
+					if(sscanf(line.c_str(), "> %s", currentSubject) != 1)
+						throw file_parse_exception(this->line_count);
+				}
+				else if (state == separator) {
+					this->putback_line();
+					state = end;
+				}
+				else
+					throw file_parse_exception(this->line_count);
+			} else if(sscanf(line.c_str(), " Score = %lf bits (%u),  Expect = %lf", &record.bitscore, &record.raw_score, &record.expect) == 3
+					|| sscanf(line.c_str(), " Score = %lf bits (%u),  Expect(%i) = %lf", &record.bitscore, &record.raw_score, &expect_i, &record.expect) == 4) {
+				if(state == subjectStart || state == begin) {
+					record.query = currentQuery;
+					record.subject = currentSubject;
+					state = matchStart;
+				}
+				else if (state == separator) {
+					this->putback_line();
+					state = end;
+				}
+				else
+					throw file_parse_exception(this->line_count);
+			} else if(sscanf(line.c_str(), " Identities = %u/%u (%lf%%)", &id1, &id2, &record.id) == 3) {
+				if(state == matchStart) {
+					state = haveid;
+				} else
+					throw file_parse_exception(this->line_count);
+			} else if(!strncmp(line.c_str(), "Query", 5)) {
+				if(state == haveid || state == separator) {
+					state = queryLine;
+					alline(line.c_str(), queryl);
+				} else
+					throw file_parse_exception(this->line_count);
+			} else if(!strncmp(line.c_str(), "Sbjct", 5)) {
+				if(state == between) {
+					state = subjectLine;
+					alline(line.c_str(), subjectl);
+					set_subst(queryl, subjectl);
+					/*if(strlen(subjectl) != strlen(queryl))
+						throw file_parse_exception(lineNumber);*/
+					//get_match(match_mask, queryl, subjectl, record.hit, record.len, record.rid, current_len, record.ungapped_len, q, s, record.stop);
+				} else
+					throw file_parse_exception(this->line_count);
+			} else if(state == queryLine && line.c_str()[0] == ' ') {
+				state = between;
+			} else if((state == subjectLine || state == separator) && line.empty()) {
+				//printf("%i\n",(int)buffer[0]);
+				if(state == subjectLine)
+					state = separator;
+				else if(state == separator)
+					state = end;
+				else
+					throw file_parse_exception(this->line_count);
+			} else {
+				if(state != begin && state != queryStart && state != haveid && state != subjectStart)
+					throw file_parse_exception(this->line_count);
+			}
+
+		}
+
+		if(this->eof())
+			return false;
+		if(state != end)
+			throw file_parse_exception(this->line_count);
+		++currentQueryCount;
+		++matchCount;
+		return true;
+
+	}
+
+	bool get(blast_match &match, const blast_tab_format&)
+	{
+		char query[nameBufferSize], s2[nameBufferSize];
+		double f1;
+		unsigned long long i1,i2,i3,i4,i5,i6,i7;
+		this->getline();
+		if(!this->eof()) {
+			while (this->line[0] == '#')
+				this->getline();
+			if(sscanf(line.c_str(), "%s%s%lf%llu%llu%llu%llu%llu%llu%llu%lf%lf", query, s2, &f1, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &match.expect, &match.bitscore) == 12) {
+				//|| sscanf(line.c_str(), "%s%s%s%lf%llu%llu%llu%llu%llu%llu%llu%lf%lf", query, query2, s2, &f1, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &match.expect, &match.bitscore) == 13) {
+				/*++matchCount;
+				if(!strcmp(query, currentQuery)) {
+					++currentQueryCount;
+				} else {
+					++queryCount;
+					currentQueryCount = 1;
+					strcpy(currentQuery, query);
+				}*/
+				match.query = query;
+				match.subject = s2;
+				return true;
+			} else {
+				printf("%s\n", line.c_str());
+				throw file_parse_exception(this->line_count);
+			}
+		} else {
+			match.set_empty();
+			return false;
+		}
+	}
+
+	bool get(blast_match &match, const blast_tab_format_with_rawscore&)
+	{
+		char query[nameBufferSize], s2[nameBufferSize];
+		double f1;
+		unsigned long long i1, i2, i3, i4, i5, i6, i7;
+		this->getline();
+		if (!this->eof()) {
+			while (this->line[0] == '#')
+				this->getline();
+			if (sscanf(line.c_str(), "%s%s%lf%llu%llu%llu%llu%llu%llu%llu%lf%lf%u", query, s2, &f1, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &match.expect, &match.bitscore, &match.raw_score) == 13) {
+				//|| sscanf(line.c_str(), "%s%s%s%lf%llu%llu%llu%llu%llu%llu%llu%lf%lf", query, query2, s2, &f1, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &match.expect, &match.bitscore) == 13) {
+				/*++matchCount;
+				if(!strcmp(query, currentQuery)) {
+				++currentQueryCount;
+				} else {
+				++queryCount;
+				currentQueryCount = 1;
+				strcpy(currentQuery, query);
+				}*/
+				match.query = query;
+				match.subject = s2;
+				return true;
+			}
+			else {
+				printf("%s\n", line.c_str());
+				throw file_parse_exception(this->line_count);
+			}
+		}
+		else {
+			match.set_empty();
+			return false;
+		}
+	}
+
+	template<typename _format>
+	bool get_read(mcont &v, const _format& format)
+	{
+		unsigned n = 0;
+		v.clear();
+		blast_match match;
+		if(!save.empty()) {
+			save.n = n++;
+			v.push_back(save);
+			save.set_empty();
+		} else {
+			if(!get(match, format))
+				return false;
+			match.n = n++;
+			v.push_back(match);
+		}
+
+		while(get(match, format) && match.query == v[0].query) {
+			if(match.subject != v.back().subject)
+				n++;
+			match.n = n;
+			v.push_back(match);
+		}
+		if(!match.empty() && match.query != v[0].query)
+			save = match;
+		return !v.empty();
+	}
+
+	unsigned getTotalQueries() const
+	{
+		return queryCount;
+	}
+
+	unsigned getCurrentQueryCount() const
+	{
+		return currentQueryCount;
+	}
+
+protected:
+	static const size_t nameBufferSize = 4096;
+	unsigned currentQueryCount, queryCount, matchCount;
+	char currentQuery[nameBufferSize], currentSubject[nameBufferSize];
+	blast_match save;
+	size_t subst_p[20][20];
+	size_t subst_n[20];
+
+};
+
+#endif /* MATCH_FILE_H_ */
diff --git a/src/extra/model_sim.cpp b/src/extra/model_sim.cpp
new file mode 100644
index 0000000..06a1453
--- /dev/null
+++ b/src/extra/model_sim.cpp
@@ -0,0 +1,358 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <time.h>
+#include <fstream>
+#include "../basic/sequence.h"
+#include "../basic/shape_config.h"
+
+struct MSS_model
+{
+	bool hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		for (unsigned s = 0; s < shapes.count(); ++s) {
+			if (l < shapes[s].length_) continue;
+			for (unsigned i = 0; i <= l - shapes[s].length_; ++i) {
+				uint64_t a, b;
+				shapes[s].set_seed(a, &x[i]);
+				shapes[s].set_seed(b, &y[i]);
+				if (a == b)
+					return true;
+			}
+		}
+		return false;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length());
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		for (unsigned i = 0; i < l; ++i) {
+			if (hit(&x[i], y.data(), l - i))
+				return true;
+			if (i > 0 && hit(x.data(), &y[i], l - i))
+				return true;
+		}
+		return false;
+	}
+};
+
+struct MSS_twohit_model
+{
+	unsigned hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		unsigned n = 0;
+		for (unsigned s = 0; s < shapes.count(); ++s) {
+			if (l < shapes[s].length_) continue;
+			for (unsigned i = 0; i <= l - shapes[s].length_; ++i) {
+				uint64_t a, b;
+				shapes[s].set_seed(a, &x[i]);
+				shapes[s].set_seed(b, &y[i]);
+				if (a == b)
+					++n;
+			}
+		}
+		return n;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length()) >= 2;
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		unsigned n = 0;
+		for (unsigned i = 0; i < l; ++i) {
+			n += hit(&x[i], y.data(), l - i);
+			if (i > 0)
+				n += hit(x.data(), &y[i], l - i);
+		}
+		return n >= 2;
+	}
+};
+
+struct MSS_twohit_diagonal_model
+{
+	unsigned hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		unsigned n = 0;
+		for (unsigned s = 0; s < shapes.count(); ++s) {
+			if (l < shapes[s].length_) continue;
+			for (unsigned i = 0; i <= l - shapes[s].length_; ++i) {
+				uint64_t a, b;
+				shapes[s].set_seed(a, &x[i]);
+				shapes[s].set_seed(b, &y[i]);
+				if (a == b)
+					++n;
+			}
+		}
+		return n;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length()) >= 2;
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		for (unsigned i = 0; i < l; ++i) {
+			if (hit(&x[i], y.data(), l - i) >= 2)
+				return true;
+			if (i > 0 && hit(x.data(), &y[i], l - i) >= 2)
+				return true;
+		}
+		return false;
+	}
+};
+
+template<int window>
+struct MSS_twohit_window_model
+{
+	bool hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		int last = -2 * window;
+		for (int i = 0; i <= l; ++i) {
+			for (unsigned s = 0; s < shapes.count(); ++s) {
+				if (l - i < shapes[s].length_) continue;
+				uint64_t a, b;
+				shapes[s].set_seed(a, &x[i]);
+				shapes[s].set_seed(b, &y[i]);
+				if (a == b) {
+					if (i != last && i - last < window)
+						return true;
+					last = i;
+				}
+			}
+		}
+		return false;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length());
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		for (unsigned i = 0; i < l; ++i) {
+			if (hit(&x[i], y.data(), l - i))
+				return true;
+			if (i > 0 && hit(x.data(), &y[i], l - i))
+				return true;
+		}
+		return false;
+	}
+};
+
+template<int window, int k, int mismatch>
+struct Mismatch_twohit_window_model
+{
+	bool hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		int last = -2 * window;
+		if (l < k)
+			return false;
+		for (int i = 0; i <= l - k; ++i) {
+			unsigned n = 0;
+			for (int j = 0; j < k; ++j)
+				if (x[i + j] != y[i + j])
+					++n;
+			if (n <= mismatch) {
+				if (i != last && i - last < window)
+					return true;
+				last = i;
+			}
+		}
+		return false;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length());
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		for (unsigned i = 0; i < l; ++i) {
+			if (hit(&x[i], y.data(), l - i))
+				return true;
+			if (i > 0 && hit(x.data(), &y[i], l - i))
+				return true;
+		}
+		return false;
+	}
+};
+
+template<int window>
+struct MSS_twohit_window_neighborhood_model
+{
+	bool hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		int last = -2 * window;
+		for (int i = 0; i <= (int)l; ++i) {
+			for (unsigned s = 0; s < shapes.count(); ++s) {
+				if (l - i < shapes[s].length_) continue;
+				if(shapes[s].score(&x[i], &y[i]) >= config.neighborhood_score) {
+					if (i != last && i - last < window)
+						return true;
+					last = i;
+				}
+			}
+		}
+		return false;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length());
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		for (unsigned i = 0; i < l; ++i) {
+			if (hit(&x[i], y.data(), l - i))
+				return true;
+			if (i > 0 && hit(x.data(), &y[i], l - i))
+				return true;
+		}
+		return false;
+	}
+};
+
+struct MSS_neighborhood_model
+{
+	bool hit(const Letter *x, const Letter *y, size_t l) const
+	{
+		for (size_t i = 0; i <= l; ++i) {
+			for (unsigned s = 0; s < shapes.count(); ++s) {
+				if (l - i < shapes[s].length_) continue;
+				if (shapes[s].score(&x[i], &y[i]) >= config.neighborhood_score)
+					return true;
+			}
+		}
+		return false;
+	}
+	bool hit(const sequence &x, const sequence &y) const
+	{
+		return hit(x.data(), y.data(), x.length());
+	}
+	bool hit_shifted(const sequence &x, const sequence &y) const
+	{
+		const size_t l = x.length();
+		for (unsigned i = 0; i < l; ++i) {
+			if (hit(&x[i], y.data(), l - i))
+				return true;
+			if (i > 0 && hit(x.data(), &y[i], l - i))
+				return true;
+		}
+		return false;
+	}
+};
+
+void get_random_seq(vector<Letter> &seq)
+{
+	for (vector<Letter>::iterator i = seq.begin(); i != seq.end(); ++i)
+		*i = get_distribution<20>(background_freq);
+}
+
+void get_related_seq(const sequence &seq, vector<Letter> &out, double id)
+{
+	static const double p[20][20] = {
+	{0, 0.051599, 0.0319706, 0.0472072, 0.0259005, 0.042533, 0.0794012, 0.104447, 0.0190464, 0.0529913, 0.0806505, 0.0561607, 0.023709, 0.0243562, 0.0447981, 0.119439, 0.0710634, 0.00618423, 0.019181, 0.099362, },
+	{ 0.0836991,0,0.0557221,0.0526752,0.00570959,0.0834397,0.0992451,0.0474531,0.0360983,0.0290852,0.0591073,0.18726,0.0187483,0.0177066,0.03043,0.062954,0.0596622,0.00896391,0.0252332,0.036807, },
+	{ 0.0688047,0.0737048,0,0.134642,0.0104452,0.0556231,0.0811654,0.0970697,0.0503946,0.0214787,0.0370703,0.069479,0.0150052,0.0171298,0.0255345,0.114536,0.0729503,0.00573275,0.021037,0.0281966, },
+	{ 0.0734774,0.0538258,0.10774,0,0.00541203,0.0638292,0.220103,0.0852837,0.0313663,0.0145824,0.0242017,0.0687326,0.00866069,0.0125848,0.0451219,0.0885509,0.0562425,0.0041692,0.0139378,0.0221784, },
+	{ 0.186323,0.0324277,0.0277663,0.0177638,0,0.0153757,0.0222231,0.052226,0.0127764,0.0743205,0.11608,0.021819,0.0292451,0.0436977,0.0221956,0.0899075,0.0771679,0.00626418,0.0267835,0.125637, },
+	{ 0.0815328,0.112847,0.0568952,0.074416,0.00530242,0,0.150972,0.0456165,0.0364876,0.0241864,0.0523059,0.119369,0.0224538,0.0139128,0.0272128,0.0645326,0.0511373,0.00542559,0.0193477,0.0360457, },
+	{ 0.0918357,0.0766689,0.0556527,0.174685,0.00514321,0.105233,0,0.0497034,0.0284655,0.0215927,0.0364467,0.102734,0.0130324,0.0127301,0.0374955,0.0725947,0.0566717,0.00542622,0.0173958,0.0364932, },
+	{ 0.20364,0.0508512,0.0818626,0.0839228,0.0149571,0.0404233,0.0622734,0,0.0241239,0.0237986,0.038645,0.0567032,0.015483,0.0207614,0.0397716,0.122147,0.0536346,0.00808141,0.0181211,0.0407985, },
+	{ 0.0699983,0.0907505,0.0813351,0.0777822,0.0081228,0.0669371,0.0813018,0.0560113,0,0.0264461,0.0551068,0.0740711,0.0180528,0.03949,0.025928,0.0666684,0.0459882,0.0124538,0.0684967,0.0350589, },
+	{ 0.0758071,0.0218901,0.0124197,0.0102327,0.0139658,0.0158577,0.0178954,0.0154911,0.00998824,0,0.261344,0.0185933,0.0553554,0.0532969,0.0164271,0.0248502,0.0451354,0.00741016,0.0241487,0.299892, },
+	{ 0.0827941,0.0356979,0.0164472,0.0130886,0.0158172,0.0256513,0.0247873,0.0195319,0.0124665,0.218909,0,0.0302946,0.0895811,0.0919587,0.0199965,0.030285,0.046212,0.0136618,0.0364274,0.176391, },
+	{ 0.0781029,0.208329,0.0570106,0.0577245,0.00610149,0.0855974,0.10978,0.0459911,0.0280067,0.0234476,0.0526726,0,0.0186556,0.014372,0.0345505,0.0674287,0.0530917,0.00620819,0.0164983,0.0364304, },
+	{ 0.0820435,0.0371522,0.0193431,0.0143829,0.0129935,0.039314,0.0273425,0.02189,0.0123121,0.135883,0.247222,0.0313609,0,0.0639739,0.0174525,0.0360643,0.0483175,0.0103003,0.0273692,0.115283, },
+	{ 0.0624752,0.023874,0.0168958,0.0146007,0.0120188,0.0162837,0.0221759,0.0282569,0.025181,0.107736,0.228084,0.018739,0.0498004,0,0.0143663,0.0337512,0.0352976,0.040237,0.152406,0.09782, },
+	{ 0.137934,0.0566305,0.0383101,0.0798596,0.00858529,0.0448655,0.091169,0.0649277,0.0214561,0.0353504,0.0589727,0.0747337,0.0158675,0.0192857,0,0.0958676,0.0712531,0.00607841,0.0187647,0.0600885, },
+	{ 0.161678,0.0503686,0.0675213,0.0725064,0.0170918,0.0439576,0.0688274,0.0920208,0.023245,0.0261139,0.039281,0.0556799,0.0163333,0.0207061,0.0417712,0,0.140562,0.00529629,0.0168799,0.0401595, },
+	{ 0.116544,0.0543551,0.0502298,0.051343,0.0162852,0.0415458,0.0696321,0.0441794,0.0200499,0.0539524,0.072698,0.0528105,0.0237411,0.0226826,0.0364311,0.149828,0,0.00676344,0.0208007,0.0961279, },
+	{ 0.0616437,0.051267,0.0204352,0.0156793,0.0128913,0.0281531,0.0336645,0.0438026,0.0318158,0.0565597,0.135468,0.0329638,0.0367357,0.153548,0.018681,0.0425701,0.0372178,0,0.126995,0.0599093, },
+	{ 0.0629104,0.0481246,0.0279043,0.0248727,0.0132862,0.0319342,0.0336743,0.0255073,0.0636279,0.0693312,0.123129,0.03326,0.0336581,0.1923,0.0183125,0.0405417,0.039996,0.0424192,0,0.0752103, },
+	{ 0.122866,0.0265131,0.0140538,0.0140485,0.020662,0.0200589,0.0307184,0.022685,0.010223,0.253759,0.190633,0.0272914,0.0436694,0.0420276,0.0241076,0.034372,0.0705984,0.00696795,0.0247446,0, } };
+
+	for (unsigned i = 0; i < seq.length(); ++i)
+		if ((double)rand() / RAND_MAX < id)
+			out[i] = seq[i];
+		else
+			out[i] = get_distribution<20>(p[(size_t)seq[i]]);
+}
+
+template<typename _model>
+void model_sim()
+{
+	static const unsigned seq_len = 300;
+	static const double id = 0.25;
+	srand((unsigned)time(0));
+
+	vector<Letter> query (seq_len), subject (seq_len);
+	const sequence q(query), s(subject);
+	
+	size_t n = 0, hit_bg = 0, hit_fg = 0;
+
+	while (true) {
+		if (n % 100 == 0)
+			get_random_seq(query);
+
+		get_random_seq(subject);
+		/*cout << q << endl;
+		cout << s << endl << endl;*/
+		if (_model().hit_shifted(q, s))
+			++hit_bg;
+
+		get_related_seq(q, subject, id);
+		if (_model().hit(q, s))
+			++hit_fg;
+
+		if (n % 100 == 0) {
+			cout << "n=" << n << " background hit%=" << percentage(hit_bg, n) <<  " foreground hit%=" << percentage(hit_fg, n) << endl;
+		}
+		++n;
+	}
+}
+
+void model_sim()
+{
+	Reduction::reduction = Reduction("A KR EDNQ C G H ILVM FYW P ST"); // murphy.10
+	model_sim<MSS_model>();
+}
+
+void model_seqs()
+{
+	static const unsigned seq_len = 300;
+	static const double id = 0.25;
+	vector<Letter> seq1(seq_len), seq2(seq_len);
+	sequence s1(seq1), s2(seq2);
+	const size_t count = atoi(config.seq_no[0].c_str());
+	std::ofstream out(config.output_file.c_str());
+	for (unsigned i = 0; i < count; ++i) {
+		get_random_seq(seq1);
+		out << '>' << i << endl;
+		out << s1 << endl;
+		get_related_seq(s1, seq2, id);
+		cout << '>' << i << endl;
+		cout << s2 << endl;
+	}
+}
\ No newline at end of file
diff --git a/src/extra/roc.cpp b/src/extra/roc.cpp
new file mode 100644
index 0000000..00dfd07
--- /dev/null
+++ b/src/extra/roc.cpp
@@ -0,0 +1,142 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <map>
+#include <set>
+#include "../util/binary_file.h"
+#include "../basic/config.h"
+#include "match_file.h"
+#include "../util/seq_file_format.h"
+
+using std::map;
+using std::set;
+
+const int roc_from = -10, roc_to = 1;
+const size_t roc_steps = (roc_to - roc_from + 1) * 9;
+
+struct Superfamily
+{
+	bool operator==(const Superfamily &x) const
+	{
+		return cl == x.cl && fold == x.fold && superfamily == x.superfamily;
+	}
+	char cl;
+	unsigned fold, superfamily;
+};
+
+map<char, map<unsigned, map<unsigned, unsigned> > > superfamilies;
+map<string, Superfamily> subjects;
+set<pair<string, string> > target;
+size_t n_targets = 0, tp = 0, fp = 0;
+double max_ev = 0;
+
+void query_roc(Superfamily superfamily, const match_file::mcont &matches, Numeric_vector<double> &coverage, Numeric_vector<double> &errors)
+{
+	coverage = Numeric_vector<double>(roc_steps);
+	errors = Numeric_vector<double>(roc_steps);
+	match_file::mcont::const_iterator i = matches.begin();
+	size_t idx = 0;
+	for (int exp = roc_from; exp <= roc_to; ++exp)
+		for (int factor = 2; factor <= 10; ++factor) {
+			const double ev = pow(10.0, exp)*factor;
+			if (idx != 0) {
+				coverage[idx] = coverage[idx - 1];
+				errors[idx] = errors[idx - 1];
+			}
+			while (i < matches.end()) {
+				if (i != matches.begin() && i->subject == (i - 1)->subject) {
+					++i;
+					continue;
+				}
+				if (i->expect > ev)
+					break;
+				if (subjects.find(i->subject) != subjects.end() && subjects[i->subject] == superfamily) {
+					++coverage[idx];
+					if (target.find(pair<string, string>(i->query, i->subject)) != target.end()) {
+						max_ev = std::max(max_ev, i->expect);
+						++n_targets;
+					}
+				}
+				else {
+					++errors[idx];
+					++fp;
+				}
+				++i;
+			}
+			++idx;
+		}
+	coverage /= superfamilies[superfamily.cl][superfamily.fold][superfamily.superfamily];
+}
+
+void roc()
+{
+	vector<char> id;
+	vector<Letter> seq;
+
+	Input_stream seqStream(config.query_file);
+	match_file file1(config.match_file1.c_str());
+	match_file::mcont v1;
+
+	Numeric_vector<double> coverage(roc_steps), errors(roc_steps), c2(roc_steps), e2(roc_steps);
+	size_t queries = 0;
+	FASTA_format format;
+	while (format.get_seq(id, seq, seqStream)) {
+		string id2(id.data(), id.size());
+		++queries;
+
+		char name[32];
+		unsigned family;
+		Superfamily superfamily;
+		if (sscanf(id2.c_str(), "%s %c.%u.%u.%u", name, &superfamily.cl, &superfamily.fold, &superfamily.superfamily, &family) != 5)
+			throw std::runtime_error("Format error");
+		++superfamilies[superfamily.cl][superfamily.fold][superfamily.superfamily];
+		subjects[name] = superfamily;
+	}
+
+	if (!config.match_file2.empty()) {
+		Input_stream target_file(config.match_file2.c_str());
+		while (target_file.getline(), !target_file.eof()) {
+			char q[16], s[128];
+			float b;
+			if (sscanf(target_file.line.c_str(), "%s %s %f", q, s, &b) != 3)
+				throw std::runtime_error("Format error");
+			if (s[0] == 'd' || s[0] == 'g')
+				target.insert(pair<string, string>(q, s));
+		}
+	}
+
+	while (file1.get_read(v1, blast_tab_format())) {
+		query_roc(subjects[v1[0].query], v1, c2, e2);
+		coverage += c2;
+		errors += e2;
+	}
+	
+	coverage /= (double)queries;
+	errors /= (double)queries;
+	cout << queries << " Sequences." << endl;
+	cout << coverage << endl;
+	cout << errors << endl;
+	/*for (int exp = roc_from; exp <= roc_to; ++exp)
+		for (int factor = 2; factor <= 10; ++factor)
+			cout << pow(10.0, exp)*factor << endl;*/
+
+	cout << endl;
+	cout << "Targets = " << n_targets << " / " << target.size() << " (" << percentage(n_targets, target.size()) << "%)" << endl;
+	cout << "max ev = " << max_ev << endl;
+	cout << "False positives = " << fp << endl;
+}
\ No newline at end of file
diff --git a/src/output/blast_pairwise_format.cpp b/src/output/blast_pairwise_format.cpp
new file mode 100644
index 0000000..7ce0d8f
--- /dev/null
+++ b/src/output/blast_pairwise_format.cpp
@@ -0,0 +1,84 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "output_format.h"
+
+void Pairwise_format::print_match(const Hsp_context& r, Text_buffer &out) const
+{
+	static const unsigned width = 60;
+	out << '>' << r.subject_name << '\n';
+	out << "Length=" << r.subject_len << "\n\n";
+	out << " Score = " << r.bit_score() << " bits (" << r.score() << "),  Expect = ";
+	out.print_e(r.evalue());
+	out << '\n';
+	out << " Identities = " << r.identities() << '/' << r.length() << " (" << percentage(r.identities(), r.length()) << "%), Positives = " << r.positives() << '/' << r.length() << " (" << percentage(r.positives(), r.length())
+		<< "%), Gaps = " << r.gaps() << '/' << r.length() << " (" << percentage(r.gaps(), r.length()) << "%)\n";
+	if (align_mode.query_translated)
+		out << " Frame = " << r.blast_query_frame() << '\n';
+	out << '\n';
+
+	Hsp_context::Iterator qi = r.begin(), mi = r.begin(), si = r.begin();
+	while (qi.good()) {
+		out << "Query  ";
+		out.print(qi.query_pos+1, 0);
+		out << "  ";
+		for (unsigned i = 0; i < width && qi.good(); ++i, ++qi)
+			out << qi.query_char();
+		out << " ";
+		out.print(qi.query_pos, 0);
+		out << '\n';
+
+		out << "             ";
+		for (unsigned i = 0; i < width && mi.good(); ++i, ++mi)
+			out << mi.midline_char();
+		out << '\n';
+
+		out << "Sbjct  ";
+		out.print(si.subject_pos+1, 0);
+		out << "  ";
+		for (unsigned i = 0; i < width && si.good(); ++i, ++si)
+			out << si.subject_char();
+		out << " ";
+		out.print(si.subject_pos, 0);
+		out << "\n\n";
+	}
+}
+
+void Pairwise_format::print_footer(Output_stream &out) const
+{
+
+}
+
+void Pairwise_format::print_query_epilog(Text_buffer &out, bool unaligned) const
+{
+
+}
+
+void Pairwise_format::print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const
+{
+	out << "Query= " << query_name << "\n\nLength=" << query_len << "\n\n";
+	if (unaligned) {
+		out << "\n***** No hits found *****\n\n\n";
+	}
+}
+
+void Pairwise_format::print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const
+{
+	static const char* header = "BLASTP 2.3.0+\n\n\n";
+	f.write(header, strlen(header));
+}
\ No newline at end of file
diff --git a/src/output/blast_tab_format.cpp b/src/output/blast_tab_format.cpp
new file mode 100644
index 0000000..32c82c7
--- /dev/null
+++ b/src/output/blast_tab_format.cpp
@@ -0,0 +1,279 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "../basic/match.h"
+#include "output_format.h"
+
+const char* Blast_tab_format::field_str[] = {
+	"qseqid",		// 0 means Query Seq - id
+	"qgi",			// 1 means Query GI
+	"qacc",			// 2 means Query accesion
+	"qaccver",		// 3 means Query accesion.version
+	"qlen",			// 4 means Query sequence length
+	"sseqid",		// 5 means Subject Seq - id
+	"sallseqid",	// 6 means All subject Seq - id(s), separated by a ';'
+	"sgi",			// 7 means Subject GI
+	"sallgi",		// 8 means All subject GIs
+	"sacc",			// 9 means Subject accession
+	"saccver",		// 10 means Subject accession.version
+	"sallacc",		// 11 means All subject accessions
+	"slen",			// 12 means Subject sequence length
+	"qstart",		// 13 means Start of alignment in query
+	"qend",			// 14 means End of alignment in query
+	"sstart",		// 15 means Start of alignment in subject
+	"send",			// 16 means End of alignment in subject
+	"qseq",			// 17 means Aligned part of query sequence
+	"sseq",			// 18 means Aligned part of subject sequence
+	"evalue",		// 19 means Expect value
+	"bitscore",		// 20 means Bit score
+	"score",		// 21 means Raw score
+	"length",		// 22 means Alignment length
+	"pident",		// 23 means Percentage of identical matches
+	"nident",		// 24 means Number of identical matches
+	"mismatch",		// 25 means Number of mismatches
+	"positive",		// 26 means Number of positive - scoring matches
+	"gapopen",		// 27 means Number of gap openings
+	"gaps",			// 28 means Total number of gaps
+	"ppos",			// 29 means Percentage of positive - scoring matches
+	"frames",		// 30 means Query and subject frames separated by a '/'
+	"qframe",		// 31 means Query frame
+	"sframe",		// 32 means Subject frame
+	"btop",			// 33 means Blast traceback operations(BTOP)
+	"staxids",		// 34 means unique Subject Taxonomy ID(s), separated by a ';'	(in numerical order)
+	"sscinames",	// 35 means unique Subject Scientific Name(s), separated by a ';'
+	"scomnames",	// 36 means unique Subject Common Name(s), separated by a ';'
+	"sblastnames",	// 37 means unique Subject Blast Name(s), separated by a ';'	(in alphabetical order)
+	"sskingdoms",	// 38 means unique Subject Super Kingdom(s), separated by a ';'	(in alphabetical order)
+	"stitle",		// 39 means Subject Title
+	"salltitles",	// 40 means All Subject Title(s), separated by a '<>'
+	"sstrand",		// 41 means Subject Strand
+	"qcovs",		// 42 means Query Coverage Per Subject
+	"qcovhsp",		// 43 means Query Coverage Per HSP
+	"qcovus",		// 44 means Query Coverage Per Unique Subject(blastn only)
+	"qtitle"		// 45 means Query title
+};
+
+Blast_tab_format::Blast_tab_format() :
+	Output_format(blast_tab)
+{
+	static const unsigned stdf[] = { 0, 5, 23, 22, 25, 27, 13, 14, 15, 16, 19, 20 };
+	const vector<string> &f = config.output_format;
+	if (f.size() <= 1) {
+		fields = vector<unsigned>(stdf, stdf + 12);
+		return;
+	}
+	for (vector<string>::const_iterator i = f.begin() + 1; i != f.end(); ++i) {
+		int j = get_idx(field_str, sizeof(field_str) / sizeof(field_str[0]), i->c_str());
+		if(j == -1)
+			throw std::runtime_error(string("Invalid output field: ") + *i);
+		fields.push_back(j);
+		if (j == 6 || j == 39 || j == 40)
+			config.salltitles = true;
+	}
+}
+
+void Blast_tab_format::print_match(const Hsp_context& r, Text_buffer &out) const
+{
+	for (vector<unsigned>::const_iterator i = fields.begin(); i != fields.end(); ++i) {
+		switch (*i) {
+		case 0:
+			out.write_until(r.query_name, Const::id_delimiters);
+			break;
+		case 4:
+			out << r.source_query.length();
+			break;
+		case 5:
+			this->print_salltitles(out, r.subject_name, false, false);
+			break;
+		case 6:
+			this->print_salltitles(out, r.subject_name, false, true);
+			break;
+		case 12:
+			out << r.subject_len;
+			break;
+		case 13:
+			out << r.oriented_query_range().begin_ + 1;
+			break;
+		case 14:
+			out << r.oriented_query_range().end_ + 1;
+			break;
+		case 15:
+			out << r.subject_range().begin_ + 1;
+			break;
+		case 16:
+			out << r.subject_range().end_;
+			break;
+		case 17:
+			r.source_query.print(out, r.query_source_range().begin_, r.query_source_range().end_, input_value_traits);
+			break;
+		case 18:
+		{
+			vector<Letter> seq;
+			seq.reserve(r.subject_range().length());
+			for (Hsp_context::Iterator j = r.begin(); j.good(); ++j)
+				if (!(j.op() == op_insertion))
+					seq.push_back(j.subject());
+			out << sequence(seq);
+			break;
+		}
+		case 19:
+			out.print_e(r.evalue());
+			break;
+		case 20:
+			out << r.bit_score();
+			break;
+		case 21:
+			out << r.score();
+			break;
+		case 22:
+			out << r.length();
+			break;
+		case 23:
+			out << (double)r.identities() * 100 / r.length();
+			break;
+		case 24:
+			out << r.identities();
+			break;
+		case 25:
+			out << r.mismatches();
+			break;
+		case 26:
+			out << r.positives();
+			break;
+		case 27:
+			out << r.gap_openings();
+			break;
+		case 28:
+			out << r.gaps();
+			break;
+		case 29:
+			out << (double)r.positives() * 100.0 / r.length();
+			break;
+		case 31:
+			out << r.blast_query_frame();
+			break;
+		case 33:
+		{
+			unsigned n_matches = 0;
+			for (Hsp_context::Iterator i = r.begin(); i.good(); ++i) {
+				switch (i.op()) {
+				case op_match:
+					++n_matches;
+					break;
+				case op_substitution:
+					if (n_matches > 0) {
+						out << n_matches;
+						n_matches = 0;
+					}
+					out << i.query_char() << i.subject_char();
+					break;
+				case op_insertion:
+					if (n_matches > 0) {
+						out << n_matches;
+						n_matches = 0;
+					}
+					out << i.query_char() << '-';
+					break;
+				case op_deletion:
+					if (n_matches > 0) {
+						out << n_matches;
+						n_matches = 0;
+					}
+					out << '-' << i.subject_char();
+					break;
+				}
+			}
+			if (n_matches > 0)
+				out << n_matches;
+		}
+			break;
+		case 39:
+			this->print_salltitles(out, r.subject_name, true, false);
+			break;
+		case 40:
+			this->print_salltitles(out, r.subject_name, true, true);
+			break;
+		case 43:
+			out << (double)r.query_source_range().length()*100.0 / r.source_query.length();
+			break;
+		case 45:
+			out << r.query_name;
+			break;
+		default:
+			throw std::runtime_error("Invalid output field");
+		}
+		if (i < fields.end() - 1)
+			out << '\t';
+	}
+	out << '\n';
+}
+
+void Blast_tab_format::print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const
+{
+	if (unaligned && config.report_unaligned == 1) {
+		for (vector<unsigned>::const_iterator i = fields.begin(); i != fields.end(); ++i) {
+			switch (*i) {
+			case 0:
+				out.write_until(query_name, Const::id_delimiters);
+				break;
+			case 4:
+				out << query_len;
+				break;
+			case 5:
+			case 6:
+			case 17:
+			case 18:
+			case 33:
+			case 39:
+			case 40:
+				out << '*';
+				break;
+			case 12:
+			case 13:
+			case 14:
+			case 15:
+			case 16:
+			case 19:
+			case 20:
+			case 21:
+			case 22:
+			case 23:
+			case 24:
+			case 25:
+			case 26:
+			case 27:
+			case 28:
+			case 29:
+			case 43:
+				out << "-1";
+				break;			
+			case 31:
+				out << '0';
+				break;
+			case 45:
+				out << query_name;
+				break;
+			default:
+				throw std::runtime_error("Invalid output field");
+			}
+			if (i < fields.end() - 1)
+				out << '\t';			
+		}
+		out << '\n';
+	}
+}
\ No newline at end of file
diff --git a/src/output/daa_file.h b/src/output/daa_file.h
new file mode 100644
index 0000000..9333582
--- /dev/null
+++ b/src/output/daa_file.h
@@ -0,0 +1,216 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef DAA_FILE_H_
+#define DAA_FILE_H_
+
+#include <string>
+#include <exception>
+#include "../util/ptr_vector.h"
+#include "../basic/config.h"
+#include "../basic/const.h"
+#include "../util/binary_buffer.h"
+#include "../util/binary_file.h"
+#include "../basic/value.h"
+#include "../data/reference.h"
+
+using std::string;
+
+struct DAA_header1
+{
+	DAA_header1():
+		magic_number (0x3c0e53476d3ee36bllu),
+		version (0)
+	{ }
+	uint64_t magic_number, version;
+};
+
+inline const char* mode_str(int mode)
+{
+	static const char* mode_str[] = { 0, 0, "blastp", "blastx", "blastn" };
+	return mode_str[mode];
+}
+
+struct DAA_header2
+{
+	DAA_header2():
+		diamond_build(Const::build_version)
+	{
+		memset(block_type, 0, sizeof(block_type));
+		memset(block_size, 0, sizeof(block_size));
+	}
+	DAA_header2(uint64_t db_seqs,
+			uint64_t db_letters,
+			int32_t gap_open,
+			int32_t gap_extend,
+			int32_t reward,
+			int32_t penalty,
+			double k,
+			double lambda,
+			double evalue,
+			const string &score_matrix,
+			unsigned mode):
+		diamond_build (Const::build_version),
+		db_seqs (db_seqs),
+		db_seqs_used (0),
+		db_letters (db_letters),
+		flags (0),
+		query_records (0),
+		mode ((int32_t)mode),
+		gap_open (gap_open),
+		gap_extend (gap_extend),
+		reward (reward),
+		penalty (penalty),
+		reserved1 (0),
+		reserved2 (0),
+		reserved3 (0),
+		k (k),
+		lambda (lambda),
+		evalue (evalue),
+		reserved5 (0)
+	{
+		memset(block_type, 0, sizeof(block_type));
+		memset(block_size, 0, sizeof(block_size));
+		strcpy(this->score_matrix, score_matrix.c_str());
+	}
+	typedef enum { empty = 0, alignments = 1, ref_names = 2, ref_lengths = 3 } Block_type;
+	uint64_t diamond_build, db_seqs, db_seqs_used, db_letters, flags, query_records;
+	int32_t mode, gap_open, gap_extend, reward, penalty, reserved1, reserved2, reserved3;
+	double k, lambda, evalue, reserved5;
+	char score_matrix[16];
+	uint64_t block_size[256];
+	char block_type[256];
+};
+
+struct DAA_file
+{
+
+	DAA_file(const string& file_name):
+		f_ (file_name),
+		query_count_ (0)
+	{
+		f_.read(&h1_, 1);
+		if(h1_.magic_number != DAA_header1().magic_number)
+			throw std::runtime_error("Input file is not a DAA file.");
+		if(h1_.version > Const::daa_version)
+			throw std::runtime_error("DAA version requires later version of DIAMOND.");
+		f_.read(&h2_, 1);
+
+		if(h2_.block_size[0] == 0)
+			throw std::runtime_error("Invalid DAA file. DIAMOND run has probably not completed successfully.");
+
+		Config::set_option(config.db_size, h2_.db_letters);
+		align_mode = Align_mode(h2_.mode);
+		ref_header.sequences = h2_.db_seqs;
+
+		f_.seek(sizeof(DAA_header1) + sizeof(DAA_header2) + (size_t)h2_.block_size[0]);
+		string s;
+		ref_name_.reserve((size_t)h2_.db_seqs_used);
+		for(uint64_t i=0;i<h2_.db_seqs_used;++i) {
+			f_.read_c_str(s);
+			ref_name_.push_back(new string(s));
+		}
+		ref_len_.resize((size_t)h2_.db_seqs_used);
+		f_.read(ref_len_.data(), (size_t)h2_.db_seqs_used);
+
+		f_.seek(sizeof(DAA_header1) + sizeof(DAA_header2));
+	}
+
+	~DAA_file()
+	{
+		f_.close();
+	}
+
+	uint64_t diamond_build() const
+	{ return h2_.diamond_build; }
+
+	uint64_t db_seqs() const
+	{ return h2_.db_seqs; }
+
+	uint64_t db_seqs_used() const
+	{ return h2_.db_seqs_used; }
+
+	uint64_t db_letters() const
+	{ return h2_.db_letters; }
+
+	const char* score_matrix() const
+	{ return h2_.score_matrix; }
+
+	int32_t gap_open_penalty() const
+	{ return h2_.gap_open; }
+
+	int32_t gap_extension_penalty() const
+	{ return h2_.gap_extend; }
+
+	int32_t match_reward() const
+	{ return h2_.reward; }
+
+	int32_t mismatch_penalty() const
+	{ return h2_.penalty; }
+
+	uint64_t query_records() const
+	{ return h2_.query_records; }
+
+	unsigned mode() const
+	{ return (unsigned)h2_.mode; }
+
+	const string& ref_name(size_t i) const
+	{ return ref_name_[i]; }
+
+	const uint32_t ref_len(size_t i) const
+	{ return ref_len_[i]; }
+
+	double lambda() const
+	{
+		return h2_.lambda;
+	}
+
+	double kappa() const
+	{
+		return h2_.k;
+	}
+
+	double evalue() const
+	{
+		return h2_.evalue;
+	}
+
+	bool read_query_buffer(Binary_buffer &buf, size_t &query_num)
+	{
+		uint32_t size;
+		f_.read(&size, 1);
+		if(size == 0)
+			return false;
+		buf.resize(size);
+		f_.read(buf.data(), size);
+		query_num = query_count_++;
+		return true;
+	}
+
+private:
+
+	Input_stream f_;
+	size_t query_count_;
+	DAA_header1 h1_;
+	DAA_header2 h2_;
+	Ptr_vector<string> ref_name_;
+	vector<uint32_t> ref_len_;
+
+};
+
+#endif /* DAA_FILE_H_ */
diff --git a/src/output/daa_record.cpp b/src/output/daa_record.cpp
new file mode 100644
index 0000000..566d8ee
--- /dev/null
+++ b/src/output/daa_record.cpp
@@ -0,0 +1,87 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "daa_record.h"
+#include "output.h"
+
+Binary_buffer::Iterator DAA_query_record::init(const Binary_buffer &buf)
+{
+	Binary_buffer::Iterator it(buf.begin());
+	uint32_t query_len;
+	it >> query_len;
+	it >> query_name;
+	uint8_t flags;
+	it >> flags;
+	if (file_.mode() == Align_mode::blastp) {
+		Packed_sequence seq(it, query_len, false, 5);
+		seq.unpack(context[0], 5, query_len);
+	}
+	else {
+		const bool have_n = (flags & 1) == 1;
+		Packed_sequence seq(it, query_len, have_n, have_n ? 3 : 2);
+		seq.unpack(source_seq, have_n ? 3 : 2, query_len);
+		translate_query(source_seq, context);
+	}
+	return it;
+}
+
+Binary_buffer::Iterator& operator>>(Binary_buffer::Iterator &it, DAA_query_record::Match &r)
+{
+	const uint32_t old_subject = r.subject_id;
+	it >> r.subject_id;
+	if (r.subject_id == old_subject)
+		++r.hsp_num;
+	else {
+		r.hsp_num = 0;
+		++r.hit_num;
+	}
+	uint8_t flag;
+	it >> flag;
+	it.read_packed(flag & 3, r.score);
+	uint32_t query_begin;
+	it.read_packed((flag >> 2) & 3, query_begin);
+	it.read_packed((flag >> 4) & 3, r.subject_range.begin_);
+	r.transcript.read(it);
+	r.subject_name = r.parent_.file_.ref_name(r.subject_id);
+	r.subject_len = r.parent_.file_.ref_len(r.subject_id);
+	if (r.parent_.file_.mode() == Align_mode::blastx) {
+		r.frame = (flag&(1 << 6)) == 0 ? query_begin % 3 : 3 + (r.parent_.source_seq.size() - 1 - query_begin) % 3;
+		r.set_translated_query_begin(query_begin, (unsigned)r.parent_.source_seq.size());
+	}
+	else if (r.parent_.file_.mode() == Align_mode::blastp) {
+		r.frame = 0;
+		r.query_range.begin_ = query_begin;
+	}
+	r.context().parse().set_query_source_range(query_begin);
+	return it;
+}
+
+Hsp_data::Hsp_data(const Intermediate_record &r, unsigned query_source_len):
+	score(r.score),
+	transcript(r.transcript)
+{
+	subject_range.begin_ = r.subject_begin;
+	if (align_mode.mode == Align_mode::blastx) {
+		frame = (r.flag&(1 << 6)) == 0 ? r.query_begin % 3 : 3 + (query_source_len - 1 - r.query_begin) % 3;
+		set_translated_query_begin(r.query_begin, query_source_len);
+	}
+	else {
+		frame = 0;
+		query_range.begin_ = r.query_begin;
+	}
+}
\ No newline at end of file
diff --git a/src/output/daa_record.h b/src/output/daa_record.h
new file mode 100644
index 0000000..c7f6cd2
--- /dev/null
+++ b/src/output/daa_record.h
@@ -0,0 +1,147 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef DAA_RECORD_H_
+#define DAA_RECORD_H_
+
+#include <limits>
+#include "daa_file.h"
+#include "../basic/packed_sequence.h"
+#include "../basic/value.h"
+#include "../basic/translate.h"
+#include "../basic/packed_transcript.h"
+#include "../align/match_func.h"
+#include "../basic/score_matrix.h"
+
+using std::string;
+using std::vector;
+
+/*void translate_query(const vector<Letter>& query, vector<Letter> *context)
+{
+	context[0] = query;
+	context[1] = Translator::reverse(query);
+}*/
+
+inline void translate_query(const vector<Letter>& query, vector<Letter> *context)
+{
+	Translator::translate(query, context);
+}
+
+struct DAA_query_record
+{
+
+	struct Match : public Hsp_data
+	{
+
+		Match(const DAA_query_record &query_record) :
+			hit_num(std::numeric_limits<uint32_t>::max()),
+			subject_id(std::numeric_limits<uint32_t>::max()),
+			parent_(query_record)
+		{ }
+
+		Hsp_context context()
+		{
+			return Hsp_context(*this,
+				(unsigned)parent_.query_num,
+				sequence(parent_.context[frame]),
+				align_mode.query_translated ? sequence(parent_.source_seq) : sequence(parent_.context[0]),
+				parent_.query_name.c_str(),
+				subject_id,
+				subject_id,
+				subject_name.c_str(),
+				subject_len,
+				hit_num,
+				hsp_num);
+		}
+
+		uint32_t hsp_num, hit_num, subject_id, subject_len;
+		string subject_name;
+
+	private:
+
+		const DAA_query_record &parent_;
+		friend Binary_buffer::Iterator& operator>>(Binary_buffer::Iterator &it, Match &r);
+
+	};
+
+	struct Match_iterator
+	{
+		Match_iterator(const DAA_query_record &parent, Binary_buffer::Iterator it) :
+			r_(parent),
+			it_(it),
+			good_(true)
+		{
+			operator++();
+		}
+		Match& operator*()
+		{
+			return r_;
+		}
+		Match* operator->()
+		{
+			return &r_;
+		}
+		bool good() const
+		{
+			return good_;
+		}
+		Match_iterator& operator++()
+		{
+			if (it_.good()) it_ >> r_; else good_ = false; return *this;
+		}
+	private:
+		Match r_;
+		Binary_buffer::Iterator it_;
+		bool good_;
+	};
+
+	DAA_query_record(const DAA_file& file, const Binary_buffer &buf, size_t query_num):
+		query_num (query_num),
+		file_(file),
+		it_(init(buf))
+	{ }
+
+	Match_iterator begin() const
+	{
+		return Match_iterator(*this, it_);
+	}
+
+	size_t query_len() const
+	{
+		return align_mode.query_translated ? source_seq.size() : context[0].size();
+	}
+
+	string query_name;
+	size_t query_num;
+	vector<Letter> source_seq;
+	vector<Letter> context[6];
+
+private:
+
+	Binary_buffer::Iterator init(const Binary_buffer &buf);
+
+	const DAA_file& file_;
+	const Binary_buffer::Iterator it_;
+	
+	friend Binary_buffer::Iterator& operator>>(Binary_buffer::Iterator &it, Match &r);
+
+};
+
+Binary_buffer::Iterator& operator>>(Binary_buffer::Iterator &it, DAA_query_record::Match &r);
+
+#endif /* DAA_RECORD_H_ */
diff --git a/src/output/daa_write.h b/src/output/daa_write.h
new file mode 100644
index 0000000..b8eb691
--- /dev/null
+++ b/src/output/daa_write.h
@@ -0,0 +1,115 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef DAA_WRITE_H_
+#define DAA_WRITE_H_
+
+#include <limits>
+#include <stdint.h>
+#include "output.h"
+#include "daa_file.h"
+#include "../basic/score_matrix.h"
+#include "../data/reference.h"
+#include "../align/align.h"
+#include "../basic/packed_sequence.h"
+
+inline void init_daa(Output_stream &f)
+{
+	DAA_header1 h1;
+	f.typed_write(&h1, 1);	
+	DAA_header2 h2_;
+	f.typed_write(&h2_, 1);
+}
+
+inline size_t write_daa_query_record(Text_buffer &buf, const char *query_name, const sequence &query)
+{
+	size_t seek_pos = buf.size();
+	buf.write((uint32_t)0);
+	uint32_t l = (uint32_t)query.length();
+	buf.write(l);
+	buf.write_c_str(query_name, find_first_of(query_name, Const::id_delimiters));
+	Packed_sequence s(query, align_mode.input_sequence_type);
+	uint8_t flags = s.has_n() ? 1 : 0;
+	buf.write(flags);
+	buf << s.data();
+	return seek_pos;
+}
+
+inline void finish_daa_query_record(Text_buffer &buf, size_t seek_pos)
+{
+	*(uint32_t*)(&buf[seek_pos]) = (uint32_t)(buf.size() - seek_pos - sizeof(uint32_t));
+}
+
+inline void write_daa_record(Text_buffer &buf, const Intermediate_record &r)
+{
+	buf.write(r.subject_id).write(r.flag);
+	buf.write_packed(r.score);
+	buf.write_packed(r.query_begin);
+	buf.write_packed(r.subject_begin);
+	buf << r.transcript.data();
+}
+
+inline void write_daa_record(Text_buffer &buf, const Hsp_data &match, unsigned query_id, unsigned subject_id)
+{
+	buf.write(ref_map.get(current_ref_block, subject_id));
+	buf.write(get_segment_flag(match));
+	buf.write_packed(match.score);
+	buf.write_packed(match.oriented_range().begin_);
+	buf.write_packed(match.subject_range.begin_);
+	buf << match.transcript.data();
+}
+
+inline void finish_daa(Output_stream &f)
+{
+	DAA_header2 h2_(ref_header.sequences,
+		config.db_size,
+		config.gap_open,
+		config.gap_extend,
+		config.reward,
+		config.penalty,
+		score_matrix.k(),
+		score_matrix.lambda(),
+		config.max_evalue,
+		to_lower_case(config.matrix),
+		align_mode.mode);
+
+	h2_.block_type[0] = DAA_header2::alignments;
+	h2_.block_type[1] = DAA_header2::ref_names;
+	h2_.block_type[2] = DAA_header2::ref_lengths;
+
+	uint32_t size = 0;
+	f.typed_write(&size, 1);
+	h2_.block_size[0] = f.tell() - sizeof(DAA_header1) - sizeof(DAA_header2);
+	h2_.db_seqs_used = ref_map.next_;
+	h2_.query_records = statistics.get(Statistics::ALIGNED);
+
+	size_t s = 0;
+	for (Ptr_vector<string>::const_iterator i = ref_map.name_.begin(); i != ref_map.name_.end(); ++i) {
+		f.write_c_str((*i)->c_str());
+		s += (*i)->length() + 1;
+	}
+	h2_.block_size[1] = s;
+
+	f.write(ref_map.len_, false);
+	h2_.block_size[2] = ref_map.len_.size() * sizeof(uint32_t);
+
+	f.seekp(sizeof(DAA_header1));
+	f.typed_write(&h2_, 1);
+}
+
+#endif /* DAA_WRITE_H_ */
diff --git a/src/output/join_blocks.cpp b/src/output/join_blocks.cpp
new file mode 100644
index 0000000..b3c593c
--- /dev/null
+++ b/src/output/join_blocks.cpp
@@ -0,0 +1,250 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "output.h"
+#include "../util/temp_file.h"
+#include "../data/queries.h"
+#include "../output/daa_write.h"
+#include "output_format.h"
+
+#ifndef ST_JOIN
+
+struct Join_fetcher
+{
+	static void init(const vector<Temp_file> &tmp_file)
+	{
+		for (vector<Temp_file>::const_iterator i = tmp_file.begin(); i != tmp_file.end(); ++i) {
+			files.push_back(Input_stream(*i));
+			query_ids.push_back(0);
+			files.back().read(&query_ids.back(), 1);
+		}
+		query_last = (unsigned)-1;
+	}
+	static void finish()
+	{
+		for (vector<Input_stream>::iterator i = files.begin(); i != files.end(); ++i)
+			i->close_and_delete();
+		files.clear();
+		query_ids.clear();
+	}
+	static unsigned next()
+	{
+		return *std::min_element(query_ids.begin(), query_ids.end());
+	}
+	void fetch(unsigned b)
+	{
+		unsigned size;
+		files[b].read(&size, 1);
+		buf[b].resize(size);
+		files[b].read(buf[b].data(), size);
+		files[b].read(&query_ids[b], 1);
+	}
+	Join_fetcher():
+		buf(current_ref_block)
+	{}
+	bool operator()()
+	{
+		query_id = next();
+		unaligned_from = query_last + 1;
+		query_last = query_id;
+		for (unsigned i = 0; i < buf.size(); ++i)
+			if (query_ids[i] == query_id)
+				fetch(i);
+			else
+				buf[i].clear();
+		return next() != Intermediate_record::finished;
+	}
+	static vector<Input_stream> files;
+	static vector<unsigned> query_ids;
+	static unsigned query_last;
+	vector<Binary_buffer> buf;
+	unsigned query_id, unaligned_from;
+};
+
+vector<Input_stream> Join_fetcher::files;
+vector<unsigned> Join_fetcher::query_ids;
+unsigned Join_fetcher::query_last;
+
+struct Join_writer
+{
+	Join_writer(Output_stream &f):
+		f_(f)
+	{}
+	void operator()(Text_buffer& buf)
+	{
+		f_.write(buf.get_begin(), buf.size());
+		buf.clear();
+	}
+	Output_stream &f_;
+};
+
+struct Join_record
+{
+
+	bool operator<(const Join_record &rhs) const
+	{
+		return rhs.same_subject_ ||  (!rhs.same_subject_ && info_.score < rhs.info_.score);
+	}
+
+	Join_record(unsigned ref_block, unsigned subject, Binary_buffer::Iterator &it):
+		block_(ref_block)
+	{
+		info_.read(it);
+		same_subject_ = info_.subject_id == subject;
+	}
+
+	static bool push_next(unsigned block, unsigned subject, Binary_buffer::Iterator &it, vector<Join_record> &v)	
+	{
+		if (it.good()) {
+			v.push_back(Join_record(block, subject, it));
+			return true;
+		}
+		else
+			return false;
+	}
+
+	unsigned block_;
+	bool same_subject_;
+	Intermediate_record info_;
+
+};
+
+void join_query(vector<Binary_buffer> &buf, Text_buffer &out, Statistics &statistics, unsigned query, const char *query_name, unsigned query_source_len)
+{
+	sequence context[6];
+	for (unsigned i = 0; i < align_mode.query_contexts; ++i)
+		context[i] = query_seqs::get()[query*align_mode.query_contexts + i];
+
+	vector<Join_record> records;
+	vector<Binary_buffer::Iterator> it;
+	for (unsigned i = 0; i<current_ref_block; ++i) {
+		it.push_back(buf[i].begin());
+		Join_record::push_next(i, std::numeric_limits<unsigned>::max(), it.back(), records);
+	}
+	std::make_heap(records.begin(), records.end());
+	unsigned block, subject, n_target_seq = 0, hsp_num = 0;
+	block = subject = std::numeric_limits<unsigned>::max();
+	int top_score = records.front().info_.score;
+
+	while (!records.empty()) {
+		const Join_record &next = records.front();
+		const unsigned b = next.block_;
+		const bool same_subject = n_target_seq > 0 && b == block && next.info_.subject_id == subject;
+
+		if (config.output_range(n_target_seq, next.info_.score, top_score) || same_subject) {
+			//printf("q=%u s=%u n=%u ss=%u\n",query, next.info_.subject_id, n_target_seq, same_subject, next.info_.score);
+
+			if(*output_format == Output_format::daa)
+				write_daa_record(out, next.info_);
+			else {
+				Hsp_data hsp(next.info_, query_source_len);
+				output_format->print_match(Hsp_context(hsp,
+					query,
+					context[hsp.frame],
+					align_mode.query_translated ? query_source_seqs::get()[query] : context[0],
+					query_name,
+					next.info_.subject_id,
+					ref_map.original_id(next.info_.subject_id),
+					ref_map.name(next.info_.subject_id),
+					ref_map.length(next.info_.subject_id),
+					n_target_seq,
+					hsp_num).parse().set_query_source_range(next.info_.query_begin), out);
+			}
+
+			statistics.inc(Statistics::MATCHES);
+			if (!same_subject) {
+				block = b;
+				subject = next.info_.subject_id;
+				++n_target_seq;
+				hsp_num = 0;
+				statistics.inc(Statistics::PAIRWISE);
+			}
+			else
+				++hsp_num;
+		}
+		else
+			break;
+
+		std::pop_heap(records.begin(), records.end());
+		records.pop_back();
+
+		if (Join_record::push_next(block, subject, it[block], records))
+			std::push_heap(records.begin(), records.end());
+	}
+}
+
+void join_worker(Task_queue<Text_buffer,Join_writer> *queue)
+{
+	Join_fetcher fetcher;
+	size_t n;
+	Text_buffer *out;
+	Statistics stat;
+
+	while (queue->get(n, out, fetcher)) {
+		stat.inc(Statistics::ALIGNED);
+		size_t seek_pos;
+		const char * query_name = query_ids::get()[fetcher.query_id].c_str();
+		const sequence query_seq = align_mode.query_translated ? query_source_seqs::get()[fetcher.query_id] : query_seqs::get()[fetcher.query_id];
+
+		if (*output_format != Output_format::daa && config.report_unaligned != 0) {
+			for (unsigned i = fetcher.unaligned_from; i < fetcher.query_id; ++i) {
+				output_format->print_query_intro(i, query_ids::get()[i].c_str(), get_source_query_len(i), *out, true);
+				output_format->print_query_epilog(*out, true);
+			}
+		}
+
+		if (*output_format == Output_format::daa)
+			seek_pos = write_daa_query_record(*out, query_name, query_seq);
+		else
+			output_format->print_query_intro(fetcher.query_id, query_name, (unsigned)query_seq.length(), *out, false);
+
+		join_query(fetcher.buf, *out, stat, fetcher.query_id, query_name, (unsigned)query_seq.length());
+
+		if (*output_format == Output_format::daa)
+			finish_daa_query_record(*out, seek_pos);
+		else
+			output_format->print_query_epilog(*out, false);
+
+		queue->push(n);
+	}
+
+	statistics += stat;
+}
+
+void join_blocks(unsigned ref_blocks, Output_stream &master_out, const vector<Temp_file> &tmp_file)
+{
+	ref_map.init_rev_map();
+	Join_fetcher::init(tmp_file);
+	Join_writer writer(master_out);
+	Task_queue<Text_buffer, Join_writer> queue(3*config.threads_, writer);
+	Thread_pool threads;
+	for (unsigned i = 0; i < config.threads_; ++i)
+		threads.push_back(launch_thread(join_worker, &queue));
+	threads.join_all();
+	Join_fetcher::finish();
+	if (*output_format != Output_format::daa && config.report_unaligned != 0) {
+		Text_buffer out;
+		for (unsigned i = Join_fetcher::query_last + 1; i < query_ids::get().get_length(); ++i) {
+			output_format->print_query_intro(i, query_ids::get()[i].c_str(), get_source_query_len(i), out, true);
+			output_format->print_query_epilog(out, true);
+		}
+		writer(out);
+	}
+}
+
+#endif
\ No newline at end of file
diff --git a/src/output/output.h b/src/output/output.h
new file mode 100644
index 0000000..62b5afb
--- /dev/null
+++ b/src/output/output.h
@@ -0,0 +1,124 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef OUTPUT_H_
+#define OUTPUT_H_
+
+#include "../util/binary_file.h"
+#include "../basic/packed_transcript.h"
+#include "../util/text_buffer.h"
+#include "../align/align_struct.h"
+#include "../data/reference.h"
+
+inline unsigned get_length_flag(unsigned x)
+{
+	if (x <= (unsigned)std::numeric_limits<uint8_t>::max())
+		return 0;
+	else if (x <= (unsigned)std::numeric_limits<uint16_t>::max())
+		return 1;
+	return 2;
+}
+
+inline unsigned get_rev_flag(unsigned frame)
+{
+	return frame > 2 ? 1 : 0;
+}
+
+inline uint8_t get_segment_flag(const Hsp_data &match)
+{
+	unsigned rev = get_rev_flag(match.frame);
+	return (uint8_t)(get_length_flag(match.score)
+		| (get_length_flag(match.oriented_range().begin_) << 2)
+		| (get_length_flag(match.subject_range.begin_) << 4)
+		| rev << 6);
+}
+
+inline uint8_t get_segment_flag(const Hsp_context &match)
+{
+	unsigned rev = get_rev_flag(match.frame());
+	return (uint8_t)(get_length_flag(match.score())
+		| (get_length_flag(match.oriented_query_range().begin_) << 2)
+		| (get_length_flag(match.subject_range().begin_) << 4)
+		| rev << 6);
+}
+
+struct Intermediate_record
+{
+	void read(Buffered_file &f)
+	{
+		f.read(query_id);
+		f.read(subject_id);
+		f.read(flag);
+		f.read_packed(flag & 3, score);
+		f.read_packed((flag >> 2) & 3, query_begin);
+		f.read_packed((flag >> 4) & 3, subject_begin);
+		transcript.read(f);
+	}
+	void read(Binary_buffer::Iterator &f)
+	{
+		f.read(subject_id);
+		f.read(flag);
+		f.read_packed(flag & 3, score);
+		f.read_packed((flag >> 2) & 3, query_begin);
+		f.read_packed((flag >> 4) & 3, subject_begin);
+		transcript.read(f);
+	}
+	static size_t write_query_intro(Text_buffer &buf, unsigned query_id)
+	{
+#ifndef ST_JOIN
+		size_t seek_pos = buf.size();
+		buf.write(query_id).write(0u);
+		return seek_pos;
+#else
+		return 0;
+#endif
+	}
+	static void finish_query(Text_buffer &buf, size_t seek_pos)
+	{
+#ifndef ST_JOIN
+		*(unsigned*)(&buf[seek_pos + sizeof(unsigned)]) = (unsigned)(buf.size() - seek_pos - sizeof(unsigned) * 2);
+#endif
+	}
+	static void write(Text_buffer &buf, const Hsp_data &match, unsigned query_id, unsigned subject_id)
+	{
+#ifdef ST_JOIN
+		buf.write(query_id);
+#endif
+		buf.write(ref_map.get(current_ref_block, subject_id))
+			.write(get_segment_flag(match))
+			.write_packed(match.score)
+			.write_packed(match.oriented_range().begin_)
+			.write_packed(match.subject_range.begin_)
+			<< match.transcript.data();
+	}
+	static void finish_file(Output_stream &f)
+	{
+		unsigned x = finished;
+		f.typed_write(&x, 1);
+	}
+	enum { finished = 0xffffffffu };
+	uint32_t query_id, subject_id, score, query_begin, subject_begin;
+	uint8_t flag;
+	Packed_transcript transcript;
+};
+
+#ifndef ST_JOIN
+void join_blocks(unsigned ref_blocks, Output_stream &master_out, const vector<Temp_file> &tmp_file);
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/output/output_file.h b/src/output/output_file.h
new file mode 100644
index 0000000..8f7b575
--- /dev/null
+++ b/src/output/output_file.h
@@ -0,0 +1,64 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef OUTPUT_FILE_H_
+#define OUTPUT_FILE_H_
+
+#include <string>
+#include "output.h"
+
+using std::string;
+
+struct Block_output : public Buffered_file
+{
+
+	struct Iterator
+	{
+		unsigned block_;
+		bool same_subject_;
+		Intermediate_record info_;
+		bool operator<(const Iterator &rhs) const
+		{ return info_.query_id > rhs.info_.query_id ||
+				(info_.query_id == rhs.info_.query_id && (rhs.same_subject_ ||
+						(!rhs.same_subject_ && info_.score < rhs.info_.score))); }
+	};
+
+	bool next(Iterator &it, unsigned subject, unsigned query)
+	{
+		if(this->eof())
+			return false;
+		it.info_.read(*this);
+		it.block_ = block_;
+		it.same_subject_ = it.info_.subject_id == subject && it.info_.query_id == query;
+		return true;
+	}
+
+	Block_output(unsigned ref_block, const Temp_file &tmp_file):
+		Buffered_file (tmp_file),
+		block_ (ref_block)
+	{ }
+
+private:
+
+	const unsigned block_;
+
+};
+
+#endif /* OUTPUT_FILE_H_ */
diff --git a/src/output/output_format.cpp b/src/output/output_format.cpp
new file mode 100644
index 0000000..6a9143a
--- /dev/null
+++ b/src/output/output_format.cpp
@@ -0,0 +1,169 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <iostream>
+#include "output_format.h"
+#include "../data/reference.h"
+
+using std::endl;
+
+auto_ptr<Output_format> output_format;
+
+Output_format* get_output_format()
+{
+	const vector<string> &f = config.output_format;
+	if (f.size() == 0) {
+		if (config.daa_file == "" || config.command == Config::view)
+			return new Blast_tab_format;
+		else if ((config.command == Config::blastp || config.command == Config::blastx) && config.daa_file.length() > 0)
+			return new DAA_format();
+	}
+	if (f[0] == "tab" || f[0] == "6")
+		return new Blast_tab_format;
+	else if (f[0] == "sam" || f[0] == "101")
+		return new Sam_format;
+	else if (f[0] == "xml" || f[0] == "5")
+		return new XML_format;
+	else if ((config.command == Config::blastp || config.command == Config::blastx) && (f[0] == "daa" || f[0] == "100"))
+		return new DAA_format;
+	else if (f[0] == "0")
+		return new Pairwise_format;
+	else
+		throw std::runtime_error("Invalid output format. Allowed values: 5,6,100,101");
+}
+
+
+void XML_format::print_match(const Hsp_context &r, Text_buffer &out) const
+{
+	if(r.hsp_num == 0) {
+		if (r.hit_num > 0)
+			out << "  </Hit_hsps>" << '\n' << "</Hit>" << '\n';
+		out << "<Hit>" << '\n'
+			<< "  <Hit_num>" << r.hit_num + 1 << "</Hit_num>" << '\n'
+			<< "  <Hit_id>gnl|BL_ORD_ID|" << r.orig_subject_id + 1 << "</Hit_id>" << '\n'
+			<< "  <Hit_def>";
+		const bool lt = (config.salltitles || (config.command == Config::view)) ? true : false;
+		this->print_salltitles(out, r.subject_name, lt, lt);
+		out << "</Hit_def> " << '\n'
+			<< "  <Hit_accession>" << r.orig_subject_id + 1 << "</Hit_accession>" << '\n'
+			<< "  <Hit_len>" << r.subject_len << "</Hit_len>" << '\n'
+			<< "  <Hit_hsps>" << '\n';
+	}
+
+	out << "    <Hsp>" << '\n'
+		<< "      <Hsp_num>" << r.hsp_num + 1 << "</Hsp_num>" << '\n'
+		<< "      <Hsp_bit-score>" << r.bit_score() << "</Hsp_bit-score>" << '\n'
+		<< "      <Hsp_score>" << r.score() << "</Hsp_score>" << '\n'
+		<< "      <Hsp_evalue>";
+	out.print_e(r.evalue());
+	out << "</Hsp_evalue>" << '\n'
+		<< "      <Hsp_query-from>" << r.query_source_range().begin_ + 1 << "</Hsp_query-from>" << '\n'
+		<< "      <Hsp_query-to>" << r.query_source_range().end_ + 1 << "</Hsp_query-to>" << '\n'
+		<< "      <Hsp_hit-from>" << r.subject_range().begin_ + 1 << "</Hsp_hit-from>" << '\n'
+		<< "      <Hsp_hit-to>" << r.subject_range().end_ << "</Hsp_hit-to>" << '\n'
+		<< "      <Hsp_query-frame>" << r.blast_query_frame() << "</Hsp_query-frame>" << '\n'
+		<< "      <Hsp_hit-frame>0</Hsp_hit-frame>" << '\n'
+		<< "      <Hsp_identity>" << r.identities() << "</Hsp_identity>" << '\n'
+		<< "      <Hsp_positive>" << r.positives() << "</Hsp_positive>" << '\n'
+		<< "      <Hsp_gaps>" << r.gaps() << "</Hsp_gaps>" << '\n'
+		<< "      <Hsp_align-len>" << r.length() << "</Hsp_align-len>" << '\n'
+		<< "         <Hsp_qseq>";
+
+	for (Hsp_context::Iterator i = r.begin(); i.good(); ++i)
+		out << i.query_char();
+		
+	out << "</Hsp_qseq>" << '\n'
+		<< "         <Hsp_hseq>";
+
+	for (Hsp_context::Iterator i = r.begin(); i.good(); ++i)
+		out << i.subject_char();
+
+	out << "</Hsp_hseq>" << '\n'
+		<< "      <Hsp_midline>";
+
+	for (Hsp_context::Iterator i = r.begin(); i.good(); ++i)
+		out << i.midline_char();
+
+	out << "</Hsp_midline>" << '\n'
+		<< "    </Hsp>" << '\n';
+}
+
+void XML_format::print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const
+{
+	std::stringstream ss;
+	ss << "<?xml version=\"1.0\"?>" << endl
+		<< "<!DOCTYPE BlastOutput PUBLIC \"-//NCBI//NCBI BlastOutput/EN\" \"http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd\">" << endl
+		<< "<BlastOutput>" << endl
+		<< "  <BlastOutput_program>" << mode_str(mode) << "</BlastOutput_program>" << endl
+		<< "  <BlastOutput_version>" << Const::program_name << ' ' << Const::version_string << "</BlastOutput_version>" << endl
+		<< "  <BlastOutput_reference>Benjamin Buchfink, Xie Chao, and Daniel Huson (2015), "Fast and sensitive protein alignment using DIAMOND", Nature Methods 12:59-60.</BlastOutput_reference>" << endl
+		<< "  <BlastOutput_db></BlastOutput_db>" << endl
+		<< "  <BlastOutput_query-ID>Query_1</BlastOutput_query-ID>" << endl
+		<< "  <BlastOutput_query-def>" << first_query_name << "</BlastOutput_query-def>" << endl
+		<< "  <BlastOutput_query-len>" << first_query_len << "</BlastOutput_query-len>" << endl
+		<< "  <BlastOutput_param>" << endl
+		<< "    <Parameters>" << endl
+		<< "      <Parameters_matrix>" << matrix << "</Parameters_matrix>" << endl
+		<< "      <Parameters_expect>" << evalue << "</Parameters_expect>" << endl
+		<< "      <Parameters_gap-open>" << gap_open << "</Parameters_gap-open>" << endl
+		<< "      <Parameters_gap-extend>" << gap_extend << "</Parameters_gap-extend>" << endl
+		<< "      <Parameters_filter></Parameters_filter>" << endl
+		<< "    </Parameters>" << endl
+		<< "  </BlastOutput_param>" << endl
+		<< "<BlastOutput_iterations>" << endl;
+	f.write(ss.str().c_str(), ss.str().length());
+}
+
+void XML_format::print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const
+{
+	out << "<Iteration>" << '\n'
+		<< "  <Iteration_iter-num>" << query_num+1 << "</Iteration_iter-num>" << '\n'
+		<< "  <Iteration_query-ID>Query_" << query_num+1 << "</Iteration_query-ID>" << '\n'
+		<< "  <Iteration_query-def>" << query_name << "</Iteration_query-def>" << '\n'
+		<< "  <Iteration_query-len>" << query_len << "</Iteration_query-len>" << '\n'
+		<< "<Iteration_hits>" << '\n';
+}
+
+void XML_format::print_query_epilog(Text_buffer &out, bool unaligned) const
+{
+	if (!unaligned) {
+		out << "  </Hit_hsps>" << '\n'
+			<< "</Hit>" << '\n';
+	}
+	((out << "</Iteration_hits>" << '\n'
+		<< "  <Iteration_stat>" << '\n'
+		<< "    <Statistics>" << '\n'
+		<< "      <Statistics_db-num>" << (size_t)ref_header.sequences << "</Statistics_db-num>" << '\n'
+		<< "      <Statistics_db-len>" << (size_t)config.db_size << "</Statistics_db-len>" << '\n'
+		<< "      <Statistics_hsp-len>0</Statistics_hsp-len>" << '\n'
+		<< "      <Statistics_eff-space>0</Statistics_eff-space>" << '\n'
+		<< "      <Statistics_kappa>").print_d(score_matrix.k()) << "</Statistics_kappa>" << '\n'
+		<< "      <Statistics_lambda>").print_d(score_matrix.lambda()) << "</Statistics_lambda>" << '\n'
+		<< "      <Statistics_entropy>0</Statistics_entropy>" << '\n'
+		<< "    </Statistics>" << '\n'
+		<< "  </Iteration_stat>" << '\n'
+		<< "</Iteration>" << '\n';
+}
+
+void XML_format::print_footer(Output_stream &f) const
+{
+	std::stringstream ss;
+	ss << "</BlastOutput_iterations>" << endl
+		<< "</BlastOutput>";
+	f.write(ss.str().c_str(), ss.str().length());
+}
\ No newline at end of file
diff --git a/src/output/output_format.h b/src/output/output_format.h
new file mode 100644
index 0000000..3047d65
--- /dev/null
+++ b/src/output/output_format.h
@@ -0,0 +1,146 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef OUTPUT_FORMAT_H_
+#define OUTPUT_FORMAT_H_
+
+#include <exception>
+#include "../basic/match.h"
+#include "../align/match_func.h"
+#include "../output/daa_file.h"
+#include "../output/daa_record.h"
+#include "../util/compressed_stream.h"
+#include "../basic/score_matrix.h"
+
+struct Output_format
+{
+	Output_format(unsigned code):
+		code(code)
+	{}
+	virtual void print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const
+	{}
+	virtual void print_query_epilog(Text_buffer &out, bool unaligned) const
+	{}
+	virtual void print_match(const Hsp_context& r, Text_buffer &out) const
+	{}
+	virtual void print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const
+	{ }
+	virtual void print_footer(Output_stream &f) const
+	{ }
+	virtual ~Output_format()
+	{ }
+	static void print_salltitles(Text_buffer &buf, const char *id, bool full_titles, bool all_titles)
+	{
+		if (!all_titles) {
+			buf.write_until(id, full_titles ? "\1" : Const::id_delimiters);
+			return;
+		}
+		if (strchr(id, '\1') == 0) {
+			buf.write_until(id, full_titles ? "\1" : Const::id_delimiters);
+			return;
+		}
+		//size_t n = 0;
+		const vector<string> t (tokenize(id, "\1"));
+		vector<string>::const_iterator i=t.begin();
+		for(;i<t.end()-1;++i) {
+			if (full_titles)
+				buf << *i << "<>";
+			else {
+				buf.write_until(i->c_str(), Const::id_delimiters);
+				buf << ";";
+			}
+			//n += i->length() + 2;
+		}
+		if(full_titles)
+			buf << *i;
+		else
+			buf.write_until(i->c_str(), Const::id_delimiters);
+		//n += i->length();
+		//return n;
+	}
+	operator unsigned() const
+	{
+		return code;
+	}
+	unsigned code;
+	enum { daa, blast_tab, blast_xml, sam, blast_pairwise };
+};
+
+extern auto_ptr<Output_format> output_format;
+
+struct DAA_format : public Output_format
+{
+	DAA_format():
+		Output_format(daa)
+	{}
+};
+
+struct Blast_tab_format : public Output_format
+{
+	static const char* field_str[];
+	Blast_tab_format();
+	virtual void print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const;
+	virtual void print_match(const Hsp_context& r, Text_buffer &out) const;
+	virtual ~Blast_tab_format()
+	{ }
+	vector<unsigned> fields;
+};
+
+struct Sam_format : public Output_format
+{
+	Sam_format():
+		Output_format(sam)
+	{ }
+	virtual void print_match(const Hsp_context& r, Text_buffer &out) const;
+	virtual void print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const;
+	virtual void print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const;
+	virtual ~Sam_format()
+	{ }
+};
+
+struct XML_format : public Output_format
+{
+	XML_format():
+		Output_format(blast_xml)
+	{}
+	virtual void print_match(const Hsp_context &r, Text_buffer &out) const;
+	virtual void print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const;
+	virtual void print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const;
+	virtual void print_query_epilog(Text_buffer &out, bool unaligned) const;
+	virtual void print_footer(Output_stream &f) const;
+	virtual ~XML_format()
+	{ }
+};
+
+struct Pairwise_format : public Output_format
+{
+	Pairwise_format() :
+		Output_format(blast_pairwise)
+	{}
+	virtual void print_match(const Hsp_context &r, Text_buffer &out) const;
+	virtual void print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const;
+	virtual void print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const;
+	virtual void print_query_epilog(Text_buffer &out, bool unaligned) const;
+	virtual void print_footer(Output_stream &f) const;
+	virtual ~Pairwise_format()
+	{ }
+};
+
+Output_format* get_output_format();
+
+#endif /* OUTPUT_FORMAT_H_ */
diff --git a/src/output/sam_format.cpp b/src/output/sam_format.cpp
new file mode 100644
index 0000000..61c29c3
--- /dev/null
+++ b/src/output/sam_format.cpp
@@ -0,0 +1,130 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "output_format.h"
+
+void print_md(const Hsp_context &r, Text_buffer &buf)
+{
+	unsigned matches = 0, del = 0;
+	for (Packed_transcript::Const_iterator i = r.begin_old(); i.good(); ++i) {
+		switch (i->op) {
+		case op_match:
+			del = 0;
+			matches += i->count;
+			break;
+		case op_insertion:
+			break;
+		case op_substitution:
+			if (matches > 0) {
+				buf << matches;
+				matches = 0;
+			}
+			else if (del > 0) {
+				buf << '0';
+				del = 0;
+			}
+			buf << value_traits.alphabet[(long)i->letter];
+			break;
+		case op_deletion:
+			if (matches > 0) {
+				buf << matches;
+				matches = 0;
+			}
+			if (del == 0)
+				buf << '^';
+			buf << value_traits.alphabet[(long)i->letter];
+			++del;
+		}
+	}
+	if (matches > 0)
+		buf << matches;
+}
+
+void print_cigar(const Hsp_context &r, Text_buffer &buf)
+{
+	static const unsigned map[] = { 0, 1, 2, 0 };
+	static const char letter[] = { 'M', 'I', 'D' };
+	unsigned n = 0, op = 0;
+	for (Packed_transcript::Const_iterator i = r.begin_old(); i.good(); ++i) {
+		if (map[i->op] == op)
+			n += i->count;
+		else {
+			if (n > 0)
+				buf << n << letter[op];
+			n = i->count;
+			op = map[i->op];
+		}
+	}
+	if (n > 0)
+		buf << n << letter[op];
+}
+
+void Sam_format::print_query_intro(size_t query_num, const char *query_name, unsigned query_len, Text_buffer &out, bool unaligned) const
+{
+	if (unaligned) {
+		out.write_until(query_name, Const::id_delimiters);
+		out << "\t4\t*\t0\t255\t*\t*\t0\t0\t*\t*\n";
+	}
+}
+
+void Sam_format::print_match(const Hsp_context& r, Text_buffer &out) const
+{
+	out.write_until(r.query_name, Const::id_delimiters);
+	out << '\t' << '0' << '\t';
+
+	const bool lt = (config.salltitles || (config.command == Config::view)) ? true : false;
+	this->print_salltitles(out, r.subject_name, lt, lt);
+
+	out << '\t'
+		<< r.subject_range().begin_ + 1 << '\t'
+		<< "255" << '\t';
+
+	print_cigar(r, out);
+
+	out << '\t'
+		<< '*' << '\t'
+		<< '0' << '\t'
+		<< '0' << '\t'
+		<< sequence(&r.query[r.query_range().begin_], r.query_range().length()) << '\t'
+		<< '*' << '\t'
+		<< "AS:i:" << (uint32_t)score_matrix.bitscore(r.score()) << '\t'
+		<< "NM:i:" << r.length() - r.identities() << '\t'
+		<< "ZL:i:" << r.subject_len << '\t'
+		<< "ZR:i:" << r.score() << '\t'
+		<< "ZE:f:";
+	out.print_e(score_matrix.evalue(r.score(), config.db_size, (unsigned)r.query.length()));
+	out << '\t'
+		<< "ZI:i:" << r.identities() * 100 / r.length() << '\t'
+		<< "ZF:i:" << blast_frame(r.frame()) << '\t'
+		<< "ZS:i:" << r.oriented_query_range().begin_ + 1 << '\t'
+		<< "MD:Z:";
+
+	print_md(r, out);
+	out << '\n';
+}
+
+void Sam_format::print_header(Output_stream &f, int mode, const char *matrix, int gap_open, int gap_extend, double evalue, const char *first_query_name, unsigned first_query_len) const
+{
+	static const char* mode_str[] = { 0, 0, "BlastP", "BlastX", "BlastN" };
+	string line = string("@HD\tVN:1.5\tSO:query\n\
+ at PG\tPN:DIAMOND\n\
+ at mm\t") + mode_str[mode] + "\n\
+ at CO\t" + mode_str[mode] + "-like alignments\n\
+ at CO\tReporting AS: bitScore, ZR: rawScore, ZE: expected, ZI: percent identity, ZL: reference length, ZF: frame, ZS: query start DNA coordinate\n";
+	f.write(line.c_str(), line.length());
+}
\ No newline at end of file
diff --git a/src/output/view.h b/src/output/view.h
new file mode 100644
index 0000000..7e6da26
--- /dev/null
+++ b/src/output/view.h
@@ -0,0 +1,149 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef VIEW_H_
+#define VIEW_H_
+
+#include "../basic/config.h"
+#include "../util/binary_file.h"
+#include "../util/text_buffer.h"
+#include "daa_file.h"
+#include "../util/binary_buffer.h"
+#include "output_format.h"
+#include "../util/task_queue.h"
+#include "../basic/score_matrix.h"
+#include "../util/thread.h"
+
+const unsigned view_buf_size = 32;
+
+struct View_writer
+{
+	View_writer():
+		f_ (config.compression == 1
+			? new Compressed_ostream(config.output_file)
+			: new Output_stream(config.output_file))
+	{ }
+	void operator()(Text_buffer &buf)
+	{
+		f_->write(buf.get_begin(), buf.size());
+		buf.clear();
+	}
+	~View_writer()
+	{
+		f_->close();
+	}
+	auto_ptr<Output_stream> f_;
+};
+
+struct View_fetcher
+{
+	View_fetcher(DAA_file &daa):
+		daa (daa)
+	{ }
+	bool operator()()
+	{
+		n = 0;
+		for(unsigned i=0;i<view_buf_size;++i)
+			if (!daa.read_query_buffer(buf[i], query_num)) {
+				query_num -= n - 1;
+				return false;
+			} else
+				++n;
+		query_num -= n - 1;
+		return true;
+	}
+	Binary_buffer buf[view_buf_size];
+	unsigned n;
+	size_t query_num;
+	DAA_file &daa;
+};
+
+void view_query(DAA_query_record &r, Text_buffer &out, const Output_format &format)
+{
+	format.print_query_intro(r.query_num, r.query_name.c_str(), (unsigned)r.query_len(), out, false);
+	for (DAA_query_record::Match_iterator i = r.begin(); i.good(); ++i) {
+		if (i->frame > 2 && config.forwardonly)
+			continue;
+		format.print_match(i->context(), out);
+	}
+	format.print_query_epilog(out, false);
+}
+
+struct View_context
+{
+	View_context(DAA_file &daa, View_writer &writer, const Output_format &format):
+		daa (daa),
+		writer (writer),
+		queue (3*config.threads_, writer),
+		format (format)
+	{ }
+	void operator()(unsigned thread_id)
+	{
+		try {
+			size_t n;
+			View_fetcher query_buf (daa);
+			Text_buffer *buffer = 0;
+			while(queue.get(n, buffer, query_buf)) {
+				for (unsigned j = 0; j < query_buf.n; ++j) {
+					DAA_query_record r(daa, query_buf.buf[j], query_buf.query_num + j);
+					view_query(r, *buffer, format);
+				}
+				queue.push(n);
+			}
+		} catch(std::exception &e) {
+			std::cout << e.what() << std::endl;
+			std::terminate();
+		}
+	}
+	DAA_file &daa;
+	View_writer &writer;
+	Task_queue<Text_buffer,View_writer> queue;
+	const Output_format &format;
+};
+
+void view()
+{
+	DAA_file daa (config.daa_file);
+	score_matrix = Score_matrix("", daa.lambda(), daa.kappa(), daa.gap_open_penalty(), daa.gap_extension_penalty());
+
+	message_stream << "Scoring parameters: " << score_matrix << endl;
+	verbose_stream << "Build version = " << daa.diamond_build() << endl;
+	message_stream << "DB sequences = " << daa.db_seqs() << endl;
+	message_stream << "DB sequences used = " << daa.db_seqs_used() << endl;
+	message_stream << "DB letters = " << daa.db_letters() << endl;
+	
+	task_timer timer("Generating output");
+	View_writer writer;
+	output_format = auto_ptr<Output_format>(get_output_format());
+
+	Binary_buffer buf;
+	size_t query_num;
+	daa.read_query_buffer(buf, query_num);
+	DAA_query_record r(daa, buf, query_num);
+	Text_buffer out;
+	view_query(r, out, *output_format);
+	
+	output_format->print_header(*writer.f_, daa.mode(), daa.score_matrix(), daa.gap_open_penalty(), daa.gap_extension_penalty(), daa.evalue(), r.query_name.c_str(), (unsigned)r.query_len());
+	writer(out);
+
+	View_context context(daa, writer, *output_format);
+	launch_thread_pool(context, config.threads_);
+	output_format->print_footer(*writer.f_);
+}
+
+#endif /* VIEW_H_ */
diff --git a/src/run/benchmark.cpp b/src/run/benchmark.cpp
new file mode 100644
index 0000000..aef448c
--- /dev/null
+++ b/src/run/benchmark.cpp
@@ -0,0 +1,320 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "../basic/sequence.h"
+#include "../data/sequence_set.h"
+#include "../dp/floating_sw.h"
+#include "../util/Timer.h"
+#include "../dp/dp.h"
+#include "../align/align.h"
+#include "../align/extend_ungapped.h"
+#include "../search/sse_dist.h"
+#include "../dp/score_profile.h"
+#include "../output/output_format.h"
+
+void benchmark_cmp()
+{
+#ifdef __SSE2__
+	const size_t n = 1000000000llu;
+	__m128i r1 = _mm_set_epi8(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
+	const __m128i r2 = _mm_set_epi8(0, 2, 3, 0, 0, 0, 0, 8, 0, 0, 0, 0, 13, 14, 0, 16);
+	Timer t;
+	t.start();
+	unsigned x = 0;
+	for (size_t i = 0; i < n; ++i) {
+		r1 = _mm_set_epi32(x, x, x, x);
+		//x += popcount32(_mm_movemask_epi8(_mm_cmpeq_epi8(r1, r2)));
+		x += _mm_movemask_epi8(_mm_cmpeq_epi8(r1, r2));
+	}
+	cout << "x=" << x << " t=" << t.getElapsedTimeInMicroSec() * 1000 / n << endl;
+#endif
+}
+
+int xdrop_ungapped2(const Letter *query, const Letter *subject)
+{
+	int score(0), st(0);
+
+	const Letter *q(query), *s(subject);
+
+	st = score;
+	while (score - st < config.raw_ungapped_xdrop
+		&& *q != '\xff'
+		&& *s != '\xff')
+	{
+		st += score_matrix(*q, *s);
+		//score = std::max(score, st);
+		++q;
+		++s;
+
+		st += score_matrix(*q, *s);
+		//score = std::max(score, st);
+		++q;
+		++s;
+
+		st += score_matrix(*q, *s);
+		score = std::max(score, st);
+		++q;
+		++s;
+	}
+	return score;
+}
+
+void benchmark_ungapped(const Sequence_set &ss, unsigned qa, unsigned sa)
+{
+	static const unsigned n = 10000000;
+	Timer t;
+	t.start();
+
+	const Letter *q = &ss[0][qa], *s = &ss[1][sa];
+	int score=0;
+
+	for (unsigned i = 0; i < n; ++i) {
+
+		score += xdrop_ungapped2(q, s);
+
+	}
+	t.stop();
+
+	cout << score << endl;
+	cout << " n/sec=" << (double)n / t.getElapsedTimeInSec() << endl;
+	cout << "t=" << t.getElapsedTimeInMicroSec() << endl;
+}
+
+void benchmark_greedy(const Sequence_set &ss, unsigned qa, unsigned sa)
+{
+	static const unsigned n = 100000;
+	vector<Diagonal_segment> d;
+	d.push_back(ungapped_extension(sa, qa, ss[0], ss[1]));
+	Long_score_profile qp(ss[0]);
+	//greedy_align(ss[0], qp, ss[1], d[0], true);
+	//greedy_align(ss[0], qp, ss[1], qa, sa, true);
+	Hsp_data hsp;
+	greedy_align2(ss[0], qp, ss[1], d, true, hsp);
+	Text_buffer buf;
+	Pairwise_format().print_match(Hsp_context(hsp, 0, ss[0], ss[0], "", 0, 0, "", 0, 0, 0), buf);
+	buf << '\0';
+	cout << buf.get_begin();
+
+	Timer t;
+	t.start();
+
+	for (unsigned i = 0; i < n; ++i) {
+
+		//greedy_align(ss[0], qp, ss[1], d[0], false);
+		//greedy_align(ss[0], qp, ss[1], qa, sa, false);
+		greedy_align2(ss[0], qp, ss[1], d, false, hsp);
+
+	}
+	t.stop();
+
+	cout << " usec=" << t.getElapsedTimeInSec() / (double)n * 1000000.0 << endl;
+	cout << "t=" << t.getElapsedTimeInMicroSec() << endl;
+}
+
+void benchmark_floating(const Sequence_set &ss, unsigned qa, unsigned sa)
+{
+	static const unsigned n = 10000;
+	uint64_t cell_updates = 0;
+	local_match hsp(0, 0, &ss[1][sa]);
+
+	{
+		Timer t;
+		t.start();
+
+		for (unsigned i = 0; i < n; ++i) {
+
+			floating_sw(&ss[0][qa],
+				hsp.subject_,
+				hsp,
+				32,
+				score_matrix.rawscore(config.gapped_xdrop),
+				config.gap_open + config.gap_extend,
+				config.gap_extend,
+				cell_updates,
+				hsp.query_anchor_,
+				hsp.subject_anchor,
+				No_score_correction(),
+				Score_only());
+
+		}
+		t.stop();
+
+		cout << hsp.score << ' ' << cell_updates << endl;
+		cout << "gcups=" << (double)cell_updates / 1e9 / t.getElapsedTimeInSec() << " n/sec=" << (double)n / t.getElapsedTimeInSec() << endl;
+	}
+}
+
+void benchmark_sw()
+{
+	Sequence_set ss;
+	vector<Letter> s1, s2;
+	unsigned qa = 0, sa = 0;
+	goto aln1;	
+	
+	/*
+	> d2va1a_ c.73.1.0 (A:) automated matches {Ureaplasma parvum [TaxId: 
+134821]}
+Length=234
+
+ Score = 26.2 bits (56),  Expect = 1.1
+ Identities = 18/66 (27%), Positives = 28/66 (42%), Gaps = 4/66 (6%)
+
+Query  24  QADATVATFFNGIDMPNQTNKTAA--FLCAALGGPNAWTGRNLKE--VHANMGVSNAQFT  79
+           Q D+++  F    D+  Q  K +    +   LGG N W G   KE  +  N+  +     
+Sbjct  16  QNDSSIIDFIKINDLAEQIEKISKKYIVSIVLGGGNIWRGSIAKELDMDRNLADNMGMMA  75
+
+Query  80  TVIGHL  85
+           T+I  L
+Sbjct  76  TIINGL  81	*/
+
+
+	s1 = sequence::from_string("SLFEQLGGQAAVQAVTAQFYANIQADATVATFFNGIDMPNQTNKTAAFLCAALGGPNAWTGRNLKEVHANMGVSNAQFTTVIGHLRSALTGAGVAAALVEQTVAVAETVRGDVVTV");
+	s2 = sequence::from_string("RKQRIVIKISGACLKQNDSSIIDFIKINDLAEQIEKISKKYIVSIVLGGGNIWRGSIAKELDMDRNLADNMGMMATIINGLALENALNHLNVNTIVLSAIKCDKLVHESSANNIKKAIEKEQVMIFVAGTGFPYFTTDSCAAIRAAETESSIILMGKNGVDGVYDSDPKINPNAQFYEHITFNMALTQNLKVMDATALALCQENNINLLVFNIDKPNAIVDVLEKKNKYTIVSK");
+	qa = 23;
+	sa = 15;
+	goto ende;	
+
+	/*
+
+	Query= d1g2na_ a.123.1.1 (A:) Ultraspiracle protein, usp {Tobacco budworm
+	(Heliothis virescens) [TaxId: 7102]}
+
+	> sp|Q6DHP9|RXRGB_DANRE Retinoic acid receptor RXR-gamma-B OS=Danio
+	rerio GN=rxrgb PE=2 SV=1
+	Length=452
+
+	Score = 189 bits (479),  Expect = 6e-055
+	Identities = 101/249 (41%), Positives = 153/249 (61%), Gaps = 24/249 (10%)
+
+	Query  4    QELSIERLLEMESLVADPSEEFQFLRVGPDSNVPPKFRAPVSSLCQIGNKQIAALVVWAR  63
+	            +++ ++++L+ E  V   +E +       +S+       PV+++C   +KQ+  LV WA+
+	Sbjct  221  EDMPVDKILDAELSVEPKTETYT------ESSPSNSTNDPVTNICHAADKQLFTLVEWAK  274
+
+	Query  64   DIPHFSQLEMEDQILLIKGSWNELLLFAIAWRSMEFLTEERDGVDGTGNRTTSPPQLMCL  123
+	             IPHFS L ++DQ++L++  WNELL+ + + RS+      +DG+               L
+	Sbjct  275  RIPHFSDLPLDDQVILLRAGWNELLIASFSHRSITV----KDGI--------------LL  316
+
+	Query  124  MPGMTLHRNSALQAGVGQIFDRVLSELSLKMRTLRVDQAEYVALKAIILLNPDVKGLKNR  183
+	              G+ +HR+SA  AGVG IF+RVL+EL  KM+ +++D+ E   L+AI+L NPD KGL N
+	Sbjct  317  GTGLHVHRSSAHSAGVGSIFNRVLTELVSKMKDMQMDKTELGCLRAIVLFNPDAKGLSNS  376
+
+	Query  184  QEVEVLREKMFLCLDEYCRRSRSSEEGRFAALLLRLPALRSISLKSFEHLFFFHLVADTS  243
+	             EVE LREK++  L+ Y ++    + GRFA LLLRLPALRSI LK  EHLFFF L+ DT
+	Sbjct  377  LEVEALREKVYASLETYTKQKYPDQPGRFAKLLLRLPALRSIGLKCLEHLFFFKLIGDTP  436
+
+	Query  244  IAGYIRDAL  252
+	            I  ++ + L
+	Sbjct  437  IDTFLMEML  445
+	*/
+
+	s1 = sequence::from_string("aavqelsierllemeslvadpseefqflrvgpdsnvppkfrapvsslcqignkqiaalvv\
+wardiphfsqlemedqillikgswnelllfaiawrsmeflteerdgvdgtgnrttsppql\
+mclmpgmtlhrnsalqagvgqifdrvlselslkmrtlrvdqaeyvalkaiillnpdvkgl\
+knrqevevlrekmflcldeycrrsrsseegrfaalllrlpalrsislksfehlfffhlva\
+dtsiagyirdalrnha");
+
+	s2 = sequence::from_string("MDTHDTYLHLHSSPLNSSPSQPPVMSSMVGHPSVISSSRPLPSPMSTLGSSMNGLPSPYS\
+VITPSLSSPSISLPSTPSMGFNTLNSPQMNSLSMNGNEDIKPPPGLAPLGNMSSYQCTSP\
+GSLSKHICAICGDRSSGKHYGVYSCEGCKGFFKRTIRKDLTYTCRDIKECLIDKRQRNRC\
+QYCRYQKCLAMGMKREAVQEERQRGKEKSDTEVETTSRFNEDMPVDKILDAELSVEPKTE\
+TYTESSPSNSTNDPVTNICHAADKQLFTLVEWAKRIPHFSDLPLDDQVILLRAGWNELLI\
+ASFSHRSITVKDGILLGTGLHVHRSSAHSAGVGSIFNRVLTELVSKMKDMQMDKTELGCL\
+RAIVLFNPDAKGLSNSLEVEALREKVYASLETYTKQKYPDQPGRFAKLLLRLPALRSIGL\
+KCLEHLFFFKLIGDTPIDTFLMEMLEAPHQIT");
+
+	qa = 3;
+	sa = 220;
+
+	goto ende;
+
+	/*Query= d1mpxa2 c.69.1.21 (A:24-404) Alpha-amino acid ester hydrolase
+	{Xanthomonas citri [TaxId: 346]}
+
+	> sp|Q9L9D7|COCE_RHOSM Cocaine esterase OS=Rhodococcus sp. (strain
+	MB1 Bresler) GN=cocE PE=1 SV=1
+	Length=574
+
+	Score = 94.0 bits (232),  Expect = 1e-019
+	Identities = 103/380 (27%), Positives = 157/380 (41%), Gaps = 51/380 (13%)
+
+	Query  20   NDYIKREVMIPMRDGVKLHTVIVLPKGAKNAPIVLTRTPYDASGRTERLA-SPHMKDLLS  78
+	            N  +   VM+PMRDGV+L   +  P      P++L R PYD   + +  A S    + L
+	Sbjct  5    NYSVASNVMVPMRDGVRLAVDLYRPDADGPVPVLLVRNPYD---KFDVFAWSTQSTNWLE  61
+
+	Query  79   AGDDVFVEGGYIRVFQDVRGKYGSEGDYVMTRPLRGPLNPSEVDHATDAWDTIDWLVKNV  138
+	                 FV  GY  V QD RG + SEG++V             VD   DA DT+ W+++
+	Sbjct  62   -----FVRDGYAVVIQDTRGLFASEGEFV-----------PHVDDEADAEDTLSWILEQ-  104
+
+	Query  139  SESNGKVGMIGSSYEGFTVVMALTNPHPALKVAVPESPMIDGWMGDDWFNYGAFRQVNFD  198
+	            +  +G VGM G SY G T   A  +    LK   P     D +    W  YG    ++ +
+	Sbjct  105  AWCDGNVGMFGVSYLGVTQWQAAVSGVGGLKAIAPSMASADLYRA-PW--YGPGGALSVE  161
+
+	Query  199  YFTGQLSKRGKGAGIARQG--HDDYSNFLQ-AGSAGDFAKAAGLEQL----------PW-  244
+	               G  +  G G   +R     +D ++F+Q A    D A AA +  L          PW
+	Sbjct  162  ALLGWSALIGTGLITSRSDARPEDAADFVQLAAILNDVAGAASVTPLAEQPLLGRLIPWV  221
+
+	Query  245  WHKLTEHAAYDAFWQEQALDKVMA--RTPLKVPTMWLQGLWDQEDMWGAIHSYAAMEPRD  302
+	              ++ +H   D  WQ  +L + +    TP  +   W  G   +     ++ ++ A+
+	Sbjct  222  IDQVVDHPDNDESWQSISLFERLGGLATPALITAGWYDGFVGE-----SLRTFVAV----  272
+
+	Query  303  KRNTLNYLVMGPWRHSQVNYDGSALGALNFEGDTARQFRHDVLRPFFDQYL-VDGAPKAD  361
+	            K N    LV+GPW HS +    +A            Q    + + FFD++L  +    A
+	Sbjct  273  KDNADARLVVGPWSHSNLT-GRNADRKFGIAATYPIQEATTMHKAFFDRHLRGETDALAG  331
+
+	Query  362  TPPVFIYNTGENHWDRLKAW  381
+	             P V ++  G + W     W
+	Sbjct  332  VPKVRLFVMGIDEWRDETDW  351
+
+	*/
+
+
+
+aln1:
+	s1 = sequence::from_string("tspmtpditgkpfvaadasndyikrevmipmrdgvklhtvivlpkgaknapivltrtpyd\
+asgrterlasphmkdllsagddvfveggyirvfqdvrgkygsegdyvmtrplrgplnpse\
+vdhatdawdtidwlvknvsesngkvgmigssyegftvvmaltnphpalkvavpespmidg\
+wmgddwfnygafrqvnfdyftgqlskrgkgagiarqghddysnflqagsagdfakaagle\
+qlpwwhkltehaaydafwqeqaldkvmartplkvptmwlqglwdqedmwgaihsyaamep\
+rdkrntlnylvmgpwrhsqvnydgsalgalnfegdtarqfrhdvlrpffdqylvdgapka\
+dtppvfiyntgenhwdrlkaw");
+
+	s2 = sequence::from_string("MVDGNYSVASNVMVPMRDGVRLAVDLYRPDADGPVPVLLVRNPYDKFDVFAWSTQSTNWL\
+EFVRDGYAVVIQDTRGLFASEGEFVPHVDDEADAEDTLSWILEQAWCDGNVGMFGVSYLG\
+VTQWQAAVSGVGGLKAIAPSMASADLYRAPWYGPGGALSVEALLGWSALIGTGLITSRSD\
+ARPEDAADFVQLAAILNDVAGAASVTPLAEQPLLGRLIPWVIDQVVDHPDNDESWQSISL\
+FERLGGLATPALITAGWYDGFVGESLRTFVAVKDNADARLVVGPWSHSNLTGRNADRKFG\
+IAATYPIQEATTMHKAFFDRHLRGETDALAGVPKVRLFVMGIDEWRDETDWPLPDTAYTP\
+FYLGGSGAANTSTGGGTLSTSISGTESADTYLYDPADPVPSLGGTLLFHNGDNGPADQRP\
+IHDRDDVLCYSTEVLTDPVEVTGTVSARLFVSSSAVDTDFTAKLVDVFPDGRAIALCDGI\
+VRMRYRETLVNPTLIEAGEIYEVAIDMLATSNVFLPGHRIMVQVSSSNFPKYDRNSNTGG\
+VIAREQLEEMCTAVNRIHRGPEHPSHIVLPIIKR");
+
+	qa = 19;
+	sa = 4;
+
+	ende:
+	ss.push_back(s1);
+	ss.push_back(s2);
+	ss.finish_reserve();
+
+	//benchmark_floating(ss, qa, sa);
+	benchmark_greedy(ss, qa, sa);
+	//benchmark_cmp();
+	//benchmark_ungapped(ss, qa, sa);
+
+}
\ No newline at end of file
diff --git a/src/run/double_indexed.cpp b/src/run/double_indexed.cpp
new file mode 100644
index 0000000..4349b0f
--- /dev/null
+++ b/src/run/double_indexed.cpp
@@ -0,0 +1,305 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <iostream>
+#include <limits>
+#include "../data/reference.h"
+#include "../data/queries.h"
+#include "../basic/statistics.h"
+#include "../basic/shape_config.h"
+#include "../align/align_queries.h"
+#include "../search/align_range.h"
+#include "../util/seq_file_format.h"
+#include "../data/load_seqs.h"
+#include "../output/output_format.h"
+#include "../data/frequent_seeds.h"
+#include "../output/daa_write.h"
+
+using std::endl;
+using std::cout;
+
+struct Search_context
+{
+	Search_context(unsigned sid, const sorted_list &ref_idx, const sorted_list &query_idx) :
+		sid(sid),
+		ref_idx(ref_idx),
+		query_idx(query_idx)
+	{ }
+	void operator()(unsigned thread_id, unsigned seedp) const
+	{
+		Statistics stat;
+		align_partition(seedp,
+			stat,
+			sid,
+			ref_idx.get_partition_cbegin(seedp),
+			query_idx.get_partition_cbegin(seedp),
+			thread_id);
+		statistics += stat;
+	}
+	const unsigned sid;
+	const sorted_list &ref_idx;
+	const sorted_list &query_idx;
+};
+
+void process_shape(unsigned sid,
+	Timer &timer_mapping,
+	unsigned query_chunk,
+	char *query_buffer,
+	char *ref_buffer)
+{
+	using std::vector;
+
+	::partition<unsigned> p(Const::seedp, config.lowmem);
+	for (unsigned chunk = 0; chunk < p.parts; ++chunk) {
+
+		message_stream << "Processing query chunk " << query_chunk << ", reference chunk " << current_ref_block << ", shape " << sid << ", index chunk " << chunk << '.' << endl;
+		const seedp_range range(p.getMin(chunk), p.getMax(chunk));
+		current_range = range;
+
+		task_timer timer("Building reference index", true);
+		sorted_list ref_idx(ref_buffer,
+			*ref_seqs::data_,
+			shapes[sid],
+			ref_hst.get(sid),
+			range,
+			ref_hst.partition());
+
+		timer.go("Building query index");
+		timer_mapping.resume();
+		sorted_list query_idx(query_buffer,
+			*query_seqs::data_,
+			shapes[sid],
+			query_hst.get(sid),
+			range,
+			query_hst.partition());
+
+		timer.go("Building seed filter");
+		frequent_seeds.build(sid, range, ref_idx, query_idx);
+
+		timer.go("Searching alignments");
+		Search_context context(sid, ref_idx, query_idx);
+		launch_scheduled_thread_pool(context, Const::seedp, config.threads_);
+	}
+	timer_mapping.stop();
+}
+
+void run_ref_chunk(Database_file &db_file,
+	Timer &timer_mapping,
+	Timer &total_timer,
+	unsigned query_chunk,
+	pair<size_t, size_t> query_len_bounds,
+	char *query_buffer,
+	Output_stream &master_out,
+	vector<Temp_file> &tmp_file)
+{
+	task_timer timer("Building reference histograms");
+	const pair<size_t, size_t> len_bounds = ref_seqs::data_->len_bounds(shapes[0].length_);
+	ref_hst = Partitioned_histogram(*ref_seqs::data_, (unsigned)len_bounds.second);
+
+	ref_map.init((unsigned)ref_seqs::get().get_length());
+
+	timer.go("Allocating buffers");
+	char *ref_buffer = sorted_list::alloc_buffer(ref_hst);
+
+	timer.go("Initializing temporary storage");
+	timer_mapping.resume();
+	Trace_pt_buffer::instance = new Trace_pt_buffer(query_seqs::data_->get_length() / align_mode.query_contexts,
+		config.tmpdir,
+		config.mem_buffered());
+	timer.finish();
+	timer_mapping.stop();
+
+	for (unsigned i = 0; i<shapes.count(); ++i)
+		process_shape(i, timer_mapping, query_chunk, query_buffer, ref_buffer);
+
+	/*timer.go("Closing temporary storage");
+	Trace_pt_buffer::instance->close();*/
+
+	timer.go("Deallocating buffers");
+	delete[] ref_buffer;
+
+	timer_mapping.resume();
+	Output_stream* out;
+	if (blocked_processing) {
+		timer.go("Opening temporary output file");
+		tmp_file.push_back(Temp_file());
+		out = new Output_stream(tmp_file.back());
+	}
+	else
+		out = &master_out;
+
+	timer.go("Computing alignments");
+	align_queries(*Trace_pt_buffer::instance, out);
+	delete Trace_pt_buffer::instance;
+
+	if (blocked_processing) {
+		Intermediate_record::finish_file(*out);
+		delete out;
+	}
+	timer_mapping.stop();
+
+	timer.go("Deallocating reference");
+	delete ref_seqs::data_;
+	delete ref_ids::data_;
+	timer.finish();
+}
+
+void run_query_chunk(Database_file &db_file,
+	Timer &timer_mapping,
+	Timer &total_timer,
+	unsigned query_chunk,
+	pair<size_t, size_t> query_len_bounds,
+	Output_stream &master_out,
+	Output_stream *unaligned_file)
+{
+	task_timer timer("Allocating buffers", true);
+	char *query_buffer = sorted_list::alloc_buffer(query_hst);
+	vector<Temp_file> tmp_file;
+	query_aligned.clear();
+	query_aligned.insert(query_aligned.end(), query_ids::get().get_length(), false);
+	timer.finish();
+
+	db_file.rewind();
+	for (current_ref_block = 0; db_file.load_seqs(); ++current_ref_block)
+		run_ref_chunk(db_file, timer_mapping, total_timer, query_chunk, query_len_bounds, query_buffer, master_out, tmp_file);
+
+	timer.go("Deallocating buffers");
+	timer_mapping.resume();
+	delete[] query_buffer;
+
+	if (blocked_processing) {
+		timer.go("Joining output blocks");
+		join_blocks(current_ref_block, master_out, tmp_file);
+	}
+
+	if (unaligned_file) {
+		timer.go("Writing unaligned queries");
+		write_unaligned(unaligned_file);
+	}
+
+	timer.go("Deallocating queries");
+	delete query_seqs::data_;
+	delete query_ids::data_;
+	delete query_source_seqs::data_;
+	timer_mapping.stop();
+}
+
+void master_thread(Database_file &db_file, Timer &timer_mapping, Timer &total_timer)
+{
+	task_timer timer("Opening the input file", true);
+	timer_mapping.start();
+	auto_ptr<Input_stream> query_file(Compressed_istream::auto_detect(config.query_file));
+	const Sequence_file_format *format_n(guess_format(*query_file));
+
+	current_query_chunk = 0;
+
+	timer.go("Opening the output file");
+	auto_ptr<Output_stream> master_out(config.compression == 1
+		? new Compressed_ostream(config.output_file)
+		: new Output_stream(config.output_file));
+	if (*output_format == Output_format::daa)
+		init_daa(*master_out);
+	auto_ptr<Output_stream> unaligned_file;
+	if (!config.unaligned.empty())
+		unaligned_file = auto_ptr<Output_stream>(new Output_stream(config.unaligned));
+	timer_mapping.stop();
+	timer.finish();
+
+	for (;; ++current_query_chunk) {
+		task_timer timer("Loading query sequences", true);
+		timer_mapping.resume();
+		size_t n_query_seqs;
+		n_query_seqs = load_seqs(*query_file, *format_n, &query_seqs::data_, query_ids::data_, query_source_seqs::data_, (size_t)(config.chunk_size * 1e9));
+		if (n_query_seqs == 0)
+			break;
+		timer.finish();
+		query_seqs::data_->print_stats();
+
+		if (current_query_chunk == 0 && *output_format != Output_format::daa)
+			output_format->print_header(*master_out, align_mode.mode, config.matrix.c_str(), config.gap_open, config.gap_extend, config.max_evalue, query_ids::get()[0].c_str(),
+				unsigned(align_mode.query_translated ? query_source_seqs::get()[0].length() : query_seqs::get()[0].length()));
+
+		if (align_mode.sequence_type == amino_acid && config.seg == "yes") {
+			timer.go("Running complexity filter");
+			Complexity_filter::get().run(*query_seqs::data_);
+		}
+
+		timer.go("Building query histograms");
+		const pair<size_t, size_t> query_len_bounds = query_seqs::data_->len_bounds(shapes[0].length_);
+		setup_search_params(query_len_bounds, 0);
+		query_hst = Partitioned_histogram(*query_seqs::data_, (unsigned)query_len_bounds.second);
+		timer_mapping.stop();
+		timer.finish();
+		//const bool long_addressing_query = query_seqs::data_->raw_len() > (size_t)std::numeric_limits<uint32_t>::max();
+
+		run_query_chunk(db_file, timer_mapping, total_timer, current_query_chunk, query_len_bounds, *master_out, unaligned_file.get());
+	}
+
+	timer.go("Closing the input file");
+	query_file->close();
+
+	timer.go("Closing the output file");
+	timer_mapping.resume();
+	if (*output_format == Output_format::daa)
+		finish_daa(*master_out);
+	else
+		output_format->print_footer(*master_out);
+	master_out->close();
+	if (unaligned_file.get())
+		unaligned_file->close();
+	timer_mapping.stop();
+
+	timer.go("Closing the database file");
+	db_file.close();
+
+	timer.finish();
+	message_stream << "Total time = " << total_timer.getElapsedTimeInSec() << "s" << endl;
+	verbose_stream << "Mapping time = " << timer_mapping.getElapsedTimeInSec() << "s" << endl;
+	statistics.print();
+}
+
+void master_thread_di()
+{
+	Timer timer2, timer_mapping;
+	timer2.start();
+
+	align_mode = Align_mode(Align_mode::from_command(config.command));
+	output_format = auto_ptr<Output_format>(get_output_format());
+
+	message_stream << "Temporary directory: " << Temp_file::get_temp_dir() << endl;
+
+	if (config.mode_very_sensitive) {
+		Config::set_option(config.chunk_size, 0.4);
+		Config::set_option(config.lowmem, 1u);
+	}
+	else {
+		Config::set_option(config.chunk_size, 2.0);
+		Config::set_option(config.lowmem, 4u);
+	}
+
+	task_timer timer("Opening the database", 1);
+	Database_file db_file;
+	timer.finish();
+	verbose_stream << "Reference = " << config.database << endl;
+	verbose_stream << "Sequences = " << ref_header.sequences << endl;
+	verbose_stream << "Letters = " << ref_header.letters << endl;
+	verbose_stream << "Block size = " << (size_t)(config.chunk_size * 1e9) << endl;
+	Config::set_option(config.db_size, (uint64_t)ref_header.letters);
+
+	master_thread(db_file, timer_mapping, timer2);
+}
\ No newline at end of file
diff --git a/src/run/main.cpp b/src/run/main.cpp
new file mode 100644
index 0000000..5b8df8e
--- /dev/null
+++ b/src/run/main.cpp
@@ -0,0 +1,108 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <iostream>
+#include "../basic/config.h"
+#include "../output/view.h"
+#include "tools.h"
+#include "../extra/compare.h"
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+void run_mapper();
+void master_thread_di();
+void model_seqs();
+
+int main(int ac, const char* av[])
+{
+
+	try {
+
+		config = Config(ac, av);
+
+		switch (config.command) {
+		case Config::help:
+			break;
+		case Config::version:
+			cout << Const::program_name << " version " << Const::version_string << endl;
+			break;
+		case Config::makedb:
+			make_db();
+			break;
+		case Config::blastp:
+		case Config::blastx:
+			if (config.algo == Config::subject_indexed)
+				run_mapper();
+			else
+				master_thread_di();
+			break;
+		case Config::view:
+			view();
+			break;
+		case Config::getseq:
+			get_seq();
+			break;
+		case Config::benchmark:
+			benchmark_sw();
+			break;
+		case Config::random_seqs:
+			random_seqs();
+			break;
+		case Config::compare:
+			compare();
+			break;
+		case Config::sort:
+			sort_file();
+			break;
+		case Config::roc:
+			roc();
+			break;
+		case Config::db_stat:
+			db_stat();
+			break;
+		case Config::model_sim:
+			model_sim();
+			break;
+		case Config::match_file_stat:
+			match_file_stat();
+			break;
+		case Config::model_seqs:
+			model_seqs();
+			break;
+		default:
+			return 1;
+		}
+	}
+	catch(std::bad_alloc &e) {
+		cerr << "Failed to allocate sufficient memory. Please refer to the manual for instructions on memory usage." << endl;
+		log_stream << "Error: " << e.what() << endl;
+		return 1;
+	} catch(std::exception& e) {
+        cerr << "Error: " << e.what() << endl;
+        log_stream << "Error: " << e.what() << endl;
+        return 1;
+    }
+    catch(...) {
+        cerr << "Exception of unknown type!" << endl;
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/src/run/mapper.cpp b/src/run/mapper.cpp
new file mode 100644
index 0000000..8d8e395
--- /dev/null
+++ b/src/run/mapper.cpp
@@ -0,0 +1,112 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <numeric>
+#include "../data/reference.h"
+#include "../output/output_format.h"
+#include "../util/seq_file_format.h"
+#include "../data/queries.h"
+#include "../output/daa_write.h"
+#include "../data/load_seqs.h"
+#include "../data/index.h"
+
+void search_query_worker(Atomic<unsigned> *next);
+
+void run_query_chunk(Output_stream &master_out)
+{
+	task_timer timer("Computing alignments");
+	Thread_pool threads;
+	Atomic<unsigned> query (0);
+	for (unsigned i = 0; i < config.threads_; ++i)
+		threads.push_back(launch_thread(search_query_worker, &query));
+	threads.join_all();
+}
+
+void run_ref_chunk(Input_stream &query_file, const Sequence_file_format &input_format, Output_stream &master_out)
+{	
+	task_timer timer("Building database index");
+	shape_from = 0;
+	shape_to = 1;
+	build_index(ref_seqs::get());
+	timer.finish();
+
+	query_file.rewind();
+
+	for (current_query_chunk = 0;; ++current_query_chunk) {
+		task_timer timer("Loading query sequences", true);
+		size_t n_query_seqs;
+		n_query_seqs = load_seqs(query_file, input_format, &query_seqs::data_, query_ids::data_, query_source_seqs::data_, (size_t)(config.chunk_size * 1e9));
+		if (n_query_seqs == 0)
+			break;
+		timer.finish();
+		query_seqs::data_->print_stats();
+		run_query_chunk(master_out);
+	}
+
+	timer.go("Deallocating memory");
+	for (unsigned i = 0; i < shapes.count(); ++i)
+		assign_ptr(seed_index[i], new Seed_index());
+}
+
+void run_mapper(Database_file &db_file, Timer &total_timer)
+{
+	task_timer timer("Opening the input file", true);
+	auto_ptr<Input_stream> query_file(Compressed_istream::auto_detect(config.query_file));
+	const Sequence_file_format *format_n(guess_format(*query_file));
+
+	timer.go("Opening the output file");
+	auto_ptr<Output_stream> master_out(config.compression == 1
+		? new Compressed_ostream(config.output_file)
+		: new Output_stream(config.output_file));
+	timer.finish();
+
+	for (current_ref_block = 0; db_file.load_seqs(); ++current_ref_block)
+		run_ref_chunk(*query_file, *format_n, *master_out);
+
+	timer.go("Closing the output file");
+	master_out->close();
+	
+	timer.go("Closing the database file");
+	db_file.close();
+
+	timer.finish();
+	message_stream << "Total wall clock time: " << total_timer.getElapsedTimeInSec() << "s" << endl;
+	statistics.print();
+}
+
+void run_mapper()
+{
+	Timer timer2;
+	timer2.start();
+
+	Reduction::reduction = Reduction("A KR EDNQ C G H ILVM FYW P ST");
+
+	align_mode = Align_mode(Align_mode::from_command(config.command));
+	output_format = auto_ptr<Output_format>(get_output_format());
+
+	message_stream << "Temporary directory: " << Temp_file::get_temp_dir() << endl;
+
+	task_timer timer("Opening the database", 1);
+	Database_file db_file;
+	timer.finish();
+	message_stream << "Reference: " << config.database <<  " (" << ref_header.sequences << " sequences, " << ref_header.letters << " letters)" << endl;
+	verbose_stream << "Block size: " << (size_t)(config.chunk_size * 1e9) << endl;
+	Config::set_option(config.db_size, (uint64_t)ref_header.letters);
+
+	run_mapper(db_file, timer2);
+}
diff --git a/src/run/tools.cpp b/src/run/tools.cpp
new file mode 100644
index 0000000..b5e4e9e
--- /dev/null
+++ b/src/run/tools.cpp
@@ -0,0 +1,107 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <set>
+#include "tools.h"
+#include "../basic/config.h"
+#include "../data/sequence_set.h"
+#include "../util/seq_file_format.h"
+#include "../data/queries.h"
+#include "../data/load_seqs.h"
+#include "../data/reference.h"
+#include "../extra/match_file.h"
+
+void get_seq()
+{
+	Database_file db_file;
+	db_file.get_seq();
+}
+
+void random_seqs()
+{
+	Database_file db_file;
+	db_file.load_seqs();
+	cout << "Sequences = " << ref_seqs::get().get_length() << endl;
+	std::set<unsigned> n;
+	const size_t count = atoi(config.seq_no[0].c_str());
+	while (n.size() < count)
+		n.insert((rand()*RAND_MAX + rand()) % ref_seqs::get().get_length());
+	Output_stream out(config.output_file);
+	unsigned j = 0;
+	
+	std::string s;
+	for (std::set<unsigned>::const_iterator i = n.begin(); i != n.end(); ++i) {
+		std::stringstream ss;
+		ss << '>' << j++ << endl;
+		if (config.reverse)
+			ref_seqs::get()[*i].print(ss, value_traits, sequence::Reversed());
+		else
+			ss << ref_seqs::get()[*i];
+		ss << endl;
+		s = ss.str();
+		out.write(s.data(), s.length());
+	}
+	out.close();
+}
+
+void sort_file()
+{
+	Input_stream f(config.query_file);
+	vector<Pair<unsigned, string> > data;
+	while (f.getline(), !f.eof()) {
+		unsigned query;
+		sscanf(f.line.c_str(), "%u", &query);
+		data.push_back(Pair<unsigned, string>(query, f.line));
+	}
+	std::stable_sort(data.begin(), data.end());
+	for (vector<Pair<unsigned, string> >::const_iterator i = data.begin(); i != data.end(); ++i)
+		cout << i->second << endl;
+	f.close();
+}
+
+void db_stat()
+{
+	Database_file db_file;
+	db_file.load_seqs();
+	cout << "Sequences = " << ref_seqs::get().get_length() << endl;
+
+	size_t letters = 0;
+	vector<size_t> letter_freq(20);
+	for (size_t i = 0; i < ref_seqs::get().get_length(); ++i) {
+		const sequence seq = ref_seqs::get()[i];
+		for (size_t j = 0; j < seq.length(); ++j) {
+			if (seq[j] < 20) {
+				++letters;
+				++letter_freq[(int)seq[j]];
+			}
+		}
+	}
+	cout << "Frequencies = ";
+	for (vector<size_t>::const_iterator i = letter_freq.begin(); i != letter_freq.end(); ++i)
+		cout << (double)*i / letters << ',';
+	cout << endl;
+
+}
+
+void match_file_stat()
+{
+	match_file file(config.match_file1.c_str());
+	blast_match match;
+	while (file.get(match, blast_format()));
+	file.get_subst();
+}
\ No newline at end of file
diff --git a/src/run/tools.h b/src/run/tools.h
new file mode 100644
index 0000000..b714b61
--- /dev/null
+++ b/src/run/tools.h
@@ -0,0 +1,31 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef TOOLS_H_
+#define TOOLS_H_
+
+void get_seq();
+void benchmark_sw();
+void random_seqs();
+void sort_file();
+void roc();
+void db_stat();
+void model_sim();
+void match_file_stat();
+
+#endif
\ No newline at end of file
diff --git a/src/search/align_range.h b/src/search/align_range.h
new file mode 100644
index 0000000..1868ba8
--- /dev/null
+++ b/src/search/align_range.h
@@ -0,0 +1,126 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef ALIGN_RANGE_H_
+#define ALIGN_RANGE_H_
+
+#include "../basic/statistics.h"
+#include "../data/sorted_list.h"
+#include "../search/trace_pt_buffer.h"
+#include "sse_dist.h"
+#include "../dp/dp.h"
+
+void setup_search_params(pair<size_t, size_t> query_len_bounds, size_t chunk_db_letters);
+
+struct Stage1_hit
+{
+	Stage1_hit(unsigned q_ref, unsigned q_offset, unsigned s_ref, unsigned s_offset) :
+		q(q_ref + q_offset),
+		s(s_ref + s_offset)
+	{}
+	bool operator<(const Stage1_hit &rhs) const
+	{
+		return q < rhs.q;
+	}
+	struct Query
+	{
+		unsigned operator()(const Stage1_hit &x) const
+		{
+			return x.q;
+		}
+	};
+	unsigned q, s;
+};
+
+inline int stage2_ungapped(const Letter *query, const Letter *subject, unsigned sid, unsigned &delta, unsigned &len)
+{
+	return xdrop_ungapped(query, subject, shapes[sid].length_, delta, len);
+}
+
+struct Range_ref
+{
+	Range_ref(vector<Finger_print>::const_iterator q_begin, vector<Finger_print>::const_iterator s_begin) :
+		q_begin(q_begin),
+		s_begin(s_begin)
+	{}
+	const vector<Finger_print>::const_iterator q_begin, s_begin;
+};
+
+struct Seed_filter
+{
+	Seed_filter(Statistics &stats, Trace_pt_buffer::Iterator &out, const unsigned sid) :
+		vq(TLS::get(vq_ptr)),
+		vs(TLS::get(vs_ptr)),
+		hits(TLS::get(hits_ptr)),
+		stats(stats),
+		out(out),
+		sid(sid)
+	{}
+	void run(const sorted_list::const_iterator &q, const sorted_list::const_iterator &s);
+	void tiled_search(vector<Finger_print>::const_iterator q,
+		vector<Finger_print>::const_iterator q_end,
+		vector<Finger_print>::const_iterator s,
+		vector<Finger_print>::const_iterator s_end,
+		const Range_ref &ref,
+		unsigned level);
+
+	static TLS_PTR vector<Finger_print> *vq_ptr, *vs_ptr;
+	static TLS_PTR vector<Stage1_hit> *hits_ptr;
+	vector<Finger_print> &vq, &vs;
+	vector<Stage1_hit> &hits;
+	Statistics &stats;
+	Trace_pt_buffer::Iterator &out;
+	const unsigned sid;
+};
+
+void stage2_search(const sorted_list::const_iterator &q,
+	const sorted_list::const_iterator &s,
+	const vector<Stage1_hit> &hits,
+	Statistics &stats,
+	Trace_pt_buffer::Iterator &out,
+	const unsigned sid);
+
+inline void align_partition(unsigned hp,
+		Statistics &stats,
+		unsigned sid,
+		sorted_list::const_iterator i,
+		sorted_list::const_iterator j,
+		unsigned thread_id)
+{
+#ifndef SIMPLE_SEARCH
+	if (hp > 0)
+		return;
+#endif
+	Trace_pt_buffer::Iterator* out = new Trace_pt_buffer::Iterator (*Trace_pt_buffer::instance, thread_id);
+	Seed_filter seed_filter(stats, *out, sid);
+	while(!i.at_end() && !j.at_end()) {
+		if(i.key() < j.key()) {
+			++i;
+		} else if(j.key() < i.key()) {
+			++j;
+		} else {
+			if(i[0] != 0)
+				seed_filter.run(j, i);
+			++i;
+			++j;
+		}
+	}
+	delete out;
+}
+
+#endif /* ALIGN_RANGE_H_ */
diff --git a/src/search/collision.cpp b/src/search/collision.cpp
new file mode 100644
index 0000000..edc3d2e
--- /dev/null
+++ b/src/search/collision.cpp
@@ -0,0 +1,116 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "collision.h"
+#include "align_range.h"
+
+// #define NO_COLLISION_FILTER
+
+bool verify_hit(const Letter *query, const Letter *subject, unsigned sid)
+{
+	const Finger_print fq(query), fs(subject);
+	if (fq.match(fs) < config.min_identities)
+		return false;
+	unsigned delta, len;
+	return stage2_ungapped(query, subject, sid, delta, len) >= config.min_ungapped_raw_score;
+}
+
+inline bool match_shape_mask(const uint64_t mask, const uint64_t shape_mask)
+{
+	return (mask & shape_mask) == shape_mask;
+}
+
+inline bool is_lower_chunk(const Letter *subject, unsigned sid)
+{
+	Packed_seed seed;
+	shapes[sid].set_seed(seed, subject);
+	return current_range.lower(seed_partition(seed));
+}
+
+inline bool is_lower_or_equal_chunk(const Letter *subject, unsigned sid)
+{
+	Packed_seed seed;
+	shapes[sid].set_seed(seed, subject);
+	return current_range.lower_or_equal(seed_partition(seed));
+}
+
+inline bool is_high_frequency(const Letter *subject, unsigned sid, bool previous_shape)
+{
+	return frequent_seeds.get(subject, sid);
+}
+
+inline bool shape_collision_right(uint64_t mask, uint64_t shape_mask, const Letter *subject, unsigned sid)
+{
+	if (!match_shape_mask(mask, shape_mask)) return false;
+	return is_lower_chunk(subject, sid)
+		&& !is_high_frequency(subject, sid, false);
+}
+
+inline bool shape_collision_left(uint64_t mask, uint64_t shape_mask, const Letter *subject, unsigned sid, bool chunked)
+{
+	if (!match_shape_mask(mask, shape_mask)) return false;
+	return (!chunked || is_lower_or_equal_chunk(subject, sid))
+		&& !is_high_frequency(subject, sid, false);
+}
+
+inline bool previous_shape_collision(uint64_t mask, uint64_t shape_mask, const Letter *subject, unsigned sid)
+{
+	if (!match_shape_mask(mask, shape_mask)) return false;
+	return !is_high_frequency(subject, sid, true);
+}
+
+bool is_primary_hit(const Letter *query,
+	const Letter *subject,
+	const unsigned seed_offset,
+	const unsigned sid,
+	const unsigned len)
+{
+#ifdef NO_COLLISION_FILTER
+	return true;
+#endif
+	assert(len > 0 && len <= config.window * 2);
+	const bool chunked(config.lowmem > 1);
+	uint64_t mask = reduced_match32(query, subject, len);
+	unsigned i = 0;
+	uint64_t current_mask = shapes[sid].mask_;
+	unsigned shape_len = len - shapes[0].length_ + 1;
+	while (i < shape_len) {
+		if (len - i > 32)
+			mask |= reduced_match32(query + 32, subject + 32, len - i - 32) << 32;
+		for (unsigned j = 0; j < 32 && i < shape_len; ++j) {
+			/*cout << sequence(&query[j], len - j) << endl;
+			cout << sequence(&subject[j], len - j) << endl;
+			print_binary(mask);
+			cout << endl;*/
+			for (unsigned k = 0; k < sid; ++k)
+				if (previous_shape_collision(mask, shapes[k].mask_, &subject[j], k) && verify_hit(&query[j], &subject[j], k)) {
+					//cout << "k=" << k << endl;
+					return false;
+				}
+			if (i < seed_offset && shape_collision_left(mask, current_mask, &subject[j], sid, chunked) && verify_hit(&query[j], &subject[j], sid))
+				return false;
+			if (chunked && i > seed_offset && shape_collision_right(mask, current_mask, &subject[j], sid) && verify_hit(&query[j], &subject[j], sid))
+				return false;
+			++i;
+			mask >>= 1;
+		}
+		query += 32;
+		subject += 32;
+	}
+	return true;
+}
\ No newline at end of file
diff --git a/src/search/collision.h b/src/search/collision.h
new file mode 100644
index 0000000..78614c2
--- /dev/null
+++ b/src/search/collision.h
@@ -0,0 +1,31 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef COLLISION_H_
+#define COLLISION_H_
+
+#include "../data/frequent_seeds.h"
+#include "sse_dist.h"
+
+bool is_primary_hit(const Letter *query,
+	const Letter *subject,
+	const unsigned seed_offset,
+	const unsigned sid,
+	const unsigned len);
+
+#endif /* COLLISION_H_ */
diff --git a/src/search/hit_filter.h b/src/search/hit_filter.h
new file mode 100644
index 0000000..9a51f05
--- /dev/null
+++ b/src/search/hit_filter.h
@@ -0,0 +1,105 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef HIT_FILTER_H_
+#define HIT_FILTER_H_
+
+#include <vector>
+#include <limits>
+#include "trace_pt_buffer.h"
+#include "../dp/smith_waterman.h"
+#include "../basic/sequence.h"
+#include "../data/queries.h"
+#include "../data/reference.h"
+
+using std::vector;
+
+#ifdef __SSE2__
+
+struct hit_filter
+{
+
+	hit_filter(Statistics &stats,
+			   Loc q_pos,
+			   Trace_pt_buffer::Iterator &out):
+		q_num_ (std::numeric_limits<unsigned>::max()),
+		seed_offset_ (std::numeric_limits<unsigned>::max()),
+		stats_ (stats),
+		q_pos_ (q_pos),
+		out_ (out),
+		subjects_ (TLS::get(subjects_ptr))
+	{ subjects_.clear(); }
+
+	void push(Loc subject, int score)
+	{
+		if(score >= config.min_hit_raw_score)
+			push_hit(subject);
+		else
+			subjects_.push_back(ref_seqs::data_->fixed_window_infix(subject+ config.seed_anchor));
+	}
+
+	void finish()
+	{
+		if(subjects_.size() == 0)
+			return;
+		unsigned left;
+		sequence query (query_seqs::data_->window_infix(q_pos_ + config.seed_anchor, left));
+		smith_waterman(query,
+				subjects_,
+				config.hit_band,
+				left,
+				config.gap_open + config.gap_extend,
+				config.gap_extend,
+				config.min_hit_raw_score,
+				*this,
+				uint8_t(),
+				stats_);
+	}
+
+	void push_hit(Loc subject)
+	{
+		if(q_num_ == std::numeric_limits<unsigned>::max()) {
+			std::pair<size_t,size_t> l (query_seqs::data_->local_position(q_pos_));
+			q_num_ = (unsigned)l.first;
+			seed_offset_ = (unsigned)l.second;
+		}
+		assert(subject < ref_seqs::get().raw_len());
+		out_.push(hit  (q_num_, subject, seed_offset_));
+		stats_.inc(Statistics::TENTATIVE_MATCHES4);
+	}
+
+	void operator()(int i, const sequence &seq, int score)
+	{ push_hit(ref_seqs::data_->position(seq.data()+config.window- config.seed_anchor)); stats_.inc(Statistics::GAPPED_HITS); }
+
+private:
+
+	unsigned q_num_, seed_offset_;
+	Statistics  &stats_;
+	Loc q_pos_;
+	Trace_pt_buffer::Iterator &out_;
+	vector<sequence> &subjects_;
+	
+	static TLS_PTR vector<sequence> *subjects_ptr;
+
+};
+
+#endif
+
+#endif /* HIT_FILTER_H_*/
diff --git a/src/search/search.cpp b/src/search/search.cpp
new file mode 100644
index 0000000..3b947e4
--- /dev/null
+++ b/src/search/search.cpp
@@ -0,0 +1,148 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "align_range.h"
+#include "hit_filter.h"
+#include "sse_dist.h"
+
+Trace_pt_buffer* Trace_pt_buffer::instance;
+#ifdef __SSE2__
+TLS_PTR vector<sequence>* hit_filter::subjects_ptr;
+#endif
+
+TLS_PTR vector<Finger_print> *Seed_filter::vq_ptr, *Seed_filter::vs_ptr;
+TLS_PTR vector<Stage1_hit> *Seed_filter::hits_ptr;
+
+const unsigned tile_size[] = { 1024, 128 };
+
+#define FAST_COMPARE2(q, s, stats, q_ref, s_ref, q_offset, s_offset, hits) if (q.match(s) >= config.min_identities) stats.inc(Statistics::TENTATIVE_MATCHES1)
+#define FAST_COMPARE(q, s, stats, q_ref, s_ref, q_offset, s_offset, hits) if (q.match(s) >= config.min_identities) hits.push_back(Stage1_hit(q_ref, q_offset, s_ref, s_offset))
+
+void query_register_search(vector<Finger_print>::const_iterator q,
+	vector<Finger_print>::const_iterator s,
+	vector<Finger_print>::const_iterator s_end,
+	const Range_ref &ref,
+	vector<Stage1_hit> &hits,
+	Statistics &stats)
+{
+	const unsigned q_ref = unsigned(q - ref.q_begin);
+	unsigned s_ref = unsigned(s - ref.s_begin);
+	Finger_print q1 = *(q++), q2 = *(q++), q3 = *(q++), q4 = *(q++), q5 = *(q++), q6 = *q;
+	const vector<Finger_print>::const_iterator end2 = s_end - (s_end - s) % 4;
+	for (; s < end2; ) {
+		Finger_print s1 = *(s++), s2 = *(s++), s3 = *(s++), s4 = *(s++);
+		stats.inc(Statistics::SEED_HITS, 6 * 4);
+		FAST_COMPARE(q1, s1, stats, q_ref, s_ref, 0, 0, hits);
+		FAST_COMPARE(q2, s1, stats, q_ref, s_ref, 1, 0, hits);
+		FAST_COMPARE(q3, s1, stats, q_ref, s_ref, 2, 0, hits);
+		FAST_COMPARE(q4, s1, stats, q_ref, s_ref, 3, 0, hits);
+		FAST_COMPARE(q5, s1, stats, q_ref, s_ref, 4, 0, hits);
+		FAST_COMPARE(q6, s1, stats, q_ref, s_ref, 5, 0, hits);
+		FAST_COMPARE(q1, s2, stats, q_ref, s_ref, 0, 1, hits);
+		FAST_COMPARE(q2, s2, stats, q_ref, s_ref, 1, 1, hits);
+		FAST_COMPARE(q3, s2, stats, q_ref, s_ref, 2, 1, hits);
+		FAST_COMPARE(q4, s2, stats, q_ref, s_ref, 3, 1, hits);
+		FAST_COMPARE(q5, s2, stats, q_ref, s_ref, 4, 1, hits);
+		FAST_COMPARE(q6, s2, stats, q_ref, s_ref, 5, 1, hits);
+		FAST_COMPARE(q1, s3, stats, q_ref, s_ref, 0, 2, hits);
+		FAST_COMPARE(q2, s3, stats, q_ref, s_ref, 1, 2, hits);
+		FAST_COMPARE(q3, s3, stats, q_ref, s_ref, 2, 2, hits);
+		FAST_COMPARE(q4, s3, stats, q_ref, s_ref, 3, 2, hits);
+		FAST_COMPARE(q5, s3, stats, q_ref, s_ref, 4, 2, hits);
+		FAST_COMPARE(q6, s3, stats, q_ref, s_ref, 5, 2, hits);
+		FAST_COMPARE(q1, s4, stats, q_ref, s_ref, 0, 3, hits);
+		FAST_COMPARE(q2, s4, stats, q_ref, s_ref, 1, 3, hits);
+		FAST_COMPARE(q3, s4, stats, q_ref, s_ref, 2, 3, hits);
+		FAST_COMPARE(q4, s4, stats, q_ref, s_ref, 3, 3, hits);
+		FAST_COMPARE(q5, s4, stats, q_ref, s_ref, 4, 3, hits);
+		FAST_COMPARE(q6, s4, stats, q_ref, s_ref, 5, 3, hits);
+		s_ref += 4;
+	}
+	for (; s < s_end; ++s) {
+		stats.inc(Statistics::SEED_HITS, 6);
+		FAST_COMPARE(q1, *s, stats, q_ref, s_ref, 0, 0, hits);
+		FAST_COMPARE(q2, *s, stats, q_ref, s_ref, 1, 0, hits);
+		FAST_COMPARE(q3, *s, stats, q_ref, s_ref, 2, 0, hits);
+		FAST_COMPARE(q4, *s, stats, q_ref, s_ref, 3, 0, hits);
+		FAST_COMPARE(q5, *s, stats, q_ref, s_ref, 4, 0, hits);
+		FAST_COMPARE(q6, *s, stats, q_ref, s_ref, 5, 0, hits);
+		++s_ref;
+	}
+}
+
+void inner_search(vector<Finger_print>::const_iterator q,
+	vector<Finger_print>::const_iterator q_end,
+	vector<Finger_print>::const_iterator s,
+	vector<Finger_print>::const_iterator s_end,
+	const Range_ref &ref,
+	vector<Stage1_hit> &hits,
+	Statistics &stats)
+{
+	unsigned q_ref = unsigned(q - ref.q_begin);
+	for (; q < q_end; ++q) {
+		unsigned s_ref = unsigned(s - ref.s_begin);
+		for (vector<Finger_print>::const_iterator s2 = s; s2 < s_end; ++s2) {
+			stats.inc(Statistics::SEED_HITS);
+			FAST_COMPARE((*q), *s2, stats, q_ref, s_ref, 0, 0, hits);
+			++s_ref;
+		}
+		++q_ref;
+	}
+}
+
+void Seed_filter::tiled_search(vector<Finger_print>::const_iterator q,
+	vector<Finger_print>::const_iterator q_end,
+	vector<Finger_print>::const_iterator s,
+	vector<Finger_print>::const_iterator s_end,
+	const Range_ref &ref,
+	unsigned level)
+{
+	switch (level) {
+	case 0:
+	case 1:
+		for (; q < q_end; q += std::min(q_end - q, (ptrdiff_t)tile_size[level]))
+			for (vector<Finger_print>::const_iterator s2 = s; s2 < s_end; s2 += std::min(s_end - s2, (ptrdiff_t)tile_size[level]))
+				tiled_search(q, q + std::min(q_end - q, (ptrdiff_t)tile_size[level]), s2, s2 + std::min(s_end - s2, (ptrdiff_t)tile_size[level]), ref, level+1);
+		break;
+	case 2:
+		for (; q < q_end; q += std::min(q_end-q,(ptrdiff_t)6))
+			if (q_end - q < 6)
+				inner_search(q, q_end, s, s_end, ref, hits, stats);
+			else
+				query_register_search(q, s, s_end, ref, hits, stats);
+	}	
+}
+
+void load_fps(const sorted_list::const_iterator &i, vector<Finger_print> &v, const Sequence_set &seqs)
+{
+	v.clear();
+	v.reserve(i.n);
+	for (unsigned j = 0; j < i.n; ++j)
+		v.push_back(Finger_print(seqs.data(i[j])));
+}
+
+void Seed_filter::run(const sorted_list::const_iterator &q, const sorted_list::const_iterator &s)
+{
+	hits.clear();
+	load_fps(q, vq, *query_seqs::data_);
+	load_fps(s, vs, *ref_seqs::data_);
+	tiled_search(vq.begin(), vq.end(), vs.begin(), vs.end(), Range_ref(vq.begin(), vs.begin()), 0);
+	std::sort(hits.begin(), hits.end());
+	stats.inc(Statistics::TENTATIVE_MATCHES1, hits.size());
+	stage2_search(q, s, hits, stats, out, sid);
+}
\ No newline at end of file
diff --git a/src/search/search_query.cpp b/src/search/search_query.cpp
new file mode 100644
index 0000000..872ca2d
--- /dev/null
+++ b/src/search/search_query.cpp
@@ -0,0 +1,51 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "../util/thread.h"
+#include "../data/queries.h"
+#include "../data/index.h"
+
+void search_query(unsigned query_id, Statistics &stat, vector<Seed> &neighbor_seeds)
+{
+	const sequence query_seq = query_seqs::get()[query_id];
+	for (unsigned sid = 0; sid < shapes.count(); ++sid) {
+		const shape &sh = shapes[sid];
+		if (query_seq.length() < sh.length_)
+			return;
+		for (unsigned i = 0; i <= query_seq.length() - sh.length_; ++i) {
+			uint64_t seed;
+			if (sh.set_seed(seed, &query_seq[i])) {
+				sorted_list::Random_access_iterator k = seed_index[sid][seed];
+				while (k.good()) {
+					stat.inc(Statistics::SEED_HITS);
+					++k;
+				}
+			}
+		}
+	}
+}
+
+void search_query_worker(Atomic<unsigned> *next)
+{
+	unsigned query_id;
+	Statistics stat;
+	vector<Seed> neighbor_seeds;
+	while ((query_id = (*next)++) < query_seqs::get().get_length())
+		search_query(query_id, stat, neighbor_seeds);
+	statistics += stat;
+}
\ No newline at end of file
diff --git a/src/search/setup.cpp b/src/search/setup.cpp
new file mode 100644
index 0000000..796122d
--- /dev/null
+++ b/src/search/setup.cpp
@@ -0,0 +1,66 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "align_range.h"
+#include "../data/reference.h"
+#include "../basic/config.h"
+
+void setup_search_params(pair<size_t, size_t> query_len_bounds, size_t chunk_db_letters)
+{
+	const double b = config.min_bit_score == 0 ? score_matrix.bitscore(config.max_evalue, ref_header.letters, (unsigned)query_len_bounds.first) : config.min_bit_score;
+
+	if (config.mode_very_sensitive) {
+		Reduction::reduction = Reduction("A KR EDNQ C G H ILVM FYW P ST"); // murphy.10
+		Config::set_option(config.index_mode, 4u);
+		::shapes = shape_config(config.index_mode, config.shapes, config.shape_mask);
+		config.seed_anchor = std::min(::shapes[0].length_ - 1, 8u);
+		Config::set_option(config.min_identities, 6u);
+		Config::set_option(config.min_ungapped_score, 19.0);
+		Config::set_option(config.window, 60u);
+		Config::set_option(config.hit_band, 8);
+		Config::set_option(config.min_hit_score, 23.0);
+	}
+	else {
+
+		if (query_len_bounds.second <= 40) {
+			Config::set_option(config.min_identities, 10u);
+			Config::set_option(config.min_ungapped_score, std::min(27.0, b));
+		}
+		else {
+			Config::set_option(config.min_identities, 9u);
+			Config::set_option(config.min_ungapped_score, std::min(23.0, b));
+		}
+
+		if (query_len_bounds.second <= 80) {
+			const int band = config.read_padding(query_len_bounds.second);
+			Config::set_option(config.window, (unsigned)(query_len_bounds.second + band));
+			Config::set_option(config.hit_band, band);
+			Config::set_option(config.min_hit_score, b);
+		}
+		else {
+			Config::set_option(config.window, 40u);
+			Config::set_option(config.hit_band, 5);
+			Config::set_option(config.min_hit_score, std::min(29.0, b));
+		}
+	}
+
+	config.min_ungapped_raw_score = score_matrix.rawscore(config.min_ungapped_score);
+	config.min_hit_raw_score = score_matrix.rawscore(config.min_hit_score);
+	log_stream << "Query len bounds " << query_len_bounds.first << ' ' << query_len_bounds.second << endl;
+	log_stream << "Search parameters " << config.min_ungapped_raw_score << ' ' << config.min_hit_score << ' ' << config.hit_cap << endl;
+}
diff --git a/src/search/sse_dist.h b/src/search/sse_dist.h
new file mode 100644
index 0000000..3ae80b6
--- /dev/null
+++ b/src/search/sse_dist.h
@@ -0,0 +1,228 @@
+/****
+Copyright (c) 2013-2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SSE_DIST_H_
+#define SSE_DIST_H_
+
+#include "../basic/reduction.h"
+#include "../basic/value.h"
+#include "../util/simd.h"
+
+inline unsigned popcount32(unsigned x)
+{
+#ifdef _MSC_VER
+	return __popcnt(x);
+	//return (unsigned)popcount_3(x);
+#else
+	return __builtin_popcount(x);
+#endif
+}
+
+inline unsigned popcount64(unsigned long long x)
+{
+#ifdef _MSC_VER
+	return (unsigned)__popcnt64(x);
+#else
+	return __builtin_popcountll(x);
+#endif
+}
+
+struct Masked {};
+
+struct Int_finger_print
+{
+	Int_finger_print(const Letter *q) :
+		r1(*(uint64_t*)(q-8)),
+		r2(*(uint64_t*)(q)),
+		r3(*(uint64_t*)(q + 8)),
+		r4(*(uint64_t*)(q +16))
+	{ }
+	Int_finger_print(const Letter *q, Masked) :
+		r1(*(uint64_t*)(q - 8)),
+		r2(*(uint64_t*)(q)),
+		r3(*(uint64_t*)(q + 8)),
+		r4(*(uint64_t*)(q + 16))
+	{ }
+	unsigned match(const Int_finger_print &rhs) const
+	{
+		return popcount64(r1 & rhs.r1) + popcount64(r2 & rhs.r2) + popcount64(r3 & rhs.r3) + popcount64(r4 & rhs.r4);
+	}
+	uint64_t r1, r2,r3,r4;
+};
+
+#ifdef __SSE2__
+
+struct Byte_finger_print
+{
+	Byte_finger_print(const Letter *q) :
+		r1(_mm_loadu_si128((__m128i const*)(q - 8))),
+		r2(_mm_loadu_si128((__m128i const*)(q + 8)))
+	{ }
+	Byte_finger_print(const Letter *q, Masked):
+		r1 (_mm_and_si128(_mm_loadu_si128((__m128i const*)(q - 8)), _mm_set1_epi8('\x7f'))),
+		r2 (_mm_and_si128(_mm_loadu_si128((__m128i const*)(q + 8)), _mm_set1_epi8('\x7f')))
+	{ }
+	static unsigned match_block(__m128i x, __m128i y)
+	{
+		return _mm_movemask_epi8(_mm_cmpeq_epi8(x, y));
+	}
+	unsigned match(const Byte_finger_print &rhs) const
+	{
+		/*for (unsigned i = 0; i < 16; ++i)
+			cout << value_traits.alphabet[r1.m128i_u8[i]];
+		for (unsigned i = 0; i < 16; ++i)
+			cout << value_traits.alphabet[r2.m128i_u8[i]];
+		cout << endl;
+		for (unsigned i = 0; i < 16; ++i)
+			cout << value_traits.alphabet[rhs.r1.m128i_u8[i]];
+		for (unsigned i = 0; i < 16; ++i)
+			cout << value_traits.alphabet[rhs.r2.m128i_u8[i]];
+		cout << endl;*/
+		return popcount32(match_block(r1, rhs.r1) << 16 | match_block(r2, rhs.r2));
+	}
+	__m128i r1, r2;
+};
+
+#else
+
+struct Byte_finger_print
+{
+	Byte_finger_print()
+	{}
+	Byte_finger_print(const Letter *q)
+	{
+		//printf("%llx\n", q);
+		memcpy(r, q - 8, 32);
+	}
+	unsigned match(const Byte_finger_print &rhs) const
+	{
+		unsigned n = 0;
+		for (unsigned i = 0; i < 32; ++i)
+			if (r[i] == rhs.r[i])
+				++n;
+		return n;
+	}
+	Letter r[32];
+	//char r[32];
+};
+
+#endif
+
+struct Halfbyte_finger_print_naive
+{
+	Halfbyte_finger_print_naive(const Letter *q) :
+		r1(reduce(q-8)),
+		r2(reduce(q+8))
+	{ }
+	static unsigned match_block(uint64_t x, uint64_t y)
+	{
+		uint64_t v = ~(x ^ y);
+		v &= v >> 1;
+		v &= 0x5555555555555555LL;
+		v &= v >> 2;
+		v &= 0x1111111111111111LL;
+		return (unsigned)popcount64(v);
+	}
+	unsigned match(const Halfbyte_finger_print_naive &rhs) const
+	{
+		return match_block(r1, rhs.r1) + match_block(r2, rhs.r2);
+	}
+	static uint64_t reduce(const Letter *q)
+	{
+		uint64_t x;
+		for (unsigned i = 0; i < 16; ++i)
+			x = (x << 4) | reduction(q[i]);
+		return x;
+	}
+	static const Reduction reduction;
+	uint64_t r1, r2;
+};
+
+
+typedef Byte_finger_print Finger_print;
+
+#ifdef __SSSE3__
+inline __m128i reduce_seq_ssse3(const __m128i &seq)
+{
+	const __m128i *row = reinterpret_cast<const __m128i*>(Reduction::reduction.map8());
+	__m128i high_mask = _mm_slli_epi16(_mm_and_si128(seq, _mm_set1_epi8('\x10')), 3);
+	__m128i seq_low = _mm_or_si128(seq, high_mask);
+	__m128i seq_high = _mm_or_si128(seq, _mm_xor_si128(high_mask, _mm_set1_epi8('\x80')));
+
+	__m128i r1 = _mm_load_si128(row);
+	__m128i r2 = _mm_load_si128(row+1);
+	__m128i s1 = _mm_shuffle_epi8(r1, seq_low);
+	__m128i s2 = _mm_shuffle_epi8(r2, seq_high);
+	return _mm_or_si128(s1, s2);
+}
+#endif
+
+#ifdef __SSE2__
+inline __m128i reduce_seq_generic(const __m128i &seq)
+{
+	__m128i r;
+	Letter* s = (Letter*)&seq;
+	uint8_t* d = (uint8_t*)&r;
+	for(unsigned i=0;i<16;++i)
+		*(d++) = Reduction::reduction(*(s++));
+	return r;
+}
+
+inline __m128i reduce_seq(const __m128i &seq)
+{
+	if(config.have_ssse3) {
+#ifdef __SSSE3__
+		return reduce_seq_ssse3(seq);
+#else
+		return reduce_seq_generic(seq);
+#endif
+	} else
+		return reduce_seq_generic(seq);
+}
+#endif
+
+inline unsigned match_block_reduced(const Letter *x, const Letter *y)
+{
+#ifdef __SSE2__
+	static const __m128i mask = _mm_set1_epi8(0x7F);
+	__m128i r1 = _mm_loadu_si128 ((__m128i const*)(x));
+	__m128i r2 = _mm_loadu_si128 ((__m128i const*)(y));
+	r2 = _mm_and_si128(r2, mask);
+	r1 = reduce_seq(r1);
+	r2 = reduce_seq(r2);
+	return _mm_movemask_epi8(_mm_cmpeq_epi8(r1, r2));
+#else
+	unsigned r = 0;
+	for (int i = 15; i >= 0; --i) {
+		r <<= 1;
+		if (Reduction::reduction(x[i]) == Reduction::reduction(y[i]))
+			r |= 1;		
+	}
+	return r;
+#endif
+}
+
+inline uint64_t reduced_match32(const Letter* q, const Letter *s, unsigned len)
+{
+	uint64_t x = match_block_reduced(q + 16, s + 16) << 16 | match_block_reduced(q, s);
+	if(len < 32)
+		x &= (1 << len) - 1;
+	return x;
+}
+
+#endif /* SSE_DIST_H_ */
diff --git a/src/search/stage2.cpp b/src/search/stage2.cpp
new file mode 100644
index 0000000..99cbcbd
--- /dev/null
+++ b/src/search/stage2.cpp
@@ -0,0 +1,126 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "align_range.h"
+#include "../util/map.h"
+#include "../dp/dp.h"
+#include "../data/queries.h"
+#include "hit_filter.h"
+#include "../data/reference.h"
+#include "collision.h"
+
+#ifdef __SSE2__
+
+void search_query_offset(Loc q,
+	const sorted_list::const_iterator &s,
+	vector<Stage1_hit>::const_iterator hits,
+	vector<Stage1_hit>::const_iterator hits_end,
+	Statistics &stats,
+	Trace_pt_buffer::Iterator &out,
+	const unsigned sid)
+{
+	const Letter* query = query_seqs::data_->data(q);
+	hit_filter hf(stats, q, out);
+
+	for (vector<Stage1_hit>::const_iterator i = hits; i < hits_end; ++i) {
+		const Loc s_pos = s[i->s];
+		const Letter* subject = ref_seqs::data_->data(s_pos);
+		/*cout << sequence(query, 32) << endl;
+		cout << sequence(subject, 32) << endl;*/
+
+		unsigned delta, len;
+		int score;
+		if ((score = stage2_ungapped(query, subject, sid, delta, len)) < config.min_ungapped_raw_score)
+			continue;
+
+		stats.inc(Statistics::TENTATIVE_MATCHES2);
+		
+		if (!is_primary_hit(query - delta, subject - delta, delta, sid, len))
+			continue;
+
+		stats.inc(Statistics::TENTATIVE_MATCHES3);
+		hf.push(s_pos, score);
+	}
+
+	hf.finish();
+}
+
+#else
+
+void search_query_offset(Loc q,
+	const sorted_list::const_iterator &s,
+	vector<Stage1_hit>::const_iterator hits,
+	vector<Stage1_hit>::const_iterator hits_end,
+	Statistics &stats,
+	Trace_pt_buffer::Iterator &out,
+	const unsigned sid)
+{
+	const Letter* query = query_seqs::data_->data(q);
+	unsigned q_num_ = std::numeric_limits<unsigned>::max(), seed_offset_;
+
+	for (vector<Stage1_hit>::const_iterator i = hits; i < hits_end; ++i) {
+		const Loc s_pos = s[i->s];
+		const Letter* subject = ref_seqs::data_->data(s_pos);
+
+		unsigned delta, len;
+		int score;
+		if ((score = stage2_ungapped(query, subject, sid, delta, len)) < config.min_ungapped_raw_score)
+			continue;
+
+		stats.inc(Statistics::TENTATIVE_MATCHES2);
+
+#ifndef NO_COLLISION_FILTER
+		if (!is_primary_hit(query - delta, subject - delta, delta, sid, len))
+			continue;
+#endif
+
+		stats.inc(Statistics::TENTATIVE_MATCHES3);
+
+		if (score < config.min_hit_raw_score) {
+			const sequence s = ref_seqs::data_->fixed_window_infix(s_pos + config.seed_anchor);
+			unsigned left;
+			sequence query(query_seqs::data_->window_infix(q + config.seed_anchor, left));
+			score = smith_waterman(query, s, config.hit_band, left, config.gap_open + config.gap_extend, config.gap_extend);
+		}
+		if (score >= config.min_hit_raw_score) {
+			if (q_num_ == std::numeric_limits<unsigned>::max()) {
+				std::pair<size_t, size_t> l(query_seqs::data_->local_position(q));
+				q_num_ = (unsigned)l.first;
+				seed_offset_ = (unsigned)l.second;
+			}
+			assert(subject < ref_seqs::get().raw_len());
+			out.push(hit(q_num_, s_pos, seed_offset_));
+			stats.inc(Statistics::TENTATIVE_MATCHES4);
+		}
+	}
+}
+
+#endif
+
+void stage2_search(const sorted_list::const_iterator &q,
+	const sorted_list::const_iterator &s,
+	const vector<Stage1_hit> &hits,
+	Statistics &stats,
+	Trace_pt_buffer::Iterator &out,
+	const unsigned sid)
+{
+	typedef Map<vector<Stage1_hit>::const_iterator, Stage1_hit::Query> Map_t;
+	Map_t map(hits.begin(), hits.end());
+	for (Map_t::Iterator i = map.begin(); i.valid(); ++i)
+		search_query_offset(q[i.begin()->q], s, i.begin(), i.end(), stats, out, sid);
+}
\ No newline at end of file
diff --git a/src/search/trace_pt_buffer.h b/src/search/trace_pt_buffer.h
new file mode 100644
index 0000000..3908f07
--- /dev/null
+++ b/src/search/trace_pt_buffer.h
@@ -0,0 +1,190 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef TRACE_PT_BUFFER_H_
+#define TRACE_PT_BUFFER_H_
+
+#include "../util/async_buffer.h"
+#include "../basic/match.h"
+
+using std::auto_ptr;
+
+#pragma pack(1)
+
+struct hit
+{
+	typedef uint32_t Seed_offset;
+
+	unsigned	query_;
+	Packed_loc	subject_;
+	Seed_offset	seed_offset_;
+	hit() :
+		query_(),
+		subject_(),
+		seed_offset_()
+	{ }
+	hit(unsigned query, Packed_loc subject, Seed_offset seed_offset) :
+		query_(query),
+		subject_(subject),
+		seed_offset_(seed_offset)
+	{ }
+	bool operator<(const hit &rhs) const
+	{
+		return query_ < rhs.query_;
+	}
+	bool blank() const
+	{
+		return subject_ == 0;
+	}
+	unsigned operator%(unsigned i) const
+	{
+		return (query_ / align_mode.query_contexts) % i;
+	}
+	unsigned operator/(size_t i) const
+	{
+		return (query_ / align_mode.query_contexts) / (unsigned)i;
+	}
+	int64_t global_diagonal() const
+	{
+		return (int64_t)subject_ - (int64_t)seed_offset_;
+	}
+	template<unsigned _d>
+	static unsigned query_id(const hit& x)
+	{
+		return x.query_ / _d;
+	}
+	template<unsigned _d>
+	struct Query_id
+	{
+		unsigned operator()(const hit& x) const
+		{
+			return query_id<_d>(x);
+		}
+	};
+	static bool cmp_subject(const hit &lhs, const hit &rhs)
+	{
+		return lhs.subject_ < rhs.subject_
+			|| (lhs.subject_ == rhs.subject_ && lhs.seed_offset_ < rhs.seed_offset_);
+	}
+	static bool cmp_normalized_subject(const hit &lhs, const hit &rhs)
+	{
+		const uint64_t x = (uint64_t)lhs.subject_ + (uint64_t)rhs.seed_offset_, y = (uint64_t)rhs.subject_ + (uint64_t)lhs.seed_offset_;
+		return x < y || (x == y && lhs.seed_offset_ < rhs.seed_offset_);
+	}
+	friend std::ostream& operator<<(std::ostream &s, const hit &me)
+	{
+		s << me.query_ << '\t' << me.subject_ << '\t' << me.seed_offset_ << '\n';
+		return s;
+	}
+} PACKED_ATTRIBUTE;
+
+#pragma pack()
+
+struct Trace_pt_buffer : public Async_buffer<hit>
+{
+	Trace_pt_buffer(size_t input_size, const string &tmpdir, bool mem_buffered):
+		Async_buffer<hit> (input_size, tmpdir, mem_buffered ? mem_bins : file_bins)
+	{ }
+	enum { mem_bins = 1, file_bins = 4 };
+	static Trace_pt_buffer *instance;
+};
+
+struct Trace_pt_list : public vector<hit>
+{
+	void init()
+	{
+		pos_ = this->begin();
+		total_ = 0;
+		count_ = 1;
+#ifdef PRE_PARTITION
+		p_.clear();
+		p_.push_back(0);
+		idx_ = 0;
+		const unsigned c = query_contexts();
+		typename vector<hit<_locr,_locl> >::iterator i = this->begin();
+		unsigned total=0,count=1;
+		for(; i < this->end();) {
+			unsigned n=0;
+			const unsigned min_size = std::max(4*total/count/5 + 1, program_options::fetch_size);
+			for(;i<this->end() && n<min_size;) {
+				const unsigned q = i->query_/c;
+				for(; i<this->end() && i->query_/c == q; ++i)
+					++n;
+			}
+			++count;
+			total += n;
+			p_.push_back(i - this->begin());
+		}
+		p_.push_back(i - this->begin());
+#endif
+	}
+	struct Query_range
+	{
+		Query_range(Trace_pt_list &parent):
+			parent_ (parent)
+		{ }
+#ifndef PRE_PARTITION
+		bool operator()()
+		{
+
+			begin = parent_.pos_;
+			//end = std::min(std::max(begin + 3*parent_.total_/parent_.count_/4 + 1, begin+program_options::fetch_size), parent_.end());
+#ifdef NDEBUG
+			end = std::min(begin + 3*parent_.total_/parent_.count_/4 + 1, parent_.end());
+#else
+			//end = parent_.end();
+			ptrdiff_t x = std::min((ptrdiff_t)(3 * parent_.total_ / parent_.count_ / 4 + 1), parent_.end() - begin);
+			end = std::min(begin + x, parent_.end());
+#endif
+			if(end >= parent_.end())
+				return false;
+			const unsigned c = align_mode.query_contexts, q = end->query_/c;
+			for(; end<parent_.end() && end->query_/c == q; ++end);
+			parent_.pos_ = end;
+			parent_.total_ += end - begin;
+			++parent_.count_;
+			return end < parent_.end();
+		}
+#else
+		bool operator()()
+		{
+			begin = parent_.begin()+parent_.p_[parent_.idx_];
+			end = parent_.begin()+parent_.p_[parent_.idx_+1];
+			printf("%lu %lu %lu\n", parent_.p_[parent_.idx_], parent_.p_[parent_.idx_+1], parent_.p_[parent_.idx_+1]-parent_.p_[parent_.idx_]);
+			++parent_.idx_;
+			return parent_.idx_ < parent_.p_.size()-1;
+		}
+#endif
+		Trace_pt_list::iterator begin, end;
+	private:
+		Trace_pt_list &parent_;
+	};
+	Query_range get_range()
+	{ return Query_range (*this); }
+private:
+	vector<hit>::iterator pos_;
+#ifdef PRE_PARTITION
+	vector<size_t> p_;
+	unsigned idx_;
+#else
+	size_t total_, count_;
+#endif
+};
+
+#endif /* TRACE_PT_BUFFER_H_ */
+
diff --git a/src/util/Timer.cpp b/src/util/Timer.cpp
new file mode 100644
index 0000000..b1ba54d
--- /dev/null
+++ b/src/util/Timer.cpp
@@ -0,0 +1,130 @@
+//////////////////////////////////////////////////////////////////////////////
+// Timer.cpp
+// =========
+// High Resolution Timer.
+// This timer is able to measure the elapsed time with 1 micro-second accuracy
+// in both Windows, Linux and Unix system 
+//
+//  AUTHOR: Song Ho Ahn (song.ahn at gmail.com)
+// CREATED: 2003-01-13
+// UPDATED: 2006-01-13
+//
+// Copyright (c) 2003 Song Ho Ahn
+//////////////////////////////////////////////////////////////////////////////
+
+#include "Timer.h"
+#include <stdlib.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// constructor
+///////////////////////////////////////////////////////////////////////////////
+Timer::Timer()
+{
+#ifdef WIN32
+    QueryPerformanceFrequency(&frequency);
+    startCount.QuadPart = 0;
+    endCount.QuadPart = 0;
+#else
+    startCount.tv_sec = startCount.tv_usec = 0;
+    endCount.tv_sec = endCount.tv_usec = 0;
+#endif
+
+    stopped = 0;
+    startTimeInMicroSec = 0;
+    endTimeInMicroSec = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// distructor
+///////////////////////////////////////////////////////////////////////////////
+Timer::~Timer()
+{
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// start timer.
+// startCount will be set at this point.
+///////////////////////////////////////////////////////////////////////////////
+void Timer::start()
+{
+    stopped = 0; // reset stop flag
+#ifdef WIN32
+    QueryPerformanceCounter(&startCount);
+#else
+    gettimeofday(&startCount, NULL);
+#endif
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// stop the timer.
+// endCount will be set at this point.
+///////////////////////////////////////////////////////////////////////////////
+void Timer::stop()
+{
+    stopped = 1; // set timer stopped flag
+
+#ifdef WIN32
+    QueryPerformanceCounter(&endCount);
+#else
+    gettimeofday(&endCount, NULL);
+#endif
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// compute elapsed time in micro-second resolution.
+// other getElapsedTime will call this first, then convert to correspond resolution.
+///////////////////////////////////////////////////////////////////////////////
+double Timer::getElapsedTimeInMicroSec()
+{
+#ifdef WIN32
+    if(!stopped)
+        QueryPerformanceCounter(&endCount);
+
+    startTimeInMicroSec = startCount.QuadPart * (1000000.0 / frequency.QuadPart);
+    endTimeInMicroSec = endCount.QuadPart * (1000000.0 / frequency.QuadPart);
+#else
+    if(!stopped)
+        gettimeofday(&endCount, NULL);
+
+    startTimeInMicroSec = (startCount.tv_sec * 1000000.0) + startCount.tv_usec;
+    endTimeInMicroSec = (endCount.tv_sec * 1000000.0) + endCount.tv_usec;
+#endif
+
+    return endTimeInMicroSec - startTimeInMicroSec;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// divide elapsedTimeInMicroSec by 1000
+///////////////////////////////////////////////////////////////////////////////
+double Timer::getElapsedTimeInMilliSec()
+{
+    return this->getElapsedTimeInMicroSec() * 0.001;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// divide elapsedTimeInMicroSec by 1000000
+///////////////////////////////////////////////////////////////////////////////
+double Timer::getElapsedTimeInSec()
+{
+    return this->getElapsedTimeInMicroSec() * 0.000001;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// same as getElapsedTimeInSec()
+///////////////////////////////////////////////////////////////////////////////
+double Timer::getElapsedTime()
+{
+    return this->getElapsedTimeInSec();
+}
diff --git a/src/util/Timer.h b/src/util/Timer.h
new file mode 100644
index 0000000..9a3e941
--- /dev/null
+++ b/src/util/Timer.h
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+// Timer.h
+// =======
+// High Resolution Timer.
+// This timer is able to measure the elapsed time with 1 micro-second accuracy
+// in both Windows, Linux and Unix system 
+//
+//  AUTHOR: Song Ho Ahn (song.ahn at gmail.com)
+// CREATED: 2003-01-13
+// UPDATED: 2006-01-13
+//
+// Copyright (c) 2003 Song Ho Ahn
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef TIMER_H_DEF
+#define TIMER_H_DEF
+
+#ifdef _MSC_VER
+#define WIN32
+#endif
+
+#ifdef WIN32   // Windows system specific
+#define NOMINMAX
+#include <windows.h>
+#else          // Unix based system specific
+#include <sys/time.h>
+#endif
+
+
+class Timer
+{
+public:
+    Timer();                                    // default constructor
+    ~Timer();                                   // default destructor
+
+    void   start();                             // start timer
+    void   stop();                              // stop the timer
+	void resume() {}
+    double getElapsedTime();                    // get elapsed time in second
+    double getElapsedTimeInSec();               // get elapsed time in second (same as getElapsedTime)
+    double getElapsedTimeInMilliSec();          // get elapsed time in milli-second
+    double getElapsedTimeInMicroSec();          // get elapsed time in micro-second
+	unsigned get_random_seed();
+
+
+protected:
+
+
+private:
+    double startTimeInMicroSec;                 // starting time in micro-second
+    double endTimeInMicroSec;                   // ending time in micro-second
+    int    stopped;                             // stop flag 
+#ifdef WIN32
+    LARGE_INTEGER frequency;                    // ticks per second
+    LARGE_INTEGER startCount;                   //
+    LARGE_INTEGER endCount;                     //
+#else
+    timeval startCount;                         //
+    timeval endCount;                           //
+#endif
+};
+
+#endif // TIMER_H_DEF
diff --git a/src/util/async_buffer.h b/src/util/async_buffer.h
new file mode 100644
index 0000000..afc0956
--- /dev/null
+++ b/src/util/async_buffer.h
@@ -0,0 +1,134 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef ASYNC_BUFFER_H_
+#define ASYNC_BUFFER_H_
+
+#include <vector>
+#include <exception>
+#include "../basic/config.h"
+#include "temp_file.h"
+
+using std::vector;
+using std::string;
+using std::endl;
+
+const unsigned async_buffer_max_bins = 4;
+
+template<typename _t>
+struct Async_buffer
+{
+
+	typedef vector<_t> Vector;
+
+	Async_buffer(size_t input_count, const string &tmpdir, unsigned bins):
+		bins_ (bins),
+		bin_size_ ((input_count + bins_ - 1) / bins_)
+	{
+		log_stream << "Async_buffer() " << input_count << ',' << bin_size_ << endl;
+		for(unsigned j=0;j<config.threads_;++j)
+			for(unsigned i=0;i<bins;++i) {
+				tmp_file_.push_back(Temp_file ());
+				size_.push_back(0);
+			}
+	}
+
+	struct Iterator
+	{
+		Iterator(Async_buffer &parent, unsigned thread_num):
+			parent_ (parent),
+			thread_num_ (thread_num)
+		{
+			for(unsigned i=0;i<parent.bins_;++i) {
+				size_[i] = 0;
+				out_[i] = parent.get_out(thread_num_, i);
+			}
+		}
+		void push(const _t &x)
+		{
+			const unsigned bin = (unsigned)(x / parent_.bin_size_);
+			assert(bin < parent_.bins());
+			buffer_[bin*buffer_size+(size_[bin]++)] = x;
+			if(size_[bin] == buffer_size)
+				flush(bin);
+		}
+		void flush(unsigned bin)
+		{
+			out_[bin]->typed_write(&buffer_[bin*buffer_size], size_[bin]);
+			parent_.add_size(thread_num_, bin, size_[bin]);
+			size_[bin] = 0;
+		}
+		~Iterator()
+		{
+			for(unsigned bin=0;bin<parent_.bins_;++bin)
+				flush(bin);
+		}
+	private:
+		enum { buffer_size = 65536 };
+		_t buffer_[async_buffer_max_bins*buffer_size];
+		size_t size_[async_buffer_max_bins];
+		Temp_file* out_[async_buffer_max_bins];
+		Async_buffer &parent_;
+		const unsigned thread_num_;
+	};
+
+	size_t load(vector<_t> &data, unsigned bin) const
+	{
+		static size_t total_size;
+		if (bin == 0)
+			total_size = 0;
+		size_t size = 0;
+		for (unsigned i = 0; i < config.threads_; ++i)
+			size += size_[i*bins_ + bin];
+		log_stream << "Async_buffer.load() " << size << "(" << (double)size*sizeof(_t)/(1<<30) << " GB)" << endl;
+		total_size += size;
+		data.resize(size);
+		_t* ptr = data.data();
+		for(unsigned i=0;i<config.threads_;++i) {
+			Input_stream f (tmp_file_[i*bins_+bin]);
+			const size_t s = size_[i*bins_+bin];
+			const size_t n = f.read(ptr, s);
+			ptr += s;
+			f.close_and_delete();
+			if (n != s)
+				throw std::runtime_error("Error reading temporary file: " + f.file_name);
+		}
+		return total_size*sizeof(_t);
+	}
+
+	unsigned bins() const
+	{ return bins_; }
+
+private:
+
+	Temp_file* get_out(unsigned threadid, unsigned bin)
+	{ return &tmp_file_[threadid*bins_+bin]; }
+
+	void add_size(unsigned thread_id, unsigned bin, size_t n)
+	{ size_[thread_id*bins_+bin] += n; }
+
+	const unsigned bins_;
+	const size_t bin_size_;
+	vector<size_t> size_;
+	vector<Temp_file> tmp_file_;
+
+};
+
+#endif /* ASYNC_BUFFER_H_ */
diff --git a/src/util/binary_buffer.h b/src/util/binary_buffer.h
new file mode 100644
index 0000000..3d4c8d7
--- /dev/null
+++ b/src/util/binary_buffer.h
@@ -0,0 +1,89 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+Author: Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef BINARY_BUFFER_H_
+#define BINARY_BUFFER_H_
+
+#include <vector>
+#include <stdexcept>
+#include <stdint.h>
+#include <string.h>
+
+using std::vector;
+using std::string;
+
+struct Binary_buffer : public vector<char>
+{
+
+	struct Iterator
+	{
+		Iterator(vector<char>::const_iterator begin, vector<char>::const_iterator end):
+			ptr_ (begin),
+			end_ (end)
+		{ }
+		Iterator& operator>>(uint32_t &x)
+		{ read(x); return *this; }
+		Iterator& operator>>(uint8_t &x)
+		{ read(x); return *this; }
+		template<typename _t>
+		void read(_t &x)
+		{
+			check(sizeof(_t));
+			x = *(_t*)(&*ptr_);
+			ptr_ += sizeof(_t);
+		}
+		template<typename _t>
+		void read(vector<_t> &v, size_t count)
+		{
+			const size_t l = sizeof(_t) * count;
+			check(l);
+			v.resize(count);
+			memcpy(v.data(), &*ptr_, l);
+			ptr_ += l;
+		}
+		void read_packed(uint8_t length, uint32_t &dst)
+		{
+			switch(length) {
+			case 0: uint8_t x; read(x); dst = x; break;
+			case 1: uint16_t y; read(y); dst = y; break;
+			case 2: read(dst);
+			}
+		}
+		Iterator& operator>>(string &dst)
+		{
+			dst.clear();
+			char c;
+			while(read(c), c != '\0')
+				dst.push_back(c);
+			return *this;
+		}
+		bool good() const
+		{ return ptr_ < end_; }
+	private:
+		void check(size_t size) const
+		{ if(ptr_+size > end_) throw std::runtime_error("Unexpected end of file."); }
+		vector<char>::const_iterator ptr_, end_;
+	};
+
+	Iterator begin() const
+	{ return Iterator (vector<char>::begin(), vector<char>::end()); }
+
+};
+
+#endif /* BINARY_BUFFER_H_ */
diff --git a/src/util/binary_file.h b/src/util/binary_file.h
new file mode 100644
index 0000000..4769f27
--- /dev/null
+++ b/src/util/binary_file.h
@@ -0,0 +1,446 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef BINARY_FILE_H_
+#define BINARY_FILE_H_
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <stdexcept>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+#include "log_stream.h"
+#include "system.h"
+
+using std::auto_ptr;
+using std::vector;
+using std::endl;
+using std::string;
+using std::runtime_error;
+
+struct File_read_exception : public std::runtime_error
+{
+	File_read_exception(const string &file_name) :
+		runtime_error(string("Error reading file ") + file_name)
+	{ }
+};
+
+struct File_write_exception : public std::runtime_error
+{
+	File_write_exception(const string &file_name) :
+		runtime_error(string("Error writing file ") + file_name + ". Disk full?")
+	{ }
+};
+
+struct File_open_exception : public std::runtime_error
+{
+	File_open_exception(const string &file_name) :
+		std::runtime_error(string("Error opening file " + file_name))
+	{ }
+};
+
+struct Output_stream
+{
+
+	Output_stream()
+	{ }
+#ifndef _MSC_VER
+	virtual ~Output_stream()
+	{}
+#endif
+	Output_stream(const string &file_name) :
+		file_name_(file_name),
+		f_(file_name.length() == 0 ? stdout : fopen(file_name.c_str(), "wb"))
+	{
+		if (f_ == 0) throw File_open_exception(file_name_);
+	}
+	virtual void close()
+	{
+		if (f_ && f_ != stdout) {
+			fclose(f_);
+			f_ = 0;
+		}
+	}
+	virtual void write(const char *ptr, size_t count)
+	{
+		size_t n;
+		if ((n = fwrite((const void*)ptr, 1, count, f_)) != count)
+			throw File_write_exception(file_name_);
+	}
+	template<typename _t>
+	void typed_write(const _t *ptr, size_t count)
+	{
+		size_t n;
+		if ((n = fwrite((const void*)ptr, sizeof(_t), count, f_)) != count)
+			throw File_write_exception(file_name_);
+	}
+	template<class _t>
+	void write(const vector<_t> &v, bool write_size = true)
+	{
+		size_t size = v.size();
+		if (write_size)
+			typed_write(&size, 1);
+		typed_write(v.data(), size);
+	}
+	void write_c_str(const string &s)
+	{
+		write(s.c_str(), s.length() + 1);
+	}
+	void seekp(size_t p)
+	{
+		if (FSEEK(f_, (int64_t)p, SEEK_SET) != 0) throw File_write_exception(file_name_);
+	}
+	size_t tell()
+	{
+		int64_t x;
+		if ((x = FTELL(f_)) == (int64_t)-1)
+			throw std::runtime_error("Error executing ftell on stream " + file_name_);
+		return (size_t)x;
+	}
+protected:
+	string file_name_;
+	FILE *f_;
+	friend struct Input_stream;
+};
+
+struct Input_stream
+{
+
+	Input_stream(const string &file_name):
+		file_name (file_name),
+		line_count(0),
+		f_(fopen(file_name.c_str(), "rb")),		
+		line_buf_used_(0),
+		line_buf_end_(0),
+		putback_line_(false),
+		eof_(false)
+	{
+		if (f_ == 0)
+			throw File_open_exception(file_name);
+	}
+
+	void rewind()
+	{
+		::rewind(f_);
+		line_count = 0;
+		line_buf_used_ = 0;
+		line_buf_end_ = 0;
+		putback_line_ = false;
+		eof_ = false;
+		line.clear();
+	}
+
+	Input_stream(const Output_stream &tmp_file):
+		file_name (tmp_file.file_name_),
+		f_(tmp_file.f_)
+	{
+		::rewind(f_);
+	}
+
+	void seek(size_t pos)
+	{
+		if (FSEEK(f_, (int64_t)pos, SEEK_SET) != 0)
+			throw std::runtime_error("Error executing seek on file " + file_name);
+	}
+
+	void seek_forward(size_t n)
+	{
+		if (FSEEK(f_, (int64_t)n, SEEK_CUR) != 0)
+			throw std::runtime_error("Error executing seek on file " + file_name);
+	}
+
+	bool eof() const
+	{
+		return eof_;
+	}
+
+	virtual size_t read_bytes(char *ptr, size_t count)
+	{
+		size_t n;
+		if ((n = fread(ptr, 1, count, f_)) != count) {
+			if (feof(f_) != 0)
+				return n;
+			else
+				throw File_read_exception(file_name);
+		}
+		return n;
+	}
+
+	template<class _t>
+	size_t read(_t *ptr, size_t count)
+	{
+		return read_bytes((char*)ptr, count*sizeof(_t))/sizeof(_t);
+	}
+
+	template<class _t>
+	void read(vector<_t> &v)
+	{
+		size_t size;
+		if (read(&size, 1) != 1)
+			throw File_read_exception(file_name);
+		v.resize(size);
+		if (read(v.data(), size) != size)
+			throw File_read_exception(file_name);
+	}
+
+	template<class _t>
+	void skip_vector()
+	{
+		size_t size;
+		if (read(&size, 1) != 1)
+			throw File_read_exception(file_name);
+		seek_forward(size * sizeof(_t));
+	}
+
+	void read_c_str(string &s)
+	{
+		int c;
+		s.clear();
+		while ((c = fgetc(f_)) != 0) {
+			if (c == EOF)
+				throw File_read_exception(file_name);
+			s += (char)c;
+		}
+	}
+
+	void close_and_delete()
+	{
+		close();
+#ifdef _MSC_VER
+		if (remove(file_name.c_str()) != 0)
+			std::cerr << "Warning: Failed to delete temporary file " << file_name << std::endl;
+#endif
+	}
+
+	virtual void close()
+	{
+		if (f_) {
+			fclose(f_);
+			f_ = 0;
+		}
+	}
+
+	void putback(char c)
+	{
+		if (ungetc(c, f_) != (int)c)
+			throw File_read_exception(file_name);
+	}
+
+	void getline()
+	{
+		if (putback_line_) {
+			putback_line_ = false;
+			++line_count;
+			return;
+		}
+		line.clear();
+		while (true) {
+			const char *p = (const char*)memchr(&line_buf_[line_buf_used_], '\n', line_buf_end_ - line_buf_used_);
+			if (p == 0) {
+				line.append(&line_buf_[line_buf_used_], line_buf_end_ - line_buf_used_);
+				line_buf_end_ = read_bytes(line_buf_, line_buf_size);
+				line_buf_used_ = 0;
+				if (line_buf_end_ == 0) {
+					eof_ = true;
+					++line_count;
+					return;
+				}
+			}
+			else {
+				const size_t n = (p - line_buf_) - line_buf_used_;
+				line.append(&line_buf_[line_buf_used_], n);
+				line_buf_used_ += n + 1;
+				const size_t s = line.length() - 1;
+				if (!line.empty() && line[s] == '\r')
+					line.resize(s);
+				++line_count;
+				return;
+			}
+		}
+	}
+
+	void putback_line()
+	{
+		putback_line_ = true;
+		--line_count;
+	}
+
+	string file_name;
+	string line;
+	size_t line_count;
+	
+protected:
+
+	enum { line_buf_size = 256 };
+
+	FILE *f_;
+	char line_buf_[line_buf_size];
+	size_t line_buf_used_, line_buf_end_;
+	bool putback_line_, eof_;
+
+};
+
+struct Buffered_file : public Input_stream
+{
+
+	Buffered_file(const string& file_name):
+		Input_stream (file_name)
+	{ init(); }
+
+	Buffered_file(const Output_stream &tmp_file):
+		Input_stream (tmp_file)
+	{ init(); }
+
+	bool eof()
+	{
+		if(ptr_ < end_)
+			return false;
+		else if(end_ < &data_[buffer_size])
+			return true;
+		else {
+			fetch();
+			return eof();
+		}
+	}
+
+	template<typename _t>
+	void read(_t &dst)
+	{
+		const char *const p = ptr_ + sizeof(_t);
+		if(p > end_) {
+			if(end_ < &data_[buffer_size])
+				throw File_read_exception(file_name);
+			fetch();
+			return read(dst);
+		}
+		dst = *reinterpret_cast<_t*>(ptr_);
+		ptr_ += sizeof(_t);
+	}
+
+	template<typename _t>
+	void read(_t* dst, size_t n)
+	{
+		for(size_t i=0;i<n;++i)
+			read(*(dst++));
+	}
+
+	void read_c_str(string &dst)
+	{
+		dst.clear();
+		char c;
+		while(read(c), c != '\0')
+			dst.push_back(c);
+	}
+
+	void read_packed(uint8_t length, uint32_t &dst)
+	{
+		switch(length) {
+		case 0: uint8_t x; read(x); dst = x; break;
+		case 1: uint16_t y; read(y); dst = y; break;
+		case 2: read(dst);
+		}
+	}
+
+	const char* ptr() const
+	{ return ptr_; }
+
+	void seek(size_t pos)
+	{
+		//this->clear();
+		Input_stream::seek(pos);
+		init();
+	}
+
+private:
+
+	void fetch()
+	{
+		ptrdiff_t d = end_ - ptr_;
+		assert(d >= 0);
+		memcpy(&data_[0], ptr_, d);
+		ptr_ = &data_[0];
+		end_ = read_block(ptr_+d, buffer_size - d);
+	}
+
+	void init()
+	{
+		ptr_ = &data_[0];
+		end_ = read_block(ptr_, buffer_size);
+	}
+
+	char* read_block(char* ptr, size_t size)
+	{ return ptr + Input_stream::read(ptr, size); }
+
+	enum { buffer_size = 8192 };
+
+	char data_[buffer_size];
+	char *ptr_, *end_;
+
+};
+
+struct Buffered_ostream
+{
+
+	Buffered_ostream(Output_stream &s):
+		stream_ (s),
+		ptr_ (&data_[0]),
+		end_ (&data_[buffer_size])
+	{ }
+
+	template<typename _t>
+	void write(const _t &x)
+	{
+		const char *const p = ptr_ + sizeof(_t);
+		if(p > end_) {
+			flush();
+			return write(x);
+		}
+		*reinterpret_cast<_t*>(ptr_) = x;
+		ptr_ += sizeof(_t);
+	}
+
+	void close()
+	{
+		flush();
+		((Output_stream*)this)->close(); 
+	}
+
+private:
+
+	void flush()
+	{
+		stream_.write(data_, ptr_ - data_);
+		ptr_ = data_;
+	}
+
+	enum { buffer_size = 4096 };
+
+	Output_stream &stream_;
+	char data_[buffer_size];
+	char *ptr_, * const end_;
+
+};
+
+#endif /* BINARY_FILE_H_ */
diff --git a/src/util/command_line_parser.cpp b/src/util/command_line_parser.cpp
new file mode 100644
index 0000000..64c38dd
--- /dev/null
+++ b/src/util/command_line_parser.cpp
@@ -0,0 +1,122 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <iostream>
+#include <algorithm>
+#include "command_line_parser.h"
+
+using std::cout;
+using std::endl;
+
+Command_line_parser & Command_line_parser::add(const Options_group & group)
+{
+	for (Ptr_vector<Option_base>::const_iterator i = group.options.begin(); i != group.options.end(); ++i) {
+		map_[(*i)->id] = *i;
+		map_short_[(*i)->short_id] = *i;
+	}
+	groups_.push_back(&group);
+	return *this;
+}
+
+Command_line_parser & Command_line_parser::add_command(const char * s, const char *desc)
+{
+	commands_.push_back(pair<string,string>(s,desc));
+	return *this;
+}
+
+void Command_line_parser::store_option(const vector<string> &v)
+{
+	if (v.size() == 0)
+		return;
+	Option_base* o = 0;
+	string id;
+	vector<string> v2;
+
+	if (v[0].length() <= 1)
+		throw std::runtime_error("Invalid option syntax.");
+	else if (v[0].substr(0, 2) == "--") {
+		id = v[0].substr(2);
+		std::map<string, Option_base*>::const_iterator i = map_.find(id);
+		if (i != map_.end())
+			o = i->second;
+	} else if (v[0][0] == '-') {
+		id = v[0][1];
+		std::map<char, Option_base*>::const_iterator i = map_short_.find(v[0][1]);
+		if (i != map_short_.end())
+			o = i->second;
+		if (v[0].length() > 2)
+			v2.push_back(v[0].substr(2));
+	} else
+		throw std::runtime_error("Command line options must begin with - or --.");
+	
+	if(o == 0)
+		throw std::runtime_error("Invalid option: " + id);
+	else {
+		v2.insert(v2.end(), v.begin() + 1, v.end());
+		o->read(v2);
+	}
+}
+
+void Command_line_parser::store(int count, const char ** str, unsigned &command)
+{
+	if (count < 2)
+		throw std::runtime_error("Syntax: diamond COMMAND [OPTIONS]. To print help message: diamond help");
+	const string cmd(str[1]);
+	for (command = 0; command < commands_.size(); ++command)
+		if (commands_[command].first == cmd || "--" + commands_[command].first == cmd)
+			break;
+	if (command == commands_.size())
+		throw std::runtime_error("Invalid command: " + cmd + ". To print help message: diamond help");
+
+	for (std::map<string, Option_base*>::const_iterator i = map_.begin(); i != map_.end(); ++i)
+		i->second->set_default();
+
+	vector<string> v;
+	for (int i = 2; i < count; ++i) {
+		if (str[i][0] == '-') {
+			store_option(v);
+			v.clear();
+		}
+		v.push_back(str[i]);
+	}
+	store_option(v);
+}
+
+void Command_line_parser::print_help()
+{
+	static const size_t col1_width = 23;
+	cout << "Syntax: diamond COMMAND [OPTIONS]" << endl << endl;
+	cout << "Commands:" << endl;
+	for (vector<pair<string, string> >::const_iterator i = commands_.begin(); i != commands_.end(); ++i)
+		if(i->second != "")
+			cout << i->first << '\t' << i->second << endl;
+	cout << endl;
+	for (vector<const Options_group*>::const_iterator i = groups_.begin(); i != groups_.end(); ++i) {
+		if ((*i)->title == "")
+			continue;
+		cout << (*i)->title << ":" << endl;
+		for (vector<Option_base*>::const_iterator j = (*i)->options.begin(); j != (*i)->options.end(); ++j) {
+			string col1 = "--" + (*j)->id;
+			if ((*j)->short_id)
+				col1 += string(" (-") + (*j)->short_id + ")";
+			col1.append(std::max(col1_width, col1.length()) - col1.length(), ' ');
+			cout << col1 << (*j)->desc << endl;
+		}
+		cout << endl;
+	}
+}
diff --git a/src/util/command_line_parser.h b/src/util/command_line_parser.h
new file mode 100644
index 0000000..cfad844
--- /dev/null
+++ b/src/util/command_line_parser.h
@@ -0,0 +1,173 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef COMMAND_LINE_PARSER_H_
+#define COMMAND_LINE_PARSER_H_
+
+#include <vector>
+#include <map>
+#include <string>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdexcept>
+#include <stdint.h>
+#include "ptr_vector.h"
+
+using std::vector;
+using std::string;
+using std::pair;
+
+template<typename _t>
+inline void read_option(_t &dst, const vector<string> &v)
+{ assert(false); }
+
+template<>
+inline void read_option<int>(int &dst, const vector<string> &v)
+{ dst = atoi(v[0].c_str()); }
+
+template<>
+inline void read_option<unsigned>(unsigned &dst, const vector<string> &v)
+{ dst = atoi(v[0].c_str()); }
+
+template<>
+inline void read_option<uint64_t>(uint64_t &dst, const vector<string> &v)
+{
+	dst = atoi(v[0].c_str());
+}
+
+template<>
+inline void read_option<double>(double &dst, const vector<string> &v)
+{
+	dst = atof(v[0].c_str());
+}
+
+template<>
+inline void read_option<string>(string &dst, const vector<string> &v)
+{ dst = v[0]; }
+
+template<>
+inline void read_option<vector<string> >(vector<string> &dst, const vector<string> &v)
+{
+	dst = v;
+}
+
+template<>
+inline void read_option<bool>(bool &dst, const vector<string> &v)
+{ dst = true; }
+
+template<typename _t>
+inline bool check_pcount(const vector<string> &v)
+{
+	return v.size() == 1;
+}
+
+template<>
+inline bool check_pcount<bool>(const vector<string> &v)
+{
+	return v.size() == 0;
+}
+
+template<>
+inline bool check_pcount<vector<string> >(const vector<string> &v)
+{
+	return v.size() > 0;
+}
+
+struct Option_base
+{
+	Option_base(const string &id, char short_id, const string &desc) :
+		id(id),
+		desc(desc),
+		short_id (short_id)		
+	{}
+	virtual void read(const vector<string> &v) = 0;
+	virtual void set_default() = 0;
+	virtual ~Option_base()
+	{}
+	const string id, desc;
+	const char short_id;
+};
+
+template<typename _t>
+struct Option : public Option_base
+{
+	Option(const char *id, char short_id, const char *desc, _t &store, _t def) :
+		Option_base(id, short_id, desc),
+		default_(def),
+		store_(store)
+	{ }
+	virtual void read(const vector<string> &v)
+	{
+		if (!check_pcount<_t>(v))
+			throw std::runtime_error("Invalid parameter count for option '--" + id + "'");
+		read_option(store_, v);
+	}
+	virtual void set_default()
+	{
+		store_ = default_;
+	}
+	virtual ~Option()
+	{}
+private:
+	const _t default_;
+	_t &store_;
+};
+
+struct Options_group
+{
+	struct Add_f
+	{
+		Add_f(Options_group &parent):
+			parent_(parent)
+		{}
+		template<typename _t>
+		Add_f& operator()(const char *id, char short_id, const char *desc, _t &store, _t def = _t())
+		{
+			parent_.options.push_back(new Option<_t>(id, short_id, desc, store, def));
+			return *this;
+		}
+	private:
+		Options_group &parent_;
+	};
+	Add_f add()
+	{
+		return Add_f(*this);
+	}
+	Options_group(const char *title):
+		title (title)
+	{}
+	Ptr_vector<Option_base> options;
+	string title;
+};
+
+struct Command_line_parser
+{
+	Command_line_parser& add(const Options_group &group);
+	Command_line_parser& add_command(const char *s, const char *desc);
+	void store(int count, const char **str, unsigned &command);
+	void print_help();
+private:
+	void store_option(const vector<string> &v);
+
+	std::map<string, Option_base*> map_;
+	std::map<char, Option_base*> map_short_;
+	vector<const Options_group*> groups_;
+	vector<pair<string,string> > commands_;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/util/complexity_filter.h b/src/util/complexity_filter.h
new file mode 100644
index 0000000..7bc4379
--- /dev/null
+++ b/src/util/complexity_filter.h
@@ -0,0 +1,89 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef COMPLEXITY_FILTER_H_
+#define COMPLEXITY_FILTER_H_
+
+#include "../blast/blast_seg.h"
+#include "../blast/blast_filter.h"
+#include "../basic/value.h"
+#include "../data/sequence_set.h"
+#include "thread.h"
+
+struct Complexity_filter
+{
+
+	Complexity_filter()
+	{ blast_seg_ = SegParametersNewAa(); }
+
+	~Complexity_filter()
+	{ SegParametersFree(blast_seg_); }
+
+	unsigned filter(Letter *seq, uint32_t length) const
+	{
+		BlastSeqLoc *seg_locs;
+		SeqBufferSeg ((uint8_t*) seq, length, 0u, blast_seg_, &seg_locs);
+		unsigned nMasked = 0;
+
+		if(seg_locs) {
+			BlastSeqLoc *l = seg_locs;
+			do {
+				for(signed i=l->ssr->left;i<=l->ssr->right;i++) {
+					nMasked++;
+					seq[i] = value_traits.mask_char;
+				}
+			} while((l=l->next) != 0);
+			BlastSeqLocFree(seg_locs);
+		}
+		return nMasked;
+	}
+
+	static const Complexity_filter& get()
+	{ return instance; }
+
+	void run(Sequence_set &seqs) const
+	{
+		Filter_context context (seqs, *this);
+		launch_scheduled_thread_pool(context, (unsigned)seqs.get_length(), config.threads_);
+	}
+
+private:
+
+	struct Filter_context
+	{
+		Filter_context(Sequence_set &seqs, const Complexity_filter &filter):
+			seqs (seqs),
+			filter (filter)
+		{ }
+		void operator()(unsigned thread_id, unsigned i)
+		{
+			filter.filter(seqs.ptr(i), (unsigned)seqs.length(i));
+		}
+		Sequence_set &seqs;
+		const Complexity_filter &filter;
+	};
+
+	SegParameters *blast_seg_;
+
+	static const Complexity_filter instance;
+
+};
+
+#endif /* COMPLEXITY_FILTER_H_ */
diff --git a/src/util/compressed_stream.cpp b/src/util/compressed_stream.cpp
new file mode 100644
index 0000000..163b0e6
--- /dev/null
+++ b/src/util/compressed_stream.cpp
@@ -0,0 +1,152 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <stdexcept>
+#include "compressed_stream.h"
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+
+Compressed_istream::Compressed_istream(const string &file_name):
+	Input_stream(file_name),
+	in(new char[chunk_size]),
+	out(new char[chunk_size]),
+	read_(0),
+	total_(0),
+	eos_(false)
+{
+	strm.zalloc = Z_NULL;
+	strm.zfree = Z_NULL;
+	strm.opaque = Z_NULL;
+	strm.avail_in = 0;
+	strm.next_in = Z_NULL;
+	strm.avail_out = chunk_size;
+	strm.next_out = (Bytef*)out.get();
+	int ret = inflateInit2(&strm, 15 + 32);
+	if (ret != Z_OK)
+		throw std::runtime_error("Error opening compressed file (inflateInit): " + file_name);
+}
+
+size_t Compressed_istream::read_bytes(char *ptr, size_t count)
+{
+	size_t n = 0;
+	do {
+		size_t m = std::min(count - n, total_ - read_);
+		memcpy(ptr, &out.get()[read_], m);
+		read_ += m;
+		ptr += m;
+		n += m;
+		if (count == n || eos_)
+			return n;
+
+		if (strm.avail_out > 0 && strm.avail_in == 0) {
+			strm.avail_in = (uInt)Input_stream::read_bytes(in.get(), chunk_size);
+			if (strm.avail_in == 0) {
+				eos_ = true;
+				return n;
+			}
+			strm.next_in = (Bytef*)in.get();
+		}
+
+		strm.avail_out = chunk_size;
+		strm.next_out = (Bytef*)out.get();
+
+		int ret = inflate(&strm, Z_NO_FLUSH);
+		if (ret == Z_STREAM_END) {
+			if(strm.avail_in == 0 && feof(this->f_))
+				eos_ = true;
+			else {
+				int ret = inflateInit2(&strm, 15 + 32);
+				if (ret != Z_OK)
+					throw std::runtime_error("Error initializing compressed stream (inflateInit): " + file_name);
+			}
+		}
+		else if (ret != Z_OK)
+			throw std::runtime_error("Inflate error.");
+
+		read_ = 0;
+		total_ = chunk_size - strm.avail_out;
+	} while (true);
+}
+
+void Compressed_istream::close()
+{
+	inflateEnd(&strm);
+	Input_stream::close();
+}
+
+bool is_gzip_stream(const unsigned char *b)
+{
+	return (b[0] == 0x1F && b[1] == 0x8B)         // gzip header
+		|| (b[0] == 0x78 && (b[1] == 0x01      // zlib header
+			|| b[1] == 0x9C
+			|| b[1] == 0xDA));
+}
+
+Input_stream *Compressed_istream::auto_detect(const string &file_name)
+{
+	unsigned char b[2];
+	Input_stream f(file_name);
+	size_t n = f.read(b, 2);
+	f.close();
+	if (n == 2 && is_gzip_stream(b))
+		return new Compressed_istream(file_name);
+	else
+		return new Input_stream(file_name);
+}
+
+Compressed_ostream::Compressed_ostream(const string &file_name):
+	Output_stream(file_name),
+	out(new char[chunk_size])
+{
+	strm.zalloc = Z_NULL;
+	strm.zfree = Z_NULL;
+	strm.opaque = Z_NULL;
+	if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK)
+		throw std::runtime_error("deflateInit error");
+}
+
+void Compressed_ostream::deflate_loop(const char * ptr, size_t count, int flush)
+{
+	strm.avail_in = (uInt)count;
+	strm.next_in = (Bytef*)ptr;
+	do {
+		strm.avail_out = chunk_size;
+		strm.next_out = (Bytef*)out.get();
+		if (deflate(&strm, flush) == Z_STREAM_ERROR)
+			throw std::runtime_error("deflate error");
+		const size_t have = chunk_size - strm.avail_out;
+		Output_stream::write(out.get(), have);
+	} while (strm.avail_out == 0);
+}
+
+void Compressed_ostream::write(const char * ptr, size_t count)
+{
+	deflate_loop(ptr, count, Z_NO_FLUSH);
+}
+
+void Compressed_ostream::close()
+{
+	deflate_loop(0, 0, Z_FINISH);
+	deflateEnd(&strm);
+}
\ No newline at end of file
diff --git a/src/util/compressed_stream.h b/src/util/compressed_stream.h
new file mode 100644
index 0000000..5dd0e82
--- /dev/null
+++ b/src/util/compressed_stream.h
@@ -0,0 +1,68 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef COMPRESSED_STREAM_H_
+#define COMPRESSED_STREAM_H_
+
+#include <string>
+#include <memory>
+#include <zlib.h>
+#include "binary_file.h"
+#include "util.h"
+
+using std::string;
+using std::auto_ptr;
+
+struct Stream_read_exception : public std::runtime_error
+{
+	Stream_read_exception(size_t line_count, const char *msg) :
+		runtime_error(string("Error reading input stream at line ") + to_string(line_count) + ": " + msg)
+	{}
+};
+
+struct Compressed_istream : public Input_stream
+{
+	Compressed_istream(const string &file_name);
+	virtual size_t read_bytes(char *ptr, size_t count);
+	virtual void close();
+	static Input_stream* auto_detect(const string &file_name);
+private:
+	z_stream strm;
+	static const size_t chunk_size = 1llu << 20;
+	auto_ptr<char> in, out;
+	size_t read_, total_;
+	bool eos_;
+};
+
+struct Compressed_ostream : public Output_stream
+{
+	Compressed_ostream(const string &file_name);
+#ifndef _MSC_VER
+	virtual ~Compressed_ostream()
+	{}
+#endif
+	virtual void write(const char *ptr, size_t count);
+	virtual void close();
+private:
+	void deflate_loop(const char *ptr, size_t count, int code);
+	static const size_t chunk_size = 1llu << 20;
+	z_stream strm;
+	auto_ptr<char> out;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/util/direction.h b/src/util/direction.h
new file mode 100644
index 0000000..6df128c
--- /dev/null
+++ b/src/util/direction.h
@@ -0,0 +1,45 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef DIRECTION_H_
+#define DIRECTION_H_
+
+struct Right { enum { mult = 1 }; };
+struct Left { enum { mult = -1 }; };
+
+Letter get_dir(const Letter* x, int i, const Right&)
+{ return *(x+i); }
+
+Letter get_dir(const Letter* x, int i, const Left&)
+{ return *(x-i); }
+
+const Letter* get_dir_ptr(const Letter* x, int i, const Right&)
+{ return x+i; }
+
+const Letter* get_dir_ptr(const Letter* x, int i, const Left&)
+{ return x-i; }
+
+const Letter* inc_dir(const Letter* x, const Right&)
+{ return x+1; }
+
+const Letter* inc_dir(const Letter* x, const Left&)
+{ return x-1; }
+
+#endif /* DIRECTION_H_ */
diff --git a/src/util/double_buffer.h b/src/util/double_buffer.h
new file mode 100644
index 0000000..21009df
--- /dev/null
+++ b/src/util/double_buffer.h
@@ -0,0 +1,55 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef DOUBLE_BUFFER_H_
+#define DOUBLE_BUFFER_H_
+
+#include <vector>
+
+using std::vector;
+using std::pair;
+
+template<typename _t>
+struct Double_buffer
+{
+
+	inline void init(size_t size, size_t padding, size_t padding_front, _t init)
+	{
+		const size_t total = size + padding + padding_front;
+		data_.resize(total*2);
+		ptr1 = &data_[padding_front];
+		ptr2 = &data_[total+padding_front];
+		for(size_t i=0;i<total*2;++i)
+			data_[i] = init;
+	}
+
+	inline pair<_t*,_t*> get(int)
+	{ std::swap(ptr1, ptr2); return pair<_t*,_t*> (ptr2, ptr1); }
+
+	inline _t* last()
+	{ return ptr1; }
+
+private:
+	_t *ptr1, *ptr2;
+	vector<_t> data_;
+
+};
+
+#endif /* DOUBLE_BUFFER_H_ */
diff --git a/src/util/fast_mutex.h b/src/util/fast_mutex.h
new file mode 100644
index 0000000..09c159e
--- /dev/null
+++ b/src/util/fast_mutex.h
@@ -0,0 +1,250 @@
+/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2010-2012 Marcus Geelnard
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source
+    distribution.
+*/
+
+#ifndef _FAST_MUTEX_H_
+#define _FAST_MUTEX_H_
+
+/// @file
+
+// Which platform are we on?
+#if !defined(_TTHREAD_PLATFORM_DEFINED_)
+  #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+    #define _TTHREAD_WIN32_
+  #else
+    #define _TTHREAD_POSIX_
+  #endif
+  #define _TTHREAD_PLATFORM_DEFINED_
+#endif
+
+// Check if we can support the assembly language level implementation (otherwise
+// revert to the system API)
+//  || defined(_M_X64)
+#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || \
+    (defined(_MSC_VER) && (defined(_M_IX86))) || \
+    (defined(__GNUC__) && (defined(__ppc__)))
+  #define _FAST_MUTEX_ASM_
+#else
+  #define _FAST_MUTEX_SYS_
+#endif
+
+#if defined(_TTHREAD_WIN32_)
+  #ifndef WIN32_LEAN_AND_MEAN
+    #define WIN32_LEAN_AND_MEAN
+    #define __UNDEF_LEAN_AND_MEAN
+  #endif
+#define NOMINMAX
+  #include <windows.h>
+  #ifdef __UNDEF_LEAN_AND_MEAN
+    #undef WIN32_LEAN_AND_MEAN
+    #undef __UNDEF_LEAN_AND_MEAN
+  #endif
+#else
+  #ifdef _FAST_MUTEX_ASM_
+    #include <sched.h>
+  #else
+    #include <pthread.h>
+  #endif
+#endif
+
+namespace tthread {
+
+/// Fast mutex class.
+/// This is a mutual exclusion object for synchronizing access to shared
+/// memory areas for several threads. It is similar to the tthread::mutex class,
+/// but instead of using system level functions, it is implemented as an atomic
+/// spin lock with very low CPU overhead.
+///
+/// The \c fast_mutex class is NOT compatible with the \c condition_variable
+/// class (however, it IS compatible with the \c lock_guard class). It should
+/// also be noted that the \c fast_mutex class typically does not provide
+/// as accurate thread scheduling as a the standard \c mutex class does.
+///
+/// Because of the limitations of the class, it should only be used in
+/// situations where the mutex needs to be locked/unlocked very frequently.
+///
+/// @note The "fast" version of this class relies on inline assembler language,
+/// which is currently only supported for 32/64-bit Intel x86/AMD64 and
+/// PowerPC architectures on a limited number of compilers (GNU g++ and MS
+/// Visual C++).
+/// For other architectures/compilers, system functions are used instead.
+class fast_mutex {
+  public:
+    /// Constructor.
+#if defined(_FAST_MUTEX_ASM_)
+    fast_mutex() : mLock(0) {}
+#else
+    fast_mutex()
+    {
+  #if defined(_TTHREAD_WIN32_)
+      InitializeCriticalSection(&mHandle);
+  #elif defined(_TTHREAD_POSIX_)
+      pthread_mutex_init(&mHandle, NULL);
+  #endif
+    }
+#endif
+
+#if !defined(_FAST_MUTEX_ASM_)
+    /// Destructor.
+    ~fast_mutex()
+    {
+  #if defined(_TTHREAD_WIN32_)
+      DeleteCriticalSection(&mHandle);
+  #elif defined(_TTHREAD_POSIX_)
+      pthread_mutex_destroy(&mHandle);
+  #endif
+    }
+#endif
+
+    /// Lock the mutex.
+    /// The method will block the calling thread until a lock on the mutex can
+    /// be obtained. The mutex remains locked until \c unlock() is called.
+    /// @see lock_guard
+    inline void lock()
+    {
+#if defined(_FAST_MUTEX_ASM_)
+      bool gotLock;
+      do {
+        gotLock = try_lock();
+        if(!gotLock)
+        {
+  #if defined(_TTHREAD_WIN32_)
+          Sleep(0);
+  #elif defined(_TTHREAD_POSIX_)
+          sched_yield();
+  #endif
+        }
+      } while(!gotLock);
+#else
+  #if defined(_TTHREAD_WIN32_)
+      EnterCriticalSection(&mHandle);
+  #elif defined(_TTHREAD_POSIX_)
+      pthread_mutex_lock(&mHandle);
+  #endif
+#endif
+    }
+
+    /// Try to lock the mutex.
+    /// The method will try to lock the mutex. If it fails, the function will
+    /// return immediately (non-blocking).
+    /// @return \c true if the lock was acquired, or \c false if the lock could
+    /// not be acquired.
+    inline bool try_lock()
+    {
+#if defined(_FAST_MUTEX_ASM_)
+      int oldLock;
+  #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+      asm volatile (
+        "movl $1,%%eax\n\t"
+        "xchg %%eax,%0\n\t"
+        "movl %%eax,%1\n\t"
+        : "=m" (mLock), "=m" (oldLock)
+        :
+        : "%eax", "memory"
+      );
+  #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+      int *ptrLock = &mLock;
+      __asm {
+        mov eax,1
+        mov ecx,ptrLock
+        xchg eax,[ecx]
+        mov oldLock,eax
+      }
+  #elif defined(__GNUC__) && (defined(__ppc__))
+      int newLock = 1;
+      asm volatile (
+        "\n1:\n\t"
+        "lwarx  %0,0,%1\n\t"
+        "cmpwi  0,%0,0\n\t"
+        "bne-   2f\n\t"
+        "stwcx. %2,0,%1\n\t"
+        "bne-   1b\n\t"
+        "isync\n"
+        "2:\n\t"
+        : "=&r" (oldLock)
+        : "r" (&mLock), "r" (newLock)
+        : "cr0", "memory"
+      );
+  #endif
+      return (oldLock == 0);
+#else
+  #if defined(_TTHREAD_WIN32_)
+      return TryEnterCriticalSection(&mHandle) ? true : false;
+  #elif defined(_TTHREAD_POSIX_)
+      return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
+  #endif
+#endif
+    }
+
+    /// Unlock the mutex.
+    /// If any threads are waiting for the lock on this mutex, one of them will
+    /// be unblocked.
+    inline void unlock()
+    {
+#if defined(_FAST_MUTEX_ASM_)
+  #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+      asm volatile (
+        "movl $0,%%eax\n\t"
+        "xchg %%eax,%0\n\t"
+        : "=m" (mLock)
+        :
+        : "%eax", "memory"
+      );
+  #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+      int *ptrLock = &mLock;
+      __asm {
+        mov eax,0
+        mov ecx,ptrLock
+        xchg eax,[ecx]
+      }
+  #elif defined(__GNUC__) && (defined(__ppc__))
+      asm volatile (
+        "sync\n\t"  // Replace with lwsync where possible?
+        : : : "memory"
+      );
+      mLock = 0;
+  #endif
+#else
+  #if defined(_TTHREAD_WIN32_)
+      LeaveCriticalSection(&mHandle);
+  #elif defined(_TTHREAD_POSIX_)
+      pthread_mutex_unlock(&mHandle);
+  #endif
+#endif
+    }
+
+  private:
+#if defined(_FAST_MUTEX_ASM_)
+    int mLock;
+#else
+  #if defined(_TTHREAD_WIN32_)
+    CRITICAL_SECTION mHandle;
+  #elif defined(_TTHREAD_POSIX_)
+    pthread_mutex_t mHandle;
+  #endif
+#endif
+};
+
+}
+
+#endif // _FAST_MUTEX_H_
+
diff --git a/src/util/hash_function.h b/src/util/hash_function.h
new file mode 100644
index 0000000..e6a743a
--- /dev/null
+++ b/src/util/hash_function.h
@@ -0,0 +1,36 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef HASH_FUNCTION_H_
+#define HASH_FUNCTION_H_
+
+struct murmur_hash {
+	uint64_t operator()(uint64_t h) const
+	{
+		h ^= h >> 33;
+		h *= 0xff51afd7ed558ccdLL;
+		h ^= h >> 33;
+		h *= 0xc4ceb9fe1a85ec53LL;
+		h ^= h >> 33;
+		return h;
+	}
+};
+
+#endif /* HASH_FUNCTION_H_ */
diff --git a/src/util/hash_table.h b/src/util/hash_table.h
new file mode 100644
index 0000000..7200678
--- /dev/null
+++ b/src/util/hash_table.h
@@ -0,0 +1,277 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef HASH_TABLE_H_
+#define HASH_TABLE_H_
+
+#include <exception>
+#include <stdint.h>
+#include <memory>
+#include <algorithm>
+#include <string.h>
+#include "hash_function.h"
+
+using std::auto_ptr;
+
+struct hash_table_overflow_exception : public std::exception
+{
+	virtual const char* what() const throw()
+	{
+		return "Hash table overflow";
+	}
+};
+
+template<typename T, T value> struct value_compare
+{
+bool operator()(T x) const
+{
+	return x == value;
+}
+};
+
+template<typename _K, typename _V, typename _E, typename _H> class hash_table
+{
+
+public:
+
+	struct entry
+	{
+		_K	key;
+		_V	value;
+	}; // __attribute__((packed));
+
+	hash_table(size_t size) :
+		table(new entry[size]),
+		size_(size)
+	{
+		memset(table, 0, size_ * sizeof(entry));
+	}
+
+	~hash_table()
+	{
+		delete[] table;
+	}
+
+	entry* operator[](_K key) const
+	{
+		entry *entry = get_entry(key);
+		if (_E()(entry->value))
+			return NULL;
+		return entry;
+	}
+
+	void insert(_K key, _V value)
+	{
+		entry *entry = get_entry(key);
+		if (_E()(entry->value))
+			entry->key = key;
+		entry->value = value;
+	}
+
+	size_t size() const
+	{
+		return size_;
+	}
+
+	size_t count() const
+	{
+		size_t n(0);
+		for (size_t i = 0; i < size_; ++i)
+			if (!_E()(table[i].value))
+				++n;
+		return n;
+	}
+
+private:
+
+	entry* get_entry(_K key) const
+	{
+		entry *p = &table[_H()(key) % size_];
+		bool wrapped = false;
+		while (p->key != key && !_E()(p->value)) {
+			++p;
+			if (p == &table[size_]) {
+				if (wrapped)
+					throw hash_table_overflow_exception();
+				p = &table[0];
+				wrapped = true;
+			}
+		}
+		return p;
+	}
+
+	entry	*table;
+	size_t	 size_;
+
+};
+
+template<typename _V> class PHash_table
+{
+
+public:
+
+	struct entry
+	{
+		uint16_t finger_print;
+		_V value;
+	}; // __attribute__((packed));
+
+	PHash_table() :
+		size_(0)
+	{}
+
+	PHash_table(size_t size) :
+		table(new entry[size]),
+		size_(size)
+	{
+		memset(table.get(), 0, size_ * sizeof(entry));
+	}
+
+	PHash_table(size_t size, double factor) :
+		size_(std::max(size_t((double)size * factor), (size_t)1llu)),
+		table(new entry[size_])
+	{
+		memset(table.get(), 0, size_ * sizeof(entry));
+	}
+	
+	entry* operator[](uint64_t hash) const
+	{
+		entry *entry = get_entry(hash);
+		if (entry->value == 0u)
+			return NULL;
+		return entry;
+	}
+
+	entry* insert(uint64_t hash)
+	{
+		entry *entry = get_entry(hash);
+		if (entry->value == 0u)
+			entry->finger_print = finger_print(hash);
+		return entry;
+	}
+
+	size_t size() const
+	{
+		return size_;
+	}
+
+	size_t count() const
+	{
+		size_t n(0);
+		for (size_t i = 0; i<size_; ++i)
+			if (table[i].value != 0u)
+				++n;
+		return n;
+	}
+
+private:
+
+	static uint16_t finger_print(uint64_t hash)
+	{
+		return (uint16_t)(hash & 0xffffllu);
+	}
+
+	entry* get_entry(uint64_t hash) const
+	{
+		entry *p = table.get() + ((hash >> 16) % size_);
+		const uint16_t fp = finger_print(hash);
+		bool wrapped = false;
+		while (p->finger_print != fp && p->value != 0u) {
+			++p;
+			if (p == table.get() + size_) {
+				if (wrapped)
+					throw hash_table_overflow_exception();
+				p = table.get();
+				wrapped = true;
+			}
+		}
+		return p;
+	}
+
+	size_t size_;
+	auto_ptr<entry> table;	
+
+};
+
+
+struct PHash_set
+{
+
+public:
+
+	typedef uint8_t fp;
+
+	PHash_set() :
+		size_(0)
+	{}
+
+	PHash_set(size_t size) :
+		table(new fp[size]),
+		size_(size)
+	{
+		memset(table.get(), 0, size_ * sizeof(fp));
+	}
+
+	bool contains(uint64_t key) const
+	{
+		fp *entry = get_entry(key);
+		return *entry != 0;
+	}
+
+	void insert(uint64_t key)
+	{
+		fp *entry = get_entry(key);
+		if (*entry == (fp)0)
+			*entry = finger_print(murmur_hash()(key));
+	}
+
+	size_t size() const
+	{
+		return size_;
+	}
+
+private:
+
+	static fp finger_print(uint64_t hash)
+	{
+		return std::max((fp)(hash & ((1llu<<(sizeof(fp)*8))-1llu)), (fp)1);
+	}
+
+	fp* get_entry(uint64_t key) const
+	{
+		const uint64_t hash = murmur_hash()(key), f = finger_print(hash);
+		fp *p = table.get() + ((hash >> sizeof(fp)*8) % size_);
+		bool wrapped = false;
+		while (*p != f && *p != (fp)0) {
+			++p;
+			if (p == table.get() + size_) {
+				if (wrapped)
+					throw hash_table_overflow_exception();
+				p = table.get();
+				wrapped = true;
+			}
+		}
+		return p;
+	}
+
+	auto_ptr<fp> table;
+	size_t size_;
+
+};
+
+#endif /* HASH_TABLE_H_ */
diff --git a/src/util/log_stream.h b/src/util/log_stream.h
new file mode 100644
index 0000000..9675726
--- /dev/null
+++ b/src/util/log_stream.h
@@ -0,0 +1,114 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef LOG_STREAM_H_
+#define LOG_STREAM_H_
+
+#include <iostream>
+#include "Timer.h"
+
+using std::endl;
+
+struct Message_stream
+{
+	Message_stream(bool to_cout=true):
+		to_cout_ (to_cout)
+	{}
+	template<typename _t>
+	Message_stream& operator<<(const _t& x)
+	{
+		if(to_cout_)
+			std::cout << x;
+		return *this;
+	}
+	//Message_stream& operator<<(std::ostream & (__cdecl *_Pfn)(std::ostream&))
+	Message_stream& operator<<(std::ostream & (*_Pfn)(std::ostream&))
+	{
+		if(to_cout_)
+			((*_Pfn)(std::cout));
+		return *this;
+	}
+private:
+	bool to_cout_;
+};
+
+extern Message_stream message_stream;
+extern Message_stream verbose_stream;
+extern Message_stream log_stream;
+
+struct task_timer
+{
+	task_timer(const char *msg, unsigned level=1) :
+		level_(level),
+		msg_(msg)
+	{
+		start(msg);
+	}
+	~task_timer()
+	{
+		finish();
+	}
+	void go(const char *msg)
+	{
+		finish();
+		start(msg);
+		msg_ = msg;
+	}
+	void finish()
+	{
+		if (!msg_)
+			return;
+		//if (print_ && !Cfg::debug_log)
+		get_stream() << " [" << timer_.getElapsedTimeInSec() << "s]" << endl;
+		/*else if (Cfg::debug_log) {
+			log_stream << '/' << msg_ << " [" << timer_.getElapsedTimeInSec() << "s]" << endl;
+		}*/
+		msg_ = 0;
+	}
+	Message_stream& get_stream() const
+	{
+		switch (level_) {
+		case 1:
+			return message_stream;
+		case 2:
+			return verbose_stream;
+		case 3:
+			return log_stream;
+		default:
+			return message_stream;
+		}
+	}
+private:
+	void start(const char *msg)
+	{
+		timer_.start();
+		//if (print_ && !Cfg::debug_log) {
+			get_stream() << msg << "... " << std::flush;
+			//fflush(stdout);
+		/**}
+		else if (Cfg::debug_log)
+			log_stream << msg << "..." << endl;*/
+	}
+	unsigned level_;
+	const char *msg_;
+	Timer timer_;
+};
+
+#endif
diff --git a/src/util/map.h b/src/util/map.h
new file mode 100644
index 0000000..48ccba4
--- /dev/null
+++ b/src/util/map.h
@@ -0,0 +1,66 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef MAP_H_
+#define MAP_H_
+
+template<typename _it, typename _key>
+struct Map
+{
+
+	struct Iterator
+	{
+		Iterator(const _it& begin, const _it& parent_end):
+			begin_ (begin),
+			parent_end_ (parent_end),
+			end_ (get_end())
+		{ }
+		void operator++()
+		{ begin_ = end_; end_ = get_end(); }
+		bool valid() const
+		{ return begin_ < parent_end_; }
+		_it& begin()
+		{ return begin_; }
+		_it& end()
+		{ return end_; }
+	private:
+		_it get_end() const
+		{
+			_it i = begin_;
+			while(i < parent_end_ && _key()(*i) == _key()(*begin_)) ++i;
+			return i;
+		}
+		_it begin_, parent_end_, end_;
+	};
+
+	Map(const _it &begin, const _it &end):
+		begin_ (begin),
+		end_ (end)
+	{ }
+
+	Iterator begin()
+	{ return Iterator(begin_, end_); }
+
+private:
+	_it begin_, end_;
+
+};
+
+#endif /* MAP_H_ */
diff --git a/src/util/merge_sort.h b/src/util/merge_sort.h
new file mode 100644
index 0000000..3868175
--- /dev/null
+++ b/src/util/merge_sort.h
@@ -0,0 +1,50 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef MERGE_SORT_H_
+#define MERGE_SORT_H_
+
+#include <algorithm>
+#include <stddef.h>
+#include "thread.h"
+
+template<typename _it>
+void merge_sort(_it begin, _it end, unsigned n_threads, unsigned level = 0)
+{
+	ptrdiff_t diff = end - begin;
+	if(diff <= 1)
+		return;
+
+	if(1u << level >= n_threads) {
+		std::sort(begin, end);
+		return;
+	}
+
+	_it mid = begin + diff/2;
+	thread *left = launch_thread(merge_sort<_it>, begin, mid, n_threads, level+1);
+	thread *right = launch_thread(merge_sort<_it>, mid, end, n_threads, level+1);
+	left->join();
+	right->join();
+	delete left;
+	delete right;
+	std::inplace_merge(begin, mid, end);
+}
+
+#endif /* MERGE_SORT_H_ */
diff --git a/src/util/ptr_vector.h b/src/util/ptr_vector.h
new file mode 100644
index 0000000..1e207e7
--- /dev/null
+++ b/src/util/ptr_vector.h
@@ -0,0 +1,64 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef PTR_VECTOR_H_
+#define PTR_VECTOR_H_
+
+#include <vector>
+
+using std::vector;
+
+template<typename _t>
+struct Ptr_vector : public vector<_t*>
+{
+
+	Ptr_vector():
+		vector<_t*>()
+	{}
+	
+	Ptr_vector(typename vector<_t*>::size_type n):
+		vector<_t*>(n)
+	{}
+
+	_t& operator[](typename vector<_t*>::size_type n)
+	{ return *vector<_t*>::operator[](n); }
+
+	const _t& operator[](typename vector<_t*>::size_type n) const
+	{ return *vector<_t*>::operator[](n); }
+
+	_t*& get(typename vector<_t*>::size_type n)
+	{
+		return vector<_t*>::operator[](n);
+	}
+
+	typename vector<_t*>::iterator erase(typename vector<_t*>::iterator first, typename vector<_t*>::iterator last)
+	{
+		for (typename vector<_t*>::iterator i = first; i < last; ++i)
+			delete *i;
+		return vector<_t*>::erase(first, last);
+	}
+
+	~Ptr_vector()
+	{
+		for(typename vector<_t*>::iterator i=this->begin(); i!=this->end(); ++i)
+			delete *i;
+	}
+
+};
+
+#endif /* PTR_VECTOR_H_ */
diff --git a/src/util/radix_sort.h b/src/util/radix_sort.h
new file mode 100644
index 0000000..ea96806
--- /dev/null
+++ b/src/util/radix_sort.h
@@ -0,0 +1,75 @@
+/****
+Copyright (c) 2015-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef RADIX_SORT_H_
+#define RADIX_SORT_H_
+
+#include <vector>
+#include "thread.h"
+
+using std::vector;
+using tthread::thread;
+
+template<typename _t, typename _int_t, unsigned _radix=8>
+_int_t get_radix(const _t &x, unsigned shift)
+{ return ((_int_t)x >> shift) & (1<<_radix-1); }
+
+template<typename _t, typename _int_t, unsigned _radix=8>
+void build_histogram(typename vector<_t>::const_iterator begin, typename vector<_t>::const_iterator end, unsigned *hst, unsigned shift)
+{
+	memset(hst, 0, sizeof(unsigned)*(1<<_radix));
+	for(typename vector<_t>::const_iterator i=begin;i<end;++i)
+		++hst[get_radix(*i, shift)];
+}
+
+template<typename _t, typename _int_t, unsigned _radix=8>
+void scatter(typename vector<_t>::const_iterator begin, typename vector<_t>::const_iterator end, typename vector<typename vector<_t>::iterator>::iterator dst, unsigned shift)
+{
+	for (typename vector<_t>::const_iterator i = begin; i < end; ++i)
+		*(dst[get_radix(*i, shift)]++) = *i;
+}
+
+template<typename _t, typename _int_t, unsigned _radix=8>
+void radix_sort(typename vector<_t>::iterator begin, typename vector<_t>::iterator end, unsigned n_threads)
+{
+	typedef unsigned Histogram[1<<_radix];
+	const size_t n = end - begin;
+	if(n == 0)
+		return;
+	vector<_t> buf (n);
+	typename vector<_t>::iterator buf_begin = buf.begin();
+	partition p (n, n_threads);
+
+	typename vector<_t>::iterator *src = &begin, *dst = &buf_begin;
+
+	for (unsigned shift = 0; shift < sizeof(_int_t) * 8 / _radix; shift += _radix) {
+		vector<Histogram> hst (p.parts);
+		vector<thread*> threads;
+		for (unsigned i = 0; i < p.parts; ++i)
+			threads.push_back(launch_thread(build_histogram, *src + p.getMin(i), *src + p.getMax(i), hst[i], shift));
+		for(unsigned i=0;i<p.parts;++i) {
+			threads[i]->join();
+			delete threads[i];
+		}
+		vector<vector<typename vector<_t>::iterator> > pointers (p.parts);
+
+		std::swap(src, dst);
+	}
+}
+
+#endif /* RADIX_SORT_H_ */
diff --git a/src/util/seq_file_format.cpp b/src/util/seq_file_format.cpp
new file mode 100644
index 0000000..5cd2037
--- /dev/null
+++ b/src/util/seq_file_format.cpp
@@ -0,0 +1,114 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include "seq_file_format.h"
+
+struct Raw_text {};
+struct Sequence_data {};
+
+template<typename _t>
+inline char convert_char(char a)
+{
+	return a;
+}
+
+template<>
+inline char convert_char<Sequence_data>(char a)
+{
+	return input_value_traits.from_char(a);
+}
+
+template<typename _t, typename _what>
+void copy_line(const string & s, vector<_t>& v, size_t d, _what)
+{
+	for (string::const_iterator i = s.begin() + d; i != s.end(); ++i)
+		v.push_back(convert_char<_what>(*i));
+}
+
+bool FASTA_format::get_seq(vector<char>& id, vector<Letter>& seq, Input_stream & s) const
+{
+	while (s.getline(), s.line.empty() && !s.eof());
+	if (s.eof())
+		return false;
+	if (s.line[0] != '>')
+		throw Stream_read_exception(s.line_count, "FASTA format error: Missing '>' at record start.");
+	id.clear();
+	seq.clear();
+	copy_line(s.line, id, 1, Raw_text());
+	while (true) {
+		s.getline();
+		if (s.line.empty()) {
+			if (s.eof())
+				break;
+			else
+				continue;
+		}
+		if (s.line[0] == '>') {
+			s.putback_line();
+			break;
+		}
+		try {
+			copy_line(s.line, seq, 0, Sequence_data());
+		}
+		catch (invalid_sequence_char_exception &e) {
+			throw Stream_read_exception(s.line_count, e.what());
+		}
+	}
+	return true;
+}
+
+bool FASTQ_format::get_seq(vector<char>& id, vector<Letter>& seq, Input_stream & s) const
+{
+	while (s.getline(), s.line.empty() && !s.eof());
+	if (s.eof())
+		return false;
+	if (s.line[0] != '@')
+		throw Stream_read_exception(s.line_count, "FASTQ format error: Missing '@' at record start.");
+	id.clear();
+	seq.clear();
+	copy_line(s.line, id, 1, Raw_text());
+	s.getline();
+	try {
+		copy_line(s.line, seq, 0, Sequence_data());
+	}
+	catch (invalid_sequence_char_exception &e) {
+		throw Stream_read_exception(s.line_count, e.what());
+	}
+	s.getline();
+	if (s.line.empty() || s.line[0] != '+')
+		throw Stream_read_exception(s.line_count, "FASTQ format error: Missing '+' line in record.");
+	s.getline();
+	return true;
+}
+
+const Sequence_file_format * guess_format(Input_stream &file)
+{
+	static const FASTA_format fasta;
+	static const FASTQ_format fastq;
+
+	file.getline();
+	file.putback_line();
+	if (file.line.empty())
+		throw std::runtime_error("Error detecting input file format. First line seems to be blank.");
+	switch (file.line[0]) {
+	case '>': return &fasta;
+	case '@': return &fastq;
+	default: throw std::runtime_error("Error detecting input file format. First line must begin with '>' (FASTA) or '@' (FASTQ).");
+	}
+	return 0;
+}
diff --git a/src/util/seq_file_format.h b/src/util/seq_file_format.h
new file mode 100644
index 0000000..5b60eda
--- /dev/null
+++ b/src/util/seq_file_format.h
@@ -0,0 +1,76 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef SEQ_FILE_FORMAT_H_
+#define SEQ_FILE_FORMAT_H_
+
+#include <vector>
+#include "../basic/value.h"
+#include "compressed_stream.h"
+
+using std::vector;
+using std::pair;
+
+struct file_format_exception : public std::exception
+{
+	virtual const char* what() const throw()
+	{
+		return "Invalid input file format";
+	}
+};
+
+struct Sequence_file_format
+{
+
+	virtual bool get_seq(vector<char> &id, vector<Letter> &seq, Input_stream &s) const = 0;
+	virtual ~Sequence_file_format()
+	{ }
+	
+};
+
+struct FASTA_format : public Sequence_file_format
+{
+
+	FASTA_format()
+	{ }
+
+	virtual bool get_seq(vector<char> &id, vector<Letter> &seq, Input_stream &s) const;
+
+	virtual ~FASTA_format()
+	{ }
+
+};
+
+struct FASTQ_format : public Sequence_file_format
+{
+
+	FASTQ_format()
+	{ }
+
+	virtual bool get_seq(vector<char> &id, vector<Letter> &seq, Input_stream &s) const;
+
+	virtual ~FASTQ_format()
+	{ }
+
+};
+
+const Sequence_file_format* guess_format(Input_stream &file);
+
+#endif /* SEQ_FILE_FORMAT_H_ */
\ No newline at end of file
diff --git a/src/util/simd.h b/src/util/simd.h
new file mode 100644
index 0000000..5992f5c
--- /dev/null
+++ b/src/util/simd.h
@@ -0,0 +1,62 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef SIMD_H_
+#define SIMD_H_
+
+#include "system.h"
+
+#ifdef _MSC_VER
+#define __MMX__
+#define __SSE__
+#define __SSE2__
+#define __SSSE3__
+#define __SSE4_1__
+#endif
+
+#ifdef __SSSE3__
+#include <tmmintrin.h>
+#endif
+#ifdef __SSE4_1__
+#include <smmintrin.h>
+#endif
+#ifdef __MMX__
+#include <mmintrin.h>
+#endif
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+inline bool check_SSSE3()
+{
+#ifdef __SSSE3__
+	int info[4];
+	cpuid(info, 0);
+	int nids = info[0];
+	if (nids >= 1) {
+		cpuid(info, 1);
+		return (info[2] & (1 << 9)) != 0;
+	}
+#endif
+	return false;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/util/system.h b/src/util/system.h
new file mode 100644
index 0000000..94651ca
--- /dev/null
+++ b/src/util/system.h
@@ -0,0 +1,53 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef SYSTEM_H_
+#define SYSTEM_H_
+
+#ifdef _WIN32
+#define cpuid(info,x)    __cpuidex(info,x,0)
+#else
+inline void cpuid(int CPUInfo[4],int InfoType) {
+    __asm__ __volatile__ (
+        "cpuid":
+        "=a" (CPUInfo[0]),
+        "=b" (CPUInfo[1]),
+        "=c" (CPUInfo[2]),
+        "=d" (CPUInfo[3]) :
+        "a" (InfoType), "c" (0)
+    );
+}
+#endif
+
+#ifdef _MSC_VER
+
+#define PACKED_ATTRIBUTE
+#define FTELL(x) _ftelli64(x)
+#define FSEEK(x,y,z) _fseeki64(x,y,z)
+
+#else
+
+#define PACKED_ATTRIBUTE __attribute__((packed))
+#define FTELL(x) ftell(x)
+#define FSEEK(x,y,z) fseek(x,y,z)
+
+#endif
+
+#endif /* SYSTEM_H_ */
diff --git a/src/util/system_c.h b/src/util/system_c.h
new file mode 100644
index 0000000..1c8023d
--- /dev/null
+++ b/src/util/system_c.h
@@ -0,0 +1,10 @@
+#ifndef SYSTEM_C_H_
+#define SYSTEM_C_H_
+
+#ifdef _MSC_VER
+typedef __int64 ssize_t;
+#define STDIN_FILENO _fileno(stdin)
+#define STDOUT_FILENO _fileno(stdout)
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/util/task_queue.h b/src/util/task_queue.h
new file mode 100644
index 0000000..dad5bc1
--- /dev/null
+++ b/src/util/task_queue.h
@@ -0,0 +1,152 @@
+/****
+Copyright (c) 2014, University of Tuebingen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****
+Author: Benjamin Buchfink
+****/
+
+#ifndef TASK_QUEUE_H_
+#define TASK_QUEUE_H_
+
+#include "tinythread.h"
+
+// #define ENABLE_LOGGING
+
+template<typename _t, typename _callback>
+struct Task_queue
+{
+
+	Task_queue(size_t limit, _callback &callback):
+		queue_ (limit),
+		state_ (limit),
+		head_ (0),
+		tail_ (0),
+		limit_ (limit),
+		head_idx_ (0),
+		queued_ (0),
+		queued_size_ (0),
+		at_end_ (false),
+		callback_ (callback)
+	{ }
+
+	volatile bool waiting() const
+	{ return tail_ - head_ >= limit_; }
+
+	template<typename _init>
+	volatile bool get(size_t &n, _t*& res, _init &init)
+	{
+		{
+			mtx_.lock();
+#ifdef ENABLE_LOGGING
+			log_stream << "Task_queue get() thread=" << tthread::thread::get_current_thread_id() << " waiting=" << waiting() << " head=" << head_ << " tail=" << tail_ << endl;
+#endif
+			while(waiting() && !at_end_)
+				cond_.wait(mtx_);
+			if(at_end_) {
+#ifdef ENABLE_LOGGING
+				log_stream << "Task_queue get() thread=" << tthread::thread::get_current_thread_id() << " quit" << endl;
+#endif
+				mtx_.unlock();
+				return false;
+			}
+			n = tail_++;
+			res = &slot(n);
+			if(!init())
+				at_end_ = true;
+#ifdef ENABLE_LOGGING
+			log_stream << "Task_queue get() thread=" << tthread::thread::get_current_thread_id() << " n=" << n << endl;
+#endif
+			mtx_.unlock();
+		}
+		if(at_end_)
+			cond_.notify_all();
+		return true;
+	}
+
+	void wake_all()
+	{ cond_.notify_all(); }
+
+	volatile void push(size_t n)
+	{
+		mtx_.lock();
+		if(n == head_) {
+#ifdef ENABLE_LOGGING
+			log_stream << "Task_queue flush() thread=" << tthread::thread::get_current_thread_id() << " n=" << n << endl;
+#endif
+			mtx_.unlock();
+			flush();
+		} else {
+#ifdef ENABLE_LOGGING
+			message_stream << "Task_queue push() thread=" << tthread::thread::get_current_thread_id() << " n=" << n << " head=" << head_ << " size=" << queued_size_ << endl;
+#endif
+			state_[idx(n)] = true;
+			++queued_;
+			queued_size_ += slot(n).size();
+			mtx_.unlock();
+		}
+	}
+
+	volatile unsigned flush()
+	{
+		bool next = false;
+		unsigned n = 0;
+		do {
+			callback_(slot(head_));
+			{
+				mtx_.lock();
+#ifdef ENABLE_LOGGING
+				log_stream << "Task_queue flush() thread=" << tthread::thread::get_current_thread_id() << " head=" << head_ << " waiting=" << tail_-head_ << "/" << limit_ << " size=" << queued_size_ << endl;
+#endif
+				state_[idx(head_)] = false;
+				++head_;
+				head_idx_ = (head_idx_ + 1) % limit_;
+				if (state_[idx(head_)]) {
+					next = true;
+#ifdef ENABLE_LOGGING
+					log_stream << "Task_queue n=" << queued_ << endl;
+#endif
+					--queued_;
+					queued_size_ -= slot(head_).size();
+				}
+				else
+					next = false;
+				mtx_.unlock();
+			}
+			cond_.notify_one();
+			++n;
+		} while (next);
+		return n;
+	}
+
+private:
+
+	size_t idx(size_t n) const
+	{ return (head_idx_ + n - head_)%limit_; }
+
+	_t& slot(size_t n)
+	{ return queue_[idx(n)]; }
+
+	vector<_t> queue_;
+	vector<bool> state_;
+	tthread::mutex mtx_;
+	tthread::condition_variable cond_;
+	volatile size_t head_, tail_, limit_, head_idx_, queued_, queued_size_;
+	bool at_end_;
+	_callback &callback_;
+
+};
+
+#endif
diff --git a/src/util/temp_file.h b/src/util/temp_file.h
new file mode 100644
index 0000000..3094a11
--- /dev/null
+++ b/src/util/temp_file.h
@@ -0,0 +1,38 @@
+/****
+Copyright (c) 2014-16, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef TEMP_FILE_H_
+#define TEMP_FILE_H_
+
+#include "binary_file.h"
+
+struct Temp_file : public Output_stream
+{
+
+	Temp_file();
+#ifndef _MSC_VER
+	virtual ~Temp_file()
+	{}
+#endif
+	static string get_temp_dir();
+	static unsigned n;
+	static uint64_t hash_key;
+
+};
+
+#endif /* TEMP_FILE_H_ */
diff --git a/src/util/text_buffer.h b/src/util/text_buffer.h
new file mode 100644
index 0000000..ce5e3bb
--- /dev/null
+++ b/src/util/text_buffer.h
@@ -0,0 +1,216 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef TEXT_BUFFER_H_
+#define TEXT_BUFFER_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdexcept>
+#include <stdint.h>
+#include <limits>
+#include "util.h"
+
+struct Text_buffer
+{
+
+	Text_buffer():
+		data_ (0),
+		ptr_ (data_)
+	{ }
+
+	~Text_buffer()
+	{
+		free(data_);
+	}
+
+	void reserve(size_t n)
+	{
+		const size_t s = ptr_ - data_, new_size = s + n + block_size - ((s + n) & (block_size - 1));
+		data_ = (char*)realloc(data_, new_size);
+		ptr_ = data_ + s;
+		if (data_ == 0) throw std::runtime_error("Failed to allocate memory.");
+	}
+
+	void operator+=(size_t n)
+	{ ptr_ += n; }
+
+	operator char*() const
+	{ return ptr_; }
+
+	char* get_begin() const
+	{ return data_; }
+
+	void clear()
+	{ ptr_ = data_; }
+
+	template<typename _t>
+	Text_buffer& write(const _t& data)
+	{
+		reserve(sizeof(_t));
+		*reinterpret_cast<_t*>(ptr_) = data;
+		ptr_ += sizeof(_t);
+		return *this;
+	}
+
+	void write_c_str(const char* s)
+	{
+		const size_t l = strlen(s)+1;
+		reserve(l);
+		memcpy(ptr_, s, l);
+		ptr_ += l;
+	}
+
+	void write_c_str(const char*s, size_t len)
+	{
+		reserve(len+1);
+		memcpy(ptr_, s, len);
+		ptr_ += len;
+		*(ptr_++) = '\0';
+	}
+
+	void write_raw(const char *s, size_t len)
+	{
+		reserve(len);
+		memcpy(ptr_, s, len);
+		ptr_ += len;
+	}
+
+	void write_until(const char *s, const char *delimiters)
+	{
+		write_raw(s, find_first_of(s, delimiters));
+	}
+
+	Text_buffer& write_packed(unsigned x)
+	{
+		if(x <= (unsigned)std::numeric_limits<uint8_t>::max())
+			write((uint8_t)x);
+		else if(x <= (unsigned)std::numeric_limits<uint16_t>::max())
+			write((uint16_t)x);
+		else
+			write(x);
+		return *this;
+	}
+
+	size_t size() const
+	{ return ptr_ - data_; }
+
+	Text_buffer& operator<<(const string &s)
+	{
+		const size_t l = s.length();
+		reserve(l);
+		memcpy(ptr_, s.c_str(), l);
+		ptr_ += l;
+		return *this;
+	}
+
+	Text_buffer& operator<<(const char* s)
+	{
+		const size_t l = strlen(s);
+		reserve(l);
+		memcpy(ptr_, s, l);
+		ptr_ += l;
+		return *this;
+	}
+
+	Text_buffer& operator<<(char c)
+	{
+		reserve(1);
+		*(ptr_++) = c;
+		return *this;
+	}
+
+	Text_buffer& operator<<(uint32_t x)
+	{
+		//write(x);
+		reserve(16);
+		ptr_ += sprintf(ptr_, "%u", x);
+		return *this;
+	}
+
+	Text_buffer& operator<<(int x)
+	{
+		//write(x);
+		reserve(16);
+		ptr_ += sprintf(ptr_, "%i", x);
+		return *this;
+	}
+
+	Text_buffer& operator<<(size_t x)
+	{
+		reserve(32);
+		ptr_ += sprintf(ptr_, "%llu", (unsigned long long)x);
+		return *this;
+	}
+
+	Text_buffer& operator<<(double x)
+	{
+		reserve(32);
+		ptr_ += sprintf(ptr_, "%.1lf", x);
+		return *this;
+	}
+
+	Text_buffer& print_d(double x)
+	{
+		reserve(32);
+		ptr_ += sprintf(ptr_, "%lf", x);
+		return *this;
+	}
+
+	Text_buffer& print_e(double x)
+	{
+		reserve(32);
+		ptr_ += sprintf(ptr_, "%.1le", x);
+		return *this;
+	}
+
+	Text_buffer& print(unsigned i, unsigned width)
+	{
+		reserve(16);
+		ptr_ += sprintf(ptr_, "%4u", i);
+		return *this;
+	}
+
+	/*Text_buffer& operator<<(uint8_t x)
+	{
+		write(x);
+		return *this;
+	}*/
+
+	template<typename _t>
+	Text_buffer& operator<<(const vector<_t> &v)
+	{
+		const size_t l = v.size() * sizeof(_t);
+		reserve(l);
+		memcpy(ptr_, v.data(), l);
+		ptr_ += l;
+		return *this;
+	}
+
+	char& operator[](size_t pos)
+	{
+		return data_[pos];
+	}
+
+protected:
+	enum { block_size = 65536 };
+	char *data_, *ptr_;
+
+};
+
+#endif /* TEXT_BUFFER_H_ */
diff --git a/src/util/thread.h b/src/util/thread.h
new file mode 100644
index 0000000..443589f
--- /dev/null
+++ b/src/util/thread.h
@@ -0,0 +1,287 @@
+/****
+Copyright (c) 2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef THREAD_H_
+#define THREAD_H_
+
+#include <vector>
+#include <exception>
+#include <stdexcept>
+#include "fast_mutex.h"
+#include "tinythread.h"
+#include "util.h"
+
+using tthread::thread;
+using std::vector;
+
+template<typename _t>
+struct Atomic
+{
+	Atomic(const _t &v):
+		v_ (v)
+	{ }
+	Atomic& operator=(const _t &v)
+	{
+		v_ = v;
+		return *this;
+	}
+	volatile _t operator++(int)
+	{
+		mtx_.lock();
+		_t r = v_++;
+		mtx_.unlock();
+		return r;
+	}
+	_t operator--(int)
+	{
+		mtx_.lock();
+		_t r = v_--;
+		mtx_.unlock();
+		return r;
+	}
+private:
+	volatile _t v_;
+	tthread::mutex mtx_;
+};
+
+template<typename _context>
+struct Thread_p
+{
+	Thread_p(unsigned thread_id, _context &context):
+		thread_id (thread_id),
+		context (&context)
+	{ }
+	unsigned thread_id;
+	_context *context;
+};
+
+template<typename _context>
+void pool_worker(void *p)
+{
+	((Thread_p<_context>*)p)->context->operator()(((Thread_p<_context>*)p)->thread_id);
+	TLS::clear();
+}
+
+template<typename _context>
+void launch_thread_pool(_context &context, unsigned threads)
+{
+	vector<tthread::thread*> t;
+	vector<Thread_p<_context> > p;
+	p.reserve(threads);
+	unsigned n = 0;
+	for(unsigned i=0;i<threads;++i) {
+		p.push_back(Thread_p<_context> (i, context));
+		t.push_back(new tthread::thread(pool_worker<_context>, (void*)&p.back()));
+		n += t.back()->get_id() == tthread::thread::id () ? 0 : 1;
+	}
+	for(vector<tthread::thread*>::iterator i=t.begin();i!=t.end();++i) {
+		(*i)->join();
+		delete *i;
+	}
+	if(n != threads)
+		throw std::runtime_error("Failed to create thread.");
+}
+
+template<typename _context>
+struct Schedule_context
+{
+	Schedule_context(_context &context, unsigned count):
+		context (context),
+		n (0),
+		count (count)
+	{ }
+	void operator()(unsigned thread_id)
+	{
+		unsigned idx;
+		while((idx = n++) < count)
+			context(thread_id, idx);
+	}
+	_context &context;
+	Atomic<unsigned> n;
+	const unsigned count;
+};
+
+template<typename _context>
+void launch_scheduled_thread_pool(_context &context, unsigned count, unsigned threads)
+{
+	Schedule_context<_context> c (context, count);
+	launch_thread_pool(c, threads);
+}
+
+template<typename _f, typename _t1>
+struct Thread_p1
+{
+	Thread_p1(_f f, _t1 p1) :
+		f(f),
+		p1(p1)
+	{ }
+	_f f;
+	_t1 p1;
+};
+
+template<typename _f, typename _t1>
+void thread_worker(void *p)
+{
+	Thread_p1<_f, _t1> *q = (Thread_p1<_f, _t1>*)p;
+	q->f(q->p1);
+	delete q;
+	TLS::clear();
+}
+
+template<typename _f, typename _t1>
+thread* launch_thread(_f f, _t1 p1)
+{
+	return new thread(thread_worker<_f, _t1>, new Thread_p1<_f, _t1>(f, p1));
+}
+
+template<typename _f, typename _t1, typename _t2>
+struct Thread_p2
+{
+	Thread_p2(_f f, _t1 p1, _t2 p2) :
+		f(f),
+		p1(p1),
+		p2(p2)
+	{ }
+	_f f;
+	_t1 p1;
+	_t2 p2;
+};
+
+template<typename _f, typename _t1, typename _t2>
+void thread_worker(void *p)
+{
+	Thread_p2<_f, _t1, _t2> *q = (Thread_p2<_f, _t1, _t2>*)p;
+	q->f(q->p1, q->p2);
+	delete q;
+	TLS::clear();
+}
+
+template<typename _f, typename _t1, typename _t2>
+thread* launch_thread(_f f, _t1 p1, _t2 p2)
+{
+	return new thread(thread_worker<_f, _t1, _t2>, new Thread_p2<_f, _t1, _t2>(f, p1, p2));
+}
+
+template<typename _f, typename _t1, typename _t2, typename _t3>
+struct Thread_p3
+{
+	Thread_p3(_f f, _t1 p1, _t2 p2, _t3 p3) :
+		f(f),
+		p1(p1),
+		p2(p2),
+		p3(p3)
+	{ }
+	_f f;
+	_t1 p1;
+	_t2 p2;
+	_t3 p3;
+};
+
+template<typename _f, typename _t1, typename _t2, typename _t3>
+void thread_worker(void *p)
+{
+	Thread_p3<_f, _t1, _t2, _t3> *q = (Thread_p3<_f, _t1, _t2, _t3>*)p;
+	q->f(q->p1, q->p2, q->p3);
+	delete q;
+	TLS::clear();
+}
+
+template<typename _f, typename _t1, typename _t2, typename _t3>
+thread* launch_thread(_f f, _t1 p1, _t2 p2, _t3 p3)
+{
+	return new thread(thread_worker<_f, _t1, _t2, _t3>, new Thread_p3<_f, _t1, _t2, _t3>(f, p1, p2, p3));
+}
+
+template<typename _f, typename _t1, typename _t2, typename _t3, typename _t4>
+struct Thread_p4
+{
+	Thread_p4(_f f, _t1 p1, _t2 p2, _t3 p3, _t4 p4):
+		f (f),
+		p1 (p1),
+		p2 (p2),
+		p3 (p3),
+		p4 (p4)
+	{ }
+	_f f;
+	_t1 p1;
+	_t2 p2;
+	_t3 p3;
+	_t4 p4;
+};
+
+template<typename _f, typename _t1, typename _t2, typename _t3, typename _t4>
+void thread_worker(void *p)
+{
+	Thread_p4<_f,_t1,_t2,_t3,_t4> *q = (Thread_p4<_f,_t1,_t2,_t3,_t4>*)p;
+	q->f(q->p1, q->p2, q->p3, q->p4);
+	delete q;
+	TLS::clear();
+}
+
+template<typename _f, typename _t1, typename _t2, typename _t3, typename _t4>
+thread* launch_thread(_f f, _t1 p1, _t2 p2, _t3 p3, _t4 p4)
+{ return new thread (thread_worker<_f,_t1,_t2,_t3,_t4>, new Thread_p4<_f,_t1,_t2,_t3,_t4> (f, p1, p2, p3, p4)); }
+
+template<typename _f, typename _t1, typename _t2, typename _t3, typename _t4, typename _t5>
+struct Thread_p5
+{
+	Thread_p5(_f f, _t1 p1, _t2 p2, _t3 p3, _t4 p4, _t5 p5) :
+		f(f),
+		p1(p1),
+		p2(p2),
+		p3(p3),
+		p4(p4),
+		p5(p5)
+	{ }
+	_f f;
+	_t1 p1;
+	_t2 p2;
+	_t3 p3;
+	_t4 p4;
+	_t5 p5;
+};
+
+template<typename _f, typename _t1, typename _t2, typename _t3, typename _t4, typename _t5>
+void thread_worker(void *p)
+{
+	Thread_p5<_f, _t1, _t2, _t3, _t4, _t5> *q = (Thread_p5<_f, _t1, _t2, _t3, _t4, _t5>*)p;
+	q->f(q->p1, q->p2, q->p3, q->p4, q->p5);
+	delete q;
+	TLS::clear();
+}
+
+template<typename _f, typename _t1, typename _t2, typename _t3, typename _t4, typename _t5>
+thread* launch_thread(_f f, _t1 p1, _t2 p2, _t3 p3, _t4 p4, _t5 p5)
+{
+	return new thread(thread_worker<_f, _t1, _t2, _t3, _t4, _t5>, new Thread_p5<_f, _t1, _t2, _t3, _t4, _t5>(f, p1, p2, p3, p4, p5));
+}
+
+
+struct Thread_pool : public vector<thread*>
+{
+	void join_all()
+	{
+		for (iterator i = begin(); i != end(); ++i) {
+			(*i)->join();
+			delete *i;
+		}
+		clear();
+	}
+};
+
+#endif /* THREAD_H_ */
diff --git a/src/util/tinythread.cpp b/src/util/tinythread.cpp
new file mode 100644
index 0000000..5ce1319
--- /dev/null
+++ b/src/util/tinythread.cpp
@@ -0,0 +1,319 @@
+/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2010-2012 Marcus Geelnard
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source
+    distribution.
+*/
+
+#include <exception>
+#include <iostream>
+#include "tinythread.h"
+
+#if defined(_TTHREAD_POSIX_)
+  #include <unistd.h>
+  #include <map>
+#elif defined(_TTHREAD_WIN32_)
+  #include <process.h>
+#endif
+
+
+namespace tthread {
+
+//------------------------------------------------------------------------------
+// condition_variable
+//------------------------------------------------------------------------------
+// NOTE 1: The Win32 implementation of the condition_variable class is based on
+// the corresponding implementation in GLFW, which in turn is based on a
+// description by Douglas C. Schmidt and Irfan Pyarali:
+// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+//
+// NOTE 2: Windows Vista actually has native support for condition variables
+// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to
+// be portable with pre-Vista Windows versions, so TinyThread++ does not use
+// Vista condition variables.
+//------------------------------------------------------------------------------
+
+#if defined(_TTHREAD_WIN32_)
+  #define _CONDITION_EVENT_ONE 0
+  #define _CONDITION_EVENT_ALL 1
+#endif
+
+#if defined(_TTHREAD_WIN32_)
+condition_variable::condition_variable() : mWaitersCount(0)
+{
+  mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
+  mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
+  InitializeCriticalSection(&mWaitersCountLock);
+}
+#endif
+
+#if defined(_TTHREAD_WIN32_)
+condition_variable::~condition_variable()
+{
+  CloseHandle(mEvents[_CONDITION_EVENT_ONE]);
+  CloseHandle(mEvents[_CONDITION_EVENT_ALL]);
+  DeleteCriticalSection(&mWaitersCountLock);
+}
+#endif
+
+#if defined(_TTHREAD_WIN32_)
+void condition_variable::_wait()
+{
+  // Wait for either event to become signaled due to notify_one() or
+  // notify_all() being called
+  int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE);
+
+  // Check if we are the last waiter
+  EnterCriticalSection(&mWaitersCountLock);
+  -- mWaitersCount;
+  bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
+                    (mWaitersCount == 0);
+  LeaveCriticalSection(&mWaitersCountLock);
+
+  // If we are the last waiter to be notified to stop waiting, reset the event
+  if(lastWaiter)
+    ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
+}
+#endif
+
+#if defined(_TTHREAD_WIN32_)
+void condition_variable::notify_one()
+{
+  // Are there any waiters?
+  EnterCriticalSection(&mWaitersCountLock);
+  bool haveWaiters = (mWaitersCount > 0);
+  LeaveCriticalSection(&mWaitersCountLock);
+
+  // If we have any waiting threads, send them a signal
+  if(haveWaiters)
+    SetEvent(mEvents[_CONDITION_EVENT_ONE]);
+}
+#endif
+
+#if defined(_TTHREAD_WIN32_)
+void condition_variable::notify_all()
+{
+  // Are there any waiters?
+  EnterCriticalSection(&mWaitersCountLock);
+  bool haveWaiters = (mWaitersCount > 0);
+  LeaveCriticalSection(&mWaitersCountLock);
+
+  // If we have any waiting threads, send them a signal
+  if(haveWaiters)
+    SetEvent(mEvents[_CONDITION_EVENT_ALL]);
+}
+#endif
+
+
+//------------------------------------------------------------------------------
+// POSIX pthread_t to unique thread::id mapping logic.
+// Note: Here we use a global thread safe std::map to convert instances of
+// pthread_t to small thread identifier numbers (unique within one process).
+// This method should be portable across different POSIX implementations.
+//------------------------------------------------------------------------------
+
+#if defined(_TTHREAD_POSIX_)
+static thread::id _pthread_t_to_ID(const pthread_t &aHandle)
+{
+  static mutex idMapLock;
+  static std::map<pthread_t, unsigned long int> idMap;
+  static unsigned long int idCount(1);
+
+  lock_guard<mutex> guard(idMapLock);
+  if(idMap.find(aHandle) == idMap.end())
+    idMap[aHandle] = idCount ++;
+  return thread::id(idMap[aHandle]);
+}
+#endif // _TTHREAD_POSIX_
+
+
+//------------------------------------------------------------------------------
+// thread
+//------------------------------------------------------------------------------
+
+/// Information to pass to the new thread (what to run).
+struct _thread_start_info {
+  void (*mFunction)(void *); ///< Pointer to the function to be executed.
+  void * mArg;               ///< Function argument for the thread function.
+  thread * mThread;          ///< Pointer to the thread object.
+};
+
+// Thread wrapper function.
+#if defined(_TTHREAD_WIN32_)
+unsigned WINAPI thread::wrapper_function(void * aArg)
+#elif defined(_TTHREAD_POSIX_)
+void * thread::wrapper_function(void * aArg)
+#endif
+{
+  // Get thread startup information
+  _thread_start_info * ti = (_thread_start_info *) aArg;
+
+  try
+  {
+    // Call the actual client thread function
+    ti->mFunction(ti->mArg);
+  }
+  catch (std::exception &e) {
+	  std::cerr << "Error: " << e.what() << std::endl;
+	  std::terminate();
+  }
+  catch(...)
+  {
+    // Uncaught exceptions will terminate the application (default behavior
+    // according to C++11)
+    std::terminate();
+  }
+
+  // The thread is no longer executing
+  lock_guard<mutex> guard(ti->mThread->mDataMutex);
+  //ti->mThread->mNotAThread = true;
+
+  // The thread is responsible for freeing the startup information
+  delete ti;
+
+  return 0;
+}
+
+thread::thread(void (*aFunction)(void *), void * aArg)
+{
+  // Serialize access to this thread structure
+  lock_guard<mutex> guard(mDataMutex);
+
+  // Fill out the thread startup information (passed to the thread wrapper,
+  // which will eventually free it)
+  _thread_start_info * ti = new _thread_start_info;
+  ti->mFunction = aFunction;
+  ti->mArg = aArg;
+  ti->mThread = this;
+
+  // The thread is now alive
+  mNotAThread = false;
+
+  // Create the thread
+#if defined(_TTHREAD_WIN32_)
+  mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID);
+#elif defined(_TTHREAD_POSIX_)
+  if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0)
+    mHandle = 0;
+#endif
+
+  // Did we fail to create the thread?
+  if(!mHandle)
+  {
+    mNotAThread = true;
+    delete ti;
+  }
+}
+
+thread::~thread()
+{
+  if(joinable())
+    std::terminate();
+}
+
+void thread::join()
+{
+  if(joinable())
+  {
+#if defined(_TTHREAD_WIN32_)
+    WaitForSingleObject(mHandle, INFINITE);
+    CloseHandle(mHandle);
+	mNotAThread = true;
+#elif defined(_TTHREAD_POSIX_)
+    pthread_join(mHandle, NULL);
+    mNotAThread = true;
+#endif
+  }
+}
+
+bool thread::joinable() const
+{
+  mDataMutex.lock();
+  bool result = !mNotAThread;
+  mDataMutex.unlock();
+  return result;
+}
+
+void thread::detach()
+{
+  mDataMutex.lock();
+  if(!mNotAThread)
+  {
+#if defined(_TTHREAD_WIN32_)
+    CloseHandle(mHandle);
+#elif defined(_TTHREAD_POSIX_)
+    pthread_detach(mHandle);
+#endif
+    mNotAThread = true;
+  }
+  mDataMutex.unlock();
+}
+
+thread::id thread::get_id() const
+{
+  if(!joinable())
+    return id();
+#if defined(_TTHREAD_WIN32_)
+  return id((unsigned long int) mWin32ThreadID);
+#elif defined(_TTHREAD_POSIX_)
+  return _pthread_t_to_ID(mHandle);
+#endif
+}
+
+unsigned thread::get_current_thread_id()
+{
+#if defined(_TTHREAD_WIN32_)
+	return GetCurrentThreadId();
+#else
+	return 0;
+#endif
+}
+
+unsigned thread::hardware_concurrency()
+{
+#if defined(_TTHREAD_WIN32_)
+  SYSTEM_INFO si;
+  GetSystemInfo(&si);
+  return (int) si.dwNumberOfProcessors;
+#elif defined(_SC_NPROCESSORS_ONLN)
+  return (int) sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(_SC_NPROC_ONLN)
+  return (int) sysconf(_SC_NPROC_ONLN);
+#else
+  // The standard requires this function to return zero if the number of
+  // hardware cores could not be determined.
+  return 0;
+#endif
+}
+
+
+//------------------------------------------------------------------------------
+// this_thread
+//------------------------------------------------------------------------------
+
+thread::id this_thread::get_id()
+{
+#if defined(_TTHREAD_WIN32_)
+  return thread::id((unsigned long int) GetCurrentThreadId());
+#elif defined(_TTHREAD_POSIX_)
+  return _pthread_t_to_ID(pthread_self());
+#endif
+}
+
+}
diff --git a/src/util/tinythread.h b/src/util/tinythread.h
new file mode 100644
index 0000000..740b497
--- /dev/null
+++ b/src/util/tinythread.h
@@ -0,0 +1,716 @@
+/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2010-2012 Marcus Geelnard
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source
+    distribution.
+*/
+
+#ifndef _TINYTHREAD_H_
+#define _TINYTHREAD_H_
+
+/// @file
+/// @mainpage TinyThread++ API Reference
+///
+/// @section intro_sec Introduction
+/// TinyThread++ is a minimal, portable implementation of basic threading
+/// classes for C++.
+///
+/// They closely mimic the functionality and naming of the C++11 standard, and
+/// should be easily replaceable with the corresponding std:: variants.
+///
+/// @section port_sec Portability
+/// The Win32 variant uses the native Win32 API for implementing the thread
+/// classes, while for other systems, the POSIX threads API (pthread) is used.
+///
+/// @section class_sec Classes
+/// In order to mimic the threading API of the C++11 standard, subsets of
+/// several classes are provided. The fundamental classes are:
+/// @li tthread::thread
+/// @li tthread::mutex
+/// @li tthread::recursive_mutex
+/// @li tthread::condition_variable
+/// @li tthread::lock_guard
+/// @li tthread::fast_mutex
+///
+/// @section misc_sec Miscellaneous
+/// The following special keywords are available: #thread_local.
+///
+/// For more detailed information (including additional classes), browse the
+/// different sections of this documentation. A good place to start is:
+/// tinythread.h.
+
+// Which platform are we on?
+#if !defined(_TTHREAD_PLATFORM_DEFINED_)
+  #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+    #define _TTHREAD_WIN32_
+  #else
+    #define _TTHREAD_POSIX_
+  #endif
+  #define _TTHREAD_PLATFORM_DEFINED_
+#endif
+
+// Platform specific includes
+#if defined(_TTHREAD_WIN32_)
+  #ifndef WIN32_LEAN_AND_MEAN
+    #define WIN32_LEAN_AND_MEAN
+    #define __UNDEF_LEAN_AND_MEAN
+  #endif
+#define NOMINMAX
+  #include <windows.h>
+  #ifdef __UNDEF_LEAN_AND_MEAN
+    #undef WIN32_LEAN_AND_MEAN
+    #undef __UNDEF_LEAN_AND_MEAN
+  #endif
+#else
+  #include <pthread.h>
+  #include <signal.h>
+  #include <sched.h>
+  #include <unistd.h>
+#endif
+
+// Generic includes
+#include <ostream>
+
+/// TinyThread++ version (major number).
+#define TINYTHREAD_VERSION_MAJOR 1
+/// TinyThread++ version (minor number).
+#define TINYTHREAD_VERSION_MINOR 1
+/// TinyThread++ version (full version).
+#define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR)
+
+// Do we have a fully featured C++11 compiler?
+#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
+  #define _TTHREAD_CPP11_
+#endif
+
+// ...at least partial C++11?
+#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
+  #define _TTHREAD_CPP11_PARTIAL_
+#endif
+
+// Macro for disabling assignments of objects.
+#ifdef _TTHREAD_CPP11_PARTIAL_
+  #define _TTHREAD_DISABLE_ASSIGNMENT(name) \
+      name(const name&) = delete; \
+      name& operator=(const name&) = delete;
+#else
+  #define _TTHREAD_DISABLE_ASSIGNMENT(name) \
+      name(const name&); \
+      name& operator=(const name&);
+#endif
+
+/// @def thread_local
+/// Thread local storage keyword.
+/// A variable that is declared with the @c thread_local keyword makes the
+/// value of the variable local to each thread (known as thread-local storage,
+/// or TLS). Example usage:
+/// @code
+/// // This variable is local to each thread.
+/// thread_local int variable;
+/// @endcode
+/// @note The @c thread_local keyword is a macro that maps to the corresponding
+/// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard
+/// allows for non-trivial types (e.g. classes with constructors and
+/// destructors) to be declared with the @c thread_local keyword, most pre-C++11
+/// compilers only allow for trivial types (e.g. @c int). So, to guarantee
+/// portable code, only use trivial types for thread local storage.
+/// @note This directive is currently not supported on Mac OS X (it will give
+/// a compiler error), since compile-time TLS is not supported in the Mac OS X
+/// executable format. Also, some older versions of MinGW (before GCC 4.x) do
+/// not support this directive.
+/// @hideinitializer
+
+#if !defined(_TTHREAD_CPP11_) && !defined(thread_local)
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+  #define thread_local __thread
+ #else
+  #define thread_local __declspec(thread)
+ #endif
+#endif
+
+
+/// Main name space for TinyThread++.
+/// This namespace is more or less equivalent to the @c std namespace for the
+/// C++11 thread classes. For instance, the tthread::mutex class corresponds to
+/// the std::mutex class.
+namespace tthread {
+
+/// Mutex class.
+/// This is a mutual exclusion object for synchronizing access to shared
+/// memory areas for several threads. The mutex is non-recursive (i.e. a
+/// program may deadlock if the thread that owns a mutex object calls lock()
+/// on that object).
+/// @see recursive_mutex
+class mutex {
+  public:
+    /// Constructor.
+    mutex()
+#if defined(_TTHREAD_WIN32_)
+      : mAlreadyLocked(false)
+#endif
+    {
+#if defined(_TTHREAD_WIN32_)
+      InitializeCriticalSection(&mHandle);
+#else
+      pthread_mutex_init(&mHandle, NULL);
+#endif
+    }
+
+    /// Destructor.
+    ~mutex()
+    {
+#if defined(_TTHREAD_WIN32_)
+      DeleteCriticalSection(&mHandle);
+#else
+      pthread_mutex_destroy(&mHandle);
+#endif
+    }
+
+    /// Lock the mutex.
+    /// The method will block the calling thread until a lock on the mutex can
+    /// be obtained. The mutex remains locked until @c unlock() is called.
+    /// @see lock_guard
+    inline void lock()
+    {
+#if defined(_TTHREAD_WIN32_)
+      EnterCriticalSection(&mHandle);
+      //while(mAlreadyLocked) Sleep(1000); // Simulate deadlock...
+      mAlreadyLocked = true;
+#else
+      pthread_mutex_lock(&mHandle);
+#endif
+    }
+
+    /// Try to lock the mutex.
+    /// The method will try to lock the mutex. If it fails, the function will
+    /// return immediately (non-blocking).
+    /// @return @c true if the lock was acquired, or @c false if the lock could
+    /// not be acquired.
+    inline bool try_lock()
+    {
+#if defined(_TTHREAD_WIN32_)
+      bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
+      if(ret && mAlreadyLocked)
+      {
+        LeaveCriticalSection(&mHandle);
+        ret = false;
+      }
+      return ret;
+#else
+      return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
+#endif
+    }
+
+    /// Unlock the mutex.
+    /// If any threads are waiting for the lock on this mutex, one of them will
+    /// be unblocked.
+    inline void unlock()
+    {
+#if defined(_TTHREAD_WIN32_)
+      mAlreadyLocked = false;
+      LeaveCriticalSection(&mHandle);
+#else
+      pthread_mutex_unlock(&mHandle);
+#endif
+    }
+
+    _TTHREAD_DISABLE_ASSIGNMENT(mutex)
+
+  private:
+#if defined(_TTHREAD_WIN32_)
+    CRITICAL_SECTION mHandle;
+    bool mAlreadyLocked;
+#else
+    pthread_mutex_t mHandle;
+#endif
+
+    friend class condition_variable;
+};
+
+/// Recursive mutex class.
+/// This is a mutual exclusion object for synchronizing access to shared
+/// memory areas for several threads. The mutex is recursive (i.e. a thread
+/// may lock the mutex several times, as long as it unlocks the mutex the same
+/// number of times).
+/// @see mutex
+class recursive_mutex {
+  public:
+    /// Constructor.
+    recursive_mutex()
+    {
+#if defined(_TTHREAD_WIN32_)
+      InitializeCriticalSection(&mHandle);
+#else
+      pthread_mutexattr_t attr;
+      pthread_mutexattr_init(&attr);
+      pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+      pthread_mutex_init(&mHandle, &attr);
+#endif
+    }
+
+    /// Destructor.
+    ~recursive_mutex()
+    {
+#if defined(_TTHREAD_WIN32_)
+      DeleteCriticalSection(&mHandle);
+#else
+      pthread_mutex_destroy(&mHandle);
+#endif
+    }
+
+    /// Lock the mutex.
+    /// The method will block the calling thread until a lock on the mutex can
+    /// be obtained. The mutex remains locked until @c unlock() is called.
+    /// @see lock_guard
+    inline void lock()
+    {
+#if defined(_TTHREAD_WIN32_)
+      EnterCriticalSection(&mHandle);
+#else
+      pthread_mutex_lock(&mHandle);
+#endif
+    }
+
+    /// Try to lock the mutex.
+    /// The method will try to lock the mutex. If it fails, the function will
+    /// return immediately (non-blocking).
+    /// @return @c true if the lock was acquired, or @c false if the lock could
+    /// not be acquired.
+    inline bool try_lock()
+    {
+#if defined(_TTHREAD_WIN32_)
+      return TryEnterCriticalSection(&mHandle) ? true : false;
+#else
+      return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
+#endif
+    }
+
+    /// Unlock the mutex.
+    /// If any threads are waiting for the lock on this mutex, one of them will
+    /// be unblocked.
+    inline void unlock()
+    {
+#if defined(_TTHREAD_WIN32_)
+      LeaveCriticalSection(&mHandle);
+#else
+      pthread_mutex_unlock(&mHandle);
+#endif
+    }
+
+    _TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
+
+  private:
+#if defined(_TTHREAD_WIN32_)
+    CRITICAL_SECTION mHandle;
+#else
+    pthread_mutex_t mHandle;
+#endif
+
+    friend class condition_variable;
+};
+
+/// Lock guard class.
+/// The constructor locks the mutex, and the destructor unlocks the mutex, so
+/// the mutex will automatically be unlocked when the lock guard goes out of
+/// scope. Example usage:
+/// @code
+/// mutex m;
+/// int counter;
+///
+/// void increment()
+/// {
+///   lock_guard<mutex> guard(m);
+///   ++ counter;
+/// }
+/// @endcode
+
+template <class T>
+class lock_guard {
+  public:
+    typedef T mutex_type;
+
+    lock_guard() : mMutex(0) {}
+
+    /// The constructor locks the mutex.
+    explicit lock_guard(mutex_type &aMutex)
+    {
+      mMutex = &aMutex;
+      mMutex->lock();
+    }
+
+    /// The destructor unlocks the mutex.
+    ~lock_guard()
+    {
+      if(mMutex)
+        mMutex->unlock();
+    }
+
+  private:
+    mutex_type * mMutex;
+};
+
+/// Condition variable class.
+/// This is a signalling object for synchronizing the execution flow for
+/// several threads. Example usage:
+/// @code
+/// // Shared data and associated mutex and condition variable objects
+/// int count;
+/// mutex m;
+/// condition_variable cond;
+///
+/// // Wait for the counter to reach a certain number
+/// void wait_counter(int targetCount)
+/// {
+///   lock_guard<mutex> guard(m);
+///   while(count < targetCount)
+///     cond.wait(m);
+/// }
+///
+/// // Increment the counter, and notify waiting threads
+/// void increment()
+/// {
+///   lock_guard<mutex> guard(m);
+///   ++ count;
+///   cond.notify_all();
+/// }
+/// @endcode
+class condition_variable {
+  public:
+    /// Constructor.
+#if defined(_TTHREAD_WIN32_)
+    condition_variable();
+#else
+    condition_variable()
+    {
+      pthread_cond_init(&mHandle, NULL);
+    }
+#endif
+
+    /// Destructor.
+#if defined(_TTHREAD_WIN32_)
+    ~condition_variable();
+#else
+    ~condition_variable()
+    {
+      pthread_cond_destroy(&mHandle);
+    }
+#endif
+
+    /// Wait for the condition.
+    /// The function will block the calling thread until the condition variable
+    /// is woken by @c notify_one(), @c notify_all() or a spurious wake up.
+    /// @param[in] aMutex A mutex that will be unlocked when the wait operation
+    ///   starts, an locked again as soon as the wait operation is finished.
+    template <class _mutexT>
+    inline void wait(_mutexT &aMutex)
+    {
+#if defined(_TTHREAD_WIN32_)
+      // Increment number of waiters
+      EnterCriticalSection(&mWaitersCountLock);
+      ++ mWaitersCount;
+      LeaveCriticalSection(&mWaitersCountLock);
+
+      // Release the mutex while waiting for the condition (will decrease
+      // the number of waiters when done)...
+      aMutex.unlock();
+      _wait();
+      aMutex.lock();
+#else
+      pthread_cond_wait(&mHandle, &aMutex.mHandle);
+#endif
+    }
+
+    /// Notify one thread that is waiting for the condition.
+    /// If at least one thread is blocked waiting for this condition variable,
+    /// one will be woken up.
+    /// @note Only threads that started waiting prior to this call will be
+    /// woken up.
+#if defined(_TTHREAD_WIN32_)
+    void notify_one();
+#else
+    inline void notify_one()
+    {
+      pthread_cond_signal(&mHandle);
+    }
+#endif
+
+    /// Notify all threads that are waiting for the condition.
+    /// All threads that are blocked waiting for this condition variable will
+    /// be woken up.
+    /// @note Only threads that started waiting prior to this call will be
+    /// woken up.
+#if defined(_TTHREAD_WIN32_)
+    void notify_all();
+#else
+    inline void notify_all()
+    {
+      pthread_cond_broadcast(&mHandle);
+    }
+#endif
+
+    _TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
+
+  private:
+#if defined(_TTHREAD_WIN32_)
+    void _wait();
+    HANDLE mEvents[2];                  ///< Signal and broadcast event HANDLEs.
+    unsigned int mWaitersCount;         ///< Count of the number of waiters.
+    CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount.
+#else
+    pthread_cond_t mHandle;
+#endif
+};
+
+
+/// Thread class.
+class thread {
+  public:
+#if defined(_TTHREAD_WIN32_)
+    typedef HANDLE native_handle_type;
+#else
+    typedef pthread_t native_handle_type;
+#endif
+
+    class id;
+
+    /// Default constructor.
+    /// Construct a @c thread object without an associated thread of execution
+    /// (i.e. non-joinable).
+    thread() : mHandle(0), mNotAThread(true)
+#if defined(_TTHREAD_WIN32_)
+    , mWin32ThreadID(0)
+#endif
+    {}
+
+    /// Thread starting constructor.
+    /// Construct a @c thread object with a new thread of execution.
+    /// @param[in] aFunction A function pointer to a function of type:
+    ///          <tt>void fun(void * arg)</tt>
+    /// @param[in] aArg Argument to the thread function.
+    /// @note This constructor is not fully compatible with the standard C++
+    /// thread class. It is more similar to the pthread_create() (POSIX) and
+    /// CreateThread() (Windows) functions.
+    thread(void (*aFunction)(void *), void * aArg);
+
+    /// Destructor.
+    /// @note If the thread is joinable upon destruction, @c std::terminate()
+    /// will be called, which terminates the process. It is always wise to do
+    /// @c join() before deleting a thread object.
+    ~thread();
+
+    /// Wait for the thread to finish (join execution flows).
+    /// After calling @c join(), the thread object is no longer associated with
+    /// a thread of execution (i.e. it is not joinable, and you may not join
+    /// with it nor detach from it).
+    void join();
+
+    /// Check if the thread is joinable.
+    /// A thread object is joinable if it has an associated thread of execution.
+    bool joinable() const;
+
+    /// Detach from the thread.
+    /// After calling @c detach(), the thread object is no longer assicated with
+    /// a thread of execution (i.e. it is not joinable). The thread continues
+    /// execution without the calling thread blocking, and when the thread
+    /// ends execution, any owned resources are released.
+    void detach();
+
+    /// Return the thread ID of a thread object.
+    id get_id() const;
+
+    /// Get the native handle for this thread.
+    /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
+    /// is a @c pthread_t.
+    inline native_handle_type native_handle()
+    {
+      return mHandle;
+    }
+
+    /// Determine the number of threads which can possibly execute concurrently.
+    /// This function is useful for determining the optimal number of threads to
+    /// use for a task.
+    /// @return The number of hardware thread contexts in the system.
+    /// @note If this value is not defined, the function returns zero (0).
+    static unsigned hardware_concurrency();
+	static unsigned get_current_thread_id();
+
+    _TTHREAD_DISABLE_ASSIGNMENT(thread)
+
+  private:
+    native_handle_type mHandle;   ///< Thread handle.
+    mutable mutex mDataMutex;     ///< Serializer for access to the thread private data.
+    bool mNotAThread;             ///< True if this object is not a thread of execution.
+#if defined(_TTHREAD_WIN32_)
+    unsigned int mWin32ThreadID;  ///< Unique thread ID (filled out by _beginthreadex).
+#endif
+
+    // This is the internal thread wrapper function.
+#if defined(_TTHREAD_WIN32_)
+    static unsigned WINAPI wrapper_function(void * aArg);
+#else
+    static void * wrapper_function(void * aArg);
+#endif
+};
+
+/// Thread ID.
+/// The thread ID is a unique identifier for each thread.
+/// @see thread::get_id()
+class thread::id {
+  public:
+    /// Default constructor.
+    /// The default constructed ID is that of thread without a thread of
+    /// execution.
+    id() : mId(0) {};
+
+    id(unsigned long int aId) : mId(aId) {};
+
+    id(const id& aId) : mId(aId.mId) {};
+
+    inline id & operator=(const id &aId)
+    {
+      mId = aId.mId;
+      return *this;
+    }
+
+    inline friend bool operator==(const id &aId1, const id &aId2)
+    {
+      return (aId1.mId == aId2.mId);
+    }
+
+    inline friend bool operator!=(const id &aId1, const id &aId2)
+    {
+      return (aId1.mId != aId2.mId);
+    }
+
+    inline friend bool operator<=(const id &aId1, const id &aId2)
+    {
+      return (aId1.mId <= aId2.mId);
+    }
+
+    inline friend bool operator<(const id &aId1, const id &aId2)
+    {
+      return (aId1.mId < aId2.mId);
+    }
+
+    inline friend bool operator>=(const id &aId1, const id &aId2)
+    {
+      return (aId1.mId >= aId2.mId);
+    }
+
+    inline friend bool operator>(const id &aId1, const id &aId2)
+    {
+      return (aId1.mId > aId2.mId);
+    }
+
+    inline friend std::ostream& operator <<(std::ostream &os, const id &obj)
+    {
+      os << obj.mId;
+      return os;
+    }
+
+  private:
+    unsigned long int mId;
+};
+
+
+// Related to <ratio> - minimal to be able to support chrono.
+typedef long long __intmax_t;
+
+/// Minimal implementation of the @c ratio class. This class provides enough
+/// functionality to implement some basic @c chrono classes.
+template <__intmax_t N, __intmax_t D = 1> class ratio {
+  public:
+    static double _as_double() { return double(N) / double(D); }
+};
+
+/// Minimal implementation of the @c chrono namespace.
+/// The @c chrono namespace provides types for specifying time intervals.
+namespace chrono {
+  /// Duration template class. This class provides enough functionality to
+  /// implement @c this_thread::sleep_for().
+  template <class _Rep, class _Period = ratio<1> > class duration {
+    private:
+      _Rep rep_;
+    public:
+      typedef _Rep rep;
+      typedef _Period period;
+
+      /// Construct a duration object with the given duration.
+      template <class _Rep2>
+        explicit duration(const _Rep2& r) : rep_(r) {};
+
+      /// Return the value of the duration object.
+      rep count() const
+      {
+        return rep_;
+      }
+  };
+
+  // Standard duration types.
+  typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds.
+  typedef duration<__intmax_t, ratio<1, 1000000> > microseconds;   ///< Duration with the unit microseconds.
+  typedef duration<__intmax_t, ratio<1, 1000> > milliseconds;      ///< Duration with the unit milliseconds.
+  typedef duration<__intmax_t> seconds;                            ///< Duration with the unit seconds.
+  typedef duration<__intmax_t, ratio<60> > minutes;                ///< Duration with the unit minutes.
+  typedef duration<__intmax_t, ratio<3600> > hours;                ///< Duration with the unit hours.
+}
+
+/// The namespace @c this_thread provides methods for dealing with the
+/// calling thread.
+namespace this_thread {
+  /// Return the thread ID of the calling thread.
+  thread::id get_id();
+
+  /// Yield execution to another thread.
+  /// Offers the operating system the opportunity to schedule another thread
+  /// that is ready to run on the current processor.
+  inline void yield()
+  {
+#if defined(_TTHREAD_WIN32_)
+    Sleep(0);
+#else
+    sched_yield();
+#endif
+  }
+
+  /// Blocks the calling thread for a period of time.
+  /// @param[in] aTime Minimum time to put the thread to sleep.
+  /// Example usage:
+  /// @code
+  /// // Sleep for 100 milliseconds
+  /// this_thread::sleep_for(chrono::milliseconds(100));
+  /// @endcode
+  /// @note Supported duration types are: nanoseconds, microseconds,
+  /// milliseconds, seconds, minutes and hours.
+  template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period>& aTime)
+  {
+#if defined(_TTHREAD_WIN32_)
+    Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
+#else
+    usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
+#endif
+  }
+}
+
+}
+
+// Define/macro cleanup
+#undef _TTHREAD_DISABLE_ASSIGNMENT
+
+#endif // _TINYTHREAD_H_
diff --git a/src/util/util.cpp b/src/util/util.cpp
new file mode 100644
index 0000000..b8ecc36
--- /dev/null
+++ b/src/util/util.cpp
@@ -0,0 +1,101 @@
+/****
+Copyright (c) 2016, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#include <stdio.h>
+#include <exception>
+#include <sstream>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include "../basic/config.h"
+#include "log_stream.h"
+#include "complexity_filter.h"
+#include "util.h"
+#include "temp_file.h"
+#include "binary_file.h"
+
+Message_stream message_stream;
+Message_stream verbose_stream (false);
+Message_stream log_stream (false);
+
+const Complexity_filter Complexity_filter::instance;
+TLS_PTR vector<Ptr_wrapper_base*> *TLS::ptr_;
+
+#ifndef _MSC_VER
+const char dir_separator = '/';
+#else
+const char dir_separator = '\\';
+#endif
+
+string extract_dir(const string & s)
+{
+	return s.find_last_of(dir_separator) == string::npos ? "" : s.substr(0, s.find_last_of(dir_separator));
+}
+
+unsigned Temp_file::n = 0;
+uint64_t Temp_file::hash_key;
+
+Temp_file::Temp_file()
+{
+	if (n == 0) {
+#ifdef WIN32
+		LARGE_INTEGER count;
+		QueryPerformanceCounter(&count);
+		hash_key = (uint64_t)(count.HighPart + count.LowPart + count.QuadPart + GetCurrentProcessId());
+#else
+		timeval count;
+		gettimeofday(&count, NULL);
+		hash_key = count.tv_sec + count.tv_usec + getpid();
+#endif
+	}
+	std::stringstream ss;
+	ss.setf(std::ios::hex, std::ios::basefield);
+	if (config.tmpdir != "")
+		ss << config.tmpdir << dir_separator;
+	ss << "diamond-" << hash_key << "-" << n++ << ".tmp";
+	ss >> this->file_name_;
+	this->f_ = fopen(this->file_name_.c_str(), "w+b");
+	if (this->f_ == 0)
+		throw std::runtime_error("Error opening temporary file: " + this->file_name_);
+#ifndef _MSC_VER
+	unlink(this->file_name_.c_str());
+#endif
+}
+
+string Temp_file::get_temp_dir()
+{
+	Temp_file t;
+	Input_stream f(t);
+	f.close_and_delete();
+	return extract_dir(f.file_name);
+}
+
+Sd::Sd(const vector<Sd> &groups):
+	A(0),
+	Q(0),
+	k(0)
+{
+	for (unsigned i = 0; i < groups.size(); ++i) {
+		k += groups[i].k;
+		A += groups[i].A * groups[i].k;
+		Q += groups[i].Q;
+	}
+	A /= k;
+	for (unsigned i = 0; i < groups.size(); ++i)
+		Q += (groups[i].A - A)*(groups[i].A - A)*groups[i].k;
+}
\ No newline at end of file
diff --git a/src/util/util.h b/src/util/util.h
new file mode 100644
index 0000000..2407bd9
--- /dev/null
+++ b/src/util/util.h
@@ -0,0 +1,542 @@
+/****
+Copyright (c) 2014-2016, University of Tuebingen, Benjamin Buchfink
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+****/
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <iostream>
+#include <string.h>
+#include <sys/stat.h>
+#include <math.h>
+#include <ctype.h>
+#include <string>
+#include "simd.h"
+#include "../basic/const.h"
+#include "../basic/packed_loc.h"
+
+using std::vector;
+using std::string;
+
+template<typename _t=size_t>
+struct partition
+{
+	_t items, parts, size, remainder;
+	partition() : items(0), parts(0), size(0), remainder(0)
+	{ }
+	partition(_t items, _t parts) : items(items), parts(std::min(parts, items))
+	{
+		if(this->parts > 0) {
+			size = items / this->parts;
+			remainder = items % this->parts;
+		} else {
+			size = 0;
+			remainder = 0;
+		}
+	}
+	_t getMin(_t i) const
+	{ _t b = std::min(i, remainder); return b*(size+1) + (i-b)*size; }
+	_t getMax(_t i) const
+	{ return getMin(i) + getCount(i); }
+	_t getCount(_t i) const
+	{ return i < remainder ? (size + 1) : size; }
+};
+
+struct interval
+{
+	interval():
+		begin_ (0),
+		end_ (0)
+	{ }
+	interval(unsigned begin, unsigned end):
+		begin_ (begin),
+		end_ (end)
+	{ }
+	unsigned length() const
+	{ return end_ > begin_ ? end_ - begin_ : 0; }
+	unsigned overlap(const interval &rhs) const
+	{ return intersect(*this, rhs).length(); }
+	double overlap_factor(const interval &rhs) const
+	{
+		return (double)overlap(rhs) / (double)length();
+	}
+	bool includes(unsigned p) const
+	{ return p >= begin_ && p < end_; }
+	friend inline interval intersect(const interval &lhs, const interval &rhs)
+	{ return interval (std::max(lhs.begin_, rhs.begin_), std::min(lhs.end_, rhs.end_)); }
+	friend std::ostream& operator<<(std::ostream &os, const interval &x)
+	{ os << "[" << x.begin_ << ";" << x.end_ << "]"; return os; }
+	bool operator<(const interval &rhs) const
+	{
+		return begin_ < rhs.begin_;
+	}
+	unsigned begin_, end_;
+};
+
+#ifdef __SSE2__
+inline void print(const __m128i &x)
+{
+	char *p=(char*)&x;
+	for(unsigned i=0;i<16;++i)
+		std::cout << int(*(p++)) << ' ';
+	std::cout << std::endl;
+}
+#endif
+
+template<typename _it, typename _key>
+inline vector<size_t> map_partition(_it begin, _it end, const _key& key, size_t min_size, size_t max_segments, size_t min_segments)
+{
+	const size_t n = end - begin;
+	const ::partition<size_t> p (n, std::max(min_segments, std::min(max_segments, n/min_size)));
+	vector<size_t> v (p.parts+1);
+	v[0] = p.getMin(0);
+	v[p.parts] = p.getMax(p.parts-1);
+	for(unsigned i=0;i<p.parts-1;++i) {
+		size_t e = p.getMax(i);
+		if(v[i] >= e) {
+			v[i+1] = v[i];
+			continue;
+		}
+		while(e < n && key(*(begin+e)) == key(*(begin+e-1)))
+			++e;
+		v[i+1] = e;
+	}
+	return v;
+}
+
+template<typename _t>
+inline _t div_up(_t x, _t m)
+{ return (x + (m-1)) / m; }
+
+template<typename _t>
+inline _t round_up(_t x, _t m)
+{ return div_up(x, m) * m; }
+
+template<typename _val, typename _dir>
+inline void print_seq(const _val* s, const _dir& d)
+{
+	unsigned i=0;
+	while(get_dir(s,i,d) != 0xff) {
+		std::cout << mask_critical(get_dir(s,i,d));
+		++i;
+	}
+}
+
+#ifdef _MSC_VER
+#define TLS_PTR __declspec(thread)
+#else
+#define TLS_PTR __thread
+#endif
+
+struct Ptr_wrapper_base
+{
+	virtual ~Ptr_wrapper_base()
+	{}
+};
+
+template<typename _t>
+struct Ptr_wrapper : public Ptr_wrapper_base
+{
+	Ptr_wrapper(_t *ptr) :
+		ptr(ptr)
+	{}
+	virtual ~Ptr_wrapper()
+	{
+		delete ptr;
+	}
+	_t *ptr;
+};
+
+struct TLS
+{
+	template<typename _t>
+	static _t& get(_t *&ptr)
+	{
+		if (ptr == 0) {
+			ptr = new _t;
+			if (ptr_ == 0)
+				ptr_ = new vector<Ptr_wrapper_base*>;
+			ptr_->push_back(new Ptr_wrapper<_t>(ptr));
+		}
+		return *ptr;
+	}
+	static void clear()
+	{
+		if (ptr_ == 0)
+			return;
+		for (vector<Ptr_wrapper_base*>::iterator i = ptr_->begin(); i != ptr_->end(); ++i)
+			delete *i;
+		delete ptr_;
+	}
+private:
+	static TLS_PTR vector<Ptr_wrapper_base*> *ptr_;
+};
+
+inline vector<string> tokenize(const char *str, const char *delimiters)
+{
+	vector<string> out;
+	while(*str != 0) {
+		while(*str != 0 && strchr(delimiters, *str))
+			++str;
+		string token;
+		while(*str != 0 && strchr(delimiters, *str) == 0)
+			token += *(str++);
+		if(token.length() > 0)
+			out.push_back(token);
+	}
+	if(out.size() == 0)
+		out.push_back(string ());
+	return out;
+}
+
+template<typename _t1, typename _t2>
+struct Pair
+{
+	Pair():
+		first (),
+		second ()
+	{ }
+	Pair(const _t1 &first, const _t2 &second):
+		first (first),
+		second (second)
+	{ }
+	bool operator<(const Pair &rhs) const
+	{
+		return first < rhs.first;
+	}
+	_t1 first;
+	_t2 second;
+};
+
+inline size_t find_first_of(const char *s, const char *delimiters)
+{
+	const char *t = s;
+	while(*t && strchr(delimiters, *t) == 0)
+		++t;
+	return t-s;
+}
+
+inline size_t print_str(char* buf, const char *s, size_t n)
+{
+	memcpy(buf, s, n);
+	*(buf+n) = 0;
+	return n;
+}
+
+inline size_t print_str(char *buf, const char *s, const char *delimiters)
+{ return print_str(buf, s, find_first_of(s, delimiters)); }
+
+inline string* get_str(const char *s, const char *delimiters)
+{
+	return new string (s, find_first_of(s, delimiters));
+}
+
+#ifdef __SSE2__
+inline __m128i _mm_set(char a)
+{
+	const int x = (int)a;
+	return _mm_set1_epi32(x << 24 | x << 16 | x << 8 | x);
+}
+#endif
+
+template<typename _t, unsigned d1, unsigned d2>
+struct Static_matrix
+{
+	_t* operator[](size_t i)
+	{ return data_[i]; }
+private:
+	_t data_[d1][d2];
+};
+
+inline void auto_append_extension(string &str, const char *ext)
+{
+	size_t l = strlen(ext);
+	if(str.length() < l || (str.length() >= l && str.substr(str.length()-l, string::npos) != ext))
+		str += ext;
+}
+
+inline bool check_dir(const string &path)
+{
+#ifndef _MSC_VER
+	struct stat sb;
+	return stat(path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode);
+#else
+	return true;
+#endif
+}
+
+string extract_dir(const string &s);
+
+inline std::ostream& indent(std::ostream &str, unsigned n)
+{
+	for (unsigned i = 0; i < n; ++i)
+		str << ' ';
+	return str;
+}
+
+inline int abs_diff(unsigned x, unsigned y)
+{
+	return abs((int)x - int(y));
+}
+
+template<typename _t, size_t n>
+struct Array
+{
+	Array()
+	{}
+	_t& operator[](size_t i)
+	{
+		return data_[i];
+	}
+	const _t& operator[](size_t i) const
+	{
+		return data_[i];
+	}
+	_t* begin()
+	{
+		return data_;
+	}
+	const _t* begin() const
+	{
+		return data_;
+	}
+	_t* end()
+	{
+		return data_ + n;
+	}
+	_t data_[n];
+};
+
+inline int ctz(uint64_t x)
+{
+#ifdef _MSC_VER
+	if (x)
+		return (int)__popcnt64((x ^ (x - 1)) >> 1);
+	else
+		return CHAR_BIT * sizeof(x);
+#else
+	return __builtin_ctzll(x);
+#endif
+}
+
+template<typename _t>
+inline void assign_ptr(_t& dst, _t *src)
+{
+	dst = *src;
+	delete src;
+}
+
+struct Sd
+{
+	Sd():
+		A(0),
+		Q(0),
+		k(1)
+	{}
+	Sd(const vector<Sd> &groups);
+	void add(double x)
+	{
+		const double d = x - A;
+		Q += (k - 1) / k*d*d;
+		A += d / k;
+		++k;
+	}
+	double mean() const
+	{
+		return A;
+	}
+	double sd() const
+	{
+		return sqrt(Q / (k - 1));
+	}
+private:
+	double A, Q, k;	
+};
+
+inline string to_upper_case(const string &s)
+{
+	string r;
+	for (string::const_iterator i = s.begin(); i != s.end(); ++i)
+		r.push_back(toupper(*i));
+	return r;
+}
+
+inline string to_lower_case(const string &s)
+{
+	string r;
+	for (string::const_iterator i = s.begin(); i != s.end(); ++i)
+		r.push_back(tolower(*i));
+	return r;
+}
+
+template<typename _t>
+struct Matrix
+{
+	void init(int rows, int cols, bool reset = false)
+	{
+		cols_ = cols;
+		if (!reset)
+			data_.resize(rows*cols);
+		else {
+			data_.clear();
+			data_.insert(data_.begin(), rows*cols, _t());
+		}
+	}
+	_t* operator[](int i)
+	{
+		return data_[i*cols_];
+	}
+private:
+	int cols_;
+	vector<_t> data_;
+};
+
+inline int get_idx(const char **a, size_t n, const char *s)
+{
+	for (size_t i = 0; i < n; ++i)
+		if (strcmp(a[i], s) == 0)
+			return (int)i;
+	return -1;
+}
+
+template<int n>
+inline int round_down(int x)
+{
+	return (x / n)*n;
+}
+
+template<int n>
+inline int round_up(int x)
+{
+	return ((x + n - 1) / n)*n;
+}
+
+template<typename _t>
+bool equal(const _t *ptr, unsigned n)
+{
+	const _t v = *ptr;
+	const _t* end = (ptr++) + n;
+	for (; ptr < end; ++ptr)
+		if (*ptr != v)
+			return false;
+	return true;
+}
+
+template<typename _t>
+inline string to_string(_t val)
+{
+	std::stringstream ss;
+	ss << val;
+	return ss.str();
+}
+
+inline string print_char(char c)
+{
+	std::stringstream ss;
+	if (c < 32)
+		ss << "ASCII " << (unsigned)c;
+	else
+		ss << c;
+	return ss.str();
+}
+
+template<typename _t, int n>
+struct Top_list
+{
+	void add(const _t &x)
+	{
+		for (int i = 0; i < n; ++i)
+			if ((int)x >(int)data_[i]) {
+				if (i < n - 1)
+					memmove(&data_[i + 1], &data_[i], sizeof(data_)/n*(n - 1 - i));
+				data_[i] = x;
+				return;
+			}
+	}
+	const _t& operator[](unsigned i) const
+	{
+		return data_[i];
+	}
+	_t& operator[](unsigned i)
+	{
+		return data_[i];
+	}
+private:
+	_t data_[n];
+};
+
+inline unsigned percentage(unsigned x, unsigned y)
+{
+	return x * 100 / y;
+}
+
+inline double percentage(size_t x, size_t y)
+{
+	return x * 100.0 / y;
+}
+
+template<typename _t>
+struct Numeric_vector : public std::vector<_t>
+{
+	Numeric_vector(size_t n):
+		vector<_t>(n)
+	{}
+	Numeric_vector& operator+=(Numeric_vector &x)
+	{
+		for (size_t i = 0; i < this->size(); ++i)
+			this->operator[](i) += x[i];
+		return *this;
+	}
+	Numeric_vector& operator/=(double x)
+	{
+		for (size_t i = 0; i < this->size(); ++i)
+			this->operator[](i) /= x;
+		return *this;
+	}
+	friend std::ostream& operator<<(std::ostream &s, const Numeric_vector &x)
+	{
+		for (size_t i = 0; i < x.size(); ++i)
+			s << x[i] << std::endl;
+		return s;
+	}
+};
+
+template<unsigned n>
+inline unsigned get_distribution(const double *p)
+{
+	const double x = (double)rand() / RAND_MAX;
+	double s = 0;
+	for (unsigned i = 0; i < n; ++i) {
+		s += p[i];
+		if (x < s)
+			return i;
+	}
+	return n - 1;
+}
+
+inline void print_binary(uint64_t x)
+{
+	for (unsigned i = 0; i < 64; ++i) {
+		std::cout << (x & 1);
+		x >>= 1;
+	}
+}
+
+#endif /* UTIL_H_ */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/diamond.git



More information about the debian-med-commit mailing list