From 2e0ec6856bf88f869e89283b650ada53bac75d80 Mon Sep 17 00:00:00 2001 From: Guillaume Rizk Date: Wed, 4 May 2022 03:12:08 -0700 Subject: [PATCH] release 1.3.0-14-ga43013f4 --- INSTALL | 2 +- Makefile | 15 +- README.md | 2 +- config.mk | 58 +- make/compare.mk | 35 - make/dragen_lib.mk | 30 +- make/dragen_stub_lib.mk | 28 +- make/install.mk | 2 +- make/lib.mk | 69 +- make/program.mk | 13 +- make/ssw_lib.mk | 37 +- make/tests.mk | 16 +- make/validate.mk | 65 +- {tests => src}/compare.cpp | 626 +++--- src/dragen-os.cpp | 6 +- src/include/align/Aligner.hpp | 47 +- src/include/align/Alignment.hpp | 1 + src/include/align/AlignmentGenerator.hpp | 22 +- src/include/align/Alignments.hpp | 2 - src/include/align/CalculateRefStartEnd.hpp | 2 +- src/include/align/Cigar.hpp | 7 +- src/include/align/Query.hpp | 2 +- src/include/align/SmithWaterman.hpp | 7 +- src/include/align/VectorSmithWaterman.hpp | 14 +- src/include/bam/Bam.hpp | 9 +- src/include/bam/BamBlockReader.hpp | 60 +- src/include/common/BufferPool.hpp | 136 -- src/include/common/Crc32Hw.hpp | 30 - src/include/common/Debug.hpp | 9 +- src/include/common/DragenConstants.hpp | 54 - src/include/common/FixedPoint.hpp | 110 - src/include/common/GenString.hpp | 57 - src/include/common/PackedUmi.hpp | 230 --- src/include/common/Program.hpp | 52 +- src/include/common/SystemCompatibility.hpp | 7 - src/include/common/Threads.hpp | 38 +- src/include/io/Bam2ReadTransformer.hpp | 5 +- src/include/io/CigarBuilder.hpp | 139 -- src/include/map/Mapper.hpp | 4 + src/include/map/SeedPosition.hpp | 2 +- src/include/options/DragenOsOptions.hpp | 5 +- src/include/reference/HashRecord.hpp | 2 +- src/include/reference/HashtableConfig.hpp | 10 +- src/include/reference/ReferenceDir.hpp | 3 - src/include/reference/ReferenceSequence.hpp | 150 +- .../{align/Sam.hpp => sam/SamGenerator.hpp} | 31 +- .../workflow/DualFastq2SamWorkflow.hpp | 29 +- .../workflow/alignment/AlignmentUtils.hpp | 29 +- src/lib/align/Aligner.cpp | 206 +- src/lib/align/AlignmentGenerator.cpp | 34 +- src/lib/align/AlignmentRescue.cpp | 14 +- src/lib/align/CalculateRefStartEnd.cpp | 8 +- src/lib/align/Cigar.cpp | 2 +- src/lib/align/PairBuilder.cpp | 74 +- src/lib/align/Pairs.cpp | 2 +- src/lib/align/SmithWaterman.cpp | 2 +- src/lib/align/VectorSmithWaterman.cpp | 62 +- .../align/tests/integration/AlignerGtest.cpp | 1 + .../tests/integration/AlignmentsGtest.cpp | 1 + .../tests/integration/PairBuilderGtest.cpp | 48 +- .../tests/integration/SmithWatermanGtest.cpp | 38 +- src/lib/align/tests/unit/CigarGtest.cpp | 18 +- src/lib/align/tests/unit/WavefrontGtest.cpp | 18 +- src/lib/common/BufferPool.cpp | 225 -- src/lib/common/PackedUmi.cpp | 177 -- src/lib/common/Program.cpp | 56 +- src/lib/common/SystemCompatibility.cpp | 33 +- src/lib/fastq/tests/unit/TokenizerGtest.cpp | 6 +- src/lib/io/CigarBuilder.cpp | 136 -- src/lib/io/tests/unit/CigarBuilderGtest.cpp | 50 - .../Fastq2DbamTransformerGtest.cpp.removed | 45 - src/lib/map/ChainBuilder.cpp | 18 +- src/lib/map/Mapper.cpp | 106 +- src/lib/map/SeedChain.cpp | 2 +- src/lib/options/DragenOsOptions.cpp | 45 +- src/lib/reference/Hashtable.cpp | 40 +- src/lib/reference/HashtableConfig.cpp | 6 +- src/lib/reference/ReferenceDir.cpp | 14 +- src/lib/reference/ReferenceSequence.cpp | 66 - .../tests/integration/HashtableGtest.cpp | 6 +- .../tests/unit/ReferenceSequenceGtest.cpp | 3 +- src/lib/sequences/CrcPolynomial.cpp | 2 +- src/lib/sequences/Seed.cpp | 14 +- .../sequences/tests/unit/CrcHasherGtest.cpp | 10 +- src/lib/sequences/tests/unit/SeedGtest.cpp | 88 +- src/lib/workflow/DualFastq2SamWorkflow.cpp | 396 ++-- src/lib/workflow/Input2SamWorkflow.cpp | 54 +- stubs/.clang-format | 3 + .../bamtools-2.4.1/include/api/BamConstants.h | 289 +++ .../dragen_api/dbam/output_dbam_header.hpp | 31 +- .../src/host/infra/public/time_to_str.hpp | 1 + .../src/host/metrics/public/run_stats.hpp | 2 + tests/HashtableGtest.cpp | 60 +- .../common/hash_generation/hash_cfg_file.c | 9 +- .../dragen/src/host/infra/crypto/crc32_hw.c | 32 +- .../host/infra/crypto/fast_nonvector_crc32c.c | 1815 +++++++++++++++++ .../dragen/src/host/infra/public/crc32_hw.h | 17 + .../host/infra/public/fast_nonvector_crc32c.h | 23 + thirdparty/dragen/update.mk | 18 + thirdparty/sswlib/ssw/ssw.c | 1142 ----------- thirdparty/sswlib/ssw/ssw.cpp | 1083 ++++++++++ thirdparty/sswlib/ssw/{ssw.h => ssw.hpp} | 137 +- thirdparty/sswlib/ssw/ssw_avx2.cpp | 510 +++++ thirdparty/sswlib/ssw/ssw_cpp.cpp | 476 ----- thirdparty/sswlib/ssw/ssw_cpp.h | 219 -- thirdparty/sswlib/ssw/ssw_internal.hpp | 85 + 106 files changed, 5665 insertions(+), 4722 deletions(-) delete mode 100644 make/compare.mk rename {tests => src}/compare.cpp (53%) delete mode 100644 src/include/common/BufferPool.hpp delete mode 100644 src/include/common/Crc32Hw.hpp delete mode 100644 src/include/common/DragenConstants.hpp delete mode 100644 src/include/common/FixedPoint.hpp delete mode 100644 src/include/common/GenString.hpp delete mode 100644 src/include/common/PackedUmi.hpp delete mode 100644 src/include/io/CigarBuilder.hpp rename src/include/{align/Sam.hpp => sam/SamGenerator.hpp} (89%) delete mode 100644 src/lib/common/BufferPool.cpp delete mode 100644 src/lib/common/PackedUmi.cpp delete mode 100644 src/lib/io/CigarBuilder.cpp delete mode 100644 src/lib/io/tests/unit/CigarBuilderGtest.cpp delete mode 100644 src/lib/io/tests/unit/Fastq2DbamTransformerGtest.cpp.removed create mode 100644 stubs/.clang-format create mode 100644 stubs/bamtools/bamtools-2.4.1/include/api/BamConstants.h create mode 100644 stubs/dragen/src/host/infra/public/time_to_str.hpp rename src/lib/common/Crc32Hw.cpp => thirdparty/dragen/src/host/infra/crypto/crc32_hw.c (93%) create mode 100644 thirdparty/dragen/src/host/infra/crypto/fast_nonvector_crc32c.c create mode 100644 thirdparty/dragen/src/host/infra/public/crc32_hw.h create mode 100644 thirdparty/dragen/src/host/infra/public/fast_nonvector_crc32c.h create mode 100644 thirdparty/dragen/update.mk delete mode 100644 thirdparty/sswlib/ssw/ssw.c create mode 100644 thirdparty/sswlib/ssw/ssw.cpp rename thirdparty/sswlib/ssw/{ssw.h => ssw.hpp} (69%) create mode 100644 thirdparty/sswlib/ssw/ssw_avx2.cpp delete mode 100644 thirdparty/sswlib/ssw/ssw_cpp.cpp delete mode 100644 thirdparty/sswlib/ssw/ssw_cpp.h create mode 100644 thirdparty/sswlib/ssw/ssw_internal.hpp diff --git a/INSTALL b/INSTALL index 9fadf75..a78d2a7 100644 --- a/INSTALL +++ b/INSTALL @@ -2,7 +2,7 @@ Prerequisites ------------- * CentOS Linux release = 7.6.1810 -* gcc-c++ >= 4.8.5-36.el7_6.2 +* gcc-c++ >= 7.1 * boost169-devel >= 1.69.0-1.el7 * imake >= 1:3.82-23.el7 diff --git a/Makefile b/Makefile index 0752e9d..c0fdd61 100644 --- a/Makefile +++ b/Makefile @@ -19,16 +19,23 @@ include config.mk -all: $(programs:%=$(BUILD)/%) +all: $(programs:%=$(DRAGEN_OS_BUILD)/%) .PHONY: clean clean: $(RMDIR) $(DRAGEN_OS_BUILD_DIR_BASE) .PHONY: help -clean: help: $(DRAGEN_OS_ROOT_DIR)/README.md cat $< + +.PHONY: help-targets +help-targets: + @$(ECHO) 'Default: all' + @$(ECHO) 'Help: help help-targets' + @$(ECHO) 'Cleanup: clean' + @$(ECHO) 'Install: install' + @$(ECHO) 'Libraries: $(library_targets)' ############################################################ ## @@ -50,7 +57,7 @@ POSTCOMPILE ?= mv -f $(@:%.o=%.Td) $(@:%.o=%.d) %/.sentinel: @mkdir -p $* && touch $@ -include $(wildcard $(BUILD)/testRunner.d) +include $(wildcard $(DRAGEN_OS_BUILD)/testRunner.d) # side effects: # - builds 'libraries' variable required for linking programs, integration and system tests @@ -68,7 +75,9 @@ programs_aux:=$(programs) include $(foreach program, $(programs), $(DRAGEN_OS_MAKE_DIR)/program.mk) # programs for system tests +ifeq (1,${HAS_GTEST}) include $(DRAGEN_OS_MAKE_DIR)/tests.mk +endif include $(DRAGEN_OS_MAKE_DIR)/install.mk endif diff --git a/README.md b/README.md index 8db2570..d7b9f63 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Once you have bioconda installed, you should be able to install Dragmap with `c Compilation was tested on CentOS 7 -* C++11 compatible compiler (e.g gcc-c++ >= 4.8.5-36.el7_6.2) +* C++17 compatible compiler (e.g gcc-c++ >= 7.1) * GNU make >= 3.82 * Boost library : boost169-devel >= 1.69.0-1.el7 * For unit tests : googletest (>= v1.6) diff --git a/config.mk b/config.mk index dfbc161..942f00c 100755 --- a/config.mk +++ b/config.mk @@ -27,8 +27,8 @@ endif #CC=$(GCC_BASE)/bin/gcc #CXX=$(GCC_BASE)/bin/g++ -CC=gcc -CXX=g++ +CC?=gcc +CXX?=g++ ############################################################ ## @@ -84,7 +84,8 @@ endif # ifneq(,$(GTEST_ROOT)) ## ############################################################ -SILENT?=$(if $(VERBOSE),,@) +SILENT?=$(if $(VERBOSE),,@ $(ECHO) making $@; ) +SILENT_SE?=$(if $(VERBOSE),,@ $(ECHO) making $$@; ) CAT?=cat ECHO?=echo EVAL?=eval @@ -105,6 +106,7 @@ endif DRAGEN_THIRDPARTY?=$(DRAGEN_OS_ROOT_DIR)/thirdparty DRAGEN_SRC_DIR?=$(DRAGEN_OS_ROOT_DIR)/thirdparty/dragen/src DRAGEN_STUBS_DIR?=$(DRAGEN_OS_ROOT_DIR)/stubs/dragen/src +BAMTOOLS_STUBS_DIR?=$(DRAGEN_OS_ROOT_DIR)/stubs/bamtools/bamtools-2.4.1 SSW_SRC_DIR?=$(DRAGEN_OS_ROOT_DIR)/thirdparty/sswlib DRAGEN_OS_SRC_DIR?=$(DRAGEN_OS_ROOT_DIR)/src DRAGEN_OS_MAKE_DIR?=$(DRAGEN_OS_ROOT_DIR)/make @@ -118,13 +120,13 @@ BUILD_TYPE=release endif # TODO: add support for differentiating by toolset DRAGEN_OS_BUILD_DIR?=$(DRAGEN_OS_BUILD_DIR_BASE)/$(BUILD_TYPE) -BUILD:=$(DRAGEN_OS_BUILD_DIR) +DRAGEN_OS_BUILD:=$(DRAGEN_OS_BUILD_DIR) ## List the libraries in the order where they should be statically linked DRAGEN_OS_LIBS := common options bam fastq sequences io reference map align workflow ## List the libraries from dragen source tree in the order where they should be statically linked -DRAGEN_LIBS := common/hash_generation host/dragen_api/sampling common host/metrics +DRAGEN_LIBS := common/hash_generation host/dragen_api/sampling common host/metrics host/infra/crypto ## List the libraries that pretend the dragen source tree libraries are being linked with rest of dragen source tree DRAGEN_STUB_LIBS := host/dragen_api host/metrics host/infra/linux @@ -145,13 +147,18 @@ endif # version must be tagged in the git repo VERSION_STRING?=$(shell git describe --tags --always --abbrev=8 2> /dev/null || echo "UNKNOWN") +CXXWARNINGS=-Werror -Wno-unused-variable -Wno-free-nonheap-object -Wno-parentheses +CWARNINGS?=-Werror -Wno-unused-variable -Wno-unused-function -Wno-format-truncation +CXXSTD?=-std=c++17 + + CPPFLAGS?=-Wall -ggdb3 #some dragen sources need this CPPFLAGS += -DLOCAL_BUILD CPPFLAGS += -D'DRAGEN_OS_VERSION="$(DRAGEN_OS_VERSION)"' CPPFLAGS += -DVERSION_STRING="$(VERSION_STRING)" -CXXFLAGS?=-std=c++11 -CFLAGS?=-std=c99 +CXXFLAGS+=$(CXXWARNINGS) $(CXXSTD) +CFLAGS+=$(CWARNINGS) LDFLAGS?= ifneq (,$(BOOST_INCLUDEDIR)) @@ -160,30 +167,27 @@ endif #CPPFLAGS += -I $(BAMTOOLS_INCLUDEDIR) CPPFLAGS += -I $(DRAGEN_THIRDPARTY) CPPFLAGS += -I $(DRAGEN_OS_SRC_DIR)/include -CPPFLAGS += -I $(DRAGEN_SRC_DIR) -I $(DRAGEN_SRC_DIR)/common/public -I $(DRAGEN_SRC_DIR)/host/metrics/public +CPPFLAGS += -I $(DRAGEN_SRC_DIR) -I $(DRAGEN_SRC_DIR)/common/public -I $(DRAGEN_SRC_DIR)/host/dragen_api/sampling +CPPFLAGS += -I $(DRAGEN_SRC_DIR)/host/infra/public -I $(DRAGEN_SRC_DIR)/host/metrics/public CPPFLAGS += -I $(SSW_SRC_DIR) -CPPFLAGS += -I $(DRAGEN_STUBS_DIR)/host/dragen_api -I $(DRAGEN_STUBS_DIR)/host/dragen_api/dbam +CPPFLAGS += -I $(DRAGEN_STUBS_DIR)/host/dragen_api -I $(DRAGEN_STUBS_DIR)/host/dragen_api/dbam CPPFLAGS += -I $(DRAGEN_STUBS_DIR)/host/infra/public -I $(DRAGEN_STUBS_DIR)/host/metrics/public +CPPFLAGS += -I $(BAMTOOLS_STUBS_DIR)/include ifneq (,$(BOOST_LIBRARYDIR)) LDFLAGS += -L $(BOOST_LIBRARYDIR) endif LDFLAGS += $(BOOST_LIBRARIES:%=-lboost_%) +CPPFLAGS += -msse4.2 -mavx2 ifdef DEBUG -CPPFLAGS += -O1 -ggdb3 -femit-class-debug-always -fno-omit-frame-pointer +CPPFLAGS += -O0 -ggdb3 -femit-class-debug-always -fno-omit-frame-pointer ifeq ($(DEBUG),glibc) ifeq (,$(BOOST_LIBRARYDIR)) $(error BOOST_LIBRARYDIR is not set. make sure that LD_LIBRARY_PATH and BOOST_LIBRARYDIR point to boost built with _GLIBCXX_DEBUG) endif #ifeq (,$(BOOST_LIBRARYDIR)) CPPFLAGS += -D_GLIBCXX_DEBUG endif #ifeq ($(DEBUG),glibc) -ifdef ASAN -CPPFLAGS += -fsanitize=address -ifeq ($(ASAN),all) -CPPFLAGS += -fsanitize=leak -fsanitize=undefined # Not supported by g++ 4.8 -endif # ifeq ($(ASAN,all) -endif # ASAN #CPPFLAGS += -pg -fstack-usage -fprofile-arcs -ftest-coverage LDFLAGS += -lgcov -Wl,--exclude-libs=ALL else # non DEBUG @@ -191,13 +195,29 @@ else # non DEBUG #CPPFLAGS += -O3 -march=skylake-avx512 # same as above # this seems to be fastest for fastq parsing. mainly because it manages to put proper PSUBB instruction for subtracing q0 from qscore chars -CPPFLAGS += -Wfatal-errors -g -msse4.2 -O2 -ftree-vectorize -finline-functions -fpredictive-commoning -fgcse-after-reload -funswitch-loops -ftree-slp-vectorize -fvect-cost-model -fipa-cp-clone -ftree-phiprop +CPPFLAGS += -g -O2 -ftree-vectorize -finline-functions -fpredictive-commoning -fgcse-after-reload -funswitch-loops -ftree-slp-vectorize -fvect-cost-model -fipa-cp-clone -ftree-phiprop # this seems slightly slower than above #CXXFLAGS += -g -mavx2 -O2 -ftree-vectorize -finline-functions -fpredictive-commoning -fgcse-after-reload -funswitch-loops -ftree-slp-vectorize -fvect-cost-model -fipa-cp-clone -ftree-phiprop endif # if DEBUG -LDFLAGS+= -lz -lstdc++ -lrt -lgomp -lpthread +ifdef ASAN +CPPFLAGS += -fsanitize=address +ifeq ($(ASAN),all) +CPPFLAGS += -fsanitize=leak -fsanitize=undefined # Not supported by g++ 4.8 +endif # ifeq ($(ASAN,all) +endif # ASAN + + +LDFLAGS+= -lz -lrt -lgomp -lpthread + +ifdef STATIC_LIBCPP +LDFLAGS+= -static-libstdc++ +else +LDFLAGS+= -lstdc++ +endif + +#LDFLAGS+= -lz -lstdc++ -lrt -lgomp -lpthread ifneq (,$(GTEST_INCLUDEDIR)) GTEST_CPPFLAGS+= -I $(GTEST_INCLUDEDIR) @@ -233,7 +253,7 @@ all_lib_sources := $(wildcard $(DRAGEN_OS_SRC_DIR)/lib/*/*.cpp) #all_lib_sources += $(wildcard $(DRAGEN_OS_SRC_DIR)/lib/*/*.c) found_lib_dirs := $(sort $(patsubst %/, %, $(dir $(all_lib_sources:$(DRAGEN_OS_SRC_DIR)/lib/%=%)))) all_dragen_lib_sources += $(wildcard $(DRAGEN_SRC_DIR)/*/*/*.cpp) $(wildcard $(DRAGEN_SRC_DIR)/*/*/*/*.cpp) -all_dragen_lib_sources += $(wildcard $(DRAGEN_SRC_DIR)/*/*/*.c) +all_dragen_lib_sources += $(wildcard $(DRAGEN_SRC_DIR)/*/*/*.c) $(wildcard $(DRAGEN_SRC_DIR)/*/*/*/*.c) found_dragen_lib_dirs := $(sort $(patsubst %/, %, $(dir $(all_dragen_lib_sources:$(DRAGEN_SRC_DIR)/%=%)))) ifneq ($(sort $(DRAGEN_OS_LIBS) $(DRAGEN_LIBS)),$(sort $(found_lib_dirs) $(found_dragen_lib_dirs))) $(error found libraries: $(sort $(found_dragen_lib_dirs) $(found_lib_dirs)): expected libraries: $(sort $(DRAGEN_OS_LIBS) $(DRAGEN_LIBS)): verify that the DRAGEN_OS_LIBS and DRAGEN_LIBS variables in config.mk lists the correct libraries) diff --git a/make/compare.mk b/make/compare.mk deleted file mode 100644 index 771aef8..0000000 --- a/make/compare.mk +++ /dev/null @@ -1,35 +0,0 @@ -SHELL:=/bin/bash - -DRAGENOS_DIR:=$(shell pwd) -BASELINE_SAM:=../drgn.flr400/mapq60Positionsc-tlsdragen.sam -FASTQ1:=../FC1-NA12878/original/FC1-NA12878-01_S1.R1_1M.fastq -FASTQ2:=../FC1-NA12878/original/FC1-NA12878-01_S1.R2_1M.fastq -#REFERENCE=/ssd/dragenos/reference_genomes/Hsapiens/hg38-noalt-with-decoy/DRAGEN/8/ -REFERENCE:=../dos-ref -OUTPUT:=/tmp -SAM_DIR:=/tmp -ID:=$(shell git rev-parse HEAD | cut -b1-8) - -default: all - -SAM:=$(OUTPUT)/new-$(ID)-FC1-NA12878-01_S1.R1_R2_1M.sam - -$(SAM): - echo $(ID) ; date ; /usr/bin/time -v $(DRAGENOS_DIR)/build/release/dragen-os \ - -1 "$(FASTQ1)" -2 "$(FASTQ2)" -r "$(REFERENCE)" \ - --preserve-map-align-order 1 --Aligner.pe-orientation 0 \ - --Aligner.pe-stat-mean-insert 210 --Aligner.pe-stat-mean-read-len 148 --Aligner.pe-stat-quartiles-insert "154 199 262" \ - --Aligner.pe-stat-stddev-insert 82 --Aligner.rescue-ceil-factor 5 \ - --enable-sampling 0 --ref-load-hash-bin 1 --mmap-reference 1 > "$@.tmp" 2> "$@.out" && mv $@.tmp $@ - -COMPARE_TXT:=/tmp/compare-$(ID).txt -$(COMPARE_TXT): $(SAM) - $(DRAGENOS_DIR)/build/release/test/compare $(BASELINE_SAM) "$<" -k 1 > $@ - -all: /tmp/compare-$(ID).txt - paste <(cat concordance.txt) <(cut -d= -f2 /tmp/compare-$(ID).txt) | awk -e '{print $$1 "|" $$2 "|"}' - -clean: - -rm $(SAM) - -rm $(COMPARE_TXT) - diff --git a/make/dragen_lib.mk b/make/dragen_lib.mk index e8a418e..ead32f7 100755 --- a/make/dragen_lib.mk +++ b/make/dragen_lib.mk @@ -14,8 +14,8 @@ endif lib_sources := $(wildcard $(DRAGEN_SRC_DIR)/$(lib_dir)/*.cpp) lib_c_sources := $(wildcard $(DRAGEN_SRC_DIR)/$(lib_dir)/*.c) -lib_objects := $(lib_sources:$(DRAGEN_SRC_DIR)/$(lib_dir)/%.cpp=$(BUILD)/drgn_$(lib_dir)/%.o) -lib_objects += $(lib_c_sources:$(DRAGEN_SRC_DIR)/$(lib_dir)/%.c=$(BUILD)/drgn_$(lib_dir)/%.o) +lib_objects := $(lib_sources:$(DRAGEN_SRC_DIR)/$(lib_dir)/%.cpp=$(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.o) +lib_objects += $(lib_c_sources:$(DRAGEN_SRC_DIR)/$(lib_dir)/%.c=$(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.o) include $(wildcard $(lib_objects:%.o=%.d)) @@ -24,28 +24,22 @@ include $(wildcard $(lib_objects:%.o=%.d)) # # ### -$(BUILD)/drgn_$(lib_dir).a: lib_objects:=$(lib_objects) -$(BUILD)/drgn_$(lib_dir).a: $(lib_objects) - $(AR) crfs $@ $(lib_objects) - -#$(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(BUILD)/$(lib_dir)/%.d $(BUILD)/$(lib_dir)/.sentinel -# $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< -# $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/drgn_$(lib_dir).a: lib_objects:=$(lib_objects) +$(DRAGEN_OS_BUILD)/drgn_$(lib_dir).a: $(lib_objects) + $(SILENT) $(AR) crfs $@ $(lib_objects) # Note: the dependency on $(libraries) is to force the order of compilation to be the same as the order of declaration of the libraries -$(BUILD)/drgn_$(lib_dir)/%.o: lib_dir:=$(lib_dir) -$(BUILD)/drgn_$(lib_dir)/%.o: $(DRAGEN_SRC_DIR)/$(lib_dir)/%.cpp $(BUILD)/drgn_$(lib_dir)/%.d $(BUILD)/drgn_$(lib_dir)/.sentinel $(libraries) - $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(DRAGEN_OS_FLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.o: lib_dir:=$(lib_dir) +$(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.o: $(DRAGEN_SRC_DIR)/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/.sentinel + $(SILENT) $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(DRAGEN_OS_FLAGS) -c -o $@ $< && $(POSTCOMPILE) -$(BUILD)/drgn_$(lib_dir)/%.o: $(DRAGEN_SRC_DIR)/$(lib_dir)/%.c $(BUILD)/drgn_$(lib_dir)/%.d $(BUILD)/drgn_$(lib_dir)/.sentinel $(libraries) - $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) $(DRAGEN_OS_FLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.o: $(DRAGEN_SRC_DIR)/$(lib_dir)/%.c $(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/drgn_$(lib_dir)/.sentinel + $(SILENT) $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) $(DRAGEN_OS_FLAGS) -c -o $@ $< && $(POSTCOMPILE) -#$(BUILD)/$(lib_dir)/%.d: ; +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.d: ; ### # must be built in reverse order for linking ### -libraries := $(BUILD)/drgn_$(lib_dir).a $(libraries) +libraries := $(DRAGEN_OS_BUILD)/drgn_$(lib_dir).a $(libraries) diff --git a/make/dragen_stub_lib.mk b/make/dragen_stub_lib.mk index e670400..625f69b 100755 --- a/make/dragen_stub_lib.mk +++ b/make/dragen_stub_lib.mk @@ -12,8 +12,8 @@ endif lib_sources := $(wildcard $(DRAGEN_STUBS_DIR)/$(lib_dir)/*.cpp) lib_c_sources := $(wildcard $(DRAGEN_STUBS_DIR)/$(lib_dir)/*.c) -lib_objects := $(lib_sources:$(DRAGEN_STUBS_DIR)/$(lib_dir)/%.cpp=$(BUILD)/stub_$(lib_dir)/%.o) -lib_objects += $(lib_c_sources:$(DRAGEN_STUBS_DIR)/$(lib_dir)/%.c=$(BUILD)/stub_$(lib_dir)/%.o) +lib_objects := $(lib_sources:$(DRAGEN_STUBS_DIR)/$(lib_dir)/%.cpp=$(DRAGEN_OS_BUILD)/stub_$(lib_dir)/%.o) +lib_objects += $(lib_c_sources:$(DRAGEN_STUBS_DIR)/$(lib_dir)/%.c=$(DRAGEN_OS_BUILD)/stub_$(lib_dir)/%.o) include $(wildcard $(lib_objects:%.o=%.d)) @@ -22,28 +22,26 @@ include $(wildcard $(lib_objects:%.o=%.d)) # # ### -$(BUILD)/stub_$(lib_dir).a: lib_objects:=$(lib_objects) -$(BUILD)/stub_$(lib_dir).a: $(lib_objects) - $(AR) crfs $@ $(lib_objects) +$(DRAGEN_OS_BUILD)/stub_$(lib_dir).a: lib_objects:=$(lib_objects) +$(DRAGEN_OS_BUILD)/stub_$(lib_dir).a: $(lib_objects) + $(SILENT) $(AR) crfs $@ $(lib_objects) -#$(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(BUILD)/$(lib_dir)/%.d $(BUILD)/$(lib_dir)/.sentinel +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/$(lib_dir)/.sentinel # $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< # $(POSTCOMPILE) # Note: the dependency on $(libraries) is to force the order of compilation to be the same as the order of declaration of the libraries -$(BUILD)/stub_$(lib_dir)/%.o: lib_dir:=$(lib_dir) -$(BUILD)/stub_$(lib_dir)/%.o: $(DRAGEN_STUBS_DIR)/$(lib_dir)/%.cpp $(BUILD)/stub_$(lib_dir)/%.d $(BUILD)/stub_$(lib_dir)/.sentinel $(libraries) - $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/stub_$(lib_dir)/%.o: lib_dir:=$(lib_dir) +$(DRAGEN_OS_BUILD)/stub_$(lib_dir)/%.o: $(DRAGEN_STUBS_DIR)/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/stub_$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/stub_$(lib_dir)/.sentinel + $(SILENT) $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< && $(POSTCOMPILE) -$(BUILD)/stub_$(lib_dir)/%.o: $(DRAGEN_STUBS_DIR)/stub_$(lib_dir)/%.c $(BUILD)/$(lib_dir)/%.d $(BUILD)/stub_$(lib_dir)/.sentinel $(libraries) - $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/stub_$(lib_dir)/%.o: $(DRAGEN_STUBS_DIR)/stub_$(lib_dir)/%.c $(DRAGEN_OS_BUILD)/$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/stub_$(lib_dir)/.sentinel + $(SILENT) $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< && $(POSTCOMPILE) -#$(BUILD)/$(lib_dir)/%.d: ; +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.d: ; ### # must be built in reverse order for linking ### -libraries := $(BUILD)/stub_$(lib_dir).a $(libraries) +libraries := $(DRAGEN_OS_BUILD)/stub_$(lib_dir).a $(libraries) diff --git a/make/install.mk b/make/install.mk index cf00b1f..b971692 100644 --- a/make/install.mk +++ b/make/install.mk @@ -4,6 +4,6 @@ bindir?=/bin install: $(programs:%=install_%) -install_%: $(BUILD)/% +install_%: $(DRAGEN_OS_BUILD)/% $(INSTALL) $< $(DESTDIR)$(bindir)/$* diff --git a/make/lib.mk b/make/lib.mk index 54c72bf..16619e0 100755 --- a/make/lib.mk +++ b/make/lib.mk @@ -12,8 +12,8 @@ endif lib_sources := $(wildcard $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/*.cpp) lib_c_sources := $(wildcard $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/*.c) -lib_objects := $(lib_sources:$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp=$(BUILD)/$(lib_dir)/%.o) -lib_objects += $(lib_c_sources:$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.c=$(BUILD)/$(lib_dir)/%.o) +lib_objects := $(lib_sources:$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp=$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o) +lib_objects += $(lib_c_sources:$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.c=$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o) include $(wildcard $(lib_objects:%.o=%.d)) @@ -49,7 +49,7 @@ include $(wildcard $(lib_objects:%.o=%.d)) ### unit_test_src_dir:=$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/tests/unit -unit_test_build_dir:=$(BUILD)/$(lib_dir)/tests/unit +unit_test_build_dir:=$(DRAGEN_OS_BUILD)/$(lib_dir)/tests/unit unit_test_sources:=$(wildcard $(unit_test_src_dir)/*Gtest.cpp) unit_tests:=$(unit_test_sources:$(unit_test_src_dir)/%Gtest.cpp=%) @@ -58,27 +58,24 @@ define UNIT_GTEST include $(wildcard $(unit_test_build_dir)/$(1)Wrapper.d $(unit_test_build_dir)/$(1)Gtest.d) .PRECIOUS: $(unit_test_build_dir)/$(1)Wrapper.cpp $(unit_test_build_dir)/$(1)Wrapper.d $(unit_test_build_dir)/$(1)Wrapper.cpp: $(unit_test_build_dir)/.sentinel - $(ECHO) > $$@ ; \ + $(SILENT_SE) $(ECHO) > $$@ ; \ [[ -e $(unit_test_src_dir)/$(1)Mocks.hpp ]] && $(ECHO) \#include \"$(1)Mocks.hpp\" >> $$@ ; \ [[ -e $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/$(1).cpp ]] && $(ECHO) \#include \"$(1).cpp\" >> $$@ ; \ $(ECHO) >> $$@ # important for case without .cpp $(unit_test_build_dir)/$(1)Wrapper.o: $(unit_test_build_dir)/$(1)Wrapper.cpp $(unit_test_build_dir)/$(1)Wrapper.d - $$(CXX) -I$(unit_test_src_dir) -I$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir) $$(DEPFLAGS) $$(CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< - $$(POSTCOMPILE) + $(SILENT_SE) $$(CXX) -I$(unit_test_src_dir) -I$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir) $$(DEPFLAGS) $$(CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< && $$(POSTCOMPILE) $(unit_test_build_dir)/$(1)Gtest.o: $(unit_test_src_dir)/$(1)Gtest.cpp $(unit_test_build_dir)/$(1)Gtest.d $(unit_test_build_dir)/.sentinel - $(CXX) -I$(unit_test_src_dir) -I$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir) $$(DEPFLAGS) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< - $$(POSTCOMPILE) + $(SILENT_SE) $(CXX) -I$(unit_test_src_dir) -I$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir) $$(DEPFLAGS) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< && $$(POSTCOMPILE) $(unit_test_build_dir)/$(1)Gtest: $(unit_test_build_dir)/$(1)Gtest.o $(unit_test_build_dir)/$(1)Wrapper.o - $$(CXX) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -o $$@ $$^ $(GTEST_LDFLAGS) $$(LDFLAGS) + $(SILENT_SE) $$(CXX) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -o $$@ $$^ $(GTEST_LDFLAGS) $$(LDFLAGS) # For developers convenience, shows the output of failed tests $(unit_test_build_dir)/$(1)Gtest.passed: $(unit_test_build_dir)/$(1)Gtest - $(SILENT){ \ + $(SILENT_SE) { \ TEST_COMMAND="$$< > $$<.failed && $$(MV) $$<.failed $$@" ; \ - $(ECHO) "$$$${TEST_COMMAND}" ; \ $(EVAL) "$$$${TEST_COMMAND}" ; \ } || { \ rc=$$$$? ; $(ECHO) ; $(ECHO) '***' ERROR '***' Failed unit test $$< "($(unit_test_src_dir)/$(1)Gtest.cpp)" ; \ @@ -86,7 +83,7 @@ $(unit_test_build_dir)/$(1)Gtest.passed: $(unit_test_build_dir)/$(1)Gtest exit $$$$rc ; \ } -$$(BUILD)/$(lib_dir).a: $(unit_test_build_dir)/$(1)Gtest.passed +$$(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a: $(unit_test_build_dir)/$(1)Gtest.passed endef # UNIT_GTEST @@ -99,25 +96,23 @@ endif # # ### -$(BUILD)/$(lib_dir).a: lib_objects:=$(lib_objects) -$(BUILD)/$(lib_dir).a: $(lib_objects) - $(AR) crfs $@ $(lib_objects) +$(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a: lib_objects:=$(lib_objects) +$(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a: $(lib_objects) + $(SILENT) $(AR) crfs $@ $(lib_objects) -#$(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(BUILD)/$(lib_dir)/%.d $(BUILD)/$(lib_dir)/.sentinel +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/$(lib_dir)/.sentinel # $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< # $(POSTCOMPILE) # Note: the dependency on $(libraries) is to force the order of compilation to be the same as the order of declaration of the libraries -$(BUILD)/$(lib_dir)/%.o: lib_dir:=$(lib_dir) -$(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(BUILD)/$(lib_dir)/%.d $(BUILD)/$(lib_dir)/.sentinel $(libraries) - $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o: lib_dir:=$(lib_dir) +$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/$(lib_dir)/.sentinel $(DRAGEN_OS_BUILD)/$(lib_dir)/%.d + $(SILENT) $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< && $(POSTCOMPILE) -$(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.c $(BUILD)/$(lib_dir)/%.d $(BUILD)/$(lib_dir)/.sentinel $(libraries) - $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.c $(DRAGEN_OS_BUILD)/$(lib_dir)/.sentinel $(DRAGEN_OS_BUILD)/$(lib_dir)/%.d + $(SILENT) $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< && $(POSTCOMPILE) -#$(BUILD)/$(lib_dir)/%.d: ; +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.d: ; ### # build and run the integration tests for the library @@ -146,8 +141,9 @@ $(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.c $(BUILD)/$(lib_ # no IOs (no file system, no network, rtc.) ### +ifeq (1,${HAS_GTEST}) integration_test_src_dir:=$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/tests/integration -integration_test_build_dir:=$(BUILD)/$(lib_dir)/tests/integration +integration_test_build_dir:=$(DRAGEN_OS_BUILD)/$(lib_dir)/tests/integration integration_test_sources:=$(wildcard $(integration_test_src_dir)/*Gtest.cpp) integration_tests:=$(integration_test_sources:$(integration_test_src_dir)/%Gtest.cpp=%) @@ -156,19 +152,17 @@ define INTEGRATION_GTEST include $(wildcard $(integration_test_build_dir)/$(1)Gtest.d) $(integration_test_build_dir)/$(1)Gtest.o: $(integration_test_src_dir)/$(1)Gtest.cpp $(integration_test_build_dir)/$(1)Gtest.d $(integration_test_build_dir)/.sentinel - $(CXX) -I$(integration_test_src_dir) -I$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir) $$(DEPFLAGS) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< - $$(POSTCOMPILE) + $(SILENT_SE) $(CXX) -I$(integration_test_src_dir) -I$(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir) $$(DEPFLAGS) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< && $$(POSTCOMPILE) $(integration_test_build_dir)/$(1)Gtest: libraries:= $(libraries) $(integration_test_build_dir)/$(1)Gtest: lib_objects:=$(lib_objects) $(integration_test_build_dir)/$(1)Gtest: $(integration_test_build_dir)/$(1)Gtest.o $(lib_objects) $(libraries) - $$(CXX) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -o $$@ $$^ $(GTEST_LDFLAGS) $$(GTEST_LDFLAGS) $$(LDFLAGS) + $(SILENT_SE) $$(CXX) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -o $$@ $$^ $(GTEST_LDFLAGS) $$(GTEST_LDFLAGS) $$(LDFLAGS) # For developers convenience, shows the output of failed tests $(integration_test_build_dir)/$(1)Gtest.passed: $(integration_test_build_dir)/$(1)Gtest - $(SILENT){ \ + $(SILENT_SE) { \ TEST_COMMAND="$$< > $$<.failed && $$(MV) $$<.failed $$@" ; \ - $(ECHO) "$$$${TEST_COMMAND}" ; \ $(EVAL) "$$$${TEST_COMMAND}" ; \ } || { \ rc=$$$$? ; $(ECHO) ; $(ECHO) '***' ERROR '***' Failed integration test $$< "($(integration_test_src_dir)/$(1)Gtest.cpp)" ; \ @@ -176,17 +170,24 @@ $(integration_test_build_dir)/$(1)Gtest.passed: $(integration_test_build_dir)/$( exit $$$$rc ; \ } -$$(BUILD)/$(lib_dir).a: $(integration_test_build_dir)/$(1)Gtest.passed +$$(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a: $(integration_test_build_dir)/$(1)Gtest.passed endef # INTEGRATION_GTEST -ifeq (1,${HAS_GTEST}) $(foreach t, $(integration_tests), $(eval $(call INTEGRATION_GTEST,$(t)))) -endif +endif #HAS_GTEST ### # must be built in reverse order for linking ### -libraries := $(BUILD)/$(lib_dir).a $(libraries) +libraries := $(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a $(libraries) + +### +# targets for external tools +### +library_targets := $(lib_dir)-lib $(library_targets) +.PHONY: $(lib_dir)-lib +$(lib_dir)-lib : $(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a + diff --git a/make/program.mk b/make/program.mk index ecfc99e..e9556fe 100644 --- a/make/program.mk +++ b/make/program.mk @@ -10,14 +10,13 @@ else programs_aux:=$(wordlist 2, $(words $(programs_aux)), $(programs_aux)) endif -$(BUILD)/$(program).o: $(DRAGEN_OS_SRC_DIR)/$(program).cpp $(BUILD)/$(program).d $(BUILD)/.sentinel - $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/$(program).o: $(DRAGEN_OS_SRC_DIR)/$(program).cpp $(DRAGEN_OS_BUILD)/$(program).d $(DRAGEN_OS_BUILD)/.sentinel + $(SILENT) $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< && $(POSTCOMPILE) -$(BUILD)/$(program): $(BUILD)/$(program).o $(libraries) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(libraries) $(LDFLAGS) +$(DRAGEN_OS_BUILD)/$(program): $(DRAGEN_OS_BUILD)/$(program).o $(libraries) + $(SILENT) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(libraries) $(LDFLAGS) -#$(BUILD)/$(program).d: ; +#$(DRAGEN_OS_BUILD)/$(program).d: ; -include $(wildcard $(BUILD)/$(program).d) +include $(wildcard $(DRAGEN_OS_BUILD)/$(program).d) diff --git a/make/ssw_lib.mk b/make/ssw_lib.mk index e9a2f1c..098d28b 100755 --- a/make/ssw_lib.mk +++ b/make/ssw_lib.mk @@ -12,8 +12,8 @@ endif lib_sources := $(wildcard $(SSW_SRC_DIR)/$(lib_dir)/*.cpp) lib_c_sources := $(wildcard $(SSW_SRC_DIR)/$(lib_dir)/*.c) -lib_objects := $(lib_sources:$(SSW_SRC_DIR)/$(lib_dir)/%.cpp=$(BUILD)/ssw_$(lib_dir)/%.o) -lib_objects += $(lib_c_sources:$(SSW_SRC_DIR)/$(lib_dir)/%.c=$(BUILD)/ssw_$(lib_dir)/%.o) +lib_objects := $(lib_sources:$(SSW_SRC_DIR)/$(lib_dir)/%.cpp=$(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.o) +lib_objects += $(lib_c_sources:$(SSW_SRC_DIR)/$(lib_dir)/%.c=$(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.o) include $(wildcard $(lib_objects:%.o=%.d)) @@ -24,28 +24,35 @@ include $(wildcard $(lib_objects:%.o=%.d)) ### -$(BUILD)/ssw_$(lib_dir).a: lib_objects:=$(lib_objects) -$(BUILD)/ssw_$(lib_dir).a: $(lib_objects) - $(AR) crfs $@ $(lib_objects) +$(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a: lib_objects:=$(lib_objects) +$(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a: $(lib_objects) + $(SILENT) $(AR) crfs $@ $(lib_objects) -#$(BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(BUILD)/$(lib_dir)/%.d $(BUILD)/$(lib_dir)/.sentinel +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.o: $(DRAGEN_OS_SRC_DIR)/lib/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/$(lib_dir)/.sentinel # $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< # $(POSTCOMPILE) # Note: the dependency on $(libraries) is to force the order of compilation to be the same as the order of declaration of the libraries -$(BUILD)/ssw_$(lib_dir)/%.o: lib_dir:=$(lib_dir) -$(BUILD)/ssw_$(lib_dir)/%.o: $(SSW_SRC_DIR)/$(lib_dir)/%.cpp $(BUILD)/ssw_$(lib_dir)/%.d $(BUILD)/ssw_$(lib_dir)/.sentinel $(libraries) - $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.o: lib_dir:=$(lib_dir) +$(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.o: $(SSW_SRC_DIR)/$(lib_dir)/%.cpp $(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/.sentinel + $(SILENT) $(CXX) $(DEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< && $(POSTCOMPILE) -$(BUILD)/ssw_$(lib_dir)/%.o: $(SSW_SRC_DIR)/$(lib_dir)/%.c $(BUILD)/ssw_$(lib_dir)/%.d $(BUILD)/ssw_$(lib_dir)/.sentinel $(libraries) - $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< - $(POSTCOMPILE) +$(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.o: $(SSW_SRC_DIR)/$(lib_dir)/%.c $(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/%.d $(DRAGEN_OS_BUILD)/ssw_$(lib_dir)/.sentinel + $(SILENT) $(CC) $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< && $(POSTCOMPILE) -#$(BUILD)/$(lib_dir)/%.d: ; +#$(DRAGEN_OS_BUILD)/$(lib_dir)/%.d: ; ### # must be built in reverse order for linking ### -libraries := $(BUILD)/ssw_$(lib_dir).a $(libraries) +libraries := $(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a $(libraries) + +### +# targets for external tools +### +library_targets := $(lib_dir)-lib $(library_targets) +.PHONY: $(lib_dir)-lib +$(lib_dir)-lib : $(DRAGEN_OS_BUILD)/libdragmap-$(lib_dir).a + + diff --git a/make/tests.mk b/make/tests.mk index 8de4882..7119c9b 100644 --- a/make/tests.mk +++ b/make/tests.mk @@ -1,6 +1,6 @@ # building all available system tests -TEST_BUILD_DIR=$(BUILD)/test +TEST_BUILD_DIR=$(DRAGEN_OS_BUILD)/test ifeq (1,$(HAS_GTEST)) system_tests:=$(patsubst $(DRAGEN_OS_TEST_DIR)/%.cpp,%,$(wildcard $(DRAGEN_OS_TEST_DIR)/*Gtest.cpp)) @@ -14,13 +14,12 @@ all: test_programs system_tool := $(1) $(TEST_BUILD_DIR)/$(1).o: $(DRAGEN_OS_TEST_DIR)/$(1).cpp $(TEST_BUILD_DIR)/$(1).d $(TEST_BUILD_DIR)/.sentinel - $$(CXX) $$(DEPFLAGS) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< - $$(POSTCOMPILE) + $(SILENT_SE) $$(CXX) $$(DEPFLAGS) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< && $$(POSTCOMPILE) $(TEST_BUILD_DIR)/$(1): $(TEST_BUILD_DIR)/$(1).o $(libraries) - $$(CXX) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -o $$@ $$< $$(libraries) $(GTEST_LDFLAGS) -lgtest_main -lgtest $$(LDFLAGS) + $(SILENT_SE) $$(CXX) $$(CPPFLAGS) $$(GTEST_CPPFLAGS) $$(CXXFLAGS) -o $$@ $$< $$(libraries) $(GTEST_LDFLAGS) -lgtest_main -lgtest $$(LDFLAGS) -#$(BUILD)/system/$(system_tool).d: ; +#$(DRAGEN_OS_BUILD)/system/$(system_tool).d: ; include $(wildcard $(TEST_BUILD_DIR)/$(1).d) endef # define SYSTEM_TEST @@ -41,13 +40,12 @@ define SYSTEM_TOOL system_tool := $(1) $(TEST_BUILD_DIR)/$(1).o: $(DRAGEN_OS_TEST_DIR)/$(1).cpp $(TEST_BUILD_DIR)/$(1).d $(TEST_BUILD_DIR)/.sentinel - $$(CXX) $$(DEPFLAGS) $$(CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< - $$(POSTCOMPILE) + $(SILENT_SE) $$(CXX) $$(DEPFLAGS) $$(CPPFLAGS) $$(CXXFLAGS) -c -o $$@ $$< && $$(POSTCOMPILE) $(TEST_BUILD_DIR)/$(1): $(TEST_BUILD_DIR)/$(1).o $(libraries) - $$(CXX) $$(CPPFLAGS) $$(CXXFLAGS) -o $$@ $$< $$(libraries) $$(LDFLAGS) + $(SILENT_SE) $$(CXX) $$(CPPFLAGS) $$(CXXFLAGS) -o $$@ $$< $$(libraries) $$(LDFLAGS) -#$(BUILD)/system/$(system_tool).d: ; +#$(DRAGEN_OS_BUILD)/system/$(system_tool).d: ; include $(wildcard $(TEST_BUILD_DIR)/$(1).d) endef # define SYSTEM_TOOL diff --git a/make/validate.mk b/make/validate.mk index 11222e8..dc40be2 100644 --- a/make/validate.mk +++ b/make/validate.mk @@ -2,9 +2,10 @@ SHELL:=/bin/bash -o pipefail SAMTOOLS:=samtools +USE_BAM ?= 0 DRAGENOS_DIR:=$(shell pwd) DRAGEN:=$(DRAGENOS_DIR)/build/release/dragen-os -COMPARE:=$(DRAGENOS_DIR)/build/release/test/compare +COMPARE:=$(DRAGENOS_DIR)/build/release/compare FASTQALL:=../FC1-NA12878/original/FC1-NA12878-01_S1.1M.fastq FASTQR1:=../FC1-NA12878/original/FC1-NA12878-01_S1.R1_1M.fastq @@ -20,14 +21,14 @@ BASELINE_PREFIX:=../drgn.flr400/mapq60Positionsc-tlsdragen #USER_PARAMS:= --Aligner.vectorized-sw yes PE_STATS:=--Aligner.pe-stat-mean-insert 209.814 --Aligner.pe-stat-stddev-insert 80.7387 \ --Aligner.pe-stat-quartiles-insert '154 198 260' --Aligner.pe-stat-mean-read-len 142.043 -STATIC_PARAMS:= --RGID rgid --RGSM rgsm --mmap-reference true --ref-load-hash-bin false --preserve-map-align-order yes +STATIC_PARAMS:= --RGID rgid --RGSM rgsm --ref-load-hash-bin false --preserve-map-align-order true PARAMS:=$(STATIC_PARAMS) $(PE_STATS) -r $(REFERENCE) $(USER_PARAMS) default: all -prefix=$(subst $(OUTPUT)/,,$(subst .sam,,$@)) -interleaved_aux=$(patsubst $(STATIC_PREFIX)-se-%,no,$(prefix)) -interleaved=$(patsubst $(STATIC_PREFIX)-pe-%,yes,$(interleaved_aux)) +prefix=$(subst .sam,,$(subst .bam,,$(subst tmp.,,$(subst $(OUTPUT)/,,$@)))) +interleaved_aux=$(patsubst $(STATIC_PREFIX)-se-%,,$(prefix)) +inter=$(patsubst $(STATIC_PREFIX)-pe-%,--interleaved,$(interleaved_aux)) swall_aux=$(patsubst %-swall-$(ID),1,$(prefix)) swall=$(patsubst %-$(ID),0,$(swall_aux)) fastq_aux=$(patsubst $(STATIC_PREFIX)-se-%,$(FASTQR1),$(prefix)) @@ -35,14 +36,6 @@ fastq=$(patsubst $(STATIC_PREFIX)-pe-%,$(FASTQALL),$(fastq_aux)) SAFEPIPETARGET= "$@.tmp" && mv $@.tmp $@ -$(OUTPUT)/$(STATIC_PREFIX)-pe-swall-$(ID).sam \ -$(OUTPUT)/$(STATIC_PREFIX)-pe-$(ID).sam \ -$(OUTPUT)/$(STATIC_PREFIX)-se-swall-$(ID).sam \ -$(OUTPUT)/$(STATIC_PREFIX)-se-$(ID).sam : - /usr/bin/time -v $(DRAGEN) $(PARAMS) \ - --output-file-prefix $(prefix) -1 $(fastq) --interleaved $(interleaved) --Aligner.sw-all=$(swall) \ - > $(SAFEPIPETARGET) - PE_SAM_FILES:= $(OUTPUT)/$(STATIC_PREFIX)-pe-swall-$(ID).sam \ $(OUTPUT)/$(STATIC_PREFIX)-pe-$(ID).sam @@ -51,31 +44,67 @@ $(OUTPUT)/$(STATIC_PREFIX)-se-$(ID).sam SAM_FILES:=$(PE_SAM_FILES) $(SE_SAM_FILES) +ifneq (1,$(USE_BAM)) +$(SAM_FILES) : + /usr/bin/time -v $(DRAGEN) $(PARAMS) \ + --output-file-prefix $(prefix) -1 $(fastq) $(inter) --Aligner.sw-all=$(swall) \ + > $(SAFEPIPETARGET) +else + +PE_BAM_FILES:= $(OUTPUT)/$(STATIC_PREFIX)-pe-swall-$(ID).bam \ +$(OUTPUT)/$(STATIC_PREFIX)-pe-$(ID).bam + +SE_BAM_FILES:= $(OUTPUT)/$(STATIC_PREFIX)-se-swall-$(ID).bam \ +$(OUTPUT)/$(STATIC_PREFIX)-se-$(ID).bam + +BAM_FILES:=$(PE_BAM_FILES) $(SE_BAM_FILES) + +$(BAM_FILES) : + mkdir -p $(OUTPUT) && \ + LC_ALL=C /usr/bin/time -v $(DRAGEN) $(PARAMS) \ + --output-directory $(OUTPUT) --output-file-prefix tmp.$(prefix) -1 $(fastq) $(inter) --Aligner.sw-all=$(swall) && \ + rename tmp.$(prefix) $(prefix) $(OUTPUT)/tmp.$(prefix)* +endif + COMP_FILES:=$(subst .sam,.comp,$(SAM_FILES)) -.PRECIOUS: $(BASELINE_PREFIX)-%.sam -$(BASELINE_PREFIX)-%.sam : $(BASELINE_PREFIX)-%.bam +#.PRECIOUS: $(BASELINE_PREFIX)-%.sam +#$(BASELINE_PREFIX)-%.sam : $(BASELINE_PREFIX)-%.bam +# $(SAMTOOLS) view -h $< > $(SAFEPIPETARGET) + +.PRECIOUS: %.sam +%.sam : %.bam $(SAMTOOLS) view -h $< > $(SAFEPIPETARGET) COMPARE_DIR=$(OUTPUT)/compare-$(ID)-$* .PRECIOUS: $(OUTPUT)/$(STATIC_PREFIX)-%-$(ID).comp $(OUTPUT)/$(STATIC_PREFIX)-%-$(ID).comp: $(BASELINE_PREFIX)-%.sam $(OUTPUT)/$(STATIC_PREFIX)-%-$(ID).sam - mkdir -p $(COMPARE_DIR) && (echo -ne "$*\t" && $(COMPARE) $^ -o $(COMPARE_DIR) -k yes --position-mismatches yes |grep -v IMPLEMENTED | grep mismatch |sed 's/=/ /') > $(SAFEPIPETARGET) + mkdir -p $(COMPARE_DIR) && (echo -ne "$*\t" && $(COMPARE) $^ -o $(COMPARE_DIR) -k yes --position-mismatches yes |grep -v IMPLEMENTED |grep -v _SD_ | grep mismatch |sed 's/=/ /') > $(SAFEPIPETARGET) % : $(OUTPUT)/$(STATIC_PREFIX)-%-$(ID).comp head -1 $< -compare-% : $(OUTPUT)/$(STATIC_PREFIX)-%-$(GOOD_ID).comp $(OUTPUT)/$(STATIC_PREFIX)-%-$(ID).comp - paste -d ' ' $^ |sed 's/$*\t//g' | cut -f 1,2,4 -d' ' +# .comp files. Do not require GOOD_ID run. Just produces the diffs against the baseline bam. +comp: pe pe-swall se se-swall +compare-% : $(BASELINE_PREFIX)-%-$(GOOD_ID).comp $(OUTPUT)/$(STATIC_PREFIX)-%-$(ID).comp + paste -d ' ' $(foreach f,$^,<(sort $f)) |sed 's/$*\t//g' | cut -f 1,2,4 -d' ' + +# Use these to see if the new build is an improvement over the GOOD_ID one compare : compare-se-swall compare-pe-swall compare-se compare-pe +sam: $(SAM_FILES) + +baseline: $(SAM_FILES) + rename -- '-$(ID)' '' $(SAM_FILES) + all: $(COMP_FILES) for f in $^; do head -1 $$f; done clean: -rm $(SAM_FILES) + -rm $(BAM_FILES) -rm $(COMP_FILES) clean-diffs: diff --git a/tests/compare.cpp b/src/compare.cpp similarity index 53% rename from tests/compare.cpp rename to src/compare.cpp index 689d952..9203eb7 100644 --- a/tests/compare.cpp +++ b/src/compare.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -18,19 +19,17 @@ class Sam { public: - Sam &operator=(const std::string &line); - bool operator==(const Sam &rhs) const; - const std::string &getUnparsed() const { return unparsed_; } - const std::string &getName() const { return name_; } - unsigned getFlags() const { return flags_; } - unsigned getFlag(unsigned i) const { return flags_ & (1 << i); } - const std::string &getSequence() const { return sequence_; } - long long getPosition() const { return position_; } - int getMapq() const { return mapq_; } - const std::string &getCigar() const { return cigar_; } - const std::unordered_map &getTags() const { - return tags_; - } + Sam& operator=(const std::string& line); + bool operator==(const Sam& rhs) const; + const std::string& getUnparsed() const { return unparsed_; } + const std::string& getName() const { return name_; } + unsigned getFlags() const { return flags_; } + unsigned getFlag(unsigned i) const { return flags_ & (1 << i); } + const std::string& getSequence() const { return sequence_; } + long long getPosition() const { return position_; } + int getMapq() const { return mapq_; } + const std::string& getCigar() const { return cigar_; } + const std::unordered_map& getTags() const { return tags_; } // reset void reset() { tags_.clear(); } // all individual flags @@ -48,158 +47,166 @@ class Sam { bool isSupplementary() const { return flags_ & 0x800; } private: - std::string unparsed_; - std::string name_; - unsigned flags_; - std::string sequence_; - long long position_; - std::string cigar_; + std::string unparsed_; + std::string name_; + unsigned flags_; + std::string sequence_; + long long position_; + std::string cigar_; std::unordered_map tags_; - int mapq_; + int mapq_; }; -typedef std::pair Count; -typedef std::pair - AltID; // for secondary/supplementary alignments +typedef std::pair Count; +typedef std::pair AltID; // for secondary/supplementary alignments // tmp containers for secondary/supplementary alignments typedef std::unordered_map> SamBuffer; struct Statistics { - Statistics() { + Statistics() + { position.fill(Count(0, 0)); flags.fill(Count(0, 0)); mapq.fill(Count(0, 0)); mapqDirection.fill(Count(0, 0)); cigar.fill(Count(0, 0)); } - void write(const std::string outputDirectory) const; - static unsigned mapqBin(const int mapq); - unsigned missing = 0; - unsigned extra = 0; - unsigned match = 0; - unsigned mismatch = 0; - unsigned moreAlignments = 0; - unsigned lessAlignments = 0; - Count unmapped = {0, 0}; - Count mapped = {0, 0}; - std::array position; // MAPQ: 60, 30-59, 1-29, 0 + void write(const std::string outputDirectory) const; + static unsigned mapqBin(const int mapq); + unsigned missing = 0; + unsigned extra = 0; + unsigned match = 0; + unsigned mismatch = 0; + unsigned moreAlignments = 0; + unsigned lessAlignments = 0; + Count unmapped = {0, 0}; + Count mapped = {0, 0}; + std::array position; // MAPQ: 60, 30-59, 1-29, 0 std::array flags; - std::array mapq; - std::array mapqDirection; - std::array cigar; + std::array mapq; + std::array mapqDirection; + std::array cigar; // note that a record may contribute to multiple mismatched tags std::unordered_map> tags; - std::unordered_map missingTags; - std::unordered_map extraTags; + std::unordered_map missingTags; + std::unordered_map extraTags; // secondary alignments stats unsigned secondaryMissing = 0; - unsigned secondaryExtra = 0; - unsigned secondaryMatch = 0; + unsigned secondaryExtra = 0; + unsigned secondaryMatch = 0; // supplementary alignments stats unsigned supplementaryMissing = 0; - unsigned supplementaryExtra = 0; - unsigned supplementaryMatch = 0; + unsigned supplementaryExtra = 0; + unsigned supplementaryMatch = 0; }; -bool getSamRecords(std::istream &is, std::vector &samRecords, - SamBuffer &secondaryBuffers, SamBuffer &supplementaryBuffers, - Sam &next); +bool getSamRecords( + std::istream& is, + std::vector& samRecords, + SamBuffer& secondaryBuffers, + SamBuffer& supplementaryBuffers, + Sam& next); void compare( - std::vector &referenceRecords, std::vector &newRecords, - Statistics &statistics, std::ostream &missingMappings, - std::ostream &extraMappings, std::ostream &positionMismatch, - std::ostream &positionMismatchReference, std::ostream &flagMismatch, - std::ostream &flagMismatchReference, std::ostream &cigarMismatch, - std::ostream &cigarMismatchReference, std::ostream &pairEndInfoMismatch, - std::ostream &pairEndInfoMismatchReference, - std::map> &tagMismatch, - std::map> &tagMismatchReference); -std::ostream &operator<<(std::ostream &os, const Sam &sam); -std::ostream &operator<<(std::ostream &os, const Statistics &statistics); - -void compareSecondary(SamBuffer &refSamBuffer, SamBuffer &newSamBuffer, - Statistics &statistics); -void compareSupplementary(SamBuffer &refSamBuffer, SamBuffer &newSamBuffer, - Statistics &statistics); + std::vector& referenceRecords, + std::vector& newRecords, + Statistics& statistics, + std::ostream& missingMappings, + std::ostream& extraMappings, + std::ostream& positionMismatch, + std::ostream& positionMismatchReference, + std::ostream& flagMismatch, + std::ostream& flagMismatchReference, + std::ostream& cigarMismatch, + std::ostream& cigarMismatchReference, + std::ostream& pairEndInfoMismatch, + std::ostream& pairEndInfoMismatchReference, + std::map>& tagMismatch, + std::map>& tagMismatchReference); +std::ostream& operator<<(std::ostream& os, const Sam& sam); +std::ostream& operator<<(std::ostream& os, const Statistics& statistics); + +void compareSecondary(SamBuffer& refSamBuffer, SamBuffer& newSamBuffer, Statistics& statistics); +void compareSupplementary(SamBuffer& refSamBuffer, SamBuffer& newSamBuffer, Statistics& statistics); void makeMismatchFiles( - const std::string &tag, const std::string &fileSuffix, - const boost::filesystem::path &outputDirectory, - std::map> &tagMismatch) { + const std::string& tag, + const std::string& fileSuffix, + const boost::filesystem::path& outputDirectory, + std::map>& tagMismatch) +{ tagMismatch.emplace( tag + std::to_string(Statistics::mapqBin(0)), - std::make_shared( - (outputDirectory / ("tag" + tag + "Mismatch0" + fileSuffix)) - .string())); + std::make_shared((outputDirectory / ("tag" + tag + "Mismatch0" + fileSuffix)).string())); tagMismatch.emplace( tag + std::to_string(Statistics::mapqBin(1)), std::make_shared( - (outputDirectory / ("tag" + tag + "Mismatch1-29" + fileSuffix)) - .string())); + (outputDirectory / ("tag" + tag + "Mismatch1-29" + fileSuffix)).string())); tagMismatch.emplace( tag + std::to_string(Statistics::mapqBin(30)), std::make_shared( - (outputDirectory / ("tag" + tag + "Mismatch30-59" + fileSuffix)) - .string())); + (outputDirectory / ("tag" + tag + "Mismatch30-59" + fileSuffix)).string())); tagMismatch.emplace( tag + std::to_string(Statistics::mapqBin(60)), std::make_shared( - (outputDirectory / ("tag" + tag + "Mismatch60" + fileSuffix)) - .string())); + (outputDirectory / ("tag" + tag + "Mismatch60" + fileSuffix)).string())); } -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) +{ namespace po = boost::program_options; po::options_description options( "Usage: compare reference.sam new.sam [options]\n" "compare the specified 'new.sam' file against 'reference.sam'.\n" "Supported options are:"); options.add_options()("help", "produce help message")( - "key-value,k", po::value()->default_value(false), + "key-value,k", + po::value()->default_value(false), "specify the output should be a list of key=value on stdout instead of a " - "set of cvs files")("output,o", - po::value()->default_value("./"), - "specify the output directory")( - "position-mismatches", po::value()->default_value(false), + "set of cvs files")( + "output,o", po::value()->default_value("./"), "specify the output directory")( + "position-mismatches", + po::value()->default_value(false), "specifies that the list of records with MAPQ>0 and incorrect positions " "should be produced")( - "cigar-mismatches", po::value()->default_value(false), + "cigar-mismatches", + po::value()->default_value(false), "specifies that the list of records with MAPQ>0 and correct positions " "and mismatching CIGAR strings should be produced")( - "flag-mismatches", po::value()->default_value(false), + "flag-mismatches", + po::value()->default_value(false), "specifies that the list of records with inconsistent-flag mappings " "should be produced")( - "missing-mappings", po::value()->default_value(false), + "missing-mappings", + po::value()->default_value(false), "specifies that the list of records with missing mappings should be " - "produced")("extra-mappings", po::value()->default_value(false), - "specifies that the list of records with extra mappings " - "should be produced")( - "pair-end-mismatches", po::value()->default_value(false), + "produced")( + "extra-mappings", + po::value()->default_value(false), + "specifies that the list of records with extra mappings " + "should be produced")( + "pair-end-mismatches", + po::value()->default_value(false), "speicifes that the list of records that are inconsistent from pair-end " "mapping(sam files are expected to be sorted by read name and FR order)")( - "input-file,i", po::value>(), + "input-file,i", + po::value>(), "input SAM files reference.sam and new.sam -- these can also be " "specified simply as positional options"); po::positional_options_description positional; positional.add("input-file", -1); po::variables_map vm; - po::store(po::command_line_parser(argc, argv) - .options(options) - .positional(positional) - .run(), - vm); + po::store(po::command_line_parser(argc, argv).options(options).positional(positional).run(), vm); po::notify(vm); if (vm.count("help")) { std::cout << options << "\n"; return 1; } - const std::vector inputFiles = - vm["input-file"].as>(); + const std::vector inputFiles = vm["input-file"].as>(); if (2 != inputFiles.size()) { std::cerr << "ERROR: exactly two input files must be specified: " "reference.sam and new.sam" @@ -211,8 +218,8 @@ int main(int argc, char *argv[]) { for (auto i : {0, 1}) { is[i].open(argv[i + 1]); if (!is[i]) { - std::cerr << "failed to open " << inputFiles[i] << ": " << errno << ": " - << strerror(errno) << std::endl; + std::cerr << "failed to open " << inputFiles[i] << ": " << errno << ": " << strerror(errno) + << std::endl; exit(2); } } @@ -231,28 +238,23 @@ int main(int argc, char *argv[]) { // compare std::array, 2> samRecords; - getSamRecords(is[0], samRecords[0], secondaryBuffers[0], - supplementaryBuffers[0], nextRecords[0]); - getSamRecords(is[1], samRecords[1], secondaryBuffers[1], - supplementaryBuffers[1], nextRecords[1]); + getSamRecords(is[0], samRecords[0], secondaryBuffers[0], supplementaryBuffers[0], nextRecords[0]); + getSamRecords(is[1], samRecords[1], secondaryBuffers[1], supplementaryBuffers[1], nextRecords[1]); Statistics statistics; // while (getSamRecords(is[0], samRecords[0], nextRecords[0]) || // getSamRecords(is[1], samRecords[1], nextRecords[1])) - std::ofstream positionMismatch; - std::ofstream positionMismatchReference; - const boost::filesystem::path outputDirectory = - vm["output"].as(); + std::ofstream positionMismatch; + std::ofstream positionMismatchReference; + const boost::filesystem::path outputDirectory = vm["output"].as(); if (vm["position-mismatches"].as()) { positionMismatch.open((outputDirectory / "positionMismatch.sam").c_str()); - positionMismatchReference.open( - (outputDirectory / "positionMismatchReference.sam").c_str()); + positionMismatchReference.open((outputDirectory / "positionMismatchReference.sam").c_str()); } std::ofstream cigarMismatch; std::ofstream cigarMismatchReference; if (vm["cigar-mismatches"].as()) { cigarMismatch.open((outputDirectory / "cigarMismatch.sam").c_str()); - cigarMismatchReference.open( - (outputDirectory / "cigarMismatchReference.sam").c_str()); + cigarMismatchReference.open((outputDirectory / "cigarMismatchReference.sam").c_str()); } std::ofstream missingMappings; if (vm["missing-mappings"].as()) { @@ -268,78 +270,97 @@ int main(int argc, char *argv[]) { std::ofstream flagMismatchReference; if (vm["flag-mismatches"].as()) { flagMismatch.open((outputDirectory / "flagMismatch.sam").c_str()); - flagMismatchReference.open( - (outputDirectory / "flagMismatchReference.sam").c_str()); + flagMismatchReference.open((outputDirectory / "flagMismatchReference.sam").c_str()); } std::ofstream pairEndInfoMismatch; std::ofstream pairEndInfoMismatchReference; if (vm["pair-end-mismatches"].as()) { pairEndInfoMismatch.open((outputDirectory / "pairEndMismatch.sam").c_str()); - pairEndInfoMismatchReference.open( - (outputDirectory / "pairEndMismatchReference.sam").c_str()); + pairEndInfoMismatchReference.open((outputDirectory / "pairEndMismatchReference.sam").c_str()); } std::map> tagMismatch; std::map> tagMismatchReference; makeMismatchFiles("XS", ".sam", outputDirectory, tagMismatch); - makeMismatchFiles("XS", "Reference.sam", outputDirectory, - tagMismatchReference); + makeMismatchFiles("XS", "Reference.sam", outputDirectory, tagMismatchReference); makeMismatchFiles("NM", ".sam", outputDirectory, tagMismatch); - makeMismatchFiles("NM", "Reference.sam", outputDirectory, - tagMismatchReference); + makeMismatchFiles("NM", "Reference.sam", outputDirectory, tagMismatchReference); makeMismatchFiles("AS", ".sam", outputDirectory, tagMismatch); - makeMismatchFiles("AS", "Reference.sam", outputDirectory, - tagMismatchReference); + makeMismatchFiles("AS", "Reference.sam", outputDirectory, tagMismatchReference); makeMismatchFiles("XQ", ".sam", outputDirectory, tagMismatch); - makeMismatchFiles("XQ", "Reference.sam", outputDirectory, - tagMismatchReference); + makeMismatchFiles("XQ", "Reference.sam", outputDirectory, tagMismatchReference); makeMismatchFiles("SA", ".sam", outputDirectory, tagMismatch); - makeMismatchFiles("SA", "Reference.sam", outputDirectory, - tagMismatchReference); + makeMismatchFiles("SA", "Reference.sam", outputDirectory, tagMismatchReference); makeMismatchFiles("MAPQ", ".sam", outputDirectory, tagMismatch); - makeMismatchFiles("MAPQ", "Reference.sam", outputDirectory, - tagMismatchReference); + makeMismatchFiles("MAPQ", "Reference.sam", outputDirectory, tagMismatchReference); std::vector empty; - int counter = 0; + int counter = 0; while ((!samRecords[0].empty()) || (!samRecords[1].empty())) { // make sure that the comparison is for the same read name of against an // empty set - if (counter % 1000000 == 0) - std::cerr << "Input " << counter << " Records(Single or Pair)...\n"; + if (counter % 1000000 == 0) std::cerr << "Input " << counter << " Records(Single or Pair)...\n"; counter++; compareSecondary(secondaryBuffers[0], secondaryBuffers[1], statistics); - compareSupplementary(supplementaryBuffers[0], supplementaryBuffers[1], - statistics); + compareSupplementary(supplementaryBuffers[0], supplementaryBuffers[1], statistics); if (samRecords[0].empty() || samRecords[1].empty() || (samRecords[0][0].getName() == samRecords[1][0].getName())) { - compare(samRecords[0], samRecords[1], statistics, missingMappings, - extraMappings, positionMismatch, positionMismatchReference, - flagMismatch, flagMismatchReference, cigarMismatch, - cigarMismatchReference, pairEndInfoMismatch, - pairEndInfoMismatchReference, tagMismatch, tagMismatchReference); - getSamRecords(is[0], samRecords[0], secondaryBuffers[0], - supplementaryBuffers[0], nextRecords[0]); - getSamRecords(is[1], samRecords[1], secondaryBuffers[1], - supplementaryBuffers[1], nextRecords[1]); + compare( + samRecords[0], + samRecords[1], + statistics, + missingMappings, + extraMappings, + positionMismatch, + positionMismatchReference, + flagMismatch, + flagMismatchReference, + cigarMismatch, + cigarMismatchReference, + pairEndInfoMismatch, + pairEndInfoMismatchReference, + tagMismatch, + tagMismatchReference); + getSamRecords(is[0], samRecords[0], secondaryBuffers[0], supplementaryBuffers[0], nextRecords[0]); + getSamRecords(is[1], samRecords[1], secondaryBuffers[1], supplementaryBuffers[1], nextRecords[1]); } else if (samRecords[0][0].getName() < samRecords[1][0].getName()) { - compare(samRecords[0], empty, statistics, missingMappings, extraMappings, - positionMismatch, positionMismatchReference, flagMismatch, - flagMismatchReference, cigarMismatch, cigarMismatchReference, - pairEndInfoMismatch, pairEndInfoMismatchReference, tagMismatch, - tagMismatchReference); - getSamRecords(is[0], samRecords[0], secondaryBuffers[0], - supplementaryBuffers[0], nextRecords[0]); - } else // (samRecords[0].getName() > samRecords[1].getName()) + compare( + samRecords[0], + empty, + statistics, + missingMappings, + extraMappings, + positionMismatch, + positionMismatchReference, + flagMismatch, + flagMismatchReference, + cigarMismatch, + cigarMismatchReference, + pairEndInfoMismatch, + pairEndInfoMismatchReference, + tagMismatch, + tagMismatchReference); + getSamRecords(is[0], samRecords[0], secondaryBuffers[0], supplementaryBuffers[0], nextRecords[0]); + } else // (samRecords[0].getName() > samRecords[1].getName()) { - compare(empty, samRecords[1], statistics, missingMappings, extraMappings, - positionMismatch, positionMismatchReference, flagMismatch, - flagMismatchReference, cigarMismatch, cigarMismatchReference, - pairEndInfoMismatch, pairEndInfoMismatchReference, tagMismatch, - tagMismatchReference); - getSamRecords(is[1], samRecords[1], secondaryBuffers[1], - supplementaryBuffers[1], nextRecords[1]); + compare( + empty, + samRecords[1], + statistics, + missingMappings, + extraMappings, + positionMismatch, + positionMismatchReference, + flagMismatch, + flagMismatchReference, + cigarMismatch, + cigarMismatchReference, + pairEndInfoMismatch, + pairEndInfoMismatchReference, + tagMismatch, + tagMismatchReference); + getSamRecords(is[1], samRecords[1], secondaryBuffers[1], supplementaryBuffers[1], nextRecords[1]); } } if (vm["key-value"].as()) { @@ -349,7 +370,8 @@ int main(int argc, char *argv[]) { } } -Sam &Sam::operator=(const std::string &line) { +Sam& Sam::operator=(const std::string& line) +{ reset(); unparsed_ = line; /* @@ -371,41 +393,45 @@ Sam &Sam::operator=(const std::string &line) { std::vector results; boost::algorithm::split(items, line, boost::is_any_of("\t")); auto iter = items.begin(); - name_ = *iter++; - flags_ = std::stoi(*iter++); + name_ = *iter++; + flags_ = std::stoi(*iter++); sequence_ = *iter++; position_ = std::stoi(*iter++); - mapq_ = std::stoi(*iter++); - cigar_ = *iter++; + mapq_ = std::stoi(*iter++); + cigar_ = *iter++; iter += 5; std::string dummy; while (iter != items.end()) { dummy = *iter++; boost::algorithm::split(results, dummy, boost::is_any_of(":")); + std::transform(results[0].begin(), results[0].end(), results[0].begin(), &toupper); tags_[results[0]] = results[2]; } return *this; } -bool Sam::operator==(const Sam &rhs) const { +bool Sam::operator==(const Sam& rhs) const +{ std::unordered_set tagsBlockList = {"XQ", "RG"}; // if(tags_.size() != rhs.getTags().size()) return false; - for (const auto &kv : tags_) { - if (tagsBlockList.find(kv.first) != tagsBlockList.end()) - continue; + for (const auto& kv : tags_) { + if (tagsBlockList.find(kv.first) != tagsBlockList.end()) continue; if (rhs.getTags().find(kv.first) != rhs.getTags().end() and tags_.at(kv.first) != rhs.getTags().at(kv.first)) return false; } - return name_ == rhs.getName() and flags_ == rhs.getFlags() and - sequence_ == rhs.getSequence() and position_ == rhs.getPosition() and - mapq_ == rhs.getMapq() and cigar_ == rhs.getCigar(); + return name_ == rhs.getName() and flags_ == rhs.getFlags() and sequence_ == rhs.getSequence() and + position_ == rhs.getPosition() and mapq_ == rhs.getMapq() and cigar_ == rhs.getCigar(); } -bool getSamRecords(std::istream &is, std::vector &samRecords, - SamBuffer &secondaryBuffers, SamBuffer &supplementaryBuffers, - Sam &next) { +bool getSamRecords( + std::istream& is, + std::vector& samRecords, + SamBuffer& secondaryBuffers, + SamBuffer& supplementaryBuffers, + Sam& next) +{ samRecords.clear(); secondaryBuffers.clear(); supplementaryBuffers.clear(); @@ -414,33 +440,33 @@ bool getSamRecords(std::istream &is, std::vector &samRecords, } if (next.isSecondary()) { secondaryBuffers.insert(std::make_pair( - std::make_pair(next.getName() + (next.isFirst() ? "1" : "2") + - next.getCigar() + next.getSequence(), - next.getPosition()), + std::make_pair( + next.getName() + (next.isFirst() ? "1" : "2") + next.getCigar() + next.getSequence(), + next.getPosition()), next)); } else if (next.isSupplementary()) { supplementaryBuffers.insert(std::make_pair( - std::make_pair(next.getName() + (next.isFirst() ? "1" : "2") + - next.getCigar() + next.getSequence(), - next.getPosition()), + std::make_pair( + next.getName() + (next.isFirst() ? "1" : "2") + next.getCigar() + next.getSequence(), + next.getPosition()), next)); } else { samRecords.push_back(next); } std::string line; - Sam last = next; + Sam last = next; while (getline(is, line) && ((next = line).getName() == last.getName())) { if (next.isSecondary()) { secondaryBuffers.insert(std::make_pair( - std::make_pair(next.getName() + (next.isFirst() ? "1" : "2") + - next.getCigar() + next.getSequence(), - next.getPosition()), + std::make_pair( + next.getName() + (next.isFirst() ? "1" : "2") + next.getCigar() + next.getSequence(), + next.getPosition()), next)); } else if (next.isSupplementary()) { supplementaryBuffers.insert(std::make_pair( - std::make_pair(next.getName() + (next.isFirst() ? "1" : "2") + - next.getCigar() + next.getSequence(), - next.getPosition()), + std::make_pair( + next.getName() + (next.isFirst() ? "1" : "2") + next.getCigar() + next.getSequence(), + next.getPosition()), next)); } else { samRecords.push_back(next); @@ -451,13 +477,18 @@ bool getSamRecords(std::istream &is, std::vector &samRecords, } void compareSingle( - const Sam &refRecord, const Sam &newRecord, Statistics &statistics, - std::ostream &positionMismatch, std::ostream &positionMismatchReference, - std::ostream &flagMismatch, std::ostream &flagMismatchReference, - std::ostream &cigarMismatch, std::ostream &cigarMismatchReference, - std::map> &tagMismatch, - std::map> - &tagMismatchReference) { + const Sam& refRecord, + const Sam& newRecord, + Statistics& statistics, + std::ostream& positionMismatch, + std::ostream& positionMismatchReference, + std::ostream& flagMismatch, + std::ostream& flagMismatchReference, + std::ostream& cigarMismatch, + std::ostream& cigarMismatchReference, + std::map>& tagMismatch, + std::map>& tagMismatchReference) +{ if (refRecord.isUnmapped()) { if (newRecord.isUnmapped()) { ++statistics.unmapped.first; @@ -516,8 +547,8 @@ void compareSingle( } else { ++statistics.mapqDirection[mapqBin].second; } - const std::string key = "MAPQ" + std::to_string(mapqBin); - const auto stream = tagMismatch.find(key); + const std::string key = "MAPQ" + std::to_string(mapqBin); + const auto stream = tagMismatch.find(key); if (tagMismatch.end() != stream) { *stream->second << newRecord.getUnparsed() << std::endl; *tagMismatchReference.at(key) << refRecord.getUnparsed() << std::endl; @@ -535,54 +566,58 @@ void compareSingle( // compare tags if (not refRecord.getTags().empty()) { - for (const auto &kv : refRecord.getTags()) { + for (const auto& kv : refRecord.getTags()) { if (newRecord.getTags().find(kv.first) != newRecord.getTags().end()) { - if (newRecord.getTags().at(kv.first) == - refRecord.getTags().at(kv.first)) { + if (newRecord.getTags().at(kv.first) == refRecord.getTags().at(kv.first)) { statistics.tags[kv.first].at(mapqBin).first++; } else { statistics.tags[kv.first].at(mapqBin).second++; - const std::string key = kv.first + std::to_string(mapqBin); - const auto stream = tagMismatch.find(key); + const std::string key = kv.first + std::to_string(mapqBin); + const auto stream = tagMismatch.find(key); if (tagMismatch.end() != stream) { *stream->second << newRecord.getUnparsed() << std::endl; - *tagMismatchReference.at(key) - << refRecord.getUnparsed() << std::endl; + *tagMismatchReference.at(key) << refRecord.getUnparsed() << std::endl; } } } else { statistics.missingTags[kv.first]++; } } - for (const auto &kv : newRecord.getTags()) { + for (const auto& kv : newRecord.getTags()) { if (refRecord.getTags().find(kv.first) == refRecord.getTags().end()) { statistics.extraTags[kv.first]++; } } } else { - for (const auto &kv : newRecord.getTags()) { + for (const auto& kv : newRecord.getTags()) { statistics.extraTags[kv.first]++; } } } -void compare(std::vector &referenceRecords, std::vector &newRecords, - Statistics &statistics, std::ostream &missingMappings, - std::ostream &extraMappings, std::ostream &positionMismatch, - std::ostream &positionMismatchReference, - std::ostream &flagMismatch, std::ostream &flagMismatchReference, - std::ostream &cigarMismatch, std::ostream &cigarMismatchReference, - std::ostream &pairEndInfoMismatch, - std::ostream &pairEndInfoMismatchReference, - std::map> &tagMismatch, - std::map> - &tagMismatchReference) { +void compare( + std::vector& referenceRecords, + std::vector& newRecords, + Statistics& statistics, + std::ostream& missingMappings, + std::ostream& extraMappings, + std::ostream& positionMismatch, + std::ostream& positionMismatchReference, + std::ostream& flagMismatch, + std::ostream& flagMismatchReference, + std::ostream& cigarMismatch, + std::ostream& cigarMismatchReference, + std::ostream& pairEndInfoMismatch, + std::ostream& pairEndInfoMismatchReference, + std::map>& tagMismatch, + std::map>& tagMismatchReference) +{ if (referenceRecords.empty() && newRecords.empty()) { std::cerr << "No SAM record to compare" << std::endl; exit(3); } if (newRecords.empty()) { - for (const auto &refRec : referenceRecords) { + for (const auto& refRec : referenceRecords) { if (missingMappings) { missingMappings << refRec.getUnparsed() << std::endl; } @@ -591,7 +626,7 @@ void compare(std::vector &referenceRecords, std::vector &newRecords, return; } if (referenceRecords.empty()) { - for (const auto &newRec : newRecords) { + for (const auto& newRec : newRecords) { if (extraMappings) { extraMappings << newRec.getUnparsed() << std::endl; } @@ -601,8 +636,7 @@ void compare(std::vector &referenceRecords, std::vector &newRecords, } if (referenceRecords.size() == 2 && - newRecords.size() == - 2) // TODO: append additional pair-end statistics if needed + newRecords.size() == 2) // TODO: append additional pair-end statistics if needed { // if(!referenceRecords[0].isFirst()) std::swap(referenceRecords[0], // referenceRecords[1]); if(!newRecords[0].isFirst()) @@ -630,17 +664,14 @@ void compare(std::vector &referenceRecords, std::vector &newRecords, exit(3); } } else if (referenceRecords.size() == 2 && newRecords.size() == 1) { - Sam missingRec = referenceRecords[0].getFlag(6) == newRecords[0].getFlag(6) - ? referenceRecords[1] - : referenceRecords[0]; + Sam missingRec = referenceRecords[0].getFlag(6) == newRecords[0].getFlag(6) ? referenceRecords[1] + : referenceRecords[0]; if (missingMappings) { missingMappings << missingRec.getUnparsed() << std::endl; } ++statistics.missing; } else if (referenceRecords.size() == 1 && newRecords.size() == 2) { - Sam newRec = referenceRecords[0].getFlag(6) == newRecords[0].getFlag(6) - ? newRecords[1] - : newRecords[0]; + Sam newRec = referenceRecords[0].getFlag(6) == newRecords[0].getFlag(6) ? newRecords[1] : newRecords[0]; if (extraMappings) { extraMappings << newRec.getUnparsed() << std::endl; } @@ -648,62 +679,65 @@ void compare(std::vector &referenceRecords, std::vector &newRecords, } // handle single comparison - for (const auto &refRec : referenceRecords) { - for (const auto &newRec : newRecords) { - if (refRec.getFlag(6) == newRec.getFlag(6)) // both or neither + for (const auto& refRec : referenceRecords) { + for (const auto& newRec : newRecords) { + if (refRec.getFlag(6) == newRec.getFlag(6)) // both or neither { - compareSingle(refRec, newRec, statistics, positionMismatch, - positionMismatchReference, flagMismatch, - flagMismatchReference, cigarMismatch, - cigarMismatchReference, tagMismatch, - tagMismatchReference); + compareSingle( + refRec, + newRec, + statistics, + positionMismatch, + positionMismatchReference, + flagMismatch, + flagMismatchReference, + cigarMismatch, + cigarMismatchReference, + tagMismatch, + tagMismatchReference); } } } } -void compareSecondary(SamBuffer &refSamBuffer, SamBuffer &newSamBuffer, - Statistics &statistics) { - for (const auto &kv : refSamBuffer) { +void compareSecondary(SamBuffer& refSamBuffer, SamBuffer& newSamBuffer, Statistics& statistics) +{ + for (const auto& kv : refSamBuffer) { if (newSamBuffer.find(kv.first) != newSamBuffer.end()) statistics.secondaryMatch++; else statistics.secondaryMissing++; } - for (const auto &kv : newSamBuffer) { - if (refSamBuffer.find(kv.first) == refSamBuffer.end()) - statistics.secondaryExtra++; + for (const auto& kv : newSamBuffer) { + if (refSamBuffer.find(kv.first) == refSamBuffer.end()) statistics.secondaryExtra++; } } -void compareSupplementary(SamBuffer &refSamBuffer, SamBuffer &newSamBuffer, - Statistics &statistics) { - for (const auto &kv : refSamBuffer) { +void compareSupplementary(SamBuffer& refSamBuffer, SamBuffer& newSamBuffer, Statistics& statistics) +{ + for (const auto& kv : refSamBuffer) { if (newSamBuffer.find(kv.first) != newSamBuffer.end()) statistics.supplementaryMatch++; else statistics.supplementaryMissing++; } - for (const auto &kv : newSamBuffer) { - if (refSamBuffer.find(kv.first) == refSamBuffer.end()) - statistics.supplementaryExtra++; + for (const auto& kv : newSamBuffer) { + if (refSamBuffer.find(kv.first) == refSamBuffer.end()) statistics.supplementaryExtra++; } } -std::ostream &operator<<(std::ostream &os, const Statistics &statistics) { +std::ostream& operator<<(std::ostream& os, const Statistics& statistics) +{ os << "missing=" << statistics.missing << std::endl; os << "extra=" << statistics.extra << std::endl; os << "match=" << statistics.match << std::endl; os << "mismatch=" << statistics.mismatch << std::endl; - static const std::array mapqStrings{"60", "30-59", "1-29", - "0"}; + static const std::array mapqStrings{"60", "30-59", "1-29", "0"}; for (auto i : {0, 1, 2, 3}) { - os << "position_match_" << mapqStrings[i] << "=" - << statistics.position[i].first << std::endl; - os << "position_mismatch_" << mapqStrings[i] << "=" - << statistics.position[i].second << std::endl; + os << "position_match_" << mapqStrings[i] << "=" << statistics.position[i].first << std::endl; + os << "position_mismatch_" << mapqStrings[i] << "=" << statistics.position[i].second << std::endl; } for (unsigned i = 0; 12 > i; ++i) { os << "flag" << i << "_match_0-60" @@ -712,47 +746,38 @@ std::ostream &operator<<(std::ostream &os, const Statistics &statistics) { << "=" << statistics.flags[i].second << std::endl; } for (auto i : {0, 1, 2, 3}) { - os << "mapq_match_" << mapqStrings[i] << "=" << statistics.mapq[i].first - << std::endl; - os << "mapq_mismatch_" << mapqStrings[i] << "=" << statistics.mapq[i].second - << std::endl; - os << "mapq_HW_LT_SW_" << mapqStrings[i] << "=" - << statistics.mapqDirection[i].first << std::endl; - os << "mapq_HW_GT_SW_" << mapqStrings[i] << "=" - << statistics.mapqDirection[i].second << std::endl; + os << "mapq_match_" << mapqStrings[i] << "=" << statistics.mapq[i].first << std::endl; + os << "mapq_mismatch_" << mapqStrings[i] << "=" << statistics.mapq[i].second << std::endl; + os << "mapq_HW_LT_SW_" << mapqStrings[i] << "=" << statistics.mapqDirection[i].first << std::endl; + os << "mapq_HW_GT_SW_" << mapqStrings[i] << "=" << statistics.mapqDirection[i].second << std::endl; os << "mapqx_match_" << mapqStrings[i] << "= NOT IMPLEMENTED" << std::endl; - os << "mapqx_mismatch_" << mapqStrings[i] << "= NOT IMPLEMENTED" - << std::endl; + os << "mapqx_mismatch_" << mapqStrings[i] << "= NOT IMPLEMENTED" << std::endl; } for (auto i : {0, 1, 2, 3}) { - os << "cigar_match_" << mapqStrings[i] << "=" << statistics.cigar[i].first - << std::endl; - os << "cigar_mismatch_" << mapqStrings[i] << "=" - << statistics.cigar[i].second << std::endl; + os << "cigar_match_" << mapqStrings[i] << "=" << statistics.cigar[i].first << std::endl; + os << "cigar_mismatch_" << mapqStrings[i] << "=" << statistics.cigar[i].second << std::endl; } for (auto i : {0, 1, 2, 3}) { - for (const auto &kv : statistics.tags) { - os << "tag_" << kv.first << "_match_" << mapqStrings[i] << "=" - << kv.second.at(i).first << std::endl; - os << "tag_" << kv.first << "_mismatch_" << mapqStrings[i] << "=" - << kv.second.at(i).second << std::endl; + for (const auto& kv : statistics.tags) { + os << "tag_" << kv.first << "_match_" << mapqStrings[i] << "=" << kv.second.at(i).first << std::endl; + os << "tag_" << kv.first << "_mismatch_" << mapqStrings[i] << "=" << kv.second.at(i).second + << std::endl; } } - for (const auto &kv : statistics.extraTags) { + for (const auto& kv : statistics.extraTags) { os << "tag_" << kv.first << "_extra" << "=" << kv.second << std::endl; } - for (const auto &kv : statistics.missingTags) { + for (const auto& kv : statistics.missingTags) { os << "tag_" << kv.first << "_missing_" << "=" << kv.second << std::endl; } os << "supplementary_match=" << statistics.supplementaryMatch << std::endl; - os << "supplementary_missing=" << statistics.supplementaryMissing - << std::endl; + os << "supplementary_missing=" << statistics.supplementaryMissing << std::endl; os << "supplementary_extra=" << statistics.supplementaryExtra << std::endl; os << "secondary_match=" << statistics.secondaryMatch << std::endl; os << "secondary_missing=" << statistics.secondaryMissing << std::endl; @@ -760,57 +785,52 @@ std::ostream &operator<<(std::ostream &os, const Statistics &statistics) { return os; } -unsigned Statistics::mapqBin(const int mapq) { - if (255 == mapq) - return 3; // MAPQ not available - if (mapq >= 60) - return 0; - if (mapq >= 30) - return 1; - if (mapq > 0) - return 2; +unsigned Statistics::mapqBin(const int mapq) +{ + if (255 == mapq) return 3; // MAPQ not available + if (mapq >= 60) return 0; + if (mapq >= 30) return 1; + if (mapq > 0) return 2; return 3; } -std::ostream &operator<<(std::ostream &os, const Sam &sam) { +std::ostream& operator<<(std::ostream& os, const Sam& sam) +{ return os << sam.getName() << '\t' << sam.getFlags() << '\t' << std::endl; } -void Statistics::write(const std::string outputDirectory) const { +void Statistics::write(const std::string outputDirectory) const +{ std::cerr << "writing into " << outputDirectory << std::endl; const boost::filesystem::path path = outputDirectory; { std::ofstream os((path / "unmapped.csv").c_str()); if (!(os << "missing,extra\n" << missing << "," << extra << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } { std::ofstream os((path / "total_match_mismatch.csv").c_str()); if (!(os << "match,mismatch\n" << match << "," << mismatch << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } const std::vector mapqBins{"60", "30_59", "1_29", "0"}; for (unsigned i = 0; 4 > i; ++i) { const std::string label = std::string("position_mismatch_") + mapqBins[i]; - std::ofstream os((path / (label + ".csv")).c_str()); + std::ofstream os((path / (label + ".csv")).c_str()); if (!(os << label << "\n" << position[i].second << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } for (unsigned i = 0; 4 > i; ++i) { const std::string label = std::string("position_match_") + mapqBins[i]; - std::ofstream os((path / (label + ".csv")).c_str()); + std::ofstream os((path / (label + ".csv")).c_str()); if (!(os << label << "\n" << position[i].first << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } @@ -825,29 +845,25 @@ void Statistics::write(const std::string outputDirectory) const { os << "," << flags[i].second; } if (!(os << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } for (unsigned i = 0; 4 > i; ++i) { const std::string label = std::string("mapq_mismatch_") + mapqBins[i]; - std::ofstream os((path / (label + ".csv")).c_str()); - if (!(os << label << ",HW_LT_SW_" << mapqBins[i] << ",HW_GT_SW_" - << mapqBins[i] << "\n" - << mapq[i].second << "," << mapqDirection[i].first << "," - << mapqDirection[i].second << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::ofstream os((path / (label + ".csv")).c_str()); + if (!(os << label << ",HW_LT_SW_" << mapqBins[i] << ",HW_GT_SW_" << mapqBins[i] << "\n" + << mapq[i].second << "," << mapqDirection[i].first << "," << mapqDirection[i].second + << std::endl)) { + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } for (unsigned i = 0; 4 > i; ++i) { const std::string label = std::string("cigar_mismatch_") + mapqBins[i]; - std::ofstream os((path / (label + ".csv")).c_str()); + std::ofstream os((path / (label + ".csv")).c_str()); if (!(os << label << "\n" << cigar[i].second << std::endl)) { - std::cerr << "failed to write output csv file: " << strerror(errno) - << std::endl; + std::cerr << "failed to write output csv file: " << strerror(errno) << std::endl; exit(5); } } diff --git a/src/dragen-os.cpp b/src/dragen-os.cpp index 2e015a5..39898a6 100644 --- a/src/dragen-os.cpp +++ b/src/dragen-os.cpp @@ -20,6 +20,8 @@ int main(int argc, char* argv[]) { - dragenos::common::run(dragenos::workflow::buildHashTable, argc, argv); - dragenos::common::run(dragenos::workflow::input2Sam, argc, argv); + dragenos::options::DragenOsOptions opts; + dragenos::common::parse_options(argc, argv, opts); + dragenos::common::run(dragenos::workflow::buildHashTable, opts); + dragenos::common::run(dragenos::workflow::input2Sam, opts); } diff --git a/src/include/align/Aligner.hpp b/src/include/align/Aligner.hpp index b0aa3ff..efca0c9 100644 --- a/src/include/align/Aligner.hpp +++ b/src/include/align/Aligner.hpp @@ -15,21 +15,10 @@ #ifndef ALIGN_ALIGNER_HPP #define ALIGN_ALIGNER_HPP -#include -#include -#include - -#include - #include "align/AlignmentGenerator.hpp" #include "align/AlignmentRescue.hpp" -#include "align/Alignments.hpp" -#include "align/InsertSizeParameters.hpp" #include "align/PairBuilder.hpp" -#include "align/SinglePicker.hpp" -#include "map/Mapper.hpp" #include "reference/Hashtable.hpp" -#include "reference/HashtableConfig.hpp" #include "reference/ReferenceDir.hpp" #include "sequences/Read.hpp" #include "sequences/ReadPair.hpp" @@ -45,19 +34,20 @@ class Aligner { // Aligner(Aligner&&) = delete; //Aligner &operator=(Aligner&&) = delete; Aligner( - const reference::ReferenceDir& referenceDir, - const reference::Hashtable& hashtable, - bool mapOnly, - const int swAll, - const SimilarityScores& similarity, - const int gapInit, - const int gapExtend, - const int unclipScore, - const int alnMinScore, - const int aln_cfg_mapq_min_len, - const uint32_t alignerUnpairedPen, - const double aln_cfg_filter_len_ratio, - const bool vectorizedSW); + const reference::ReferenceSequence& refSeq, + const reference::HashtableConfig& htConfig, + const reference::Hashtable& hashtable, + bool mapOnly, + const int swAll, + const SimilarityScores& similarity, + const int gapInit, + const int gapExtend, + const int unclipScore, + const int alnMinScore, + const int aln_cfg_mapq_min_len, + const uint32_t alignerUnpairedPen, + const double aln_cfg_filter_len_ratio, + const bool vectorizedSW); typedef sequences::Read Read; typedef sequences::ReadPair ReadPair; typedef align::Alignment Alignment; @@ -135,10 +125,11 @@ class Aligner { void filter(AlignmentPairs& alignmentPairs, std::array& unpairedAlignments); private: - const reference::ReferenceDir& referenceDir_; - const bool mapOnly_; - const int swAll_; - const bool vectorizedSW_; + const reference::ReferenceSequence& refSeq_; + const reference::HashtableConfig& htConfig_; + const bool mapOnly_; + const int swAll_; + const bool vectorizedSW_; /// read the hashtable config data and throw on error //std::vector getHashtableConfigData(const boost::filesystem::path referenceDir) const; /// maps hashtable data and throw on error diff --git a/src/include/align/Alignment.hpp b/src/include/align/Alignment.hpp index dc1c8e8..3c84709 100644 --- a/src/include/align/Alignment.hpp +++ b/src/include/align/Alignment.hpp @@ -30,6 +30,7 @@ typedef uint32_t FlagType; struct AlignmentHeader { enum Flag : FlagType { + NONE = 0, MULTIPLE_SEGMENTS = 0x1, ALL_PROPERLY_ALIGNED = 0x2, UNMAPPED = 0x4, diff --git a/src/include/align/AlignmentGenerator.hpp b/src/include/align/AlignmentGenerator.hpp index 90d2378..05b64e7 100644 --- a/src/include/align/AlignmentGenerator.hpp +++ b/src/include/align/AlignmentGenerator.hpp @@ -16,6 +16,7 @@ #define ALIGN_ALIGNMENT_GENERATOR_HPP #include "align/Alignments.hpp" +#include "align/SmithWaterman.hpp" #include "align/VectorSmithWaterman.hpp" #include "map/ChainBuilder.hpp" #include "reference/ReferenceDir.hpp" @@ -29,11 +30,13 @@ class AlignmentGenerator { typedef sequences::Read Read; typedef map::ChainBuilder ChainBuilder; AlignmentGenerator( - const reference::ReferenceDir& referenceDir, - SmithWaterman& smithWaterman, - VectorSmithWaterman& vectorSmithWaterman, - bool vectorizedSW) - : referenceDir_(referenceDir), + const reference::ReferenceSequence& refSeq, + const reference::HashtableConfig& htConfig, + SmithWaterman& smithWaterman, + VectorSmithWaterman& vectorSmithWaterman, + bool vectorizedSW) + : refSeq_(refSeq), + htConfig_(htConfig), smithWaterman_(smithWaterman), vectorSmithWaterman_(vectorSmithWaterman), vectorizedSW_(vectorizedSW) @@ -50,10 +53,11 @@ class AlignmentGenerator { const int readIdx); private: - const reference::ReferenceDir& referenceDir_; - SmithWaterman& smithWaterman_; - VectorSmithWaterman& vectorSmithWaterman_; - const bool vectorizedSW_; + const reference::ReferenceSequence& refSeq_; + const reference::HashtableConfig& htConfig_; + SmithWaterman& smithWaterman_; + VectorSmithWaterman& vectorSmithWaterman_; + const bool vectorizedSW_; void updateFetchChain(const Read& read, map::SeedChain& seedChain, Alignment& alignment); }; // class AlignmentGenerator diff --git a/src/include/align/Alignments.hpp b/src/include/align/Alignments.hpp index fe774ce..6e18798 100644 --- a/src/include/align/Alignments.hpp +++ b/src/include/align/Alignments.hpp @@ -17,8 +17,6 @@ #include "align/Alignment.hpp" #include "align/SimilarityScores.hpp" -#include "align/SmithWaterman.hpp" -#include "align/VectorSmithWaterman.hpp" namespace dragenos { namespace align { diff --git a/src/include/align/CalculateRefStartEnd.hpp b/src/include/align/CalculateRefStartEnd.hpp index 67ff527..1980967 100644 --- a/src/include/align/CalculateRefStartEnd.hpp +++ b/src/include/align/CalculateRefStartEnd.hpp @@ -22,7 +22,7 @@ namespace dragenos { namespace align { -std::pair calculateRefStartEnd(const sequences::Read& read, const map::SeedChain& chain); +std::pair calculateRefStartEnd(const sequences::Read& read, const map::SeedChain& chain); } // namespace align } // namespace dragenos diff --git a/src/include/align/Cigar.hpp b/src/include/align/Cigar.hpp index b7d7955..1ea0f23 100644 --- a/src/include/align/Cigar.hpp +++ b/src/include/align/Cigar.hpp @@ -22,6 +22,8 @@ #include #include +#include "common/Debug.hpp" + namespace dragenos { namespace align { @@ -54,8 +56,9 @@ class Cigar { bool operator!=(const Operation& that) const { return that.first != first || that.second != second; } bool operator==(const Operation& that) const { return that.first == first && that.second == second; } }; + typedef std::vector Operations; - const Operation* const getOperations() const { return operations_.data(); } + const Operation* getOperations() const { return operations_.data(); } /// set the cigar operations from the individual operations in operations sequence string uint32_t setOperationSequence(const std::string& operationsSequence, int softClipStart = 0); unsigned getNumberOfOperations() const { return operations_.size(); } @@ -94,7 +97,7 @@ class Cigar { bool empty() const { return operations_.empty(); } private: - std::vector operations_; + Operations operations_; }; class SerializedCigar { diff --git a/src/include/align/Query.hpp b/src/include/align/Query.hpp index 73b5de1..33c52cc 100644 --- a/src/include/align/Query.hpp +++ b/src/include/align/Query.hpp @@ -50,7 +50,7 @@ class Query : public sequences::Read::Bases // public std::vector decltype(begin()) {return begin() + beginOffset_;} private: diff --git a/src/include/align/SmithWaterman.hpp b/src/include/align/SmithWaterman.hpp index 70c4af3..52f6b87 100644 --- a/src/include/align/SmithWaterman.hpp +++ b/src/include/align/SmithWaterman.hpp @@ -252,7 +252,7 @@ class SmithWatermanT { "|\\^", "|\\<^", "+x", "+<", "+^", "+<^", "+\\", "+\\<", "+\\^", "+\\<^", }; - assert(bs < sizeof(BS) / sizeof(BS[0])); + assert(size_t(bs) < sizeof(BS) / sizeof(BS[0])); return BS[bs]; } @@ -305,7 +305,7 @@ class SmithWatermanT { int qpos = width - 1; int rpos = -width; - for (int i = 0; history.size() > i; ++i) { + for (std::size_t i = 0; history.size() > i; ++i) { qpos += (sw.motions_.at(i) == Motion::down); rpos += (sw.motions_.at(i) == Motion::right); os << "qpos=" << std::max(0, qpos - int(sw.width) + 1) @@ -350,6 +350,9 @@ class SmithWatermanT { typedef SmithWatermanT SmithWaterman; +template +const int SmithWatermanT::width; + } // namespace align } // namespace dragenos diff --git a/src/include/align/VectorSmithWaterman.hpp b/src/include/align/VectorSmithWaterman.hpp index 9430fdd..73056d2 100644 --- a/src/include/align/VectorSmithWaterman.hpp +++ b/src/include/align/VectorSmithWaterman.hpp @@ -17,7 +17,7 @@ #include "align/SimilarityScores.hpp" #include "common/DragenLogger.hpp" -#include "ssw/ssw.h" +#include "ssw/ssw.hpp" #include "align/Alignment.hpp" #include "align/Database.hpp" @@ -46,6 +46,8 @@ class VectorSmithWaterman { } } + sswBias_ = ssw_get_bias(sswScoringMat_, sswAlphabetSize_); + #ifdef TRACE_VECTOR_SMITH_WATERMAN printf("Scoring matrix for vectorized Smith Waterman\n"); printf(" "); @@ -92,9 +94,15 @@ class VectorSmithWaterman { const int8_t unclipScore_; int8_t* sswScoringMat_; int sswAlphabetSize_; + int32_t sswBias_; std::array querySize_; - std::array profile_; - std::array profileRev_; +#ifdef __AVX2__ + std::array profile_; + std::array profileRev_; +#else + std::array profile_; + std::array profileRev_; +#endif }; } // namespace align diff --git a/src/include/bam/Bam.hpp b/src/include/bam/Bam.hpp index 72b1528..c5b2f42 100644 --- a/src/include/bam/Bam.hpp +++ b/src/include/bam/Bam.hpp @@ -63,6 +63,11 @@ class BamRecordAccessor { return std::distance(first, second) == std::distance(that.first, that.second) && std::equal(first, second, that.first); } + + friend std::ostream& operator<<(std::ostream& os, const Name& name) + { + return os << std::string_view(name.first, std::distance(name.first, name.second)); + } }; const BamRecordHeader* h_; @@ -82,10 +87,12 @@ class BamRecordAccessor { bool suplementary() const { return h_->flag & Flag::SUPPLEMENTARY_ALIGNMENT; } bool reverse() const { return h_->flag & Flag::REVERSE_COMPLEMENT; } bool paired() const { return h_->flag & Flag::MULTIPLE_SEGMENTS; } + bool first() const { return h_->flag & Flag::FIRST_IN_TEMPLATE; } + bool last() const { return h_->flag & Flag::LAST_IN_TEMPLATE; } const std::size_t readLength() const { return h_->l_seq; } const char* nameBegin() const { return h_->read_name; } - const char* nameEnd() const { return nameBegin() + h_->l_read_name; } + const char* nameEnd() const { return nameBegin() + h_->l_read_name - 1; } const Name getName(const char qnameSuffixDelim) const { return Name(nameBegin(), std::find(nameBegin(), nameEnd(), qnameSuffixDelim)); diff --git a/src/include/bam/BamBlockReader.hpp b/src/include/bam/BamBlockReader.hpp index 9eb17e4..565c512 100644 --- a/src/include/bam/BamBlockReader.hpp +++ b/src/include/bam/BamBlockReader.hpp @@ -44,7 +44,8 @@ class BamBlockReader { public: typedef std::istream::char_type char_type; - BamBlockReader(std::istream& stream, const char inputQnameSuffixDelim) : stream_(stream), inputQnameSuffixDelim_ (inputQnameSuffixDelim) + BamBlockReader(std::istream& stream, const char inputQnameSuffixDelim) + : stream_(stream), inputQnameSuffixDelim_(inputQnameSuffixDelim) { skipToFirstRecord(); } @@ -94,34 +95,67 @@ class BamBlockReader { /** * \brief find first incomplete record * \return number of bytes in s ending at the end of last complete record + * \postcondition returned number of bytes does not break pair apart */ std::size_t findFirstIncomplete(const char_type* s, std::size_t n) const { - const char_type* prevPrev = 0; - const char_type* prev = 0; + const char_type* prevGood = 0; + const char_type* lastGood = 0; + const char_type* lastCompleteAny = 0; BamRecordAccessor bra(s); while (sizeof(BamRecordHeader) < n && bra.size() <= n) { n -= bra.size(); if (!bra.secondary() && !bra.suplementary()) { - prevPrev = prev; - prev = bra.current(); + prevGood = lastGood; + lastGood = bra.current(); } + lastCompleteAny = bra.current(); // std::cerr << bra << std::endl; bra.envelop(bra.next()); } - if (!prev) { - BOOST_THROW_EXCEPTION(BamException("Insufficient buffer to read a single bam record")); + if (!lastGood) { + // could not find a single useful record in the block. Probably position-sorted bam file. + // just make sure we're making some progress and return the end of last fully contained record + if (!lastCompleteAny) { + BOOST_THROW_EXCEPTION(BamException("Insufficient buffer to read a single bam record")); + } + return std::distance(s, (const char*)lastCompleteAny); } - BamRecordAccessor prevBra(prev); - if (prevBra.paired()) { - if (!prevPrev || BamRecordAccessor(prevPrev).getName(inputQnameSuffixDelim_) == - prevBra.getName(inputQnameSuffixDelim_)) { - return std::distance(s, (const char*)prevBra.next()); + BamRecordAccessor r2(lastGood); + if (r2.paired()) { + // let lastGood is in only if it is read 2 of pair and read 1 is already in + // assume prevGood is pointing at r1 + if (!prevGood) { + if (!r2.first()) { + BOOST_THROW_EXCEPTION(BamException( + std::string("Incorrect order of records in bam detected at record name: ") + << r2.getName(inputQnameSuffixDelim_) + << ". DRAGMAP requires name-sorted bam with read 1 immediately followed by read 2")); + } + } else { + BamRecordAccessor r1(prevGood); + if (r1.getName(inputQnameSuffixDelim_) == r2.getName(inputQnameSuffixDelim_)) { + // include last full paired record because its mate is already in + if (!r1.paired() || !r1.first() || !r2.last()) { + BOOST_THROW_EXCEPTION(BamException( + std::string("Improper order of records in bam detected at record name: ") + << r2.getName(inputQnameSuffixDelim_) + << " DRAGMAP requires name-sorted bam with read 1 immediately followed by read 2")); + } + return std::distance(s, (const char*)r2.next()); + } else if (!r2.first()) { + BOOST_THROW_EXCEPTION(BamException( + std::string("Wrong order of records in bam detected at record name: ") + << r2.getName(inputQnameSuffixDelim_) + << ". DRAGMAP requires name-sorted bam with read 1 immediately followed by read 2")); + } } + // else exclude last paired record because we have not read the mate yet } - return std::distance(s, (const char*)prev); + // else single-ended record is fine + return std::distance(s, (const char*)lastGood); } void readMagic() diff --git a/src/include/common/BufferPool.hpp b/src/include/common/BufferPool.hpp deleted file mode 100644 index 9576fac..0000000 --- a/src/include/common/BufferPool.hpp +++ /dev/null @@ -1,136 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef COMMON_BUFFER_POOL_HPP -#define COMMON_BUFFER_POOL_HPP - -#include -#include -#include -#include -#include "inttypes.h" - -namespace dragenos { -namespace common { - -class BufferPool { -private: - enum { BUFFER_ALIGNMENT = 1 << 12 }; - -private: - typedef uint8_t* Buffer; - typedef std::deque Buffer_c; - typedef Buffer_c::iterator Buffer_it; - - typedef std::queue Buffer_q; - -public: - BufferPool(uint32_t numBuffers, size_t bufferSize); - - virtual ~BufferPool(); - - // Borrow a buffer from the pool - Buffer borrow(const bool wait = true, const bool clear = true); // borrow a buffer from the pool - - // Put a buffer back on the freelist - void replace(void* buf); // the buffer to replace in the freelist - - // trigger our condition variable to allow users to wake up and exit - void exit() - { - std::unique_lock lock(m_mutex); - m_exit = true; - m_cond.notify_one(); - } - - void unexit() - { - std::unique_lock lock(m_mutex); - m_exit = false; - } - - // Return the number of free buffers in the buffer pool - size_t getNumFree() - { - std::lock_guard lock(m_mutex); - return (m_totalSize - m_totalBorrowed) / m_bufferSize; - } - // Return the number of free buffers in the buffer pool (debug only) - // Caller shall accept stale values - size_t getNumFreeDebugOnly() { return (m_totalSize - m_totalBorrowed) / m_bufferSize; } - - // Return the total number of buffers in the buffer pool - uint32_t getNumBuffers() { return m_totalSize / m_bufferSize; } - - // Add #num_buffers# worth of capacity to the pool - void addBufferCapacity(size_t num_buffers) - { - m_totalSize += (m_bufferSize * num_buffers); - m_cond.notify_one(); - } - - // Returns when a free buffer is avaiable. - void waitForFreeBuffer() - { - std::unique_lock lock(m_mutex); - while (m_totalBorrowed + m_bufferSize >= m_totalSize && !m_exit) { //m_free.empty() ) { - m_cond.wait(lock); - } - } - - // Return size of each buffer - size_t getBufferSize() const { return m_bufferSize; } - - // Return number of bytes currently on loan (i.e. borrowed) - size_t getTotalBorrowed() const { return m_totalBorrowed; } - - // Get the high water mark for the buffer pool - size_t getHighWatermark() const { return m_highWatermark; } - - // Get number of bytes still on loan, but about to be replace()'d due to being in an - // i/o queue or some other such latency. - size_t getPendingReplaces() const { return m_pendingReplaces; } - - // Take note that we should expect #n# bytes to be coming back via replace() soon. - void incPendingReplaces(const size_t n) - { - std::unique_lock lock(m_mutex); - m_pendingReplaces += n; - } - - // Return total amount of memory (both borrowed and available) in the pool - size_t getTotalSize() const { return m_totalSize; } - - bool SetPreallocation(bool preallocateFlag); - -private: - size_t m_bufferSize; // Size of each buffer - size_t m_totalSize; // Total number of bytes used for our buffers - size_t m_totalBorrowed; // How many bytes have been borrow()'ed - size_t m_highWatermark; // The high water mark for the Buffer pool - size_t m_pendingReplaces; // How many bytes are about to be returned - std::mutex m_mutex; // Protect changes to the free/allocated lists - std::condition_variable m_cond; // Signals freelist non-emptiness - bool m_exit; - - bool m_preallocated; - Buffer_q m_preallocatedBuffers; - - void ActivatePreallocation(); - void DeactivatePreallocation(); -}; - -} // namespace common -} // namespace dragenos -#endif // #ifndef COMMON_BUFFER_POOL_HPP diff --git a/src/include/common/Crc32Hw.hpp b/src/include/common/Crc32Hw.hpp deleted file mode 100644 index 6923f8f..0000000 --- a/src/include/common/Crc32Hw.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef COMMON_CRC32_HW_HPP -#define COMMON_CRC32_HW_HPP - -#include -#include - -namespace dragenos { -namespace common { - -uint32_t crc32c_hw(uint32_t crc, const void* buf, std::size_t len); -bool machine_has_sse42(); - -} // namespace common -} // namespace dragenos - -#endif //#ifndef COMMON_CRC32_HW_HPP diff --git a/src/include/common/Debug.hpp b/src/include/common/Debug.hpp index 298a7fc..cb8848e 100644 --- a/src/include/common/Debug.hpp +++ b/src/include/common/Debug.hpp @@ -100,13 +100,6 @@ static std::ostream nostream(0); } #endif -inline std::string parseStat(const std::string& stat) -{ - std::vector statFields; - boost::algorithm::split(statFields, stat, boost::algorithm::is_any_of(" ")); - return std::string(statFields.at(22) + "vm " + statFields.at(23) + "res"); -} - class ScopedMallocBlock : boost::noncopyable { public: enum Mode { Invalid = 0, Off, Warning, Strict }; @@ -235,7 +228,7 @@ class CerrLocker { boost::io::ios_base_all_saver ias_; public: - CerrLocker(const CerrLocker& that) : lock_(cerrMutex_), ias_(std::cerr) {} + CerrLocker(const CerrLocker& /* that */) : lock_(cerrMutex_), ias_(std::cerr) {} CerrLocker() : lock_(cerrMutex_), ias_(std::cerr) {} operator bool() const { return false; } diff --git a/src/include/common/DragenConstants.hpp b/src/include/common/DragenConstants.hpp deleted file mode 100644 index 48f68f4..0000000 --- a/src/include/common/DragenConstants.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef COMMON_DRAGEN_CONSTANTS_HPP -#define COMMON_DRAGEN_CONSTANTS_HPP - -#include // for _SC_PAGE_SIZE - -#include - -namespace DragenConstants { - -// -// General -// -const uint64_t DRAGEN_1KB = 0x400; -const uint64_t DRAGEN_4KB = 0x1000; -const uint64_t DRAGEN_8KB = 0x2000; -const uint64_t DRAGEN_16KB = 0x4000; -const uint64_t DRAGEN_32KB = 0x8000; -const uint64_t DRAGEN_64KB = 0x10000; -const uint64_t DRAGEN_128KB = 0x20000; -const uint64_t DRAGEN_256KB = 0x40000; -const uint64_t DRAGEN_512KB = 0x80000; -const uint64_t DRAGEN_1MB = 1 << 20; -const uint64_t DRAGEN_1GB = 1 << 30; - -// We have a hard-coded limit to the number of read groups we can handle, -// due to a corresponding hardware limit -const uint16_t DRAGEN_MAX_READ_GROUPS = 1024; - -// The line for whether a dataset is an exome or a genome -const double DRAGEN_EXOME_CUTOFF = 50.0; -const double DRAGEN_GERMLINE_EXOME_CUTOFF = 50.0; -const double DRAGEN_SOMATIC_EXOME_CUTOFF = 40.0; -const double DRAGEN_SOMATIC_NORMAL_EXOME_CUTOFF = 80.0; - -typedef enum vcType { NONE, GERMLINE, SOMATIC, SOMATIC_NORMAL } vcType_t; -} // namespace DragenConstants - -#define DRAGEN_PAGE_SIZE sysconf(_SC_PAGE_SIZE) - -#endif // #ifndef COMMON_DRAGEN_CONSTANTS_HPP diff --git a/src/include/common/FixedPoint.hpp b/src/include/common/FixedPoint.hpp deleted file mode 100644 index 3e48bb1..0000000 --- a/src/include/common/FixedPoint.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef COMMON_FIXED_POINT_HPP -#define COMMON_FIXED_POINT_HPP - -#include -#include -#include - -//#include "dragen_exception.hpp" - -namespace dragenos { -namespace common { - -class FixedPointNumber { -private: - typedef int32_t value_type; - typedef int64_t product_type; - -public: - FixedPointNumber(const uint8_t int_bits, const uint8_t frac_bits) - : m_IntegerBits(int_bits), m_FractionBits(frac_bits), m_Value(0) - { - } - - FixedPointNumber(const uint8_t int_bits, const uint8_t frac_bits, value_type val) - : m_IntegerBits(int_bits), m_FractionBits(frac_bits), m_Value(val) - { - } - - void AssignInt(int32_t x) { m_Value = x << m_FractionBits; } - - void AssignFloat(float f, bool useRound = true) - { - const int32_t one = static_cast((1) << m_FractionBits); - if (useRound) { - m_Value = static_cast(round(f * one)); - } else { - m_Value = static_cast(ceil(f * one)); - } - } - - void SetValue(value_type x) { m_Value = x; } - - value_type GetValue() const { return m_Value; } - - double AsDouble() const - { - const uint64_t one = 1 << m_FractionBits; - return static_cast(m_Value) / one; - } - - uint8_t GetFractionBits() const { return m_FractionBits; } - - uint16_t GetNumBits() const { return m_IntegerBits + m_FractionBits; } - - //--------------------------------------------------------------------------------adam - // AssignLog2 - run Mike's fast approximation of a log2, as described in his - // architecture notes. - // - void AssignLog2(uint32_t n) - { - BOOST_ASSERT(n > 0); - // The integer part of the log is simply the most significant bit. - // Builtin_clz returns number of leading (from msb-side) zero-bits. - const uint32_t msb = 8 * sizeof(n) - __builtin_clz(n) - 1; - - // The fraction part is the next 7 bits below the msb - uint32_t frac = n & ((static_cast(1) << msb) - 1); - uint32_t bits_in_mask = std::min(static_cast(7), msb); - frac >>= msb - bits_in_mask; - m_Value = (msb << m_FractionBits) | (frac << (m_FractionBits - bits_in_mask)); - } - - //--------------------------------------------------------------------------------adam - // Multiply: fixed-point multiplication, using an intermediate result twice as - // large as the operands. - // - void Multiply(const FixedPointNumber& x, const FixedPointNumber& y) - { - BOOST_ASSERT(8 * sizeof(product_type) >= x.GetNumBits() + y.GetNumBits()); - - const uint8_t shift = (x.GetFractionBits() + y.GetFractionBits() - m_FractionBits); - product_type product = (x.GetValue() * y.GetValue()) >> shift; - - // TODO: check for overflow - m_Value = product; - } - -private: - uint8_t m_IntegerBits; - uint8_t m_FractionBits; - value_type m_Value; -}; - -} // namespace common -} // namespace dragenos -#endif // #ifndef COMMON_FIXED_POINT_HPP diff --git a/src/include/common/GenString.hpp b/src/include/common/GenString.hpp deleted file mode 100644 index f49f829..0000000 --- a/src/include/common/GenString.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef COMMON_GEN_STRING_HPP -#define COMMON_GEN_STRING_HPP - -#include - -//////////////////////////////////////////////////////////////////////////////// -// Template metaprogram to generate gen_string_() function for each of 1 to 30 -// variable-type arguments. The preprocessor output looks like this: -// -// template < typename T0 > -// std::string gen_string_( const T0 &t0) { -// std::ostringstream oss; -// oss << t0; -// return oss.str(); -//} -// -// template < typename T0 , typename T1 > -// std::string gen_string_( const T0 &t0 , const T1 &t1) { -// std::ostringstream oss; -// oss << t0 << t1; -// return oss.str(); -// } -// -// and so on, up to thirty classes. -#include -#include -#include -#define GEN_STRING_LSHIFTER(z, ITER, data) data##ITER - -#define GEN_STRING(z, ITER, data) \ - template \ - std::string gen_string_(BOOST_PP_ENUM_BINARY_PARAMS(ITER, const T, &t)) \ - { \ - std::ostringstream oss; \ - oss BOOST_PP_REPEAT(ITER, GEN_STRING_LSHIFTER, << t); \ - return oss.str(); \ - } -BOOST_PP_REPEAT_FROM_TO(1, 30, GEN_STRING, ~) -// -// ... end of boost gen_string_ metaprogram. -//////////////////////////////////////////////////////////////////////////////// - -#endif diff --git a/src/include/common/PackedUmi.hpp b/src/include/common/PackedUmi.hpp deleted file mode 100644 index 14e2fdd..0000000 --- a/src/include/common/PackedUmi.hpp +++ /dev/null @@ -1,230 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef COMMON_PACKED_UMI_HPP -#define COMMON_PACKED_UMI_HPP - -#include -#include -#include -#include -#include -#include -#include - -#pragma pack(1) - -namespace dragenos { -namespace common { -//--------------------------------------------------------------------------------adamb -// A class representing a bit-packed UMI, attached to DBAM records in a blob -// for quick access and use in duplicate-marking and read-collapsing -// -class PackedUmi { -public: - enum { MAX_UMI_LEN = 8 }; - -public: - typedef uint32_t PackedSeq_t; - -private: - //--------------------------------------------------------------------------- - // A structure packing the lengths of the pair of UMI sequences into one byte - struct SeqLen_t { - public: - SeqLen_t& operator=(const SeqLen_t& other) - { - m_lens = other.m_lens; - return *this; - } - - public: - SeqLen_t(const uint8_t l1, const uint8_t l2) : m_lens((l1 & 0xFF) | ((l2 & 0xFF) << 4)) {} - - uint8_t getLen(const uint16_t whichSeq) const { return (m_lens >> (4 * whichSeq)) & 0x0F; } - - private: - uint8_t m_lens; // lengths, packed 4-bytes per length. - }; - -public: - PackedUmi() : m_lens(0, 0), m_seqs{0, 0}, m_isN{0xFF, 0xFF} {}; - - PackedUmi( - const char* seq1, // UMI sequence for first end - const size_t len1, // length of first-end UMI sequence - const char* seq2, // UMI sequence for second end - const size_t len2) // length of second-end UMI sequence - ; - - PackedUmi(const PackedSeq_t ps1, const PackedSeq_t ps2); - - PackedUmi& operator=(const PackedUmi& other) - { - m_lens = other.m_lens; - m_seqs = other.m_seqs; - m_isN = other.m_isN; - return *this; - } - - uint8_t getLen(const uint32_t whichSeq) const - { - return std::min(static_cast(MAX_UMI_LEN), m_lens.getLen(whichSeq)); - } - - void getAsciiSeq(const uint32_t whichSeq, char* ascii_out, const uint8_t maxLen) const - { - getAsciiSeq(ascii_out, std::min(maxLen, getLen(whichSeq)), m_seqs[whichSeq], m_isN[whichSeq]); - } - - PackedSeq_t getPackedSeq(const uint32_t whichSeq) const - { - return packSeq(getLen(whichSeq), m_isN[whichSeq], m_seqs[whichSeq]); - } - - uint64_t asUint64() const - { - return (static_cast(getPackedSeq(0)) << 32) | (static_cast(getPackedSeq(1))); - } - - template - void getTag(OutputStream& os) const - { - os.write("RXZ", 3); - print(os); - } - - template - void print(OutputStream& os) const - { - char ascii[MAX_UMI_LEN]; - for (auto i = 0; i < 2; ++i) { - getAsciiSeq(i, ascii, sizeof(ascii)); - os.write(ascii, getLen(i)); - if (i == 0) os.put('-'); - } - } - - bool operator==(const PackedUmi& other) const - { - return ( - (getLen(0) == other.getLen(0)) && (getLen(1) == other.getLen(1)) && - (getPackedSeq(0) == other.getPackedSeq(0)) && (getPackedSeq(1) == other.getPackedSeq(1))); - } - - // Compare packed UMI's lexicographically. We need this to mimic ReCo's ordering - // of families alphabetically by sequence. - bool operator<(const PackedUmi& other) const - { - char mine[MAX_UMI_LEN]; - char theirs[MAX_UMI_LEN]; - for (uint32_t i = 0; i < 2; ++i) { - memset(mine, 0, MAX_UMI_LEN); - memset(theirs, 0, MAX_UMI_LEN); - getAsciiSeq(i, mine, MAX_UMI_LEN); - other.getAsciiSeq(i, theirs, MAX_UMI_LEN); - - const int comparison = strncmp(mine, theirs, std::min(getLen(i), other.getLen(i))); - if (comparison < 0) - return true; - else if (comparison > 0) - return false; - } - - return false; - } - - bool isReverseOf(const PackedUmi& other) const - { - return ( - (getLen(0) == other.getLen(1)) && (getLen(1) == other.getLen(0)) && - (getPackedSeq(0) == other.getPackedSeq(1)) && (getPackedSeq(1) == other.getPackedSeq(0))); - } - - static void packedSeqToAscii(char* ascii_out, const uint8_t maxLen, const PackedSeq_t packedSeq) - { - const uint32_t len = (packedSeq >> 24) & 0xFF; - BOOST_ASSERT_MSG( - maxLen > len, "ERROR: must reserve enough space to hold the UMI sequence plus a null-terminator"); - const uint16_t seq = packedSeq & 0xFFFF; - const uint8_t isN = (packedSeq >> 16) & 0xFF; - return getAsciiSeq(ascii_out, len, seq, isN); - } - - static PackedSeq_t asciiToPackedSeq(const std::string& seq) - { - uint16_t packedSeq = 0; - uint8_t isN = 0; - const size_t len = seq.size(); - transformSequence(seq.c_str(), len, &packedSeq, &isN); - return packSeq(len, isN, packedSeq); - } - - bool isValid() const { return getLen(1) && getLen(2); } - - void reverseComplement(); - - bool arrangeEndsLexicographically(); - - bool lexicographicallyPrecedes(const PackedUmi& other) const; - -private: - static PackedSeq_t packSeq(const uint16_t len, const uint8_t isN, const uint16_t seq) - { - return (static_cast(len) << 24) | (static_cast(isN) << 16) | - (static_cast(seq)); - } - - void transformSequence( // transform one of the two member sequences - const uint16_t whichSeq, // 0 or 1 - const char* seq, // input ASCII FASTQ-format sequence - const size_t len) // how many bytes in #seq# - ; - - static void transformSequence( // transform ASCII FASTQ-format sequence to DBAM - const char* seq, // input ASCII FASTQ-format sequence - const size_t len, // how many bytes in #seq# - uint16_t* dest, // where to put the packed sequence bits - uint8_t* isN) // where to put the 'isN' bits - ; - -private: - static void getAsciiSeq(char* ascii_out, const uint8_t maxLen, uint16_t seq, const uint8_t isN) - { - static char DBAM2FASTQ_BASES[] = "ACGT"; - uint8_t i = 0; - for (i = 0; i < maxLen; ++i, seq >>= 2) { - if (isN & (1 << i)) - ascii_out[i] = 'N'; - else - ascii_out[i] = DBAM2FASTQ_BASES[seq & 0x3]; - } - ascii_out[i] = 0; - } - -private: - SeqLen_t m_lens; // how long are the two UMI sequences - std::array m_seqs; // the UMI sequences, in DBAM format - std::array m_isN; // bit per base, whether it's an N -}; -#pragma pack() - -struct PackedUmiHashkeyCalculator { - size_t operator()(const PackedUmi& pu) const { return std::hash()(pu.asUint64()); } -}; - -} // namespace common -} // namespace dragenos - -#endif // #ifndef COMMON_PACKED_UMI_HPP diff --git a/src/include/common/Program.hpp b/src/include/common/Program.hpp index 905c5fa..93d4675 100644 --- a/src/include/common/Program.hpp +++ b/src/include/common/Program.hpp @@ -64,7 +64,7 @@ class Options : boost::noncopyable { typedef boost::shared_ptr OptionDescriptionPtr; typedef std::vector OptionDescriptionPtrs; std::string helpDefaults(const OptionDescriptionPtrs& options) const; - std::string help(const OptionDescriptionPtrs& options, const bool markdown) const; + std::string help(const OptionDescriptionPtrs& options) const; private: virtual std::string usagePrefix() const = 0; @@ -113,6 +113,56 @@ void run(void (*callback)(const O&), int argc, char* argv[]) } } +template +void parse_options(int argc, char* argv[], O& options) +{ + // fix for Failed to parse the options: locale::facet::_S_create_c_locale name not valid + setenv("LC_ALL", "C", 0); + try { + const typename O::Action action = options.parse(argc, argv); + if (O::RUN == action) { + return; + } else if (O::HELP == action) { + std::cout << options.usage() << std::endl; + exit(0); + } else if (O::VERSION == action) { + std::cout << Version::string() << std::endl; + exit(0); + } else { + // std::clog << options.usage() << std::endl; + exit(1); + } + } catch (const dragenos::common::ExceptionData& exception) { + std::clog << "Error: " << exception.getContext() << ": " << exception.getMessage() << std::endl; + exit(1); + } catch (const boost::exception& e) { + std::clog << "Error: boost::exception: " << boost::diagnostic_information(e) << std::endl; + exit(2); + } catch (const std::exception& e) { + std::clog << e.what() << std::endl; + exit(3); + } +} + +template +void run(void (*callback)(const O&), const O& options) +{ + // fix for Failed to parse the options: locale::facet::_S_create_c_locale name not valid + setenv("LC_ALL", "C", 0); + try { + callback(options); + } catch (const dragenos::common::ExceptionData& exception) { + std::clog << "Error: " << exception.getContext() << ": " << exception.getMessage() << std::endl; + exit(1); + } catch (const boost::exception& e) { + std::clog << "Error: boost::exception: " << boost::diagnostic_information(e) << std::endl; + exit(2); + } catch (const std::exception& e) { + std::clog << e.what() << std::endl; + exit(3); + } +} + } // namespace common } // namespace dragenos diff --git a/src/include/common/SystemCompatibility.hpp b/src/include/common/SystemCompatibility.hpp index 3602f6c..fcc5e38 100644 --- a/src/include/common/SystemCompatibility.hpp +++ b/src/include/common/SystemCompatibility.hpp @@ -60,13 +60,6 @@ typedef struct __declspec(intrin_type) __declspec(align(16)) vint128_t { #define TSTRING(s) s // nothing to set here. users do it with ulimit #define SET_MAX_FILES -#define DRAGEN_OS_TRACE_STAT(prefix) \ - { \ - std::string statm; \ - std::ifstream ifs("/proc/self/stat"); \ - std::getline(ifs, statm); \ - DRAGEN_OS_THREAD_CERR << "STAT: " << prefix << " " << dragenos::common::parseStat(statm) << std::endl; \ - } // vectorizing 128 bit unsigned integer typedef unsigned long long vint128_t __attribute__((__vector_size__(16))); diff --git a/src/include/common/Threads.hpp b/src/include/common/Threads.hpp index 063cf3c..34b027d 100644 --- a/src/include/common/Threads.hpp +++ b/src/include/common/Threads.hpp @@ -46,7 +46,7 @@ class ScopeEndCall : public ScopeEndCallBase { public: explicit ScopeEndCall(FuncT f) : f_(f) {} - ~ScopeEndCall() override { f_(std::uncaught_exception()); } + ~ScopeEndCall() override { f_(std::uncaught_exceptions()); } }; /** @@ -63,9 +63,10 @@ const detail::ScopeEndCall makeScopeEndCallHolder(FuncT f) /** * \brief ensures f is called during the stack unwind of the scope following the macro */ -#define ASYNC_BLOCK_WITH_CLEANUP(f) \ - if (const rnaq::common::detail::ScopeEndCallBase& b = rnaq::common::detail::makeScopeEndCallHolder(f)) { \ - (void)b; \ +#define ASYNC_BLOCK_WITH_CLEANUP(f) \ + if (const dragenos::common::detail::ScopeEndCallBase& b = \ + dragenos::common::detail::makeScopeEndCallHolder(f)) { \ + (void)b; \ } else //-------------------------------------------------------------------------------rpetrovski @@ -84,6 +85,10 @@ class unlock_guard { ~unlock_guard() { l.lock(); } }; +struct ThreadPoolException : public std::logic_error { + using std::logic_error::logic_error; +}; + template class BasicThreadPool { public: @@ -115,6 +120,7 @@ class BasicThreadPool { std::size_t threadsReady_ = 0; std::exception_ptr firstThreadException_; + bool aThreadFailed_ = false; typedef std::vector ThreadVector; typedef ThreadVector::size_type size_type; @@ -176,6 +182,9 @@ class BasicThreadPool { template void execute(lock_type& lock, F func, const unsigned threads) { + if (aThreadFailed_) { + throw ThreadPoolException("Attempt to execute a failed threadpool"); + } if (firstThreadException_) { // std::cerr << "[" << std::this_thread::get_id() << "]\tWARNING: execute called when an exception is pending " << std::endl; std::rethrow_exception(firstThreadException_); @@ -218,6 +227,18 @@ class BasicThreadPool { } } + /* + * \return always false or throws an exception + */ + bool checkThreadFailed() const + { + if (aThreadFailed_) { + throw ThreadPoolException("Another thread failed in the threadpool"); + } + + return false; + } + void waitForChange(lock_type& lock) { if (firstThreadException_) { @@ -225,6 +246,10 @@ class BasicThreadPool { std::rethrow_exception(firstThreadException_); } + if (aThreadFailed_) { + throw ThreadPoolException("Attempt to wait in a failed threadpool"); + } + if (!terminateRequested_) { stateChangedCondition_.wait(lock); } @@ -233,6 +258,10 @@ class BasicThreadPool { // std::cerr << "[" << std::this_thread::get_id() << "]\tWARNING: rethrowing a thread exception " << std::endl; std::rethrow_exception(firstThreadException_); } + + if (aThreadFailed_) { + throw ThreadPoolException("Another thread failed while waiting for state change"); + } } void notify_all() { stateChangedCondition_.notify_all(); } @@ -313,6 +342,7 @@ class BasicThreadPool { try { executor->execute(lock); } catch (...) { + aThreadFailed_ = true; executor->complete_ = true; --executor->threadsIn_; stateChangedCondition_.notify_all(); diff --git a/src/include/io/Bam2ReadTransformer.hpp b/src/include/io/Bam2ReadTransformer.hpp index d2b86c6..46031d4 100644 --- a/src/include/io/Bam2ReadTransformer.hpp +++ b/src/include/io/Bam2ReadTransformer.hpp @@ -35,7 +35,10 @@ class BamToReadTransformer { friend DumpT& dump(DumpT& dump, const BamToReadTransformer& transformer); public: - BamToReadTransformer(const char qnameSuffixDelim = DEFAULT_QNAME_DELIM) {} + BamToReadTransformer(const char qnameSuffixDelim = DEFAULT_QNAME_DELIM) + : qnameSuffixDelim_(qnameSuffixDelim) + { + } void operator()(const bam::BamRecordAccessor& bra, unsigned pos, uint64_t fragmentId, sequences::Read& read) { diff --git a/src/include/io/CigarBuilder.hpp b/src/include/io/CigarBuilder.hpp deleted file mode 100644 index 98796fb..0000000 --- a/src/include/io/CigarBuilder.hpp +++ /dev/null @@ -1,139 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#ifndef IO_CIGAR_BUILDER_HPP -#define IO_CIGAR_BUILDER_HPP - -#include // for std::reverse -#include -#include - -#include - -//#include "dragen_exception.hpp" - -namespace dragenos { -namespace io { - -//--------------------------------------------------------------------------------adam -// CigarBuilder - a class to build up a cigar string one operation at a time -// -class CigarBuilder { -private: - static const uint8_t MATCH; - static const uint8_t INS; - static const uint8_t DEL; - static const uint8_t REFSKIP; - static const uint8_t SOFTCLIP; - static const uint8_t HARDCLIP; - static const uint8_t PAD; - static const uint8_t SEQMATCH; - static const uint8_t MISMATCH; - -public: - CigarBuilder(); - - void AddMatch() { IncrementCurrentOp(MATCH); } - - void AddInsertion() { IncrementCurrentOp(INS); } - - void AddDeletion() { IncrementCurrentOp(DEL); } - - void AddSoftClip() { IncrementCurrentOp(SOFTCLIP); } - - void AddHardClip() { IncrementCurrentOp(HARDCLIP); } - - friend std::ostream& operator<<(std::ostream& os, const CigarBuilder& cigar); - - void Reverse() - { // reverse the order of the CIGAR records - std::reverse(m_Records.begin(), m_Records.end()); - } - - void ConsolidateRecords(); - - const std::vector* GetRecords() { return &m_Records; } - - void SetReadStart(const int32_t read_start) { m_ReadStart = read_start; } - - int32_t GetReadStart() const { return m_ReadStart; } - - void SetReadEnd(const int32_t read_end) { m_ReadEnd = read_end; } - - int32_t GetReadEnd() const { return m_ReadEnd; } - - void SetRefStart(const int64_t ref_start) { m_RefStart = ref_start; } - - int64_t GetRefStart() const { return m_RefStart; } - - void SetRefEnd(const int64_t ref_end) { m_RefEnd = ref_end; } - - int64_t GetRefEnd() const { return m_RefEnd; } - - size_t GetLen() const { return m_Records.size() * sizeof(uint16_t); } - - // void Trim(const uint32_t read_len) - // ; - -private: - void IncrementCurrentOp(const uint8_t op); - - uint8_t GetCurrentOp() const; - - uint16_t GetCurrentCount() const; - -private: - std::vector m_Records; - int32_t m_ReadStart; - int32_t m_ReadEnd; - int64_t m_RefStart; - int64_t m_RefEnd; -}; - -inline std::ostream& operator<<(std::ostream& os, const CigarBuilder& cigar) -{ - for (std::vector::const_iterator it = cigar.m_Records.begin(); it != cigar.m_Records.end(); - ++it) { - uint16_t num = (*it) >> 4; - uint8_t op = (*it) & 0xF; - os << num; - if (op == CigarBuilder::MATCH) - os << "M"; - else if (op == CigarBuilder::INS) - os << "I"; - else if (op == CigarBuilder::DEL) - os << "D"; - else if (op == CigarBuilder::REFSKIP) - os << "N"; - else if (op == CigarBuilder::SOFTCLIP) - os << "S"; - else if (op == CigarBuilder::HARDCLIP) - os << "H"; - else if (op == CigarBuilder::PAD) - os << "P"; - else if (op == CigarBuilder::SEQMATCH) - os << "="; - else if (op == CigarBuilder::MISMATCH) - os << "X"; - else - BOOST_ASSERT(false); - } - // os << ", TOTAL BASES: " << total; - return os; -} - -} // namespace io -} // namespace dragenos - -#endif // #ifndef IO_CIGAR_BUILDER_HPP diff --git a/src/include/map/Mapper.hpp b/src/include/map/Mapper.hpp index 6666170..d3b3942 100644 --- a/src/include/map/Mapper.hpp +++ b/src/include/map/Mapper.hpp @@ -190,6 +190,10 @@ class Mapper { const uint64_t extensionIdBinMask_; /// mask used to keep all related hashes (probing region, chains, extensions) in the same memory segment const uint64_t addressSegmentMask_; + + /// local vectors used in addToPositionChains, member variables for malloc optimization + mutable std::vector hashRecords_; + mutable std::vector extendTableIntervals_; }; } // namespace map diff --git a/src/include/map/SeedPosition.hpp b/src/include/map/SeedPosition.hpp index 1febb68..30a7d47 100644 --- a/src/include/map/SeedPosition.hpp +++ b/src/include/map/SeedPosition.hpp @@ -31,7 +31,7 @@ class SeedPosition { } ReferencePosition getReferencePosition() const { return position_; } const sequences::Seed& getSeed() const { return seed_; } - const unsigned getHalfExtension() const { return halfExtension_; } + unsigned getHalfExtension() const { return halfExtension_; } /// Projected reference position of the leftmost base of the read ReferencePosition getFirstProjection(bool reverseComplement) const; /// Projected reference position of the rightmost base of the read diff --git a/src/include/options/DragenOsOptions.hpp b/src/include/options/DragenOsOptions.hpp index cffbdf8..6ca832b 100644 --- a/src/include/options/DragenOsOptions.hpp +++ b/src/include/options/DragenOsOptions.hpp @@ -53,7 +53,10 @@ class DragenOsOptions : public common::Options { bool mapOnly_; int swAll_ = 0; // Aligner.sw-all - std::string methodSmithWaterman_ = "mengyao"; // "mengyao" : vectorized SW library / "dragen" for legacy code + std::string methodSmithWatermanDeprecated_; + std::string methodSmithWaterman_ = + "mengyao"; // "mengyao" : vectorized SW library / "dragen" for legacy code + bool samplingEnabled_ = true; // sampling-enabled double alignerPeMeanInsert_ = 0.0; // Aligner.pe-stat-mean-insert double alignerPeStddevInsert_ = 0.0; // Aligner.pe-stat-stddev-insert diff --git a/src/include/reference/HashRecord.hpp b/src/include/reference/HashRecord.hpp index 8f9d296..5475340 100644 --- a/src/include/reference/HashRecord.hpp +++ b/src/include/reference/HashRecord.hpp @@ -130,7 +130,7 @@ class HashRecord { bool isHit() const { return 0xF != getBits(); } bool isDummyHit() const { return 0 == getPosition(); } uint64_t getOpCode() const { return getBits(); } - uint64_t getType() const { return isHit() ? HIT : getOpCode(); } + uint64_t getType() const { return isHit() ? uint64_t(HIT) : getOpCode(); } uint8_t getThreadId() const { return getBits(); } uint32_t getMatchBits() const { return getBits(); } bool isLastInThread() const { return getFlag(); } diff --git a/src/include/reference/HashtableConfig.hpp b/src/include/reference/HashtableConfig.hpp index 0e170c4..3508fa5 100644 --- a/src/include/reference/HashtableConfig.hpp +++ b/src/include/reference/HashtableConfig.hpp @@ -256,14 +256,14 @@ class HashtableConfig { } unsigned getPrimarySeedBases() const { return header_.priSeedBases; } /// convert a position from the hashtable into reference coordinates (sequence id, offset) - std::pair convertToReferenceCoordinates(int64_t position) const; + std::pair convertToReferenceCoordinates(uint64_t position) const; /// get the range of positions for a given sequence static std::pair getPositionRange(const Sequence& sequence) { const size_t trimmedLength = sequence.seqLen - sequence.begTrim - sequence.endTrim; return std::pair(sequence.seqStart, sequence.seqStart + trimmedLength); } - bool beyondLastCfgSequence(int64_t position) const + bool beyondLastCfgSequence(uint64_t position) const { const auto& sequence = sequences_.back(); return position > (sequence.seqStart - sequence.begTrim + sequence.seqLen); @@ -284,7 +284,7 @@ class HashtableConfig { const std::string hashFname_; const std::string altLiftover_; // extract the header from the raw data - const Header* const header(const char* const data, const size_t size) const + const Header* header(const char* const data, const size_t size) const { if (sizeof(Header) > size) { BOOST_THROW_EXCEPTION( @@ -336,10 +336,10 @@ class HashtableConfig { assert(ret.size() == sequences_.size()); return ret; } - std::string refIdxFname(const char* const data, const size_t size) const + std::string refIdxFname(const char* const data, const size_t /*size*/) const { size_t bufOffset = sizeof(header_) + header_.numRefSeqs * sizeof(detail::hashtableSeq_t); - for (auto i = 0; i < header_.numRefSeqs; ++i) { + for (uint32_t i = 0; i < header_.numRefSeqs; ++i) { bufOffset += sequenceNames_[i].size() + 1; } const char* hostVersion = data + bufOffset; diff --git a/src/include/reference/ReferenceDir.hpp b/src/include/reference/ReferenceDir.hpp index 6c5a218..cc4e524 100644 --- a/src/include/reference/ReferenceDir.hpp +++ b/src/include/reference/ReferenceDir.hpp @@ -36,9 +36,6 @@ class ReferenceDir { }; class ReferenceDir7 : public ReferenceDir { - const bool mmap_; - const bool load_; - public: ReferenceDir7(const boost::filesystem::path& path, bool mmap, bool load); ~ReferenceDir7(); diff --git a/src/include/reference/ReferenceSequence.hpp b/src/include/reference/ReferenceSequence.hpp index 163d23e..e5b0626 100644 --- a/src/include/reference/ReferenceSequence.hpp +++ b/src/include/reference/ReferenceSequence.hpp @@ -16,9 +16,13 @@ #define REFERENCE_REFERENCE_SEQUENCE_HPP #include +#include #include #include #include +#ifdef __AVX2__ +#include +#endif #include "common/Exceptions.hpp" @@ -89,6 +93,7 @@ class ReferenceSequence { : trimmedRegions_(std::move(trimmedRegions)), data_(data), size_(size) { } + void reset(std::vector trimmedRegions, const unsigned char* data, const size_t size) { trimmedRegions_ = std::move(trimmedRegions); @@ -96,30 +101,104 @@ class ReferenceSequence { size_ = size; } - template - void getBases(size_t beginPosition, size_t endPosition, IT out) const + void getBases(size_t beginPosition, size_t endPosition, std::vector& out) const { - for (auto position = beginPosition; position != endPosition; ++position) { - const unsigned char base4bpb = getBase(position); - *out++ = base4bpb; - //const unsigned char base2bpb = reference::ReferenceSequence::translateTo2bpb(base4bpb); - //*out++ = base2bpb; + checkPosition(endPosition); + + size_t len = endPosition - beginPosition; + size_t pos = 0; + out.clear(); + out.resize(len); + + // handle even position index + if (beginPosition % 2 == 1) { + out[pos] = getBaseNoCheck(beginPosition + pos); + pos++; + } + +#ifdef __AVX2__ + constexpr int ELEMS_AVX2 = 32; + unsigned char* dst = out.data(); + __m128i mask = _mm_set1_epi8(0x0F); + + for (; pos + ELEMS_AVX2 <= len; pos += ELEMS_AVX2) { + __m128i data = _mm_loadu_si128((__m128i*)(&data_[(beginPosition + pos) / 2])); + __m128i low = _mm_and_si128(data, mask); + __m128i high = _mm_and_si128(_mm_srli_epi16(data, 4), mask); + + __m256i lowExt = _mm256_cvtepu8_epi16(low); + __m256i highExt = _mm256_cvtepu8_epi16(high); + __m256i highShifted = _mm256_slli_si256(highExt, 1); // shifting out the byte 15 but we don't care + + __m256i resBases = _mm256_or_si256(lowExt, highShifted); + _mm256_storeu_si256((__m256i*)&dst[pos], resBases); + } +#endif + + // process remaining bases + for (; pos != len; pos++) { + const unsigned char base4bpb = getBaseNoCheck(beginPosition + pos); + out[pos] = base4bpb; + } + } + + void getRcBases(size_t beginPosition, size_t endPosition, std::vector& out) const + { + checkPosition(endPosition); + + size_t len = endPosition - beginPosition; + out.clear(); + out.resize(len); + for (size_t pos = 0; pos < len; pos++) { + const unsigned char base4bpb = getRcBaseNoCheck(pos + beginPosition); + out[pos] = base4bpb; } } - template - void getRcBases(size_t beginPosition, size_t endPosition, IT out) const + inline unsigned char getBase(size_t position) const { - for (auto position = beginPosition; position != endPosition; ++position) { - const unsigned char base4bpb = getRcBase(position); - *out++ = base4bpb; - //const unsigned char base2bpb = reference::ReferenceSequence::translateToR2bpb(base4bpb); - //*out++ = base2bpb; +#if 0 + size_t address = position; + auto extractBase = [this](size_t address) -> unsigned char + { + const unsigned char result = data_[address / 2]; + return ((address % 2) ? (result >> 4) : result) & 0xF; + }; + for (const auto &trimmedRegion: trimmedRegions_) + { + if (position >= trimmedRegion[1]) + { + // adjust address to account for trimmed bases + address -= (trimmedRegion[1] - trimmedRegion[0]); + } + else if (position >= trimmedRegion[0]) + { + return 15; // 15 == encoded N + } + else + { + // return base in sequence before trimmed region + return extractBase(address); + } } + // if we get here we are past the last trim region - check if still be in the sequence + if (address / 2 >= size_) + { + BOOST_THROW_EXCEPTION(common::InvalidParameterException("position greater than reference size")); + } + return extractBase(address); +#endif + // has high impact on performance + checkPosition(position); + return getBaseNoCheck(position); + } + + inline unsigned char getRcBase(size_t position) const + { + checkPosition(position); + return getRcBaseNoCheck(position); } - unsigned char getBase(size_t position) const; - unsigned char getRcBase(size_t position) const; const unsigned char* getData() const { return data_; } size_t getSize() const { return size_; } /// decode 4 bits into AIUPAC character using only 4 LSB @@ -130,6 +209,45 @@ class ReferenceSequence { static unsigned char translateToR2bpb(unsigned char base4bpb); private: + void checkPosition(size_t position) const + { + if (position / 2 >= size_) { + boost::format message = + boost::format("position greater than reference size: %i > 2 * %i") % position % size_; + BOOST_THROW_EXCEPTION(common::InvalidParameterException(message.str())); + } + } + + inline unsigned char getBaseNoCheck(size_t position) const + { + const unsigned char twoBases = data_[position / 2]; + const bool msb = (position % 2); // use the 4 MSB for odd positions + return msb ? (twoBases >> 4) : (twoBases & 0xF); + } + + inline unsigned char getRcBaseNoCheck(size_t position) const + { + unsigned char b = getBaseNoCheck(position); + const static std::array translate{0b0000, // 0b0000 + 0b1000, // 0b0001 + 0b0100, // 0b0010 + 0b1100, // 0b0011 + 0b0010, // 0b0100 + 0b1010, // 0b0101 + 0b0110, // 0b0110 + 0b1110, // 0b0111 + 0b0001, // 0b1000 + 0b1001, // 0b1001 + 0b0101, // 0b1010 + 0b1101, // 0b1011 + 0b0011, // 0b1100 + 0b1011, // 0b1101 + 0b0111, // 0b1110 + 0b1111}; // 0b1111 + + return translate[b]; + } + std::vector trimmedRegions_; /// raw data from reference.bin, encoded as 2 bases per byte const unsigned char* data_; diff --git a/src/include/align/Sam.hpp b/src/include/sam/SamGenerator.hpp similarity index 89% rename from src/include/align/Sam.hpp rename to src/include/sam/SamGenerator.hpp index 24e2ffd..fe877fe 100644 --- a/src/include/align/Sam.hpp +++ b/src/include/sam/SamGenerator.hpp @@ -15,23 +15,22 @@ #ifndef ALIGN_SAM_HPP #define ALIGN_SAM_HPP -#include #include -#include #include -#include "align/Alignment.hpp" +#include "align/Mapq.hpp" +#include "reference/HashtableConfig.hpp" #include "sequences/Read.hpp" namespace dragenos { -namespace align { +namespace sam { -class Sam { +class SamGenerator { static const char Q0_ = 33; const reference::HashtableConfig& hashtableConfig_; public: - Sam(const reference::HashtableConfig& hashtableConfig) : hashtableConfig_(hashtableConfig) {} + SamGenerator(const reference::HashtableConfig& hashtableConfig) : hashtableConfig_(hashtableConfig) {} template static std::string getReadName(const ReadT& read) @@ -52,8 +51,8 @@ class Sam { } else { os << (-1 == alignment.getReference() ? std::string("=") : hashtableConfig_.getSequenceName(alignment.getReference())) - << '\t' << alignment.getPosition() + 1 << '\t' << std::min(alignment.getMapq(), MAPQ_MAX) - << '\t'; + << '\t' << alignment.getPosition() + 1 << '\t' + << std::min(alignment.getMapq(), align::MAPQ_MAX) << '\t'; if (alignment.getCigar().empty()) { os << "*\t"; } else { @@ -64,7 +63,7 @@ class Sam { if (!alignment.hasMultipleSegments() || (alignment.isUnmapped() && alignment.isUnmappedNextSegment())) { os << "*\t0\t"; } else { - os << (-1 == alignment.getNextReference() + os << (-1 == alignment.getNextReference() || alignment.getReference() == alignment.getNextReference() ? std::string("=") : hashtableConfig_.getSequenceName(alignment.getNextReference())) << '\t' << alignment.getNextPosition() + 1 << '\t'; @@ -76,14 +75,14 @@ class Sam { if (-1 != alignment.getScore()) { os << "\tAS:i:" << alignment.getScore(); } - if (INVALID_SCORE != alignment.getXs()) { + if (align::INVALID_SCORE != alignment.getXs()) { os << "\tXS:i:" << alignment.getXs(); } if (-1 != alignment.getMismatchCount()) { os << "\tNM:i:" << alignment.getMismatchCount(); } - if (MAPQ_MAX < alignment.getMapq()) { - os << "\tXQ:i:" << std::min(alignment.getMapq(), HW_MAPQ_MAX); + if (align::MAPQ_MAX < alignment.getMapq()) { + os << "\tXQ:i:" << std::min(alignment.getMapq(), align::HW_MAPQ_MAX); } if (alignment.getSa()) { @@ -92,7 +91,7 @@ class Sam { << ',' << (sa.reverse() ? "-," : "+,") << sa.getCigar() << ',' // << std::min(sa.getMapq(), MAPQ_MAX) << - << std::min(sa.getMapq(), HW_MAPQ_MAX) << ',' << sa.getNm() << ';'; + << std::min(sa.getMapq(), align::HW_MAPQ_MAX) << ',' << sa.getNm() << ';'; } return os; } @@ -119,7 +118,7 @@ class Sam { { const auto& bases = read.getBases(); const auto& cigar = a.getCigar(); - if (cigar.countEndHardClips() + cigar.countStartHardClips() >= bases.size()) return os; + if (cigar.countEndHardClips() + cigar.countStartHardClips() >= int(bases.size())) return os; if (a.isReverseComplement()) { auto range = boost::adaptors::reverse(bases); range.advance_begin(cigar.countStartHardClips()); @@ -143,7 +142,7 @@ class Sam { { const auto& qualities = read.getQualities(); const auto& cigar = a.getCigar(); - if (cigar.countEndHardClips() + cigar.countStartHardClips() >= qualities.size()) return os; + if (cigar.countEndHardClips() + cigar.countStartHardClips() >= int(qualities.size())) return os; if (a.isReverseComplement()) { auto range = boost::adaptors::reverse(qualities); range.advance_begin(cigar.countStartHardClips()); @@ -190,7 +189,7 @@ class Sam { } }; -} // namespace align +} // namespace sam } // namespace dragenos #endif // #ifndef ALIGN_SAM_HPP diff --git a/src/include/workflow/DualFastq2SamWorkflow.hpp b/src/include/workflow/DualFastq2SamWorkflow.hpp index 67afc92..8ff6c00 100644 --- a/src/include/workflow/DualFastq2SamWorkflow.hpp +++ b/src/include/workflow/DualFastq2SamWorkflow.hpp @@ -22,9 +22,10 @@ namespace dragenos { namespace workflow { class DualFastq2SamWorkflow { - const options::DragenOsOptions& options_; - const reference::ReferenceDir7& referenceDir_; - const reference::Hashtable& hashtable_; + const options::DragenOsOptions& options_; + const reference::ReferenceSequence& refSeq_; + const reference::HashtableConfig& htConfig_; + const reference::Hashtable& hashtable_; // IMPORTANT: this has to divide INIT_INTERVAL_SIZE without remainder. Else the whole insert // size stats detection will hang because it depends on processing alignment results exactly // after sending INIT_INTERVAL_SIZE into the aligner. @@ -42,10 +43,11 @@ class DualFastq2SamWorkflow { public: DualFastq2SamWorkflow( - const options::DragenOsOptions& options, - const reference::ReferenceDir7& referenceDir, - const reference::Hashtable& hashtable) - : options_(options), referenceDir_(referenceDir), hashtable_(hashtable) + const options::DragenOsOptions& options, + const reference::ReferenceSequence& refSeq, + const reference::HashtableConfig& htConfig, + const reference::Hashtable& hashtable) + : options_(options), refSeq_(refSeq), htConfig_(htConfig), hashtable_(hashtable) { } @@ -56,6 +58,19 @@ class DualFastq2SamWorkflow { align::InsertSizeParameters requestInsertSizeInfo( align::InsertSizeDistribution& insertSizeDistribution, std::istream& inputR1, std::istream& inputR2); + void alignDualFastqBlock( + common::ThreadPool::lock_type& lock, + std::size_t& cpuThreads, + std::size_t& threadID, + std::vector& mappingMetricsVector, + align::InsertSizeDistribution& insertSizeDistribution, + fastq::FastqNRecordReader& r1Reader, + fastq::FastqNRecordReader& r2Reader, + std::ostream& os, + const align::SinglePicker& singlePicker, + const align::SimilarityScores& similarity, + const sam::SamGenerator& sam); + template void alignDualFastq( align::InsertSizeParameters& insertSizeParameters, diff --git a/src/include/workflow/alignment/AlignmentUtils.hpp b/src/include/workflow/alignment/AlignmentUtils.hpp index adccd4c..a2c9a26 100644 --- a/src/include/workflow/alignment/AlignmentUtils.hpp +++ b/src/include/workflow/alignment/AlignmentUtils.hpp @@ -75,7 +75,8 @@ void storePeSupplementary( if (alignments.end() != sup) { sup->setFlags( align::Alignment::SUPPLEMENTARY_ALIGNMENT | align::Alignment::MULTIPLE_SEGMENTS | - (mate.isReverseComplement() ? align::Alignment::REVERSE_COMPLEMENT_NEXT_SEGMENT : 0)); + (mate.isReverseComplement() ? align::Alignment::REVERSE_COMPLEMENT_NEXT_SEGMENT + : align::Alignment::NONE)); sup->cigar().softClipsToHardClips(); sup->setNextPosition(mate.getPosition()); if (mate.getReference() != sup->getReference()) { @@ -115,9 +116,10 @@ void storePeSecondary( // std::cerr << "m:" << m << std::endl; a.setFlags( align::Alignment::SECONDARY_ALIGNMENT | align::Alignment::MULTIPLE_SEGMENTS | - (m.isUnmapped() ? align::Alignment::UNMAPPD_NEXT_SEGMENT : 0) | - (m.isReverseComplement() ? align::Alignment::REVERSE_COMPLEMENT_NEXT_SEGMENT : 0) | - (ap.isProperPair() ? align::Alignment::ALL_PROPERLY_ALIGNED : 0)); + (m.isUnmapped() ? align::Alignment::UNMAPPD_NEXT_SEGMENT : align::Alignment::NONE) | + (m.isReverseComplement() ? align::Alignment::REVERSE_COMPLEMENT_NEXT_SEGMENT + : align::Alignment::NONE) | + (ap.isProperPair() ? align::Alignment::ALL_PROPERLY_ALIGNED : align::Alignment::NONE)); a.cigar().softClipsToHardClips(); a.setXs(primary->at(readIdx).getScore()); @@ -146,13 +148,12 @@ void storePairedBest( const align::Alignment& m = pair.at(a.isFirstInTemplate()); a.setNextPosition(m.getPosition()); a.setFlags( - align::Alignment::MULTIPLE_SEGMENTS | (m.isUnmapped() ? align::Alignment::UNMAPPD_NEXT_SEGMENT : 0) | - (m.isReverseComplement() ? align::Alignment::REVERSE_COMPLEMENT_NEXT_SEGMENT : 0) | - (pair.isProperPair() ? align::Alignment::ALL_PROPERLY_ALIGNED : 0)); + align::Alignment::MULTIPLE_SEGMENTS | + (m.isUnmapped() ? align::Alignment::UNMAPPD_NEXT_SEGMENT : align::Alignment::NONE) | + (m.isReverseComplement() ? align::Alignment::REVERSE_COMPLEMENT_NEXT_SEGMENT : align::Alignment::NONE) | + (pair.isProperPair() ? align::Alignment::ALL_PROPERLY_ALIGNED : align::Alignment::NONE)); if (a.getReference() == m.getReference()) { - a.setNextReference(-1); - const int tlen = getTlen(a, m, insertSizeParameters.orientation_); if (!align::pairMatch(insertSizeParameters, a, m) || !pair.isProperPair()) { @@ -205,10 +206,14 @@ void alignAndStorePair( aligner.unpaired(0), best, 0, - [&](align::AlignmentPair& ap) {}) || + [&](align::AlignmentPair& /*ap*/) {}) || !pairBuilder.findSecondary( - pair.getLength(), alignmentPairs, aligner.unpaired(1), best, 1, [&](align::AlignmentPair& ap) { - })) { + pair.getLength(), + alignmentPairs, + aligner.unpaired(1), + best, + 1, + [&](align::AlignmentPair& /*ap*/) {})) { storeUnmappedPair(pair, store); return; } diff --git a/src/lib/align/Aligner.cpp b/src/lib/align/Aligner.cpp index 9622824..6d1b4ca 100644 --- a/src/lib/align/Aligner.cpp +++ b/src/lib/align/Aligner.cpp @@ -21,7 +21,6 @@ #include #include "common/DragenLogger.hpp" #include "common/Exceptions.hpp" -#include "ssw/ssw_cpp.h" #include "align/Aligner.hpp" #include "align/CalculateRefStartEnd.hpp" @@ -35,20 +34,22 @@ namespace dragenos { namespace align { Aligner::Aligner( - const reference::ReferenceDir& referenceDir, - const reference::Hashtable& hashtable, - const bool mapOnly, - const int swAll, - const SimilarityScores& similarity, - const int gapInit, - const int gapExtend, - const int unclipScore, - const int alnMinScore, - const int aln_cfg_mapq_min_len, - const uint32_t aln_cfg_unpaired_pen, - const double aln_cfg_filter_len_ratio, - const bool vectorizedSW) - : referenceDir_(referenceDir), + const reference::ReferenceSequence& refSeq, + const reference::HashtableConfig& htConfig, + const reference::Hashtable& hashtable, + const bool mapOnly, + const int swAll, + const SimilarityScores& similarity, + const int gapInit, + const int gapExtend, + const int unclipScore, + const int alnMinScore, + const int aln_cfg_mapq_min_len, + const uint32_t aln_cfg_unpaired_pen, + const double aln_cfg_filter_len_ratio, + const bool vectorizedSW) + : refSeq_(refSeq), + htConfig_(htConfig), mapOnly_(mapOnly), swAll_(swAll), vectorizedSW_(vectorizedSW), @@ -62,7 +63,7 @@ Aligner::Aligner( aln_cfg_unpaired_pen_(aln_cfg_unpaired_pen), smithWaterman_(similarity, gapInit, gapExtend, unclipScore), vectorSmithWaterman_(similarity, gapInit, gapExtend, unclipScore), - alignmentGenerator_(referenceDir_, smithWaterman_, vectorSmithWaterman_, vectorizedSW_), + alignmentGenerator_(refSeq_, htConfig_, smithWaterman_, vectorSmithWaterman_, vectorizedSW_), chainBuilders_{map::ChainBuilder(aln_cfg_filter_len_ratio), map::ChainBuilder(aln_cfg_filter_len_ratio)} { } @@ -117,7 +118,7 @@ void Aligner::generateUngappedAlignments( void Aligner::runSmithWatermanAll( const Read& read, const map::ChainBuilder& chainBuilder, Alignments& alignments, const int readIdx) { - for (int i = 0; i < chainBuilder.size(); ++i) { + for (std::size_t i = 0; i < chainBuilder.size(); ++i) { alignmentGenerator_.generateAlignment(alnMinScore_, read, chainBuilder.at(i), alignments.at(i), readIdx); } @@ -144,12 +145,12 @@ void Aligner::updateIneligibility( void Aligner::generateUngappedAlignment(const Read& read, map::SeedChain& seedChain, Alignment& alignment) { FlagType flags = !read.getPosition() ? Alignment::FIRST_IN_TEMPLATE : Alignment::LAST_IN_TEMPLATE; - flags |= seedChain.isReverseComplement() ? Alignment::REVERSE_COMPLEMENT : 0; - flags |= seedChain.isFiltered() ? Alignment::UNMAPPED : 0; + flags |= seedChain.isReverseComplement() ? Alignment::REVERSE_COMPLEMENT : Alignment::NONE; + flags |= seedChain.isFiltered() ? Alignment::UNMAPPED : Alignment::NONE; alignment.resetFlags(flags); const size_t referenceOffset = seedChain.firstReferencePosition(); - updateIneligibility(referenceDir_.getHashtableConfig(), referenceOffset, read, alignment); + updateIneligibility(htConfig_, referenceOffset, read, alignment); if (seedChain.isFiltered()) { return; @@ -210,16 +211,16 @@ unsigned Aligner::calculatePotentialScore( int Aligner::initializeUngappedAlignmentScores( const Read& read, const bool rcFlag, const size_t referenceOffset, Alignment& alignment) { - std::string operations; - static const char ALIGNMENT_MATCH = Cigar::getOperationName(Cigar::ALIGNMENT_MATCH); - static const char SOFT_CLIP = Cigar::getOperationName(Cigar::SOFT_CLIP); - static const int SOFT_CLIP_ADJUSTMENT = -5; - static const unsigned char N = 0xF; + std::string operations; + static const char ALIGNMENT_MATCH = Cigar::getOperationName(Cigar::ALIGNMENT_MATCH); + static const char SOFT_CLIP = Cigar::getOperationName(Cigar::SOFT_CLIP); + static const int SOFT_CLIP_ADJUSTMENT = -5; + // static const unsigned char N = 0xF; operations.clear(); const auto& readBases = rcFlag ? read.getRcBases() : read.getBases(); int alignmentScore = -SOFT_CLIP_ADJUSTMENT; - int maxScore = 0; - int lastPosition = 0; + // int maxScore = 0; + // int lastPosition = 0; // best stretch with strictly positive scores int bestFirst = 0; int bestLast = 0; @@ -229,19 +230,22 @@ int Aligner::initializeUngappedAlignmentScores( int currentLast = 0; int currentScore = 0; - const reference::HashtableConfig& hashtableConfig = referenceDir_.getHashtableConfig(); - auto refCoords = hashtableConfig.convertToReferenceCoordinates(referenceOffset); - const reference::HashtableConfig::Sequence& seq = hashtableConfig.getSequences().at(refCoords.first); - const auto posRange = hashtableConfig.getPositionRange(seq); + auto refCoords = htConfig_.convertToReferenceCoordinates(referenceOffset); + const reference::HashtableConfig::Sequence& seq = htConfig_.getSequences().at(refCoords.first); + const auto posRange = htConfig_.getPositionRange(seq); const int seqLeft = std::min(readBases.size(), posRange.second - referenceOffset); - for (unsigned i = 0; i < seqLeft; ++i) { - const auto readBase = readBases[i]; - const unsigned char referenceBase = referenceDir_.getReferenceSequence().getBase(referenceOffset + i); - const bool goodReadBase = (readBase > 0) && (readBase != N); - const bool goodReferenceBase = (referenceBase > 0) && (referenceBase != N); - const bool goodBase = goodReadBase && goodReferenceBase; - const bool match = goodBase && (readBase == referenceBase); + Database databaseSeqLeft; + databaseSeqLeft.reserve(seqLeft + 1); + refSeq_.getBases(referenceOffset, referenceOffset + seqLeft, databaseSeqLeft); + + for (int i = 0; i < seqLeft; ++i) { + const auto readBase = readBases[i]; + const unsigned char referenceBase = databaseSeqLeft[i]; + // const bool goodReadBase = (readBase > 0) && (readBase != N); + // const bool goodReferenceBase = (referenceBase > 0) && (referenceBase != N); + // const bool goodBase = goodReadBase && goodReferenceBase; + // const bool match = goodBase && (readBase == referenceBase); alignmentScore += similarity_(readBase, referenceBase); alignmentScore = std::max(0, alignmentScore); if (0 == alignmentScore) { @@ -281,9 +285,20 @@ int Aligner::initializeUngappedAlignmentScores( } // TODO: check if final soft clip is needed int malus = 0; - for (unsigned i = bestLast + 1; i < seqLeft; ++i) { + + Database databaseBestLastToSeqLeft; + size_t bestToLastRefStart = referenceOffset + bestLast + 1; + databaseBestLastToSeqLeft.reserve(seqLeft + 1); + refSeq_.getBases(bestToLastRefStart, bestToLastRefStart + seqLeft, databaseBestLastToSeqLeft); + + /* + databaseBestLastToSeqLeft.reserve(seqLeft - bestLast + 1); + refSeq_.getBases(referenceOffset + bestLast + 1, referenceOffset + bestLast + 1 + seqLeft, databaseBestLastToSeqLeft); + */ + + for (int i = bestLast + 1; i < seqLeft; ++i) { const auto readBase = readBases[i]; - const unsigned char referenceBase = referenceDir_.getReferenceSequence().getBase(referenceOffset + i); + const unsigned char referenceBase = databaseBestLastToSeqLeft[i - (bestLast + 1)]; malus += similarity_(readBase, referenceBase); } if (bestLast + 1 < seqLeft && malus >= SOFT_CLIP_ADJUSTMENT) { @@ -299,18 +314,16 @@ int Aligner::initializeUngappedAlignmentScores( alignment.setScore(std::max(0, bestScore)); alignment.setPotentialScore(calculatePotentialScore(read, bestScore, bestFirst, bestLast + 1)); Database database; + database.reserve(read.getLength() - bestFirst + 1); if (alignment.isReverseComplement()) { - referenceDir_.getReferenceSequence().getRcBases( - referenceOffset + bestFirst, referenceOffset + read.getLength(), std::back_inserter(database)); + refSeq_.getRcBases(referenceOffset + bestFirst, referenceOffset + read.getLength(), database); } else { - referenceDir_.getReferenceSequence().getBases( - referenceOffset + bestFirst, referenceOffset + read.getLength(), std::back_inserter(database)); + refSeq_.getBases(referenceOffset + bestFirst, referenceOffset + read.getLength(), database); } // deal with before reference starts - const auto referenceCoordinates = - referenceDir_.getHashtableConfig().convertToReferenceCoordinates(referenceOffset); - const int refClip = std::max(-referenceCoordinates.second, int64_t(0)); - const int move = alignment.setCigarOperations( + const auto referenceCoordinates = htConfig_.convertToReferenceCoordinates(referenceOffset); + const int refClip = std::max(-referenceCoordinates.second, int64_t(0)); + const int move = alignment.setCigarOperations( operations, database.begin(), database.end(), @@ -370,20 +383,19 @@ void Aligner::getAlignments(const Read& read, Alignments& alignments) } bool Aligner::rescueMate( - const InsertSizeParameters& insertSizeParameters, - const Read& anchoredRead, - const Read& rescuedRead, - const map::SeedChain& anchoredSeedChain, - Alignment& anchoredAlignment, - const AlignmentRescue& alignmentRescue, - map::SeedChain& rescuedSeedChain, - Alignment& rescuedAlignment, - const int anchoredIdx) + const InsertSizeParameters& /*insertSizeParameters*/, + const Read& anchoredRead, + const Read& rescuedRead, + const map::SeedChain& anchoredSeedChain, + Alignment& anchoredAlignment, + const AlignmentRescue& alignmentRescue, + map::SeedChain& rescuedSeedChain, + Alignment& rescuedAlignment, + const int anchoredIdx) { const int rescuedIdx = !anchoredIdx; - if (alignmentRescue.scan( - rescuedRead, anchoredSeedChain, referenceDir_.getReferenceSequence(), rescuedSeedChain)) { + if (alignmentRescue.scan(rescuedRead, anchoredSeedChain, refSeq_, rescuedSeedChain)) { // std::cerr << "rescued:" << rescuedSeedChain << std::endl; if (alignmentGenerator_.generateAlignment( alnMinScore_, rescuedRead, rescuedSeedChain, rescuedAlignment, rescuedIdx)) { @@ -842,14 +854,13 @@ void Aligner::generateDummyAlignments( // TODO: implement for (const auto& seedChain : chainBuilder) { FlagType flags = !read.getPosition() ? Alignment::FIRST_IN_TEMPLATE : Alignment::LAST_IN_TEMPLATE; - flags |= seedChain.isReverseComplement() ? Alignment::REVERSE_COMPLEMENT : 0; + flags |= seedChain.isReverseComplement() ? Alignment::REVERSE_COMPLEMENT : Alignment::NONE; alignments.resize(alignments.size() + 1); auto& alignment = alignments.back(); alignment.resetFlags(flags); // get the reference name from the ReferenceDir and the first diagonal - const size_t referenceOffset = seedChain.firstReferencePosition(); - const reference::HashtableConfig& hashtableConfig = referenceDir_.getHashtableConfig(); - const auto referenceCoordinates = hashtableConfig.convertToReferenceCoordinates(referenceOffset); + const size_t referenceOffset = seedChain.firstReferencePosition(); + const auto referenceCoordinates = htConfig_.convertToReferenceCoordinates(referenceOffset); alignment.setReference(referenceCoordinates.first); const unsigned templateLength = seedChain.lastReferencePosition() - seedChain.firstReferencePosition() + 1; @@ -999,74 +1010,5 @@ void Aligner::filter(Alignments& alignments) } } -#if 0 - -static void checkDirectoryAndFile(const boost::filesystem::path &dir, const boost::filesystem::path &file) -{ - using namespace dragenos::common; - if (!exists(dir)) - BOOST_THROW_EXCEPTION(IoException(ENOENT, std::string("ERROR: directory ") + dir.string() + " doesn't exist")); - const auto filePath = dir / file; - if (!exists(filePath)) - BOOST_THROW_EXCEPTION(IoException(ENOENT, std::string("ERROR: file not found: ") + filePath.string())); - if (!is_regular_file(filePath)) - BOOST_THROW_EXCEPTION(IoException(ENOENT, std::string("ERROR: not a file: ") + filePath.string())); -} - -static uintmax_t getFileSize(const boost::filesystem::path &filePath) -{ - using namespace dragenos::common; - boost::system::error_code ec; - const auto fileSize = file_size(filePath, ec); - if (ec) - BOOST_THROW_EXCEPTION(IoException(ec.value(), std::string("ERROR: failed to get stats for file: ") + filePath.string())); - return fileSize; -} - -std::vector Aligner::getHashtableConfigData(const boost::filesystem::path referenceDir) const -{ - using namespace dragenos::common; - checkDirectoryAndFile(referenceDir, "hash_table.cfg.bin"); - const auto hashtableConfigFile = referenceDir / "hash_table.cfg.bin"; - const auto fileSize = getFileSize(hashtableConfigFile); - std::vector data(fileSize); - std::ifstream is(hashtableConfigFile.string()); - if ( (!is.read(data.data(), fileSize)) || (static_cast(fileSize) != is.gcount()) ) - { - boost::format message = boost::format("ERROR: failed to read %i bytes from binary hashtable config: %i bytes read from %s") % fileSize % is.gcount() % hashtableConfigFile.string(); - BOOST_THROW_EXCEPTION(IoException(errno, message.str())); - } - return data; -} - -uint64_t *Aligner::mmapHashtableData(const boost::filesystem::path referenceDir) const -{ - using namespace dragenos::common; - checkDirectoryAndFile(referenceDir, "hash_table.bin"); - const auto hashtableDataFile = referenceDir / "hash_table.bin"; - const auto fileSize = getFileSize(hashtableDataFile); - if (fileSize != hashtableConfig_.getHashtableBytes()) - { - boost::format message = boost::format("ERROR: hashtable size different from size in config file: expected %i bytes: actual %i bytes") % hashtableConfig_.getHashtableBytes() % fileSize; - BOOST_THROW_EXCEPTION(IoException(errno, message.str())); - } - const auto hashtableFd = open(hashtableDataFile.c_str(), O_RDONLY, 0); - if (-1 == hashtableFd) - { - BOOST_THROW_EXCEPTION(IoException(errno, std::string("ERROR: failed to open hashtable data file ") + hashtableDataFile.string())); - } - const int prot = PROT_READ; - const int flags = MAP_PRIVATE | MAP_NORESERVE; - const int offset = 0; - auto table = static_cast (mmap(NULL, fileSize, prot, flags, hashtableFd, offset)); - if (MAP_FAILED == table) - { - BOOST_THROW_EXCEPTION(IoException(errno, std::string("ERROR: failed to map hashtable data file ") + hashtableDataFile.string())); - } - return reinterpret_cast(table); -} - -#endif - } // namespace align } // namespace dragenos diff --git a/src/lib/align/AlignmentGenerator.cpp b/src/lib/align/AlignmentGenerator.cpp index 6785454..f6d1e9b 100644 --- a/src/lib/align/AlignmentGenerator.cpp +++ b/src/lib/align/AlignmentGenerator.cpp @@ -30,11 +30,9 @@ void AlignmentGenerator::generateAlignments( void AlignmentGenerator::updateFetchChain(const Read& read, map::SeedChain& seedChain, Alignment& alignment) { - const reference::HashtableConfig& hashtableConfig = referenceDir_.getHashtableConfig(); - // only update chain if the alignment is valid const size_t referenceOffset = seedChain.firstReferencePosition(); - auto refCoords = hashtableConfig.convertToReferenceCoordinates(referenceOffset); + auto refCoords = htConfig_.convertToReferenceCoordinates(referenceOffset); int move = alignment.getPosition() - refCoords.second; if (alignment.isPerfect()) { if (seedChain.isReverseComplement()) { @@ -75,7 +73,7 @@ void updateIneligibility(const reference::HashtableConfig& hashtableConfig, Alig const auto& sequences = hashtableConfig.getSequences(); const auto& sequence = sequences.at(alignment.getReference()); if (alignment.getPosition() + alignment.getCigar().getReferenceLength() <= 0 || - sequence.seqLen <= alignment.getPosition()) { + int(sequence.seqLen) <= alignment.getPosition()) { alignment.setIneligibilityStatus(true); } } @@ -105,12 +103,11 @@ bool AlignmentGenerator::generateAlignment( auto beginPosition = refStartEnd.first; auto endPosition = refStartEnd.second + 1; - const reference::HashtableConfig& hashtableConfig = referenceDir_.getHashtableConfig(); // endPosition should be bound by sequence end - if (not hashtableConfig.beyondLastCfgSequence(refStartEnd.first)) { - auto refCoords = hashtableConfig.convertToReferenceCoordinates(refStartEnd.first); - const reference::HashtableConfig::Sequence& seq = hashtableConfig.getSequences().at(refCoords.first); - const auto posRange = hashtableConfig.getPositionRange(seq); + if (not htConfig_.beyondLastCfgSequence(refStartEnd.first)) { + auto refCoords = htConfig_.convertToReferenceCoordinates(refStartEnd.first); + const reference::HashtableConfig::Sequence& seq = htConfig_.getSequences().at(refCoords.first); + const auto posRange = htConfig_.getPositionRange(seq); endPosition = std::min(endPosition, posRange.second); if (endPosition <= beginPosition) return false; } else { @@ -130,10 +127,11 @@ bool AlignmentGenerator::generateAlignment( // assert(endPosition > beginPosition); database.clear(); + database.reserve(endPosition - beginPosition + 1); if (seedChain.isReverseComplement()) { - referenceDir_.getReferenceSequence().getRcBases(beginPosition, endPosition, std::back_inserter(database)); + refSeq_.getRcBases(beginPosition, endPosition, database); } else { - referenceDir_.getReferenceSequence().getBases(beginPosition, endPosition, std::back_inserter(database)); + refSeq_.getBases(beginPosition, endPosition, database); } // align the read for the current seedChain @@ -201,14 +199,14 @@ bool AlignmentGenerator::generateAlignment( beginPosition - seedChain.firstReferencePosition(); // - SmithWaterman::SW_CELLS; //Alignment::FlagType flags = !read.getPosition() ? Alignment::FIRST_IN_TEMPLATE : Alignment::LAST_IN_TEMPLATE; - flags |= seedChain.isReverseComplement() ? Alignment::REVERSE_COMPLEMENT : 0; + flags |= seedChain.isReverseComplement() ? Alignment::REVERSE_COMPLEMENT : Alignment::NONE; } // get the reference name from the ReferenceDir and the first diagonal const size_t referenceOffset = seedChain.firstReferencePosition(); - auto referenceCoordinates = hashtableConfig.convertToReferenceCoordinates(referenceOffset + move); + auto referenceCoordinates = htConfig_.convertToReferenceCoordinates(referenceOffset + move); if (0 > referenceCoordinates.second) { - if (std::abs(referenceCoordinates.second) < read.getLength()) { + if (std::size_t(std::abs(referenceCoordinates.second)) < read.getLength()) { // oops! the sequence starts before reference and the read is long enough to reach the next contig. Redo // CIGAR. move = int(alignment.setCigarOperations( @@ -222,7 +220,7 @@ bool AlignmentGenerator::generateAlignment( beginPosition - seedChain.firstReferencePosition(); // - SmithWaterman::SW_CELLS; // get the reference name from the ReferenceDir and the first diagonal const size_t referenceOffset = seedChain.firstReferencePosition(); - referenceCoordinates = hashtableConfig.convertToReferenceCoordinates(referenceOffset + move); + referenceCoordinates = htConfig_.convertToReferenceCoordinates(referenceOffset + move); } else { // the whole read falls into holes of reference sequences listed in hash_table.cfg) // TODO:consider if there are second layer of holes(padding bytes) within reference.bin and also need to @@ -236,7 +234,7 @@ bool AlignmentGenerator::generateAlignment( alignment.setReference(referenceCoordinates.first); alignment.setPosition(referenceCoordinates.second); - updateIneligibility(referenceDir_.getHashtableConfig(), alignment); + updateIneligibility(htConfig_, alignment); if (alnMinScore > alignment.getScore()) { alignment.setUnmapped(); @@ -245,8 +243,8 @@ bool AlignmentGenerator::generateAlignment( // debug info #ifdef TRACE_ALIGNMENTS std::cerr << "[ALIGNMENT]\tsmith-waterman\t" << alignment << "\t" << seedChain - << "\tcontig:" << std::string(hashtableConfig.getSequenceNames()[referenceCoordinates.first]) - << "(" << referenceCoordinates.first << "):" << referenceCoordinates.second << std::endl; + << "\tcontig:" << std::string(htConfig_.getSequenceNames()[referenceCoordinates.first]) << "(" + << referenceCoordinates.first << "):" << referenceCoordinates.second << std::endl; #endif return true; diff --git a/src/lib/align/AlignmentRescue.cpp b/src/lib/align/AlignmentRescue.cpp index 1ec4fe0..450e710 100644 --- a/src/lib/align/AlignmentRescue.cpp +++ b/src/lib/align/AlignmentRescue.cpp @@ -41,12 +41,13 @@ bool AlignmentRescue::triggeredBy(const SeedChain& anchoredChain, const bool any */ } +// clears referenceBases before data is added uint32_t AlignmentRescue::getReferenceInterval( const SeedChain& anchoredChain, const int rescuedReadLength, const reference::ReferenceSequence& reference, std::vector& referenceBases, - const bool second) const + const bool /*second*/) const { typedef map::SeedPosition::ReferencePosition ReferencePosition; const bool rescue_end = anchoredChain.isReverseComplement(); @@ -81,11 +82,13 @@ uint32_t AlignmentRescue::getReferenceInterval( // const int ref_length = ((((last_ref_pos + 1 - first_ref_pos) + 3) >> 2) << 2); // const int ref_length = (last_ref_pos + 1 - first_ref_pos); assert(first_ref_pos <= last_ref_pos); + referenceBases.clear(); + referenceBases.reserve(ref_length + 1); if (isReversedRescue(anchoredChain)) { - reference.getRcBases(last_ref_pos - ref_length + 1, last_ref_pos + 1, std::back_inserter(referenceBases)); + reference.getRcBases(last_ref_pos - ref_length + 1, last_ref_pos + 1, referenceBases); std::reverse(referenceBases.begin(), referenceBases.end()); } else { - reference.getBases(first_ref_pos, first_ref_pos + ref_length, std::back_inserter(referenceBases)); + reference.getBases(first_ref_pos, first_ref_pos + ref_length, referenceBases); } // std::cerr << "after=" << after << ", anchorPosition=" << anchorPosition<< ", length=" << length << ", pe_min_insert_=" << pe_min_insert_ << ", rescuedReadLength=" << rescuedReadLength << ", minPosition= " << minPosition << ", referenceBases.size()=" << referenceBases.size() << ", isReversedRescue(anchoredChain): " << isReversedRescue(anchoredChain) << std::endl; @@ -137,7 +140,6 @@ bool AlignmentRescue::scan( if (((pe_orientation_ == Orientation::pe_orient_fr_c) || (pe_orientation_ == Orientation::pe_orient_rf_c))) { // get the rescue reference interval - referenceBases.clear(); const auto rescueIntervalStart = getReferenceInterval(anchoredChain, rescuedRead.getLength(), reference, referenceBases); @@ -358,7 +360,9 @@ std::array AlignmentRescue::getRescueKmers( } bool AlignmentRescue::findRescueChain( - const Read& rescuedRead, const std::vector& referenceBases, SeedChain& rescuedChain) const + const Read& /*rescuedRead*/, + const std::vector& /*referenceBases*/, + SeedChain& /*rescuedChain*/) const { return false; } diff --git a/src/lib/align/CalculateRefStartEnd.cpp b/src/lib/align/CalculateRefStartEnd.cpp index e177673..8929868 100644 --- a/src/lib/align/CalculateRefStartEnd.cpp +++ b/src/lib/align/CalculateRefStartEnd.cpp @@ -30,8 +30,8 @@ namespace dragenos { namespace align { -static const int ALN_CFG_SW_EARLY_MAX = 256; -std::pair calculateRefStartEnd(const sequences::Read& read, const map::SeedChain& chain) +static const int ALN_CFG_SW_EARLY_MAX = 256; +std::pair calculateRefStartEnd(const sequences::Read& read, const map::SeedChain& chain) { // std::cerr << "calculateRefStartEnd:" << chain << std::endl; // const auto beginPosition = chain.firstReferencePosition();// - 36;// - 12; @@ -97,14 +97,14 @@ std::pair calculateRefStartEnd(const sequences::Read& read, co // // + // // chain.isReverseComplement(); - const int64_t ref_start = /*ch_cmd.ref_reverse ? + const uint64_t ref_start = /*ch_cmd.ref_reverse ? (chain.lastSeedReferencePosition() + ref_start_adj) :*/ chain.firstSeedReferencePosition() - ref_start_adj; // -- Compute the last reference base to fetch const int64_t ref_m1_v = ref_length - 1; - const int64_t ref_end = /*ch_cmd.ref_reverse ? (ref_start - ref_m1_v) :*/ (ref_start + ref_m1_v); + const uint64_t ref_end = /*ch_cmd.ref_reverse ? (ref_start - ref_m1_v) :*/ (ref_start + ref_m1_v); // std::cerr << "beg_gap=" << beg_gap << ", end_gap=" << end_gap << ", skip_gap=" << skip_gap << ", tail_gap=" << tail_gap << // ", head_gap=" << head_gap << std::uppercase << diff --git a/src/lib/align/Cigar.cpp b/src/lib/align/Cigar.cpp index 03b3889..e5f65f5 100644 --- a/src/lib/align/Cigar.cpp +++ b/src/lib/align/Cigar.cpp @@ -280,7 +280,7 @@ const Cigar::OperationCode Cigar::OPERATION_CODES[256] = {INV, Cigar::OperationCode Cigar::getOperationCode(const char operationName) { - return OPERATION_CODES[operationName]; + return OPERATION_CODES[int(operationName)]; } /** diff --git a/src/lib/align/PairBuilder.cpp b/src/lib/align/PairBuilder.cpp index 699f7bf..6b60ad9 100644 --- a/src/lib/align/PairBuilder.cpp +++ b/src/lib/align/PairBuilder.cpp @@ -117,13 +117,13 @@ int PairBuilder::computePairPenalty( m2a_penalty = aln_cfg_unpaired_pen_; } else { // std::cerr << "c1:" << *c1 << " c2:" << *c2 <getCigar() - .countEndClips(); //readPair[0].getLength() - c1->lastReadBase() - 1; //back().getSeed().getReadPosition() - 1; + // const int inp_result_qry_end_gap = + // a1->getCigar() + // .countEndClips(); //readPair[0].getLength() - c1->lastReadBase() - 1; //back().getSeed().getReadPosition() - 1; // std::cerr << "inp_result_qry_end_gap:" << inp_result_qry_end_gap << std::endl; - const int result_rrec_qry_end_gap = - a2->getCigar() - .countEndClips(); //readPair[1].getLength() - c2->lastReadBase() - 1; //back().getSeed().getReadPosition() - 1; + // const int result_rrec_qry_end_gap = + // a2->getCigar() + // .countEndClips(); //readPair[1].getLength() - c2->lastReadBase() - 1; //back().getSeed().getReadPosition() - 1; // std::cerr << "result_rrec_qry_end_gap:" << result_rrec_qry_end_gap << std::endl; const int inp_eff_beg = a1->getUnclippedStartPosition(); @@ -182,8 +182,8 @@ int PairBuilder::computePairPenalty( // std::cerr << "m2a_scale:" << m2a_scale << std::endl; const int m2a_prod = (m2a_scale * m2a_penalty) >> 10; - const int m2a_prod_frac_bits_c = 10; - const int m2a_prod_pen = m2a_prod; // >> m2a_prod_frac_bits_c; + // const int m2a_prod_frac_bits_c = 10; + const int m2a_prod_pen = m2a_prod; // >> m2a_prod_frac_bits_c; // std::cerr << "m2a_prod_pen:" << m2a_prod_pen << std::endl; return m2a_prod_pen; @@ -380,25 +380,45 @@ void PairBuilder::updateMapq( ScoreType sub_pair_score_v[2] = {INVALID_SCORE, INVALID_SCORE}; ScoreType secondBestSeScore[2] = {INVALID_SCORE, INVALID_SCORE}; - AlignmentPairs::const_iterator secondBestPair[2] = {findSecondBestScore( - averageReadLength, - pairs, - unpairedAlignments, - best, - 0, - sub_count[0], - sub_pair_score_v[0], - secondBestSeScore[0]), - - findSecondBestScore( - averageReadLength, - pairs, - unpairedAlignments, - best, - 1, - sub_count[1], - sub_pair_score_v[1], - secondBestSeScore[1])}; + // AlignmentPairs::const_iterator secondBestPair[2] = {findSecondBestScore( + // averageReadLength, + // pairs, + // unpairedAlignments, + // best, + // 0, + // sub_count[0], + // sub_pair_score_v[0], + // secondBestSeScore[0]), + // + // findSecondBestScore( + // averageReadLength, + // pairs, + // unpairedAlignments, + // best, + // 1, + // sub_count[1], + // sub_pair_score_v[1], + // secondBestSeScore[1])}; + + findSecondBestScore( + averageReadLength, + pairs, + unpairedAlignments, + best, + 0, + sub_count[0], + sub_pair_score_v[0], + secondBestSeScore[0]); + + findSecondBestScore( + averageReadLength, + pairs, + unpairedAlignments, + best, + 1, + sub_count[1], + sub_pair_score_v[1], + secondBestSeScore[1]); updateEndMapq( averageReadLength, best, 0, sub_count[0], sub_pair_score_v[0], secondBestSeScore, secondBestSeScore); diff --git a/src/lib/align/Pairs.cpp b/src/lib/align/Pairs.cpp index acd67f0..8eec1f8 100644 --- a/src/lib/align/Pairs.cpp +++ b/src/lib/align/Pairs.cpp @@ -223,7 +223,7 @@ bool pairMatch(const InsertSizeParameters& insert_stats, const Alignment& a1, co // ", rct_eff_beg=" << rct_eff_beg << ", rct_eff_end=" << rct_eff_end << std::endl; return (inp_result.isReverseComplement() xor result_rrec.isReverseComplement() ^ - InsertSizeParameters::Orientation::pe_orient_ff_c == insert_stats.orientation_) && + (InsertSizeParameters::Orientation::pe_orient_ff_c == insert_stats.orientation_)) && insert_len >= insert_stats.min_ && insert_len <= insert_stats.max_ && inp_result.reference_ == result_rrec.reference_ && !template_bad; } diff --git a/src/lib/align/SmithWaterman.cpp b/src/lib/align/SmithWaterman.cpp index a0651e0..d64bf83 100644 --- a/src/lib/align/SmithWaterman.cpp +++ b/src/lib/align/SmithWaterman.cpp @@ -285,6 +285,7 @@ void SmithWatermanT::reset( // this is required to avoid reallocation of score vectors when scores_ runs out of capacity for adding new scores_.reserve(querySize * std::distance(databaseBegin, databaseEnd) + width); bs_.clear(); + bs_.reserve(querySize * std::distance(databaseBegin, databaseEnd) + width); motions_.clear(); globalMax_ = 0; @@ -336,7 +337,6 @@ void SmithWatermanT::moveDown() assert(scores_.capacity() > scores_.size()); scores_.push_back(wavefront_.moveDown(similarities, gapInit_, gapExtend_)); - bs_.push_back(wavefront_.getLastBs()); updateMotions(Motion::down); updateMax(); diff --git a/src/lib/align/VectorSmithWaterman.cpp b/src/lib/align/VectorSmithWaterman.cpp index b1b0105..1548aeb 100644 --- a/src/lib/align/VectorSmithWaterman.cpp +++ b/src/lib/align/VectorSmithWaterman.cpp @@ -15,22 +15,23 @@ #include "align/VectorSmithWaterman.hpp" #include #include -#include "ssw/ssw.h" +#include "ssw/ssw.hpp" namespace dragenos { namespace align { void VectorSmithWaterman::destroyReadContext(int readIdx) { - if (profile_[readIdx] != NULL) { - init_destroy(profile_[readIdx]); - profile_[readIdx] = NULL; - } +#ifdef __AVX2__ + init_destroy_avx2(profile_[readIdx]); + init_destroy_avx2(profileRev_[readIdx]); +#else + init_destroy_sse2(profile_[readIdx]); + init_destroy_sse2(profileRev_[readIdx]); +#endif - if (profileRev_[readIdx] != NULL) { - init_destroy(profileRev_[readIdx]); - profileRev_[readIdx] = NULL; - } + profile_[readIdx] = NULL; + profileRev_[readIdx] = NULL; } void VectorSmithWaterman::initReadContext( @@ -48,18 +49,29 @@ void VectorSmithWaterman::initReadContext( destroyReadContext(readIdx); - const int8_t* queryBeginInt = (int8_t*)query_[readIdx].data(); - profile_[readIdx] = ssw_init(queryBeginInt, querySize_[readIdx], sswScoringMat_, sswAlphabetSize_, 2); - + const int8_t* queryBeginInt = (int8_t*)query_[readIdx].data(); const int8_t* queryRevBeginInt = (int8_t*)queryRev_[readIdx].data(); - profileRev_[readIdx] = ssw_init(queryRevBeginInt, querySize_[readIdx], sswScoringMat_, sswAlphabetSize_, 2); + +#ifdef __AVX2__ + // AVX2 variant initializes profile only for 8-bit scoring (last argument 0), + // 16-bit scoring is initialized only when needed + profile_[readIdx] = + ssw_init_avx2(queryBeginInt, querySize_[readIdx], sswScoringMat_, sswAlphabetSize_, sswBias_, 0); + profileRev_[readIdx] = + ssw_init_avx2(queryRevBeginInt, querySize_[readIdx], sswScoringMat_, sswAlphabetSize_, sswBias_, 0); +#else + profile_[readIdx] = + ssw_init_sse2(queryBeginInt, querySize_[readIdx], sswScoringMat_, sswAlphabetSize_, sswBias_, 2); + profileRev_[readIdx] = + ssw_init_sse2(queryRevBeginInt, querySize_[readIdx], sswScoringMat_, sswAlphabetSize_, sswBias_, 2); +#endif } // returns alignment score // returns operations list in cigar uint16_t VectorSmithWaterman::align( - const unsigned char* queryBegin, - const unsigned char* queryEnd, + const unsigned char* /*queryBegin*/, + const unsigned char* /*queryEnd*/, const unsigned char* databaseBegin, const unsigned char* databaseEnd, bool reverseQuery, @@ -74,7 +86,11 @@ uint16_t VectorSmithWaterman::align( // const int querySize = std::distance(queryBeginInt, queryEndInt); const int dbSize = std::distance(databaseBeginInt, databaseEndInt); - s_profile* profile; +#ifdef __AVX2__ + s_profile_avx2* profile; +#else + s_profile_sse2* profile; +#endif // use the already built profile int querySize = querySize_[readIdx]; @@ -89,13 +105,19 @@ uint16_t VectorSmithWaterman::align( uint8_t flag = 0; //flag |= 0x08; // report ref position //flag |= 0x0F; // report cigar - flag = 1; // always compute cigar + // 1 - always compute cigar; 1 << 5 - get just the start and end positions + flag = 1; uint16_t filters = 0; int32_t filterd = 0; int32_t maskLen = querySize / 2; result = - ssw_align(profile, databaseBeginInt, dbSize, gapInit_, gapExtend_, flag, filters, filterd, maskLen); +#ifdef __AVX2__ + ssw_align_avx2( +#else + ssw_align_sse2( +#endif + profile, databaseBeginInt, dbSize, gapInit_, gapExtend_, flag, filters, filterd, maskLen); this->getCigarOperations(*result, querySize, cigar); @@ -158,7 +180,7 @@ std::string VectorSmithWaterman::convert_cigar(const s_align& s_al, const int& q if (s_al.cigarLen > 0) { std::ostringstream cigar_string; if (s_al.read_begin1 > 0) { - uint32_t cigar = to_cigar_int(s_al.read_begin1, 'S'); + // uint32_t cigar = to_cigar_int(s_al.read_begin1, 'S'); cigar_string << s_al.read_begin1 << 'S'; } @@ -168,7 +190,7 @@ std::string VectorSmithWaterman::convert_cigar(const s_align& s_al, const int& q int end = query_len - s_al.read_end1 - 1; if (end > 0) { - uint32_t cigar = to_cigar_int(end, 'S'); + // uint32_t cigar = to_cigar_int(end, 'S'); cigar_string << end << 'S'; } diff --git a/src/lib/align/tests/integration/AlignerGtest.cpp b/src/lib/align/tests/integration/AlignerGtest.cpp index 5826ff5..24a5f27 100644 --- a/src/lib/align/tests/integration/AlignerGtest.cpp +++ b/src/lib/align/tests/integration/AlignerGtest.cpp @@ -5,6 +5,7 @@ #include "gtest/gtest.h" #include "align/Aligner.hpp" +#include "align/SinglePicker.hpp" #include "reference/ReferenceDir.hpp" static char emptySpace[1024] = {}; diff --git a/src/lib/align/tests/integration/AlignmentsGtest.cpp b/src/lib/align/tests/integration/AlignmentsGtest.cpp index 5469831..9244c6f 100644 --- a/src/lib/align/tests/integration/AlignmentsGtest.cpp +++ b/src/lib/align/tests/integration/AlignmentsGtest.cpp @@ -4,6 +4,7 @@ #include "gtest/gtest.h" #include "align/Alignments.hpp" +#include "align/SmithWaterman.hpp" TEST(Alignments, OneBaseDeletion) { diff --git a/src/lib/align/tests/integration/PairBuilderGtest.cpp b/src/lib/align/tests/integration/PairBuilderGtest.cpp index f323fd8..ab7557d 100644 --- a/src/lib/align/tests/integration/PairBuilderGtest.cpp +++ b/src/lib/align/tests/integration/PairBuilderGtest.cpp @@ -104,6 +104,31 @@ TEST(PairBuilder, updateMapq) ASSERT_EQ(48, alignments.front()[1].getMapq()); } +unsigned char encodeBase(const char base) +{ + switch (base) { + case 'A': + return 1; + break; + case 'C': + return 2; + break; + case 'G': + return 4; + break; + case 'T': + return 8; + break; + default: + throw std::invalid_argument(std::string("unknown base: ") + base); + } +} + +void text2Bases(char* begin, char* end) +{ + std::transform(begin, end, begin, [](const char c){return encodeBase(c);}); +} + TEST(PairBuilder, pickBest1) { const short match = 1; @@ -112,13 +137,15 @@ TEST(PairBuilder, pickBest1) const ReferenceDirDummy referenceDir; const align::PairBuilder pairBuilder(similarityScores, 19, 80, 25, 0, 0, 0, false, 50); - const unsigned char reference[] = + char reference[] = "TCCATCGAGATGGACGCCGTTGGCGCTCTCCGTCTTTCTCCATTGCGTCGTGGCCTTGCTATTGACTCTACTGTAGACATTTTTACTTTTTATGTCCCTCTTATG"; - static const unsigned SEQUENCE_FLANKS = 20; + text2Bases(reference, reference + sizeof(reference) - 1); + + static const unsigned SEQUENCE_FLANKS = 10; const std::string name = "blah"; const std::string bases( - (const char*)reference + SEQUENCE_FLANKS, (const char*)reference + sizeof(reference) - SEQUENCE_FLANKS); + (const char*)reference + SEQUENCE_FLANKS, (const char*)reference + sizeof(reference) - 1 - SEQUENCE_FLANKS * 2); const std::string qualities = "#AAAAEEEEEEEEEEEEEEEEEEEEEEE6EEEEEEEEEEEEEEEEEAEAEEEEEEEEEEEEAEEE/EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"; @@ -140,6 +167,8 @@ TEST(PairBuilder, pickBest1) id, position); +// std::cerr << readPair[1] << std::endl; + AlignmentPairs alignments; const InsertSizeParameters insertSizeParameters = { @@ -193,8 +222,8 @@ TEST(PairBuilder, pickBest1) const auto best = pairBuilder.pickBest(readPair, alignments, unpaired); // unique alignment pair. Both ends get mapq 60 ASSERT_NE(alignments.end(), best); - ASSERT_EQ(488, best->at(0).getMapq()); - ASSERT_EQ(155, best->at(1).getMapq()); + ASSERT_EQ(460, best->at(0).getMapq()); + ASSERT_EQ(137, best->at(1).getMapq()); } TEST(PairBuilder, pickBest2) @@ -205,8 +234,9 @@ TEST(PairBuilder, pickBest2) const ReferenceDirDummy referenceDir; const align::PairBuilder pairBuilder(similarityScores, 19, 80, 25, 0, 0, 0, false, 50); - const unsigned char reference[] = + char reference[] = "TCCATCGAGATGGACGCCGTTGGCGCTCTCCGTCTTTCTCCATTGCGTCGTGGCCTTGCTATTGACTCTACTGTAGACATTTTTACTTTTTATGTCCCTCTTATG"; + text2Bases(reference, reference + sizeof(reference) - 1); static const unsigned SEQUENCE_FLANKS = 20; const std::string name = "blah"; @@ -310,8 +340,9 @@ TEST(PairBuilder, pickBest3) const ReferenceDirDummy referenceDir; const align::PairBuilder pairBuilder(similarityScores, 19, 80, 25, 0, 0, 0, false, 50); - const unsigned char reference[] = + char reference[] = "TCCATCGAGATGGACGCCGTTGGCGCTCTCCGTCTTTCTCCATTGCGTCGTGGCCTTGCTATTGACTCTACTGTAGACATTTTTACTTTTTATGTCCCTCTTATG"; + text2Bases(reference, reference + sizeof(reference) - 1); static const unsigned SEQUENCE_FLANKS = 20; const std::string name = "blah"; @@ -415,8 +446,9 @@ TEST(PairBuilder, pickBest4) const ReferenceDirDummy referenceDir; const align::PairBuilder pairBuilder(similarityScores, 19, 80, 25, 0, 0, 0, false, 50); - const unsigned char reference[] = + char reference[] = "TCCATCGAGATGGACGCCGTTGGCGCTCTCCGTCTTTCTCCATTGCGTCGTGGCCTTGCTATTGACTCTACTGTAGACATTTTTACTTTTTATGTCCCTCTTATG"; + text2Bases(reference, reference + sizeof(reference) - 1); static const unsigned SEQUENCE_FLANKS = 20; const std::string name = "blah"; diff --git a/src/lib/align/tests/integration/SmithWatermanGtest.cpp b/src/lib/align/tests/integration/SmithWatermanGtest.cpp index 0e34fd0..26a6c77 100644 --- a/src/lib/align/tests/integration/SmithWatermanGtest.cpp +++ b/src/lib/align/tests/integration/SmithWatermanGtest.cpp @@ -9,14 +9,14 @@ TEST(SmithWaterman, Reset) using namespace dragenos::align; typedef SmithWatermanT SmithWaterman; constexpr auto width = SmithWaterman::width; - const auto NOT_A_BASE = SmithWaterman::NOT_A_QUERY_BASE; +// const auto NOT_A_BASE = SmithWaterman::NOT_A_QUERY_BASE; constexpr int MATCH = 2; constexpr int MISMATCH = -3; constexpr int gapExtend = 4; constexpr int gapInit = 5; const SimilarityScores similarity(MATCH, MISMATCH); const auto random = std::string("ACGTTGAGGTTCCGTAGTATGACCTGTTTTAACGTTAGGCTGGAAAGTNNC"); - ASSERT_GE(random.size(), width); + ASSERT_GE(random.size(), (size_t)width); const Query query(random.begin(), random.end()); SmithWaterman sw(similarity, gapInit, gapExtend); const Database database(random.begin(), random.end()); @@ -40,17 +40,19 @@ TEST(SmithWaterman, MoveDown) const SimilarityScores similarity(MATCH, MISMATCH); const auto random = std::string("ACGTTGAGGTTCCGTAGTATGACCTGTTTTAACGTTAGGCTGGAAAGTNNC"); // CNNTGAAAGGTCGGATTGCAATTTTGTCCAGTATGATGCCTTGGAGTTGCA - ASSERT_GE(random.size(), width); + ASSERT_GE(random.size(), (size_t)width); const Query query(random.begin(), random.end()); const Database database(random.begin(), random.end()); SmithWaterman sw(similarity, gapInit, gapExtend); sw.reset( query.data(), query.data() + query.size(), database.data(), database.data() + database.size(), false); - ASSERT_EQ(sw.getMotions().size(), 0); - ASSERT_EQ(sw.getScores().size(), 0); + //RP: move down is illegal as initially antidiagonal is outside the matrix + sw.moveRight(); + ASSERT_EQ(sw.getMotions().size(), 1u); + ASSERT_EQ(sw.getScores().size(), 1u); sw.moveDown(); - ASSERT_EQ(sw.getMotions().size(), 1); - ASSERT_EQ(sw.getScores().size(), 1); + ASSERT_EQ(sw.getMotions().size(), 2u); + ASSERT_EQ(sw.getScores().size(), 2u); // first base matches, but first column is all 0 in HW ASSERT_EQ(sw.getScores().back()[0], 0); // all other have NOT_A_BASE on the query @@ -58,15 +60,15 @@ TEST(SmithWaterman, MoveDown) ASSERT_EQ(sw.getScores().back()[i], 0) << "i == " << i; ASSERT_EQ(sw.getMotions().back(), Motion::down); sw.moveDown(); - ASSERT_EQ(sw.getMotions().size(), 2); - ASSERT_EQ(sw.getScores().size(), 2); + ASSERT_EQ(sw.getMotions().size(), 3u); + ASSERT_EQ(sw.getScores().size(), 3u); // All mismatches (AC vs CA) for (size_t i = 0; sw.getScores().back().size() > i; ++i) ASSERT_EQ(sw.getScores().back()[i], 0) << "i == " << i; ASSERT_EQ(sw.getMotions().back(), Motion::down); sw.moveDown(); - ASSERT_EQ(sw.getMotions().size(), 3); - ASSERT_EQ(sw.getScores().size(), 3); + ASSERT_EQ(sw.getMotions().size(), 4u); + ASSERT_EQ(sw.getScores().size(), 4u); // ACG vs GCA: C matches ASSERT_EQ(sw.getScores().back()[0], 0); ASSERT_EQ(sw.getMotions().back(), Motion::down); @@ -76,7 +78,7 @@ TEST(SmithWaterman, MoveRight) { using namespace dragenos::align; typedef SmithWatermanT SmithWaterman; - typedef SmithWaterman::Motion Motion; +// typedef SmithWaterman::Motion Motion; constexpr auto width = SmithWaterman::width; constexpr int MATCH = 3; constexpr int MISMATCH = -4; @@ -84,18 +86,18 @@ TEST(SmithWaterman, MoveRight) constexpr int gapInit = 5; const SimilarityScores similarity(MATCH, MISMATCH); const auto random = std::string("ACGTTGAGGTTCCGTAGTATGACCTGTTTTAACGTTAGGCTGGAAAGT") + "AATTCCAGNNC"; - ASSERT_GE(random.size(), width); + ASSERT_GE(random.size(), (size_t)width); const Query query(random.begin(), random.begin() + width); const Database database(random.begin(), random.end()); SmithWaterman sw(similarity, gapInit, gapExtend); sw.reset( query.data(), query.data() + query.size(), database.data(), database.data() + database.size(), false); - ASSERT_EQ(sw.getMotions().size(), 0); - ASSERT_EQ(sw.getScores().size(), 0); + ASSERT_EQ(sw.getMotions().size(), 0u); + ASSERT_EQ(sw.getScores().size(), 0u); // move down into the actual query string for (unsigned i = 0; width > i; ++i) sw.moveRight(); - ASSERT_EQ(sw.getMotions().size(), width); - ASSERT_EQ(sw.getScores().size(), width); + ASSERT_EQ(sw.getMotions().size(), (size_t)width); + ASSERT_EQ(sw.getScores().size(), (size_t)width); } TEST(SmithWaterman, PeakPosition) @@ -148,7 +150,7 @@ TEST(SmithWaterman, AllSimilar) constexpr int MISMATCH = -3; const SimilarityScores similarity(MATCH, MISMATCH); const auto random = std::string("ACGTTGAGGTTCCGTAGTATGACCTGTTTTAACGTTAGGCTGGAAAGT"); - ASSERT_EQ(random.size(), width); + ASSERT_EQ(random.size(), (size_t)width); const Query query(random.begin(), random.end()); const Database database(random.begin(), random.end()); SmithWaterman sw(similarity, 5, 4); diff --git a/src/lib/align/tests/unit/CigarGtest.cpp b/src/lib/align/tests/unit/CigarGtest.cpp index 94b2b55..753acc4 100644 --- a/src/lib/align/tests/unit/CigarGtest.cpp +++ b/src/lib/align/tests/unit/CigarGtest.cpp @@ -8,7 +8,7 @@ TEST(Cigar, OperationNames) { using dragenos::align::Cigar; - ASSERT_EQ(Cigar::SEQUENCE_MISMATCH + 1, std::extent::value); + ASSERT_EQ((unsigned long)Cigar::SEQUENCE_MISMATCH + 1, std::extent::value); ASSERT_EQ('M', Cigar::getOperationName(Cigar::ALIGNMENT_MATCH)); ASSERT_EQ('I', Cigar::getOperationName(Cigar::INSERT)); ASSERT_EQ('D', Cigar::getOperationName(Cigar::DELETE)); @@ -24,22 +24,22 @@ TEST(Cigar, Operations) { using dragenos::align::Cigar; Cigar cigar; - ASSERT_EQ(0, cigar.getNumberOfOperations()); + ASSERT_EQ(0u, cigar.getNumberOfOperations()); const Cigar::Operation opM17(Cigar::ALIGNMENT_MATCH, 17); const Cigar::Operation opI21(Cigar::INSERT, 21); const Cigar::Operation opD35(Cigar::DELETE, 35); cigar.emplace_back(opM17.first, opM17.second); - ASSERT_EQ(1, cigar.getNumberOfOperations()); + ASSERT_EQ(1u, cigar.getNumberOfOperations()); cigar.push_back(opI21); - ASSERT_EQ(2, cigar.getNumberOfOperations()); + ASSERT_EQ(2u, cigar.getNumberOfOperations()); cigar.push_back(Cigar::Operation(opD35.first, opD35.second)); - ASSERT_EQ(3, cigar.getNumberOfOperations()); + ASSERT_EQ(3u, cigar.getNumberOfOperations()); ASSERT_EQ(Cigar::ALIGNMENT_MATCH, cigar.getOperations()->first); ASSERT_EQ(Cigar::INSERT, (cigar.getOperations() + 1)->first); ASSERT_EQ(Cigar::DELETE, (cigar.getOperations() + 2)->first); - ASSERT_EQ(17, cigar.getOperations()->second); - ASSERT_EQ(21, (cigar.getOperations() + 1)->second); - ASSERT_EQ(35, (cigar.getOperations() + 2)->second); + ASSERT_EQ(17u, cigar.getOperations()->second); + ASSERT_EQ(21u, (cigar.getOperations() + 1)->second); + ASSERT_EQ(35u, (cigar.getOperations() + 2)->second); cigar.clear(); - ASSERT_EQ(0, cigar.getNumberOfOperations()); + ASSERT_EQ(0u, cigar.getNumberOfOperations()); } diff --git a/src/lib/align/tests/unit/WavefrontGtest.cpp b/src/lib/align/tests/unit/WavefrontGtest.cpp index f7acf0b..a6edae0 100644 --- a/src/lib/align/tests/unit/WavefrontGtest.cpp +++ b/src/lib/align/tests/unit/WavefrontGtest.cpp @@ -13,9 +13,9 @@ TEST(Wavefront, Constructor) for (const auto v : w0.getLastScores()) { ASSERT_EQ(v, 0); } - ASSERT_EQ(w0.next(), 0); - ASSERT_EQ(w0.last(), 2); - ASSERT_EQ(w0.penultimate(), 1); + ASSERT_EQ(w0.next(), 0u); + ASSERT_EQ(w0.last(), 2u); + ASSERT_EQ(w0.penultimate(), 1u); const auto uniformAntidiagonal = [](short init) { Antidiagonal tmp; for (auto& v : tmp.data) v = init; @@ -32,13 +32,13 @@ TEST(Wavefront, Constructor) const History h4{a2, a3, a4}; const History h5{a3, a4, a5}; const Wavefront w1(h2, h3, h4, 1, Wavefront::right); - ASSERT_EQ(w1.next(), 1); - ASSERT_EQ(w1.last(), 0); - ASSERT_EQ(w1.penultimate(), 2); + ASSERT_EQ(w1.next(), 1u); + ASSERT_EQ(w1.last(), 0u); + ASSERT_EQ(w1.penultimate(), 2u); const Wavefront w2(h3, h4, h5, 2, Wavefront::down); - ASSERT_EQ(w2.next(), 2); - ASSERT_EQ(w2.last(), 1); - ASSERT_EQ(w2.penultimate(), 0); + ASSERT_EQ(w2.next(), 2u); + ASSERT_EQ(w2.last(), 1u); + ASSERT_EQ(w2.penultimate(), 0u); } TEST(Wavefront, moveRightE) diff --git a/src/lib/common/BufferPool.cpp b/src/lib/common/BufferPool.cpp deleted file mode 100644 index 217304b..0000000 --- a/src/lib/common/BufferPool.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#include "common/BufferPool.hpp" - -#include -#include - -#include -#include - -#include -#include "common/DragenConstants.hpp" -#include "common/Exceptions.hpp" -//#include "dragen_exception.hpp" - -/* ============ end of #include directives ============ */ -//#include "edico_memdebug.h" - -namespace dragenos { -namespace common { - -//--------------------------------------------------------------------------------adam -// constructor - sets up the pool freelist of the specified size -BufferPool::BufferPool( - uint32_t numBuffers, // how many buffers to put in the pool - size_t bufferSize) // size of each buffer - : m_bufferSize(bufferSize), - m_totalSize(numBuffers * bufferSize), - m_totalBorrowed(0), - m_highWatermark(0), - m_pendingReplaces(0), - m_exit(false), - m_preallocated(false) -{ - BOOST_ASSERT(m_totalSize > 0); -} - -//--------------------------------------------------------------------------------adam -// destructor - free the entire pool. -BufferPool::~BufferPool() -{ - if (m_preallocated) { - DeactivatePreallocation(); - } -} - -//------------------------------------------------------------------------ alain -bool BufferPool::SetPreallocation(bool preallocateFlag) -{ - std::unique_lock lock(m_mutex); - bool prevMode = m_preallocated; - - // ensure no allocation was made - BOOST_ASSERT(m_totalBorrowed == 0); - - if (m_preallocated != preallocateFlag) { - // there is a change of mode - if (m_preallocated) { - // was preallocated, now non-preallocated - DeactivatePreallocation(); - - } else { - // was non-preallocated, now preallocated - ActivatePreallocation(); - } - - } else { - // no mode change, nothing to do - } - - return prevMode; -} - -//------------------------------------------------------------------------ alain -// preallocate buffers -void BufferPool::ActivatePreallocation() -{ - Buffer buf; - uint32_t numBuffers = m_totalSize / m_bufferSize; - - BOOST_ASSERT(m_preallocatedBuffers.size() == 0); - - while (m_preallocatedBuffers.size() != numBuffers) { - buf = NULL; - if (!posix_memalign(reinterpret_cast(&buf), DRAGEN_PAGE_SIZE, m_bufferSize)) { - BOOST_THROW_EXCEPTION( - MemoryException(std::string("Failed to preallocate buffers: ") + strerror(errno))); - } - m_preallocatedBuffers.push(buf); - } - - BOOST_ASSERT(m_preallocatedBuffers.size() == numBuffers); - - m_preallocated = true; -} - -//------------------------------------------------------------------------ alain -// free up preallocated buffers -void BufferPool::DeactivatePreallocation() -{ - while (m_preallocatedBuffers.size() > 0) { - Buffer buf = reinterpret_cast(m_preallocatedBuffers.front()); - m_preallocatedBuffers.pop(); - free(buf); - } - - BOOST_ASSERT(m_preallocatedBuffers.size() == 0); - - m_preallocated = false; -} - -//--------------------------------------------------------------------------------adam -// borrow -- wait until the pool is non-empty, and return a buffer from the freelist -// -BufferPool::Buffer BufferPool::borrow(const bool wait, const bool clear) -{ - Buffer b = NULL; - - { - // If necessary, wait until there is a buffer available - std::unique_lock lock(m_mutex); - while (m_totalBorrowed >= m_totalSize) { - if (!wait) { - // return immediately with invalid value - return NULL; - } - m_cond.wait(lock); - } - m_totalBorrowed += m_bufferSize; - - // Update the max borrowed if needed - if (m_highWatermark < m_totalBorrowed) m_highWatermark = m_totalBorrowed; - - if (m_preallocated) { - // get from the pool - b = reinterpret_cast(m_preallocatedBuffers.front()); - m_preallocatedBuffers.pop(); - if (clear) { - memset(b, 0, m_bufferSize); - } - return b; - } - } - - if (m_preallocated) { - // b already is set in the critical section above - } else { - // dynamically allocate - if (!posix_memalign(reinterpret_cast(&b), DRAGEN_PAGE_SIZE, m_bufferSize)) { - BOOST_THROW_EXCEPTION(MemoryException(std::string("Failed to allocate buffer: ") + strerror(errno))); - } - } - - // alaing: add "and b" to the if condition to make SCA happy. - // In the report, clang SCA assumes m_preallocated could have changed value - // between the test in locked section and the test outside the locked section - // which we know won't happen because mode is not changed during the lifetime - // of the object - if (clear and b) { - // JimmyB make this an option for e.g. if used in the VC where the user fills the - // buffer this seems to be unnecesarry - // - // You may wonder whether this memset is necessary, and is too expensive. Well, - // I tried commenting it out, and turns out it *is* necessary. I think because - // we are relying on it to initialize the dbam header scructures. - memset(b, 0, m_bufferSize); - } - return b; -} - -//--------------------------------------------------------------------------------adam -// replace - put #buf# back into the freelist -// -void BufferPool::replace(void* abuf) -{ - if (abuf == - 0) { // Can occur when a buffer must be given to give 'last buffer' signal, but no data is available - m_cond.notify_one(); // Wake up other threads in case anyone is still waiting - return; - } - - Buffer buf = reinterpret_cast(abuf); - - if (m_preallocated) { - // return to the pool in the critical section below - } else { - // free dynamically-allocated buffer - free(buf); - } - - { - // Return the buffer to the tail of the freelist - std::lock_guard lock(m_mutex); - BOOST_ASSERT_MSG( - m_totalBorrowed >= m_bufferSize, - (boost::format("total borrowed: %i, buffer size: %i") % m_totalBorrowed % m_bufferSize) - .str() - .c_str()); - if (m_pendingReplaces >= m_bufferSize) { - m_pendingReplaces -= m_bufferSize; - } - - if (m_preallocated) { - // back to the pool - m_preallocatedBuffers.push(buf); - } - } - - // Let anyone waiting know that there's a buffer available now. - m_cond.notify_one(); -} -} // namespace common -} // namespace dragenos diff --git a/src/lib/common/PackedUmi.cpp b/src/lib/common/PackedUmi.cpp deleted file mode 100644 index a8d6936..0000000 --- a/src/lib/common/PackedUmi.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#include "common/PackedUmi.hpp" - -#include -#include - -//#include "dragen_exception.hpp" - -namespace dragenos { -namespace common { - -//--------------------------------------------------------------------------------adamb -// constructor -- extract the sequences & lengths into our internal, binary, packed -// format -// -PackedUmi::PackedUmi(const char* seq1, const size_t len1, const char* seq2, const size_t len2) - : m_lens(len1, len2), m_seqs{0, 0}, m_isN{0, 0} -{ - BOOST_ASSERT(m_lens.getLen(0) == len1); - BOOST_ASSERT(m_lens.getLen(1) == len2); - BOOST_ASSERT_MSG((len1 <= 8) && (len2 <= 8), "ERROR: max support UMI length is 8bp"); - transformSequence(0, seq1, len1); - transformSequence(1, seq2, len2); -} - -//--------------------------------------------------------------------------------adamb -// iniatialize from two pre-packed binary UMIs -// -PackedUmi::PackedUmi(const PackedSeq_t ps1, const PackedSeq_t ps2) - : m_lens(ps1 >> 24, ps2 >> 24), - m_seqs{static_cast(ps1 & 0xFFFF), static_cast(ps2 & 0xFFFF)}, - m_isN{static_cast((ps1 >> 16) & 0xFF), static_cast((ps2 >> 16) & 0xFF)} -{ -} - -//--------------------------------------------------------------------------------adamb -// Take an input ASCII sequence, transform it into our packed representation, -// and store it in this object in one of the two sequence slots. -// -void PackedUmi::transformSequence( - const uint16_t whichSeq, // 0 or 1 - const char* seq, // input ASCII FASTQ-format sequence - const size_t len) // how many bytes in #seq# -{ - transformSequence(seq, len, &m_seqs[whichSeq], &m_isN[whichSeq]); -} - -//--------------------------------------------------------------------------------adamb -// Transform #seq# (which is #len# bases long) into (two bits per base) -// DBAM format in #dest#. -// -void PackedUmi::transformSequence( - const char* seq, // input ASCII FASTQ-format sequence - const size_t len, // how many bytes in #seq# - uint16_t* dest, // where to put the packed sequence bits - uint8_t* isN) // where to put the 'isN' bits -{ - // Make sure the destinations are cleared - *dest = 0; - *isN = 0; - - // Assume that the sequence was initialized to zero before this call - for (size_t i = 0; i < len; ++i) { - // Here is the translation table we are shooting for: - // - // A (0x41) => 0 - // C (0x43) => 1 - // G (0x47) => 2 - // T (0x54) => 3 - // - // Turns out we can get this like this: - // - // ((x>>1) ^ (x>>2)) & 3 - // - // A: ((0x20) ^ (0x10)) & 3 = 0 - // C: ((0x21) ^ (0x10)) & 3 = 1 - // G: ((0x23) ^ (0x11)) & 3 = 2 - // T: ((0x2A) ^ (0x15)) & 3 = 3 - // - const uint8_t& ascii_base = seq[i]; - const uint16_t dbam_base = ((ascii_base >> 1) ^ (ascii_base >> 2)) & 3; - const uint8_t shift = i * 2; - *dest |= (dbam_base << shift); - - if (ascii_base == 'N') (*isN) |= (1 << i); - } -} - -//--------------------------------------------------------------------------------adamb -// Replace the sequences with their reverse-complements. -// -void PackedUmi::reverseComplement() -{ - char s[MAX_UMI_LEN]; - - for (size_t i = 0; i < 2; ++i) { - // Get the original sequence in ASCII format: - const uint16_t len = getLen(i); - getAsciiSeq(i, s, MAX_UMI_LEN); - - // Reverse it: - std::reverse(s, s + len); - - // Pack it back into m_seq and m_isN: - transformSequence(s, len, &m_seqs[i], &m_isN[i]); - - // And complement it, taking advantage of DBAM format's nice property - // that a twos-complement of the sequence is the sequence's biological - // complement. - m_seqs[i] = (~m_seqs[i]); - } -} - -//--------------------------------------------------------------------------------adamb -// Arrange the two ends of the umi so that the one with the "first" lexicographic -// ASCII representation is sequence 0, and the other one is sequence 1 -// Returns true if the ends were swapped, false otherwise. -// -bool PackedUmi::arrangeEndsLexicographically() -{ - char s0[MAX_UMI_LEN]; - const uint16_t len0 = getLen(0); - getAsciiSeq(0, s0, MAX_UMI_LEN); - - char s1[MAX_UMI_LEN]; - const uint16_t len1 = getLen(1); - getAsciiSeq(1, s1, MAX_UMI_LEN); - - // If the first sequence comes first alphabetically, then do nothing. - if (strncmp(s0, s1, std::min(len0, len1)) <= 0) return false; - - // The second sequence comes first alphabetically. Swap the two ends. - m_seqs[0] = m_seqs[1] = 0; - transformSequence(s0, len0, &m_seqs[1], &m_isN[1]); - transformSequence(s1, len1, &m_seqs[0], &m_isN[0]); - m_lens = SeqLen_t(len1, len0); - return true; -} - -//--------------------------------------------------------------------------------adamb -// Return true if this packed UMI's ASCII representation precedes that of the -// #other# UMI -// -bool PackedUmi::lexicographicallyPrecedes(const PackedUmi& other) const -{ - for (auto i = 0; i < 2; ++i) { - char mine[MAX_UMI_LEN]; - const uint16_t mylen = getLen(i); - getAsciiSeq(i, mine, MAX_UMI_LEN); - - char theirs[MAX_UMI_LEN]; - const uint16_t theirlen = other.getLen(i); - other.getAsciiSeq(i, theirs, MAX_UMI_LEN); - - if (strncmp(mine, theirs, std::min(mylen, theirlen)) < 0) { - return true; - } - } - - return false; -} - -} // namespace common -} // namespace dragenos diff --git a/src/lib/common/Program.cpp b/src/lib/common/Program.cpp index db9dcd9..de4bc8d 100644 --- a/src/lib/common/Program.cpp +++ b/src/lib/common/Program.cpp @@ -23,14 +23,11 @@ namespace dragenos { namespace common { #define HELP_STR "help" -#define HELP_MD_STR "help-md" #define HELP_DEFAULTS_STR "help-defaults" Options::Options() { namedOptions_.add_options()(HELP_STR ",h", "produce help message and exit"); - namedOptions_.add_options()( - HELP_MD_STR, "produce help message pre-formatted as a markdown file section and exit"); namedOptions_.add_options()( HELP_DEFAULTS_STR, "produce tab-delimited list of command line options and their default values"); namedOptions_.add_options()("version,V", bpo::bool_switch(&version_), "print program version information"); @@ -76,7 +73,7 @@ Options::Action Options::parse(int argc, const char* const argv[]) } bpo::notify(vm_); - if (vm_.count(HELP_STR) || vm_.count(HELP_MD_STR) || vm_.count(HELP_DEFAULTS_STR)) { + if (vm_.count(HELP_STR) || vm_.count(HELP_DEFAULTS_STR)) { return HELP; } else if (version_) { return VERSION; @@ -134,44 +131,21 @@ static unsigned short getTerminalColumns() return ws_col; } -std::string Options::help(const OptionDescriptionPtrs& sortedOptions, const bool markdown) const +std::string Options::help(const OptionDescriptionPtrs& sortedOptions) const { - std::ostringstream os; - if (!markdown) { - const unsigned effectiveLineLength = getTerminalColumns(); - bpo::options_description printedDescriptions( - "Command line options", - effectiveLineLength < 50 ? bpo::options_description::m_default_line_length : effectiveLineLength, - effectiveLineLength < 50 ? bpo::options_description::m_default_line_length / 2 - : effectiveLineLength - 50); - - for (const OptionDescriptionPtr& odPtr : sortedOptions) { - printedDescriptions.add(odPtr); - } - - os << this->usagePrefix() << "\n\n" << printedDescriptions << std::endl; - } else { - // markdown lines are prepended by two spaces - const unsigned effectiveLineLength = MARKDOWN_LINE_LENGTH - 2; - bpo::options_description printedDescriptions(effectiveLineLength, effectiveLineLength - 50); - - for (const OptionDescriptionPtr& odPtr : sortedOptions) { - printedDescriptions.add(odPtr); - } - - std::vector lines; - os << printedDescriptions << std::endl; - std::string str = os.str(); - boost::algorithm::split(lines, str, boost::algorithm::is_any_of("\n\r")); - os.str(""); - - os << "**Usage**\n\n" << this->usagePrefix() << "\n\n**Options**\n" << std::endl; - BOOST_FOREACH (const std::string& line, lines) { - // pre-pend two spaces to the two spaces that boost adds so that we get 4 spaces for markdown to - // recognise pre-formatted text. - os << " " << line << std::endl; - } + std::ostringstream os; + const unsigned effectiveLineLength = getTerminalColumns(); + bpo::options_description printedDescriptions( + "Command line options", + effectiveLineLength < 50 ? bpo::options_description::m_default_line_length : effectiveLineLength, + effectiveLineLength < 50 ? bpo::options_description::m_default_line_length / 2 + : effectiveLineLength - 50); + + for (const OptionDescriptionPtr& odPtr : sortedOptions) { + printedDescriptions.add(odPtr); } + + os << this->usagePrefix() << "\n\n" << printedDescriptions << std::endl; return os.str(); } @@ -184,7 +158,7 @@ std::string Options::usage() const return helpDefaults(sortedOptions); } - return help(sortedOptions, vm_.count(HELP_MD_STR)); + return help(sortedOptions); } } // namespace common diff --git a/src/lib/common/SystemCompatibility.cpp b/src/lib/common/SystemCompatibility.cpp index ada34f6..d194cef 100644 --- a/src/lib/common/SystemCompatibility.cpp +++ b/src/lib/common/SystemCompatibility.cpp @@ -93,35 +93,16 @@ int getTerminalWindowSize(unsigned short int& ws_row, unsigned short int& ws_col ws_col = ws.ws_col; return 0; } +#else // just return whatever suitable constant dimensions + static const int VT100_ROWS = 24; + static const int VT100_COLS = 80; + ws_row = VT100_ROWS; + ws_col = VT100_COLS; #endif // HAVE_SYS_IOCTL_H return -1; } -int linuxFallocate(int fd, std::size_t offset, std::size_t len) -{ -#ifdef HAVE_FALLOCATE - // FALLOC_FL_KEEP_SIZE is not available on CentOS 5 -#ifdef FALLOC_FL_KEEP_SIZE - return fallocate(fd, FALLOC_FL_KEEP_SIZE, offset, len); -#endif // FALLOC_FL_KEEP_SIZE - -#endif // HAVE_FALLOCATE - - return 0; -} - -int linuxFtruncate(int fd, std::size_t len) -{ -// this is not a typo. fallocate and ftruncate have to come together or else we -// risk creating files with unfilled garbage at the end -#ifdef HAVE_FALLOCATE - return ftruncate(fd, len); -#endif // FALLOC_FL_KEEP_SIZE - - return 0; -} - } // namespace common } // namespace dragenos @@ -342,7 +323,7 @@ int64_t clock() bool isLittleEndian() { - const uint64_t v = 0x0706050403020100; + const uint64_t v = 0x0706050403020100; const unsigned char* const p = reinterpret_cast(&v); for (unsigned i = 0; i < sizeof(v); ++i) { if (p[i] != i) { @@ -373,7 +354,7 @@ uint64_t getFileSize(const PathCharType* filePath) boost::filesystem::path getModuleFileName() { char szBuffer[10240]; - int readBytes = readlink("/proc/self/exe", szBuffer, sizeof(szBuffer)); + int readBytes = readlink("/proc/self/exe", szBuffer, sizeof(szBuffer)); DRAGEN_OS_ASSERT_MSG(-1 != readBytes, "TODO: handle the readlink error: " << errno); // readlink does not zero-terminate the string. szBuffer[readBytes] = 0; diff --git a/src/lib/fastq/tests/unit/TokenizerGtest.cpp b/src/lib/fastq/tests/unit/TokenizerGtest.cpp index b2a71e3..a3cdfd8 100644 --- a/src/lib/fastq/tests/unit/TokenizerGtest.cpp +++ b/src/lib/fastq/tests/unit/TokenizerGtest.cpp @@ -182,13 +182,13 @@ TEST(Tokenizer, ZeroLength) ASSERT_EQ(false, stm.eof()); ASSERT_EQ(false, t.token().empty()); ASSERT_EQ(true, t.token().valid()); - ASSERT_EQ(0, t.token().readLength()); + ASSERT_EQ(0u, t.token().readLength()); ASSERT_EQ(true, t.next()); ASSERT_EQ(true, stm.eof()); ASSERT_EQ(false, t.token().empty()); ASSERT_EQ(true, t.token().valid()); - ASSERT_NE(0, t.token().readLength()); + ASSERT_NE(0u, t.token().readLength()); ASSERT_EQ(false, t.next()); ASSERT_EQ(true, stm.eof()); @@ -207,5 +207,5 @@ TEST(Tokenizer, EmptyInput) ASSERT_EQ(true, stm.eof()); ASSERT_EQ(true, t.token().empty()); ASSERT_EQ(false, t.token().valid()); - ASSERT_EQ(0, t.token().readLength()); + ASSERT_EQ(0u, t.token().readLength()); } diff --git a/src/lib/io/CigarBuilder.cpp b/src/lib/io/CigarBuilder.cpp deleted file mode 100644 index 95f19b9..0000000 --- a/src/lib/io/CigarBuilder.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/** - ** DRAGEN Open Source Software - ** Copyright (c) 2019-2020 Illumina, Inc. - ** All rights reserved. - ** - ** This software is provided under the terms and conditions of the - ** GNU GENERAL PUBLIC LICENSE Version 3 - ** - ** You should have received a copy of the GNU GENERAL PUBLIC LICENSE Version 3 - ** along with this program. If not, see - ** . - ** - **/ - -#include "io/CigarBuilder.hpp" - -/* ============ end of #include directives ============ */ -//#include "edico_memdebug.h" - -namespace dragenos { -namespace io { - -const uint8_t CigarBuilder::MATCH = 0; -const uint8_t CigarBuilder::INS = 1; -const uint8_t CigarBuilder::DEL = 2; -const uint8_t CigarBuilder::REFSKIP = 3; -const uint8_t CigarBuilder::SOFTCLIP = 4; -const uint8_t CigarBuilder::HARDCLIP = 5; -const uint8_t CigarBuilder::PAD = 6; -const uint8_t CigarBuilder::SEQMATCH = 7; -const uint8_t CigarBuilder::MISMATCH = 8; - -//--------------------------------------------------------------------------------adam -// consructor -// -CigarBuilder::CigarBuilder() : m_ReadStart(0), m_ReadEnd(0), m_RefStart(0), m_RefEnd(0) {} - -//--------------------------------------------------------------------------------adam -// GetCurrentOp - get the operation (e.g. match, insert, etc) that we're currently -// tallying -// -uint8_t CigarBuilder::GetCurrentOp() const -{ - if (m_Records.empty()) return 255; - - // Force tallying a new record if we've filled one up. - if (GetCurrentCount() == 63) return 255; - - const size_t i = m_Records.size() - 1; - return m_Records[i] & 0xF; -} - -//--------------------------------------------------------------------------------adam -// GetCurrentOp - get the number of bases that have been tallied up for the current -// op (e.g. match, insert, del, etc) -// -uint16_t CigarBuilder::GetCurrentCount() const -{ - if (m_Records.empty()) return 0; - - const size_t i = m_Records.size() - 1; - return m_Records[i] >> 4; -} - -//--------------------------------------------------------------------------------adam -// IncrementCurrentOp - add another match/insert/delete to the cigar. If it's the -// same op as the previous one, increment the number. Otherwise finish up the current -// cigar record and start a new one for the new op. -// -void CigarBuilder::IncrementCurrentOp(const uint8_t op) -{ - if (op != GetCurrentOp()) { - m_Records.push_back(0); - } - - const size_t i = m_Records.size() - 1; - uint16_t count = GetCurrentCount() + 1; - m_Records[i] = (count << 4) | (static_cast(op) & 0xF); -} - -//--------------------------------------------------------------------------------adam -// ConsolidateRecords - combine neighboring records of the same type, so long -// as they won't overflow the maximum count per record -// -void CigarBuilder::ConsolidateRecords() -{ - if (!m_Records.size()) return; - - std::vector new_records; - new_records.push_back(m_Records[0] & 0xF); - const uint16_t BUCKET_MAX = 0xFFF; - - for (std::vector::const_iterator it = m_Records.begin(); it != m_Records.end(); ++it) { - uint32_t num = (*it) >> 4; - uint8_t op = (*it) & 0xF; - - const uint8_t current_record_op = new_records.back() & 0xF; - const uint32_t current_record_count = new_records.back() >> 4; - if ((op != current_record_op) || (current_record_count + num > BUCKET_MAX)) { - new_records.push_back((num << 4) | op); - } else { - new_records.back() = ((current_record_count + num) << 4) | op; - } - } - m_Records.swap(new_records); -} - -/* -//--------------------------------------------------------------------------------adam -// Trim - cut off the record to ensure it covers only read_len bases -// -void CigarBuilder::Trim(const uint32_t read_len) -{ - int64_t count = 0; - uint32_t i = 0; - for ( ; i < m_Records.size() && (count < read_len); ++i ) { - uint16_t num = m_Records[i] >> 4; - uint8_t op = m_Records[i] & 0xF; - if ( op == MATCH || op == DELETION ) - count += num; - } - - if ( count > read_len ) { - uint16_t num = m_Records[i] >> 4; - - uint8_t op = m_Records[i] & 0xF; - uint16_t newnum = read_len - count; - ASSERT(newnum < num); - m_Records[i] = (newnum << 4) | op; - } - m_Records.resize(i+1); -} -*/ - -} // namespace io -} // namespace dragenos diff --git a/src/lib/io/tests/unit/CigarBuilderGtest.cpp b/src/lib/io/tests/unit/CigarBuilderGtest.cpp deleted file mode 100644 index 842347f..0000000 --- a/src/lib/io/tests/unit/CigarBuilderGtest.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "gtest/gtest.h" -#include "inttypes.h" - -#include "io/CigarBuilder.hpp" - -TEST(CigarBuilderTest, Test1) -{ - dragenos::io::CigarBuilder cigar; - for (int i = 0; i < 5; ++i) cigar.AddMatch(); - for (int i = 0; i < 15; ++i) cigar.AddInsertion(); - for (int i = 0; i < 25; ++i) cigar.AddDeletion(); - for (int i = 0; i < 35; ++i) cigar.AddSoftClip(); - cigar.ConsolidateRecords(); - - std::ostringstream os; - os << cigar; - ASSERT_STREQ("5M15I25D35S", os.str().c_str()); -} - -TEST(CigarBuilderTest, LongSeries) -{ - dragenos::io::CigarBuilder cigar; - for (int i = 0; i < 5; ++i) cigar.AddSoftClip(); - for (int i = 0; i < 130; ++i) cigar.AddInsertion(); - for (int i = 0; i < 130; ++i) cigar.AddMatch(); - for (int i = 0; i < 130; ++i) cigar.AddDeletion(); - for (int i = 0; i < 130; ++i) cigar.AddSoftClip(); - cigar.ConsolidateRecords(); - - std::ostringstream os; - os << cigar; - ASSERT_STREQ("5S130I130M130D130S", os.str().c_str()); -} - -TEST(CigarBuilderTest, LongReverse) -{ - dragenos::io::CigarBuilder cigar; - for (int i = 0; i < 5; ++i) cigar.AddSoftClip(); - for (int i = 0; i < 130; ++i) cigar.AddInsertion(); - for (int i = 0; i < 130; ++i) cigar.AddMatch(); - for (int i = 0; i < 130; ++i) cigar.AddDeletion(); - for (int i = 0; i < 130; ++i) cigar.AddSoftClip(); - - cigar.Reverse(); - cigar.ConsolidateRecords(); - - std::ostringstream os; - os << cigar; - ASSERT_STREQ("130S130D130M130I5S", os.str().c_str()); -} diff --git a/src/lib/io/tests/unit/Fastq2DbamTransformerGtest.cpp.removed b/src/lib/io/tests/unit/Fastq2DbamTransformerGtest.cpp.removed deleted file mode 100644 index 6bbd475..0000000 --- a/src/lib/io/tests/unit/Fastq2DbamTransformerGtest.cpp.removed +++ /dev/null @@ -1,45 +0,0 @@ -#include "gtest/gtest.h" -#include "inttypes.h" -#include - -#include "io/Fastq2DbamTransformer.hpp" - -TEST(Fastq2DbamTransformerTest, transformSequence) -{ - std::string dna = "ACGTNAACCGGTTNNGAT"; - const std::vector sequence(dna.begin(), dna.end()); - const unsigned fastqOffset = 64; // alternately 33 - const std::vector qualities = [&sequence,fastqOffset](){std::vector q(sequence.size()); std::iota(q.begin(), q.end(), fastqOffset); return q;}(); - ASSERT_EQ(sequence.size(), qualities.size()); - std::vector dbam(sequence.size()); - ASSERT_EQ(sequence.size(), dbam.size()); - dragenos::io::Fastq2DbamTransformer::transformSequence(sequence.data(), sequence.size(), qualities.data(), dbam.data(), fastqOffset, false, false); - for (unsigned i = 0; sequence.size() > i; ++i) - { - const auto d = dbam[i]; - const uint8_t bases[] = {'A','C','G','T'}; - const uint8_t db = bases[d & 3]; - const uint8_t expectedB = sequence[i] == 'N' ? 'G' : sequence[i]; - ASSERT_EQ(expectedB, db); - const uint8_t dq = d >> 2; - const uint8_t expectedQ = sequence[i] == 'N' ? fastqOffset : qualities[i]; - ASSERT_EQ(expectedQ, dq + fastqOffset); - } -} - -TEST(Fastq2DbamTransformerTest, transformSequencePerformance) -{ - const std::vector sequence(1UL << 26, 'C'); - const std::vector qualities(sequence.size(), 68); - ASSERT_EQ(sequence.size(), qualities.size()); - const unsigned length = 125; - std::vector dbam(length, 0); - for (unsigned int i = 0; sequence.size() + length -1 > i; ++i) - { - const uint8_t* const s = sequence.data() + i; - const uint8_t* const q = qualities.data() + i; - const unsigned fastqOffset = 64; // alternately 33 - dragenos::io::Fastq2DbamTransformer::transformSequence(s, length, q, dbam.data(), fastqOffset, false, false); - } -} - diff --git a/src/lib/map/ChainBuilder.cpp b/src/lib/map/ChainBuilder.cpp index 0cadf34..242d97d 100644 --- a/src/lib/map/ChainBuilder.cpp +++ b/src/lib/map/ChainBuilder.cpp @@ -88,10 +88,10 @@ void ChainBuilder::filterChains() SeedChain* inferior = nullptr; - int maxcov_beg = std::numeric_limits::max(); - int maxcov_end = std::numeric_limits::min(); - int max_coverage = 0; - for (int i = 0; i < seedChainCount_; ++i) { + unsigned maxcov_beg = std::numeric_limits::max(); + unsigned maxcov_end = std::numeric_limits::min(); + unsigned max_coverage = 0; + for (std::size_t i = 0; i < seedChainCount_; ++i) { if (seedChains_[i].getReadCovLength() > max_coverage) { max_coverage = seedChains_[i].getReadCovLength(); maxcov_beg = seedChains_[i].firstReadBase(); @@ -99,14 +99,14 @@ void ChainBuilder::filterChains() } } - assert(!seedChainCount_ || maxcov_beg != std::numeric_limits::max()); - assert(!seedChainCount_ || maxcov_end != std::numeric_limits::min()); + assert(!seedChainCount_ || maxcov_beg != unsigned(std::numeric_limits::max())); + assert(!seedChainCount_ || maxcov_end != unsigned(std::numeric_limits::min())); - for (int j = 0; j < seedChainCount_; ++j) { + for (std::size_t j = 0; j < seedChainCount_; ++j) { inferior = &seedChains_[j]; - int chain_filt_ratio = int(chainFilterRatio_ * (1 << 8)); - int cov_thresh = (chain_filt_ratio * inferior->getReadCovLength()) >> 8; // + chainFilterConstant_; + int chain_filt_ratio = int(chainFilterRatio_ * (1 << 8)); + unsigned cov_thresh = (chain_filt_ratio * inferior->getReadCovLength()) >> 8; // + chainFilterConstant_; { int len_div4_v = inferior->getReadCovLength() >> 2; if (maxcov_beg <= inferior->firstReadBase() + len_div4_v && diff --git a/src/lib/map/Mapper.cpp b/src/lib/map/Mapper.cpp index 0a65694..6eaa2c5 100644 --- a/src/lib/map/Mapper.cpp +++ b/src/lib/map/Mapper.cpp @@ -13,11 +13,13 @@ **/ #include -#include +//#include #include #include -#include "common/Crc32Hw.hpp" +#include "host/infra/public/crc32_hw.h" + +//#include "common/Crc32Hw.hpp" #include "common/DragenLogger.hpp" #include "map/Mapper.hpp" @@ -178,16 +180,16 @@ void Mapper::addToPositionChains( //std::cerr << "Mapper::addToPositionChains" << std::endl; ////////// - // TODO: check the cost of the underlying memory allocations and cache the hash records buffer if needed - std::vector hashRecords; - std::vector extendTableIntervals; - unsigned fromHalfExtension = 0; // all seeds start as primary seeds - const auto forwardData = seed.getPrimaryData(false); - const auto reverseData = seed.getPrimaryData(true); - const bool seedIsReverseComplement = (reverseData < forwardData); - const auto primaryData = seedIsReverseComplement ? reverseData : forwardData; - const auto hash = getHashtable()->getPrimaryHasher()->getHash64(primaryData); - getHashtable()->getHits(hash, false, hashRecords, extendTableIntervals); + hashRecords_.clear(); + extendTableIntervals_.clear(); + + unsigned fromHalfExtension = 0; // all seeds start as primary seeds + const auto forwardData = seed.getPrimaryData(false); + const auto reverseData = seed.getPrimaryData(true); + const bool seedIsReverseComplement = (reverseData < forwardData); + const auto primaryData = seedIsReverseComplement ? reverseData : forwardData; + const auto hash = getHashtable()->getPrimaryHasher()->getHash64(primaryData); + getHashtable()->getHits(hash, false, hashRecords_, extendTableIntervals_); //////////////// // std::cerr << "Mapper::addToPositionChains: found " << hashRecords.size() << " hash records:"; @@ -195,13 +197,13 @@ void Mapper::addToPositionChains( // std::cerr << std::endl; //////////////// - if (hashRecords.empty() and extendTableIntervals.empty()) { + if (hashRecords_.empty() and extendTableIntervals_.empty()) { return; } // DEPRECATED - V7 only - if (HashRecord::HIFREQ == hashRecords.front().getType()) { + if (HashRecord::HIFREQ == hashRecords_.front().getType()) { addRandomSamplesToPositionChains( - seed, seedIsReverseComplement, fromHalfExtension, hashRecords, chainBuilder); + seed, seedIsReverseComplement, fromHalfExtension, hashRecords_, chainBuilder); return; } // at this point, it's either HIT or EXTEND records. First EXTEND as needed @@ -213,16 +215,16 @@ void Mapper::addToPositionChains( uint32_t lastExtendTableSize = 0; // defend against orphan EXTEND record BestIntervalTracker localBestIntvl(seed, 0, 0, 0); - if (extendTableIntervals.size() != lastExtendTableSize) { // new intervals seen - if (extendTableIntervals.size() != 1) { + if (extendTableIntervals_.size() != lastExtendTableSize) { // new intervals seen + if (extendTableIntervals_.size() != 1) { boost::format message = - boost::format("Expected size:1 extendTableIntervals, but got %i") % extendTableIntervals.size(); + boost::format("Expected size:1 extendTableIntervals, but got %i") % extendTableIntervals_.size(); BOOST_THROW_EXCEPTION(common::PostConditionException(message.str())); } - nextStart = extendTableIntervals.front().getStart(); + nextStart = extendTableIntervals_.front().getStart(); localBestIntvl = - BestIntervalTracker(seed, nextStart, extendTableIntervals.front().getLength(), fromHalfExtension); - lastExtendTableSize = extendTableIntervals.size(); + BestIntervalTracker(seed, nextStart, extendTableIntervals_.front().getLength(), fromHalfExtension); + lastExtendTableSize = extendTableIntervals_.size(); #ifdef TRACE_SEED_CHAINS std::cerr << "Init localBestIntvlPtr with\t" << localBestIntvl.getSeed() << "\tseedLength:" << localBestIntvl.getSeedLength() @@ -232,12 +234,12 @@ void Mapper::addToPositionChains( #endif } - while (!hashRecords.empty() && (HashRecord::EXTEND == hashRecords.front().getType())) { + while (!hashRecords_.empty() && (HashRecord::EXTEND == hashRecords_.front().getType())) { const uint64_t addressSegment = hash & addressSegmentMask_; - const auto extendRecord = hashRecords.front(); + const auto extendRecord = hashRecords_.front(); // DEPRECATED - V7 only addRandomSamplesToPositionChains( - seed, seedIsReverseComplement, fromHalfExtension, hashRecords, chainBuilder); + seed, seedIsReverseComplement, fromHalfExtension, hashRecords_, chainBuilder); //////////////// // std::cerr << "Mapper::addToPositionChains: extented seed from " << fromHalfExtension << " to " << (fromHalfExtension + extendRecord.getExtensionLength() / 2) << ":"; @@ -249,26 +251,27 @@ void Mapper::addToPositionChains( // std::cerr << std::endl; //////////////// - hashRecords.clear(); + hashRecords_.clear(); if (seed.isValid(fromHalfExtension + extendRecord.getExtensionLength() / 2)) { const auto extendedKey = getExtendedKey(seed, extensionHash, extendRecord, fromHalfExtension, seedIsReverseComplement); const auto extendedHash = addressSegment | getHashtable()->getSecondaryHasher()->getHash64(extendedKey); - getHashtable()->getHits(extendedHash, true, hashRecords, extendTableIntervals); + getHashtable()->getHits(extendedHash, true, hashRecords_, extendTableIntervals_); fromHalfExtension += extendRecord.getExtensionLength() / 2; extensionHash = extendedHash; // if extension failed, i.e. neither HIT nor INTERVAL - if (hashRecords.empty() and lastExtendTableSize == extendTableIntervals.size()) extensionFailed = true; + if (hashRecords_.empty() and lastExtendTableSize == extendTableIntervals_.size()) + extensionFailed = true; // local best interval tracking, process if extendTableIntervals is updated - else if (lastExtendTableSize != extendTableIntervals.size()) { - nextStart += extendTableIntervals.back().getStart(); + else if (lastExtendTableSize != extendTableIntervals_.size()) { + nextStart += extendTableIntervals_.back().getStart(); BestIntervalTracker currentIntvl( - seed, nextStart, extendTableIntervals.back().getLength(), fromHalfExtension); + seed, nextStart, extendTableIntervals_.back().getLength(), fromHalfExtension); if (!localBestIntvl.isValidInterval()) { - if (extendTableIntervals.size() != 1) { + if (extendTableIntervals_.size() != 1) { boost::format message = boost::format("Expected size:1 extendTableIntervals, but got %i") % - extendTableIntervals.size(); + extendTableIntervals_.size(); BOOST_THROW_EXCEPTION(common::PostConditionException(message.str())); } localBestIntvl = currentIntvl; @@ -304,22 +307,22 @@ void Mapper::addToPositionChains( << std::endl; #endif } - lastExtendTableSize = extendTableIntervals.size(); + lastExtendTableSize = extendTableIntervals_.size(); } // else we see orphan EXTEND record or only HIT } else extensionFailed = true; } - if (!extendTableIntervals.empty() && - extendTableIntervals.back().getLength() > getHashtable()->getMaxSeedFrequency()) + if (!extendTableIntervals_.empty() && + extendTableIntervals_.back().getLength() > getHashtable()->getMaxSeedFrequency()) extensionFailed = true; // global best interval tracking if (localBestIntvl.isValidInterval()) globalBestIntvls.push_back(localBestIntvl); #ifdef TRACE_SEED_CHAINS - std::cerr << "Mapper::addToPositionChains: found " << extendTableIntervals.size() + std::cerr << "Mapper::addToPositionChains: found " << extendTableIntervals_.size() << " extendTableIntervals records:"; - for (const auto& record : extendTableIntervals) + for (const auto& record : extendTableIntervals_) std::cerr << " " << std::setfill('0') << std::setw(8) << (record.getStart()) << ":" << std::setw(8) << (record.getLength()) << std::setfill(' ') << "\thex:" << std::hex << std::setfill('0') << std::setw(8) << (record.getStart()) << ":" << std::setw(8) << (record.getLength()) @@ -328,9 +331,10 @@ void Mapper::addToPositionChains( #endif // at this point there should be only HIT records (possibly 0) - add them to the seed chains - if (!hashRecords.empty()) { + if (!hashRecords_.empty()) { bool isHitSeen = false; - for (const auto& record : boost::adaptors::reverse(hashRecords)) { + // for (const auto& record : boost::adaptors::reverse(hashRecords_)) { + for (const auto& record : boost::make_iterator_range(hashRecords_.rbegin(), hashRecords_.rend())) { // special case encountered in alt-aware hashtables if (record.isDummyHit()) { continue; @@ -351,15 +355,15 @@ void Mapper::addToPositionChains( } } if (isHitSeen) return; - } else if (!extendTableIntervals.empty()) { + } else if (!extendTableIntervals_.empty()) { const uint32_t start = std::accumulate( - extendTableIntervals.begin(), - extendTableIntervals.end(), + extendTableIntervals_.begin(), + extendTableIntervals_.end(), 0UL, [](const uint32_t current, const ExtendTableInterval& interval) { return current + interval.getStart(); }); - const uint32_t length = extendTableIntervals.back().getLength(); + const uint32_t length = extendTableIntervals_.back().getLength(); if (extensionFailed) { num_extension_failure++; @@ -375,7 +379,7 @@ void Mapper::addToPositionChains( SeedPosition(seed, record.getPosition(), fromHalfExtension), orientation, isRandomSample); } } else { - assert(extendTableIntervals.back().getLength() <= getHashtable()->getMaxSeedFrequency()); + assert(extendTableIntervals_.back().getLength() <= getHashtable()->getMaxSeedFrequency()); for (uint32_t i = start + length - 1; i != start - 1; --i) { const auto& record = getHashtable()->getExtendTableRecord(i); const bool isRandomSample = false; @@ -394,6 +398,10 @@ void Mapper::addToPositionChains( // boost::format("Expected non-empty extendTableIntervals, but got %i") % extendTableIntervals.size(); // BOOST_THROW_EXCEPTION(common::PostConditionException(message.str())); } + + // used only locally + hashRecords_.clear(); + extendTableIntervals_.clear(); } void Mapper::addExtraIntervalSamplesToPositionChains( @@ -468,7 +476,7 @@ void Mapper::getRandomSamplesFromMatchInterval( // For 1 random sample after failed seed extension: if (1 == sampleSize) { maxRounds = 1; - uint32_t A = common::crc32c_hw(0, reinterpret_cast(readName.data()), readName.size()); + uint32_t A = crc32c_hw(0, reinterpret_cast(readName.data()), readName.size()); uint32_t B = read->getPosition() << 31; B |= 0x40000000; B |= seed.getReadPosition() & 0x3FFFFFFF; @@ -477,8 +485,8 @@ void Mapper::getRandomSamplesFromMatchInterval( // For K random samples from a (single) extra interval: else if (1 < sampleSize) { maxRounds = 0x4000; - SEED = common::crc32c_hw(0, reinterpret_cast(readName.data()), readName.size()); - SEED = read->getPosition() ? (SEED ^(1<<31)) : SEED; + SEED = crc32c_hw(0, reinterpret_cast(readName.data()), readName.size()); + SEED = read->getPosition() ? (SEED ^ (1 << 31)) : SEED; } else { boost::format message = boost::format("Expected positive target sampleSize: %d") % sampleSize; BOOST_THROW_EXCEPTION(common::PostConditionException(message.str())); @@ -493,7 +501,7 @@ void Mapper::getRandomSamplesFromMatchInterval( uint32_t K = 0; for (uint32_t X = SEED; K < sampleSize and X < SEED + maxRounds; X++) { - C = common::crc32c_hw(C, reinterpret_cast(&X), 4); + C = crc32c_hw(C, reinterpret_cast(&X), 4); sampledIndex = std::floor(intvl_len * double(C) / std::pow(2, 32)); const auto& record = getHashtable()->getExtendTableRecord(intvl_start + sampledIndex); @@ -513,7 +521,7 @@ void Mapper::getRandomSamplesFromMatchInterval( } if (0x4000 < intvl_len) { Z = SEED + sampledIndex; - sampledIndex = common::crc32c_hw(0, reinterpret_cast(&Z), 4) & 0x3FFF; + sampledIndex = crc32c_hw(0, reinterpret_cast(&Z), 4) & 0x3FFF; } if (hitVector.test(sampledIndex)) { #ifdef TRACE_SEED_CHAINS diff --git a/src/lib/map/SeedChain.cpp b/src/lib/map/SeedChain.cpp index 195a23e..9a622dc 100644 --- a/src/lib/map/SeedChain.cpp +++ b/src/lib/map/SeedChain.cpp @@ -120,7 +120,7 @@ bool SeedChain::passesRadiusTest(const uint32_t diagonal) const (rightmost / SMALL_QUANTIZER + MAX_RADIUS >= diagonal / SMALL_QUANTIZER); } -bool SeedChain::terminates(const Seed& seed) const +bool SeedChain::terminates(const Seed& /*seed*/) const { return (!seedPositions_.empty() and diagonalTable_.empty()); } diff --git a/src/lib/options/DragenOsOptions.cpp b/src/lib/options/DragenOsOptions.cpp index 4ee13d9..41e32c2 100644 --- a/src/lib/options/DragenOsOptions.cpp +++ b/src/lib/options/DragenOsOptions.cpp @@ -42,6 +42,13 @@ using common::InvalidOptionException; DragenOsOptions::DragenOsOptions() : refDir_("./"), inputFile1_(""), inputFile2_(""), mapOnly_(false) { + // deprecated command line options. Still valid but will error when conflict with official ones or warning + // when the corresponding official is not being used instead. + unnamedOptions_.add_options()( + "Aligner.sw-method", + bpo::value(&methodSmithWatermanDeprecated_), + "Smith Waterman implementation (dragen / mengyao default = dragen)"); + namedOptions_.add_options()( "ref-dir,r", bpo::value(&refDir_), @@ -81,8 +88,8 @@ DragenOsOptions::DragenOsOptions() : refDir_("./"), inputFile1_(""), inputFile2_ "Aligner.sw-all", bpo::value(&swAll_)->default_value(swAll_), "Value of 1 forces smith waterman on all candidate alignments")( - "Aligner.sw-method", - bpo::value(&methodSmithWaterman_)->default_value(methodSmithWaterman_), + "Aligner.smith-waterman-method", + bpo::value(&methodSmithWaterman_), "Smith Waterman implementation (dragen / mengyao default = dragen)")( "map-only", bpo::value(&mapOnly_)->default_value(mapOnly_), @@ -284,6 +291,29 @@ DragenOsOptions::DragenOsOptions() : refDir_("./"), inputFile1_(""), inputFile2_ ("verbose,v", bpo::bool_switch(&verbose_)->default_value(verbose_), "Be talkative"); } +template +void checkWarnDeprecatedOption( + bpo::variables_map& vm, + const std::string& officialName, + OptionType& official, + const std::string& deprecatedName, + const OptionType& deprecated) +{ + if (!vm.count(officialName) && vm.count(deprecatedName) && official != deprecated) { + std::cerr << "WARNING: option '" << deprecatedName + << "' is deprecated. While still valid, it is recommended to use '" << officialName + << "' instead." << std::endl; + official = deprecated; + return; + } + + if (vm.count(officialName) && vm.count(deprecatedName) && official != deprecated) { + BOOST_THROW_EXCEPTION(InvalidOptionException( + std::string("value specified for '") + officialName + "' conflicts with '" + deprecatedName + + "'. Please resolve command line option conflict.")); + } +} + void DragenOsOptions::postProcess(bpo::variables_map& vm) { if (vm.count("help") || version_) { @@ -294,12 +324,19 @@ void DragenOsOptions::postProcess(bpo::variables_map& vm) return; } - if (inputFile1_.empty() || !boost::filesystem::is_regular_file(inputFile1_)) { + checkWarnDeprecatedOption( + vm, + "Aligner.smith-waterman-method", + methodSmithWaterman_, + "Aligner.sw-method", + methodSmithWatermanDeprecated_); + + if (inputFile1_.empty() || boost::filesystem::is_directory(inputFile1_)) { BOOST_THROW_EXCEPTION( InvalidOptionException("fastq-file1 or bam-input must point to an existing fastq file")); } - if (!inputFile2_.empty() && !boost::filesystem::is_regular_file(inputFile2_)) { + if (!inputFile2_.empty() && boost::filesystem::is_directory(inputFile2_)) { BOOST_THROW_EXCEPTION(InvalidOptionException("fastq-file2 must point to an existing fastq file")); } diff --git a/src/lib/reference/Hashtable.cpp b/src/lib/reference/Hashtable.cpp index 180891d..d5dc6c2 100644 --- a/src/lib/reference/Hashtable.cpp +++ b/src/lib/reference/Hashtable.cpp @@ -30,13 +30,13 @@ Hashtable::Hashtable(const HashtableConfig* config, const uint64_t* table, const } bool Hashtable::processInitialBucket( - const Bucket& bucket, - const Hash& hash, - const uint64_t matchBits, - const uint8_t hashThreadId, - std::vector& hits, - std::vector& extendTableIntervals, - const bool trace) const + const Bucket& bucket, + const Hash& hash, + const uint64_t matchBits, + const uint8_t hashThreadId, + std::vector& hits, + std::vector& /*extendTableIntervals*/, + const bool trace) const { // TODO: check if it is required to have at least one hash record in the thread Id to start probing bool lastInThread = true; @@ -105,12 +105,12 @@ bool Hashtable::processInitialBucket( } bool Hashtable::probeBucket( - const Bucket& bucket, - const uint64_t matchBits, - const uint8_t hashThreadId, - std::vector& hits, - std::vector& extendTableIntervals, - const bool trace) const + const Bucket& bucket, + const uint64_t matchBits, + const uint8_t hashThreadId, + std::vector& hits, + std::vector& /*extendTableIntervals*/, + const bool trace) const { auto hashRecord = bucket.cbegin(); // alternate exit on relevant hashRecord->isLastInThread() @@ -200,13 +200,13 @@ bool Hashtable::followChain(const HashRecord& record, const Hash hash) const } bool Hashtable::chainBucket( - const Bucket& bucket, - const Hash& hash, - const uint64_t matchBits, - const uint8_t hashThreadId, - std::vector& hits, - std::vector& extendTableIntervals, - const bool trace) const + const Bucket& bucket, + const Hash& hash, + const uint64_t matchBits, + const uint8_t hashThreadId, + std::vector& hits, + std::vector& /*extendTableIntervals*/, + const bool trace) const { //bool fullBucket = true; auto hashRecord = bucket.cbegin(); diff --git a/src/lib/reference/HashtableConfig.cpp b/src/lib/reference/HashtableConfig.cpp index 4f46845..ce8a9d3 100644 --- a/src/lib/reference/HashtableConfig.cpp +++ b/src/lib/reference/HashtableConfig.cpp @@ -54,13 +54,13 @@ std::vector HashtableConfig::getTrimmedRegions() const return trimmedRegions; } -std::pair HashtableConfig::convertToReferenceCoordinates(int64_t position) const +std::pair HashtableConfig::convertToReferenceCoordinates(uint64_t position) const { auto sequence = std::lower_bound( sequences_.begin(), sequences_.end(), position, - [](const HashtableConfig::Sequence& sq, int64_t position) { + [](const HashtableConfig::Sequence& sq, uint64_t position) { const auto positionRange = getPositionRange(sq); return positionRange.first < position; }); @@ -95,7 +95,7 @@ std::pair HashtableConfig::convertToReferenceCoordinates(int64_ ++sequence; } - const auto lastRange = getPositionRange(sequences_.back()); + // const auto lastRange = getPositionRange(sequences_.back()); // boost::format message = boost::format("reference position greater than last sequence position: last sequence end=%i: queried position=%i") % lastRange.second % position; // TODO: verify that the position can actually be greater than the end of the sequence (because of padding) // BOOST_THROW_EXCEPTION(common::InvalidParameterException(message.str())); diff --git a/src/lib/reference/ReferenceDir.cpp b/src/lib/reference/ReferenceDir.cpp index 4d9f942..977619c 100644 --- a/src/lib/reference/ReferenceDir.cpp +++ b/src/lib/reference/ReferenceDir.cpp @@ -52,7 +52,7 @@ typename ReferenceDir7::UcharPtr ReferenceDir7::ReadFileIntoBuffer( size = file.tellg(); file.seekg(0, file.beg); - UcharPtr bufPtr(new uint8_t[size], [this](uint8_t* p) -> void { delete (p); }); + UcharPtr bufPtr(new uint8_t[size], [this](uint8_t* p) -> void { delete [](p); }); file.read(reinterpret_cast(bufPtr.get()), size); if (!file) { // THROW(DragenException, "Could not load reference - could not read ", path); @@ -63,19 +63,17 @@ typename ReferenceDir7::UcharPtr ReferenceDir7::ReadFileIntoBuffer( } ReferenceDir7::ReferenceDir7(const boost::filesystem::path& path, bool mmap, bool load) - : mmap_(mmap), - load_(load), - path_(path), + : path_(path), hashtableConfigData_(getHashtableConfigData()), hashtableConfig_(hashtableConfigData_.data(), hashtableConfigData_.size()) { - if (mmap_) { + if (mmap) { hashtableData_ = mmapData(hashtableBin, hashtableConfig_.getHashtableBytes()); extendTableData_ = (exists(path_ / extendTableBin)) ? mmapData(extendTableBin, hashtableConfig_.getExtendTableBytes()) : nullptr; referenceData_ = mmapData(referenceBin, hashtableConfig_.getReferenceSequenceLength() / 2); - } else if (load_) { + } else if (load) { hashtableData_ = readData(hashtableBin, hashtableConfig_.getHashtableBytes()); extendTableData_ = (exists(path_ / extendTableBin)) ? readData(extendTableBin, hashtableConfig_.getExtendTableBytes()) @@ -113,6 +111,10 @@ ReferenceDir7::ReferenceDir7(const boost::filesystem::path& path, bool mmap, boo nullptr, nullptr); + if (err) { + BOOST_THROW_EXCEPTION(std::logic_error(err)); + } + // restore stdout dup2(stdoutori, 1); diff --git a/src/lib/reference/ReferenceSequence.cpp b/src/lib/reference/ReferenceSequence.cpp index 22d78c5..0fe0b3f 100644 --- a/src/lib/reference/ReferenceSequence.cpp +++ b/src/lib/reference/ReferenceSequence.cpp @@ -19,72 +19,6 @@ namespace dragenos { namespace reference { -unsigned char ReferenceSequence::getBase(size_t position) const -{ -#if 0 - size_t address = position; - auto extractBase = [this](size_t address) -> unsigned char - { - const unsigned char result = data_[address / 2]; - return ((address % 2) ? (result >> 4) : result) & 0xF; - }; - for (const auto &trimmedRegion: trimmedRegions_) - { - if (position >= trimmedRegion[1]) - { - // adjust address to account for trimmed bases - address -= (trimmedRegion[1] - trimmedRegion[0]); - } - else if (position >= trimmedRegion[0]) - { - return 15; // 15 == encoded N - } - else - { - // return base in sequence before trimmed region - return extractBase(address); - } - } - // if we get here we are past the last trim region - check if still be in the sequence - if (address / 2 >= size_) - { - BOOST_THROW_EXCEPTION(common::InvalidParameterException("position greater than reference size")); - } - return extractBase(address); -#endif - if (position / 2 >= size_) { - boost::format message = - boost::format("position greater than reference size: %i > 2 * %i") % position % size_; - BOOST_THROW_EXCEPTION(common::InvalidParameterException(message.str())); - } - const unsigned char twoBases = data_[position / 2]; - const bool msb = (position % 2); // use the 4 MSB for odd positions - return msb ? (twoBases >> 4) : (twoBases & 0xF); -} - -unsigned char ReferenceSequence::getRcBase(size_t position) const -{ - unsigned char b = getBase(position); - const static std::array translate{0b0000, // 0b0000 - 0b1000, // 0b0001 - 0b0100, // 0b0010 - 0b1100, // 0b0011 - 0b0010, // 0b0100 - 0b1010, // 0b0101 - 0b0110, // 0b0110 - 0b1110, // 0b0111 - 0b0001, // 0b1000 - 0b1001, // 0b1001 - 0b0101, // 0b1010 - 0b1101, // 0b1011 - 0b0011, // 0b1100 - 0b1011, // 0b1101 - 0b0111, // 0b1110 - 0b1111}; // 0b1111 - - return translate[b]; -} - char ReferenceSequence::decodeBase(unsigned char base) { const static std::string translate{"PACMGRSVTWYHKDBN"}; diff --git a/src/lib/reference/tests/integration/HashtableGtest.cpp b/src/lib/reference/tests/integration/HashtableGtest.cpp index a8cb015..b3e3942 100644 --- a/src/lib/reference/tests/integration/HashtableGtest.cpp +++ b/src/lib/reference/tests/integration/HashtableGtest.cpp @@ -13,8 +13,8 @@ TEST(Hashtable, Constants) { using dragenos::reference::HashRecord; using dragenos::reference::Hashtable; - ASSERT_EQ(8, Hashtable::getRecordsPerBucket()); - ASSERT_EQ(8, Hashtable::getBytesPerRecord()); + ASSERT_EQ(8u, Hashtable::getRecordsPerBucket()); + ASSERT_EQ(8u, Hashtable::getBytesPerRecord()); ASSERT_EQ(sizeof(HashRecord), Hashtable::getBytesPerRecord()); - ASSERT_EQ(64, Hashtable::getBytesPerBucket()); + ASSERT_EQ(64u, Hashtable::getBytesPerBucket()); } diff --git a/src/lib/reference/tests/unit/ReferenceSequenceGtest.cpp b/src/lib/reference/tests/unit/ReferenceSequenceGtest.cpp index fb56450..2105696 100644 --- a/src/lib/reference/tests/unit/ReferenceSequenceGtest.cpp +++ b/src/lib/reference/tests/unit/ReferenceSequenceGtest.cpp @@ -82,7 +82,8 @@ TEST(ReferenceSequence, getBase) ASSERT_EQ(4, referenceSequence.getBase(2)); ASSERT_EQ(8, referenceSequence.getBase(3)); ASSERT_EQ(8, referenceSequence.getBase(bases.size() - 1)); - ASSERT_THROW(referenceSequence.getBase(bases.size()), dragenos::common::InvalidParameterException); + // check in getBase disabled due to performance reasons + //ASSERT_THROW(referenceSequence.getBase(bases.size()), dragenos::common::InvalidParameterException); } TEST(ReferenceSequence, getSequenceCopy) {} diff --git a/src/lib/sequences/CrcPolynomial.cpp b/src/lib/sequences/CrcPolynomial.cpp index f5c29b9..8ac7ab8 100644 --- a/src/lib/sequences/CrcPolynomial.cpp +++ b/src/lib/sequences/CrcPolynomial.cpp @@ -24,7 +24,7 @@ namespace sequences { std::array CrcPolynomial::generateData(unsigned bitCount, const uint8_t* data) { - std::array result; + std::array result = {}; const unsigned byteCount = (bitCount + 7) / 8; if (bitCount > result.size() * 8) { BOOST_THROW_EXCEPTION(common::InvalidParameterException(std::string("Suport at most 128 bits"))); diff --git a/src/lib/sequences/Seed.cpp b/src/lib/sequences/Seed.cpp index 6eca51f..08cc02c 100644 --- a/src/lib/sequences/Seed.cpp +++ b/src/lib/sequences/Seed.cpp @@ -24,16 +24,16 @@ namespace sequences { bool Seed::isValid(const Read& read, unsigned readPosition, unsigned primaryLength) { - static constexpr Read::Base N = 0xf; + // static constexpr Read::Base N = 0xf; if (readPosition + primaryLength > read.getLength()) { return false; } -// for (unsigned i = 0; primaryLength > i; ++i) { -// const Read::Base base = read.getBase4bpb(readPosition + i); -// if ((0 == base) || (N == base)) { -// return false; -// } -// } + // for (unsigned i = 0; primaryLength > i; ++i) { + // const Read::Base base = read.getBase4bpb(readPosition + i); + // if ((0 == base) || (N == base)) { + // return false; + // } + // } return true; } diff --git a/src/lib/sequences/tests/unit/CrcHasherGtest.cpp b/src/lib/sequences/tests/unit/CrcHasherGtest.cpp index b13d328..3e5a67e 100644 --- a/src/lib/sequences/tests/unit/CrcHasherGtest.cpp +++ b/src/lib/sequences/tests/unit/CrcHasherGtest.cpp @@ -11,9 +11,9 @@ TEST(CrcHasher, KnownHashValues) // polynomial and value taken and verified from Hashtable V8 const CrcPolynomial primaryPolynomial(54, std::string("2C991CE6A8DD55")); const CrcHasher primaryHasher(primaryPolynomial); - ASSERT_EQ(primaryHasher.getHash64(0x3543543543), 0x35de20855c4d8e); - ASSERT_EQ(primaryHasher.getHash64(0x10d50d50d50), 0x2643a64efec778); - ASSERT_EQ(primaryHasher.getHash64(0x14354354354), 0x24e8498f420b6f); - ASSERT_EQ(primaryHasher.getHash64(0x150d50d50d5), 0x9287b35d36195); - ASSERT_EQ(primaryHasher.getHash64(0xd50d50d50d), 0x22d3a73e8851c7); + ASSERT_EQ(primaryHasher.getHash64(0x3543543543), 0x35de20855c4d8eu); + ASSERT_EQ(primaryHasher.getHash64(0x10d50d50d50), 0x2643a64efec778u); + ASSERT_EQ(primaryHasher.getHash64(0x14354354354), 0x24e8498f420b6fu); + ASSERT_EQ(primaryHasher.getHash64(0x150d50d50d5), 0x9287b35d36195u); + ASSERT_EQ(primaryHasher.getHash64(0xd50d50d50d), 0x22d3a73e8851c7u); } diff --git a/src/lib/sequences/tests/unit/SeedGtest.cpp b/src/lib/sequences/tests/unit/SeedGtest.cpp index 65af5e6..7e385cf 100644 --- a/src/lib/sequences/tests/unit/SeedGtest.cpp +++ b/src/lib/sequences/tests/unit/SeedGtest.cpp @@ -38,12 +38,12 @@ TEST(SeedTest, getSeedOffsets) const uint8_t forceLastN = 3; const auto seedOffsets = dragenos::sequences::Seed::getSeedOffsets(readLength, seedLength, period, pattern, forceLastN); - ASSERT_EQ(5, seedOffsets.size()); - ASSERT_EQ(0, seedOffsets[0]); - ASSERT_EQ(4, seedOffsets[1]); - ASSERT_EQ(6, seedOffsets[2]); - ASSERT_EQ(7, seedOffsets[3]); - ASSERT_EQ(8, seedOffsets[4]); + ASSERT_EQ(5u, seedOffsets.size()); + ASSERT_EQ(0u, seedOffsets[0]); + ASSERT_EQ(4u, seedOffsets[1]); + ASSERT_EQ(6u, seedOffsets[2]); + ASSERT_EQ(7u, seedOffsets[3]); + ASSERT_EQ(8u, seedOffsets[4]); } { const size_t readLength = 151; @@ -54,50 +54,50 @@ TEST(SeedTest, getSeedOffsets) const uint8_t forceLastN = 3; const auto seedOffsets = dragenos::sequences::Seed::getSeedOffsets(readLength, seedLength, period, pattern, forceLastN); - ASSERT_EQ(69, seedOffsets.size()); - ASSERT_EQ(0, seedOffsets[0]); - ASSERT_EQ(2, seedOffsets[1]); - ASSERT_EQ(4, seedOffsets[2]); - ASSERT_EQ(130, seedOffsets[65]); - ASSERT_EQ(132, seedOffsets[66]); - ASSERT_EQ(133, seedOffsets[67]); - ASSERT_EQ(134, seedOffsets[68]); + ASSERT_EQ(69u, seedOffsets.size()); + ASSERT_EQ(0u, seedOffsets[0]); + ASSERT_EQ(2u, seedOffsets[1]); + ASSERT_EQ(4u, seedOffsets[2]); + ASSERT_EQ(130u, seedOffsets[65]); + ASSERT_EQ(132u, seedOffsets[66]); + ASSERT_EQ(133u, seedOffsets[67]); + ASSERT_EQ(134u, seedOffsets[68]); } } TEST(SeedTest, generateReverseComplement) { using dragenos::sequences::Seed; - ASSERT_EQ(0x0, Seed::generateReverseComplement(0x0UL, 0)); - ASSERT_EQ(0x0, Seed::generateReverseComplement(0x3UL, 1)); - ASSERT_EQ(0x1, Seed::generateReverseComplement(0x2UL, 1)); - ASSERT_EQ(0x2, Seed::generateReverseComplement(0x1UL, 1)); - ASSERT_EQ(0x3, Seed::generateReverseComplement(0x0UL, 1)); + ASSERT_EQ(0x0u, Seed::generateReverseComplement(0x0UL, 0)); + ASSERT_EQ(0x0u, Seed::generateReverseComplement(0x3UL, 1)); + ASSERT_EQ(0x1u, Seed::generateReverseComplement(0x2UL, 1)); + ASSERT_EQ(0x2u, Seed::generateReverseComplement(0x1UL, 1)); + ASSERT_EQ(0x3u, Seed::generateReverseComplement(0x0UL, 1)); // 2 bases that are reverse complement of each other - ASSERT_EQ(0x3, Seed::generateReverseComplement(0x3UL, 2)); // TA - ASSERT_EQ(0x6, Seed::generateReverseComplement(0x6UL, 2)); // GC - ASSERT_EQ(0x9, Seed::generateReverseComplement(0x9UL, 2)); // CG - ASSERT_EQ(0xC, Seed::generateReverseComplement(0xCUL, 2)); // AT + ASSERT_EQ(0x3u, Seed::generateReverseComplement(0x3UL, 2)); // TA + ASSERT_EQ(0x6u, Seed::generateReverseComplement(0x6UL, 2)); // GC + ASSERT_EQ(0x9u, Seed::generateReverseComplement(0x9UL, 2)); // CG + ASSERT_EQ(0xCu, Seed::generateReverseComplement(0xCUL, 2)); // AT // 2 bases that are the same - ASSERT_EQ(0x0, Seed::generateReverseComplement(0xFUL, 2)); // AA - ASSERT_EQ(0x5, Seed::generateReverseComplement(0xAUL, 2)); // CC - ASSERT_EQ(0xA, Seed::generateReverseComplement(0x5UL, 2)); // GG - ASSERT_EQ(0xF, Seed::generateReverseComplement(0x0UL, 2)); // TT + ASSERT_EQ(0x0u, Seed::generateReverseComplement(0xFUL, 2)); // AA + ASSERT_EQ(0x5u, Seed::generateReverseComplement(0xAUL, 2)); // CC + ASSERT_EQ(0xAu, Seed::generateReverseComplement(0x5UL, 2)); // GG + ASSERT_EQ(0xFu, Seed::generateReverseComplement(0x0UL, 2)); // TT // other 2 base combinations - ASSERT_EQ(0x1, Seed::generateReverseComplement(0xBUL, 2)); // CA - ASSERT_EQ(0x2, Seed::generateReverseComplement(0x7UL, 2)); // GA - ASSERT_EQ(0xD, Seed::generateReverseComplement(0x8UL, 2)); // CT - ASSERT_EQ(0xE, Seed::generateReverseComplement(0x4UL, 2)); // GT - ASSERT_EQ(0x4, Seed::generateReverseComplement(0xEUL, 2)); // AC - ASSERT_EQ(0x7, Seed::generateReverseComplement(0x2UL, 2)); // TC - ASSERT_EQ(0x8, Seed::generateReverseComplement(0xDUL, 2)); // AG - ASSERT_EQ(0xB, Seed::generateReverseComplement(0x1UL, 2)); // TG + ASSERT_EQ(0x1u, Seed::generateReverseComplement(0xBUL, 2)); // CA + ASSERT_EQ(0x2u, Seed::generateReverseComplement(0x7UL, 2)); // GA + ASSERT_EQ(0xDu, Seed::generateReverseComplement(0x8UL, 2)); // CT + ASSERT_EQ(0xEu, Seed::generateReverseComplement(0x4UL, 2)); // GT + ASSERT_EQ(0x4u, Seed::generateReverseComplement(0xEUL, 2)); // AC + ASSERT_EQ(0x7u, Seed::generateReverseComplement(0x2UL, 2)); // TC + ASSERT_EQ(0x8u, Seed::generateReverseComplement(0xDUL, 2)); // AG + ASSERT_EQ(0xBu, Seed::generateReverseComplement(0x1UL, 2)); // TG // some random sequences - ASSERT_EQ(0x5F21, Seed::generateReverseComplement(0xB70AUL, 8)); // CAGATTCC -> GGAATCTG - ASSERT_EQ(0x35F21, Seed::generateReverseComplement(0x2DC28UL, 9)); // CAGATTCCT -> AGGAATCTG - ASSERT_EQ(0xE5F21, Seed::generateReverseComplement(0xB70A4UL, 10)); // CAGATTCCGT -> ACGGAATCTG - ASSERT_EQ(0x275F21, Seed::generateReverseComplement(0x2DC289UL, 11)); // CAGATTCCTCG -> CGAGGAATCTG - ASSERT_EQ(0xDE5F21, Seed::generateReverseComplement(0xB70A48UL, 12)); // CAGATTCCGTCT -> AGACGGAATCTG + ASSERT_EQ(0x5F21u, Seed::generateReverseComplement(0xB70AUL, 8)); // CAGATTCC -> GGAATCTG + ASSERT_EQ(0x35F21u, Seed::generateReverseComplement(0x2DC28UL, 9)); // CAGATTCCT -> AGGAATCTG + ASSERT_EQ(0xE5F21u, Seed::generateReverseComplement(0xB70A4UL, 10)); // CAGATTCCGT -> ACGGAATCTG + ASSERT_EQ(0x275F21u, Seed::generateReverseComplement(0x2DC289UL, 11)); // CAGATTCCTCG -> CGAGGAATCTG + ASSERT_EQ(0xDE5F21u, Seed::generateReverseComplement(0xB70A48UL, 12)); // CAGATTCCGTCT -> AGACGGAATCTG } TEST(SeedTest, Constructor) @@ -132,10 +132,10 @@ TEST(SeedTest, getPrimaryData) using dragenos::sequences::Seed; Read read; // single base seeds - ASSERT_EQ(151, read.getLength()); + ASSERT_EQ(151u, read.getLength()); for (unsigned i = 0; read.getLength() > i; ++i) { - ASSERT_EQ(read.getBase2bpb(i), Seed(&read, i, 1).getPrimaryData(false)) << "i: " << i; - ASSERT_EQ((~read.getBase2bpb(i)) & 3, Seed(&read, i, 1).getPrimaryData(true)) << "i: " << i; + ASSERT_EQ((unsigned long)read.getBase2bpb(i), Seed(&read, i, 1).getPrimaryData(false)) << "i: " << i; + ASSERT_EQ((unsigned long)(~read.getBase2bpb(i)) & 3, Seed(&read, i, 1).getPrimaryData(true)) << "i: " << i; } ASSERT_THROW( Seed(&read, read.getLength(), 1).getPrimaryData(false), dragenos::common::PreConditionException); @@ -172,7 +172,7 @@ TEST(SeedTest, getExtendedData) typedef Seed::Data Data; Read read; // single base wings - ASSERT_EQ(151, read.getLength()); + ASSERT_EQ(151u, read.getLength()); for (unsigned i = 1; read.getLength() > i + 1; ++i) { const Data l = read.getBase2bpb(i - 1); const Data r = read.getBase2bpb(i + 1); diff --git a/src/lib/workflow/DualFastq2SamWorkflow.cpp b/src/lib/workflow/DualFastq2SamWorkflow.cpp index 1fb17db..a4be874 100644 --- a/src/lib/workflow/DualFastq2SamWorkflow.cpp +++ b/src/lib/workflow/DualFastq2SamWorkflow.cpp @@ -25,9 +25,10 @@ #include "mapping_stats.hpp" #include "align/Aligner.hpp" -#include "align/Sam.hpp" +#include "align/SinglePicker.hpp" #include "fastq/Tokenizer.hpp" #include "io/Fastq2ReadTransformer.hpp" +#include "sam/SamGenerator.hpp" #include "workflow/DualFastq2SamWorkflow.hpp" @@ -195,6 +196,202 @@ void DualFastq2SamWorkflow::parseDualFastq( } } +void DualFastq2SamWorkflow::alignDualFastqBlock( + common::ThreadPool::lock_type& lock, + std::size_t& cpuThreads, + std::size_t& threadID, + std::vector& mappingMetricsVector, + align::InsertSizeDistribution& insertSizeDistribution, + fastq::FastqNRecordReader& r1Reader, + fastq::FastqNRecordReader& r2Reader, + std::ostream& os, + const align::SinglePicker& singlePicker, + const align::SimilarityScores& similarity, + const sam::SamGenerator& sam) +{ + align::PairBuilder pairBuilder( + similarity, + options_.alnMinScore_, + options_.alignerUnpairedPen_, + options_.alignerXsPairPen_, + options_.alignerSecAligns_, + options_.alignerSecScoreDelta_, + options_.alignerSecPhredDelta_, + options_.alignerSecAlignsHard_, + options_.alignerMapqMinLen_); + + // aligner is not stateless, make sure each thread uses its own. + align::Aligner aligner( + refSeq_, + htConfig_, + hashtable_, + options_.mapOnly_, + options_.swAll_, + similarity, + options_.gapInitPenalty_, + options_.gapExtendPenalty_, + options_.unclipScore_, + options_.alnMinScore_, + options_.alignerMapqMinLen_, + options_.alignerUnpairedPen_, + options_.mapperFilterLenRatio_, + !options_.methodSmithWaterman_.compare("mengyao")); + + std::vector r1Block; + // arbitrary preallocation to avoid unnecessary copy/paste + r1Block.reserve(RECORDS_AT_A_TIME_ * 1024); + std::vector r2Block; + r2Block.reserve(RECORDS_AT_A_TIME_ * 1024); + + // records in output format + std::vector tmpBuffer; + tmpBuffer.reserve(RECORDS_AT_A_TIME_ * 1024); + boost::iostreams::filtering_ostream ostrm; + ostrm.push(boost::iostreams::back_insert_device>(tmpBuffer)); + // minimum data required for insert size calculation + std::vector insBuffer; + insBuffer.reserve(RECORDS_AT_A_TIME_ * 1024); + + ReadGroupAlignmentCounts& mappingMetricsLocal = mappingMetricsVector[threadID]; + threadID++; + + do { + const int ourBlock = blockToStart_++; + + // keep track of which read is reading + int r1Records = -1; + int r2Records = -1; + // no more than 2 threads are allowed in + common::CPU_THREADS().execute( + lock, + [&](common::ThreadPool::lock_type& lock) { + readBlockThread(lock, ourBlock, r1Records, r1Block, r1Reader, r2Records, r2Block, r2Reader); + }, + 2); + + // readBlockThread(lock, ourBlock, r1Records, r1Block, r1Reader, r2Records, r2Block, r2Reader); + // if our block, go see if we've read something + if (blockToRead_ == ourBlock) { + // could be -1 or 0 if by the time we decide to read our block we run out of data + if (0 < r1Records) { + if (r1Records != r2Records) { + throw std::logic_error(std::string("fastq files have different number of records ")); + } + + // both reads completed, let others move on + ++blockToRead_; + common::CPU_THREADS().notify_all(); + + while (blockToGetInsertSizes_ != ourBlock) { + common::CPU_THREADS().waitForChange(lock); + } + + align::InsertSizeParameters insertSizeParameters; + { + common::unlock_guard unlock(lock); + boost::iostreams::filtering_istream inputR1; + inputR1.push(boost::iostreams::basic_array_source{&r1Block.front(), + &r1Block.front() + r1Block.size()}); + boost::iostreams::filtering_istream inputR2; + inputR2.push(boost::iostreams::basic_array_source{&r2Block.front(), + &r2Block.front() + r2Block.size()}); + insertSizeParameters = requestInsertSizeInfo(insertSizeDistribution, inputR1, inputR2); + } + assert(blockToGetInsertSizes_ == ourBlock); + ++blockToGetInsertSizes_; + common::CPU_THREADS().notify_all(); + + while (options_.mapperNumThreads_ == int(cpuThreads) || blockToAlign_ != ourBlock) { + common::CPU_THREADS().waitForChange(lock); + } + ++cpuThreads; + ++blockToAlign_; + common::CPU_THREADS().notify_all(); + { + common::unlock_guard unlock(lock); + boost::iostreams::filtering_istream inputR1; + inputR1.push(boost::iostreams::basic_array_source{&r1Block.front(), + &r1Block.front() + r1Block.size()}); + boost::iostreams::filtering_istream inputR2; + inputR2.push(boost::iostreams::basic_array_source{&r2Block.front(), + &r2Block.front() + r2Block.size()}); + insBuffer.clear(); + tmpBuffer.clear(); + + alignDualFastq( + insertSizeParameters, + inputR1, + inputR2, + aligner, + singlePicker, + pairBuilder, + [&](const sequences::Read& r, const align::Alignment& a) { + sam.generateRecord(ostrm, r, a, options_.rgid_) << "\n"; + + const auto before = insBuffer.size(); + insBuffer.resize(before + sequences::SerializedRead::getByteSize(r)); + const auto before2 = insBuffer.size(); + insBuffer.resize(before2 + align::SerializedAlignment::getByteSize(a)); + + // resize can invalidate references... + sequences::SerializedRead& sr = + *reinterpret_cast(&insBuffer.front() + before); + sr << r; + + align::SerializedAlignment& sa = + *reinterpret_cast(&insBuffer.front() + before2); + sa << a; + + mappingMetricsLocal.addRecord(sa, sr); + }); + ostrm.flush(); + } + + --cpuThreads; + common::CPU_THREADS().notify_all(); + + if (options_.preserveMapAlignOrder_) { + while (blockToStore_ != ourBlock) { + common::CPU_THREADS().waitForChange(lock); + } + } else { + while (-1 != blockToStore_) { + common::CPU_THREADS().waitForChange(lock); + } + blockToStore_ = ourBlock; + } + + { + common::unlock_guard unlock(lock); + for (auto it = insBuffer.begin(); insBuffer.end() != it;) { + char* p = &*it; + const sequences::SerializedRead* pRead = reinterpret_cast(p); + it += pRead->getByteSize(); + p = &*it; + const align::SerializedAlignment* pAlignment = + reinterpret_cast(p); + it += pAlignment->getByteSize(); + // sam.generateRecord(os, *pRead, *pAlignment, options_.rgid_) << "\n"; + insertSizeDistribution.add(*pAlignment, *pRead); + } + if (!os.write(&tmpBuffer.front(), tmpBuffer.size())) { + throw std::logic_error(std::string("Error writing output stream. Error: ") + strerror(errno)); + } + } + assert(blockToStore_ == ourBlock); + if (options_.preserveMapAlignOrder_) { + ++blockToStore_; + } else { + blockToStore_ = -1; + } + common::CPU_THREADS().notify_all(); + } + } + // else we're a thread that waited to read its block until it learned that there will be no more + // input data. just quietly exit + } while (!common::CPU_THREADS().checkThreadFailed() && !r1Eof_ && !r2Eof_); +} + void DualFastq2SamWorkflow::parseDualFastq( std::istream& r1Stream, std::istream& r2Stream, @@ -249,7 +446,7 @@ void DualFastq2SamWorkflow::parseDualFastq( fastq::FastqNRecordReader r1Reader(r1Stream); fastq::FastqNRecordReader r2Reader(r2Stream); - const align::Sam sam(referenceDir_.getHashtableConfig()); + const sam::SamGenerator sam(htConfig_); std::size_t cpuThreads = 0; std::size_t threadID = 0; @@ -260,194 +457,23 @@ void DualFastq2SamWorkflow::parseDualFastq( common::CPU_THREADS(poolThreadCount) .execute( [&](common::ThreadPool::lock_type& lock) { - align::PairBuilder pairBuilder( - similarity, - options_.alnMinScore_, - options_.alignerUnpairedPen_, - options_.alignerXsPairPen_, - options_.alignerSecAligns_, - options_.alignerSecScoreDelta_, - options_.alignerSecPhredDelta_, - options_.alignerSecAlignsHard_, - options_.alignerMapqMinLen_); - - // aligner is not stateless, make sure each thread uses its own. - align::Aligner aligner( - referenceDir_, - hashtable_, - options_.mapOnly_, - options_.swAll_, + alignDualFastqBlock( + lock, + cpuThreads, + threadID, + mappingMetricsVector, + insertSizeDistribution, + r1Reader, + r2Reader, + os, + singlePicker, similarity, - options_.gapInitPenalty_, - options_.gapExtendPenalty_, - options_.unclipScore_, - options_.alnMinScore_, - options_.alignerMapqMinLen_, - options_.alignerUnpairedPen_, - options_.mapperFilterLenRatio_, - !options_.methodSmithWaterman_.compare("mengyao")); - - std::vector r1Block; - // arbitrary preallocation to avoid unnecessary copy/paste - r1Block.reserve(RECORDS_AT_A_TIME_ * 1024); - std::vector r2Block; - r2Block.reserve(RECORDS_AT_A_TIME_ * 1024); - - // records in output format - std::vector tmpBuffer; - tmpBuffer.reserve(RECORDS_AT_A_TIME_ * 1024); - boost::iostreams::filtering_ostream ostrm; - ostrm.push(boost::iostreams::back_insert_device>(tmpBuffer)); - // minimum data required for insert size calculation - std::vector insBuffer; - insBuffer.reserve(RECORDS_AT_A_TIME_ * 1024); - - ReadGroupAlignmentCounts& mappingMetricsLocal = mappingMetricsVector[threadID]; - threadID++; - - do { - const int ourBlock = blockToStart_++; - - // keep track of which read is reading - int r1Records = -1; - int r2Records = -1; - // no more than 2 threads are allowed in - common::CPU_THREADS().execute( - lock, - [&](common::ThreadPool::lock_type& lock) { - readBlockThread( - lock, ourBlock, r1Records, r1Block, r1Reader, r2Records, r2Block, r2Reader); - }, - 2); - - // readBlockThread(lock, ourBlock, r1Records, r1Block, r1Reader, r2Records, r2Block, r2Reader); - // if our block, go see if we've read something - if (blockToRead_ == ourBlock) { - // could be -1 or 0 if by the time we decide to read our block we run out of data - if (0 < r1Records) { - if (r1Records != r2Records) { - throw std::logic_error(std::string("fastq files have different number of records ")); - } - - // both reads completed, let others move on - ++blockToRead_; - common::CPU_THREADS().notify_all(); - - while (blockToGetInsertSizes_ != ourBlock) { - common::CPU_THREADS().waitForChange(lock); - } - - align::InsertSizeParameters insertSizeParameters; - { - common::unlock_guard unlock(lock); - boost::iostreams::filtering_istream inputR1; - inputR1.push(boost::iostreams::basic_array_source{ - &r1Block.front(), &r1Block.front() + r1Block.size()}); - boost::iostreams::filtering_istream inputR2; - inputR2.push(boost::iostreams::basic_array_source{ - &r2Block.front(), &r2Block.front() + r2Block.size()}); - insertSizeParameters = requestInsertSizeInfo(insertSizeDistribution, inputR1, inputR2); - } - assert(blockToGetInsertSizes_ == ourBlock); - ++blockToGetInsertSizes_; - common::CPU_THREADS().notify_all(); - - while (options_.mapperNumThreads_ == cpuThreads || blockToAlign_ != ourBlock) { - common::CPU_THREADS().waitForChange(lock); - } - ++cpuThreads; - ++blockToAlign_; - common::CPU_THREADS().notify_all(); - { - common::unlock_guard unlock(lock); - boost::iostreams::filtering_istream inputR1; - inputR1.push(boost::iostreams::basic_array_source{ - &r1Block.front(), &r1Block.front() + r1Block.size()}); - boost::iostreams::filtering_istream inputR2; - inputR2.push(boost::iostreams::basic_array_source{ - &r2Block.front(), &r2Block.front() + r2Block.size()}); - insBuffer.clear(); - tmpBuffer.clear(); - - alignDualFastq( - insertSizeParameters, - inputR1, - inputR2, - aligner, - singlePicker, - pairBuilder, - [&](const sequences::Read& r, const align::Alignment& a) { - sam.generateRecord(ostrm, r, a, options_.rgid_) << "\n"; - - const auto before = insBuffer.size(); - insBuffer.resize(before + sequences::SerializedRead::getByteSize(r)); - const auto before2 = insBuffer.size(); - insBuffer.resize(before2 + align::SerializedAlignment::getByteSize(a)); - - // resize can invalidate references... - sequences::SerializedRead& sr = - *reinterpret_cast(&insBuffer.front() + before); - sr << r; - - align::SerializedAlignment& sa = - *reinterpret_cast(&insBuffer.front() + before2); - sa << a; - - mappingMetricsLocal.addRecord(sa, sr); - }); - ostrm.flush(); - } - - --cpuThreads; - common::CPU_THREADS().notify_all(); - - if (options_.preserveMapAlignOrder_) { - while (blockToStore_ != ourBlock) { - common::CPU_THREADS().waitForChange(lock); - } - } else { - while (-1 != blockToStore_) { - common::CPU_THREADS().waitForChange(lock); - } - blockToStore_ = ourBlock; - } - - { - common::unlock_guard unlock(lock); - for (auto it = insBuffer.begin(); insBuffer.end() != it;) { - char* p = &*it; - const sequences::SerializedRead* pRead = - reinterpret_cast(p); - it += pRead->getByteSize(); - p = &*it; - const align::SerializedAlignment* pAlignment = - reinterpret_cast(p); - it += pAlignment->getByteSize(); - // sam.generateRecord(os, *pRead, *pAlignment, options_.rgid_) << "\n"; - insertSizeDistribution.add(*pAlignment, *pRead); - } - if (!os.write(&tmpBuffer.front(), tmpBuffer.size())) { - throw std::logic_error( - std::string("Error writing output stream. Error: ") + strerror(errno)); - } - } - assert(blockToStore_ == ourBlock); - if (options_.preserveMapAlignOrder_) { - ++blockToStore_; - } else { - blockToStore_ = -1; - } - common::CPU_THREADS().notify_all(); - } - } - // else we're a thread that waited to read its block until it learned that there will be no more - // input data. just quietly exit - } while (!r1Eof_ && !r2Eof_); + sam); }, options_.mapperNumThreads_); // aggregate and print mapping metrics - for (int ii = 0; ii < mappingMetricsVector.size(); ii++) { + for (std::size_t ii = 0; ii < mappingMetricsVector.size(); ii++) { mappingMetricsGlobal.add(mappingMetricsVector[ii]); } diff --git a/src/lib/workflow/Input2SamWorkflow.cpp b/src/lib/workflow/Input2SamWorkflow.cpp index 5f70ee8..cbc2776 100644 --- a/src/lib/workflow/Input2SamWorkflow.cpp +++ b/src/lib/workflow/Input2SamWorkflow.cpp @@ -24,7 +24,7 @@ #include #include "align/Aligner.hpp" -#include "align/Sam.hpp" +#include "align/SinglePicker.hpp" #include "bam/BamBlockReader.hpp" #include "bam/Tokenizer.hpp" #include "common/Debug.hpp" @@ -36,6 +36,7 @@ #include "mapping_stats.hpp" #include "options/DragenOsOptions.hpp" #include "reference/ReferenceDir.hpp" +#include "sam/SamGenerator.hpp" #include "workflow/DualFastq2SamWorkflow.hpp" #include "workflow/Input2SamWorkflow.hpp" @@ -182,12 +183,13 @@ fastq::FastqBlockReader makeBlockReader( template void parseSingleInput( - std::istream& is, - std::ostream& os, - const options::DragenOsOptions& options, - const reference::ReferenceDir7& referenceDir, - const reference::Hashtable& hashtable, - std::ostream& mappingMetricsLogStream) + std::istream& is, + std::ostream& os, + const options::DragenOsOptions& options, + const reference::ReferenceSequence& refSeq, + const reference::HashtableConfig& htConfig, + const reference::Hashtable& hashtable, + std::ostream& mappingMetricsLogStream) { std::chrono::system_clock::time_point timeStart = std::chrono::system_clock::now(); @@ -224,7 +226,7 @@ void parseSingleInput( options.alignerSecAlignsHard_, options.alignerMapqMinLen_); - const align::Sam sam(referenceDir.getHashtableConfig()); + const sam::SamGenerator sam(htConfig); // idle threads needed to hold results that arrive out of order const int poolThreadCount = options.mapperNumThreads_ * 2; @@ -258,7 +260,8 @@ void parseSingleInput( options.alignerMapqMinLen_); align::Aligner aligner( - referenceDir, + refSeq, + htConfig, hashtable, options.mapOnly_, options.swAll_, @@ -288,7 +291,9 @@ void parseSingleInput( ReadGroupAlignmentCounts& mappingMetricsLocal = mappingMetricsVector[threadID]; threadID++; - while (!reader.eof()) { + // common::CPU_THREADS().checkThreadFailed() is needed to prevent lucky threads + // from spending eternity trying to complete the processing of broken data + while (!common::CPU_THREADS().checkThreadFailed() && !reader.eof()) { const std::size_t n = reader.read(&inBuffer[0], BUFFER_SIZE); const int ourBlock = blockToRead; @@ -312,7 +317,7 @@ void parseSingleInput( ++blockToGetInsertSizes; common::CPU_THREADS().notify_all(); - while (options.mapperNumThreads_ == cpuThreads || blockToAlign != ourBlock) { + while (options.mapperNumThreads_ == int(cpuThreads) || blockToAlign != ourBlock) { common::CPU_THREADS().waitForChange(lock); } ++cpuThreads; @@ -401,7 +406,7 @@ void parseSingleInput( options.mapperNumThreads_); // aggregate and print mapping metrics - for (int ii = 0; ii < mappingMetricsVector.size(); ii++) { + for (std::size_t ii = 0; ii < mappingMetricsVector.size(); ii++) { mappingMetricsGlobal.add(mappingMetricsVector[ii]); } @@ -424,11 +429,12 @@ bool isGzip(const std::string& fileName) } void parseSingleInput( - std::ostream& os, - const options::DragenOsOptions& options, - const reference::ReferenceDir7& referenceDir, - const reference::Hashtable& hashtable, - std::ostream& mappingMetricsLogStream) + std::ostream& os, + const options::DragenOsOptions& options, + const reference::ReferenceSequence& refSeq, + const reference::HashtableConfig& htConfig, + const reference::Hashtable& hashtable, + std::ostream& mappingMetricsLogStream) { std::cerr << "Running fastq workflow on " << options.mapperNumThreads_ << " threads. System supports " << std::thread::hardware_concurrency() << " threads." << std::endl; @@ -444,10 +450,10 @@ void parseSingleInput( try { if (isBam(options.inputFile1_)) { parseSingleInput( - input, os, options, referenceDir, hashtable, mappingMetricsLogStream); + input, os, options, refSeq, htConfig, hashtable, mappingMetricsLogStream); } else { parseSingleInput( - input, os, options, referenceDir, hashtable, mappingMetricsLogStream); + input, os, options, refSeq, htConfig, hashtable, mappingMetricsLogStream); } } catch (boost::iostreams::gzip_error& e) { BOOST_THROW_EXCEPTION(std::runtime_error( @@ -503,7 +509,7 @@ void input2Sam(const dragenos::options::DragenOsOptions& options) } } std::ostream& samFile = os.is_open() ? os : std::cout; - align::Sam::generateHeader( + sam::SamGenerator::generateHeader( samFile, referenceDir.getHashtableConfig(), options.getCommandLine(), options.rgid_, options.rgsm_); std::ofstream mappingMetricsLogStream; @@ -534,12 +540,14 @@ void input2Sam(const dragenos::options::DragenOsOptions& options) parseSingleInput( samFile, options, - referenceDir, + referenceDir.getReferenceSequence(), + referenceDir.getHashtableConfig(), hashtable, mappingMetricsLogStream.is_open() ? mappingMetricsLogStream : std::cerr); } else { - DualFastq2SamWorkflow workflow(options, referenceDir, hashtable); - std::ofstream insertSizeDistributionLogStream; + DualFastq2SamWorkflow workflow( + options, referenceDir.getReferenceSequence(), referenceDir.getHashtableConfig(), hashtable); + std::ofstream insertSizeDistributionLogStream; if (!options.outputDirectory_.empty()) { namespace bfs = boost::filesystem; diff --git a/stubs/.clang-format b/stubs/.clang-format new file mode 100644 index 0000000..7968b43 --- /dev/null +++ b/stubs/.clang-format @@ -0,0 +1,3 @@ +DisableFormat: true +SortIncludes: false + diff --git a/stubs/bamtools/bamtools-2.4.1/include/api/BamConstants.h b/stubs/bamtools/bamtools-2.4.1/include/api/BamConstants.h new file mode 100644 index 0000000..baee67c --- /dev/null +++ b/stubs/bamtools/bamtools-2.4.1/include/api/BamConstants.h @@ -0,0 +1,289 @@ +// *************************************************************************** +// BamConstants.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 16 October 2011 (DB) +// --------------------------------------------------------------------------- +// Provides basic constants for handling BAM files. +// *************************************************************************** + +#ifndef BAM_CONSTANTS_H +#define BAM_CONSTANTS_H + +// RP: bamtools is a stub in dragmap because all we need is some of the constants below. Including BAM_CIGAR_SHIFT that +// has to be a #define to avoid conflict with ssw.h +//#include "api/api_global.h" +#include +#include + +/*! \namespace BamTools::Constants + \brief Provides basic constants for handling BAM files. +*/ + +namespace BamTools { +namespace Constants { + +const uint8_t BAM_SIZEOF_INT = 4; + +// header magic number +const char* const BAM_HEADER_MAGIC = "BAM\1"; +const uint8_t BAM_HEADER_MAGIC_LENGTH = 4; + +// BAM alignment core size +const uint8_t BAM_CORE_SIZE = 32; +const uint8_t BAM_CORE_BUFFER_SIZE = 8; + +// BAM alignment flags +const int BAM_ALIGNMENT_PAIRED = 0x0001; +const int BAM_ALIGNMENT_PROPER_PAIR = 0x0002; +const int BAM_ALIGNMENT_UNMAPPED = 0x0004; +const int BAM_ALIGNMENT_MATE_UNMAPPED = 0x0008; +const int BAM_ALIGNMENT_REVERSE_STRAND = 0x0010; +const int BAM_ALIGNMENT_MATE_REVERSE_STRAND = 0x0020; +const int BAM_ALIGNMENT_READ_1 = 0x0040; +const int BAM_ALIGNMENT_READ_2 = 0x0080; +const int BAM_ALIGNMENT_SECONDARY = 0x0100; +const int BAM_ALIGNMENT_QC_FAILED = 0x0200; +const int BAM_ALIGNMENT_DUPLICATE = 0x0400; + +// CIGAR constants +const char* const BAM_CIGAR_LOOKUP = "MIDNSHP=X"; +const uint8_t BAM_CIGAR_MATCH = 0; +const uint8_t BAM_CIGAR_INS = 1; +const uint8_t BAM_CIGAR_DEL = 2; +const uint8_t BAM_CIGAR_REFSKIP = 3; +const uint8_t BAM_CIGAR_SOFTCLIP = 4; +const uint8_t BAM_CIGAR_HARDCLIP = 5; +const uint8_t BAM_CIGAR_PAD = 6; +const uint8_t BAM_CIGAR_SEQMATCH = 7; +const uint8_t BAM_CIGAR_MISMATCH = 8; + +const char BAM_CIGAR_MATCH_CHAR = 'M'; +const char BAM_CIGAR_INS_CHAR = 'I'; +const char BAM_CIGAR_DEL_CHAR = 'D'; +const char BAM_CIGAR_REFSKIP_CHAR = 'N'; +const char BAM_CIGAR_SOFTCLIP_CHAR = 'S'; +const char BAM_CIGAR_HARDCLIP_CHAR = 'H'; +const char BAM_CIGAR_PAD_CHAR = 'P'; +const char BAM_CIGAR_SEQMATCH_CHAR = '='; +const char BAM_CIGAR_MISMATCH_CHAR = 'X'; + +//RP: this has to be a define or else it will conflict with ssw.h +#define BAM_CIGAR_SHIFT 4u +//const int BAM_CIGAR_SHIFT = 4; +const int BAM_CIGAR_MASK = ((1 << BAM_CIGAR_SHIFT) - 1); + +// BAM tag types & sizes +const char BAM_TAG_TYPE_ASCII = 'A'; +const char BAM_TAG_TYPE_INT8 = 'c'; +const char BAM_TAG_TYPE_UINT8 = 'C'; +const char BAM_TAG_TYPE_INT16 = 's'; +const char BAM_TAG_TYPE_UINT16 = 'S'; +const char BAM_TAG_TYPE_INT32 = 'i'; +const char BAM_TAG_TYPE_UINT32 = 'I'; +const char BAM_TAG_TYPE_FLOAT = 'f'; +const char BAM_TAG_TYPE_STRING = 'Z'; +const char BAM_TAG_TYPE_HEX = 'H'; +const char BAM_TAG_TYPE_ARRAY = 'B'; + +const uint8_t BAM_TAG_TAGSIZE = 2; +const uint8_t BAM_TAG_TYPESIZE = 1; +const uint8_t BAM_TAG_ARRAYBASE_SIZE = 8; + +// DNA bases +const char* const BAM_DNA_LOOKUP = "=ACMGRSVTWYHKDBN"; +const uint8_t BAM_BASECODE_EQUAL = 0; +const uint8_t BAM_BASECODE_A = 1; +const uint8_t BAM_BASECODE_C = 2; +const uint8_t BAM_BASECODE_M = 3; +const uint8_t BAM_BASECODE_G = 4; +const uint8_t BAM_BASECODE_R = 5; +const uint8_t BAM_BASECODE_S = 6; +const uint8_t BAM_BASECODE_V = 7; +const uint8_t BAM_BASECODE_T = 8; +const uint8_t BAM_BASECODE_W = 9; +const uint8_t BAM_BASECODE_Y = 10; +const uint8_t BAM_BASECODE_H = 11; +const uint8_t BAM_BASECODE_K = 12; +const uint8_t BAM_BASECODE_D = 13; +const uint8_t BAM_BASECODE_B = 14; +const uint8_t BAM_BASECODE_N = 15; + +const char BAM_DNA_EQUAL = '='; +const char BAM_DNA_A = 'A'; +const char BAM_DNA_C = 'C'; +const char BAM_DNA_M = 'M'; +const char BAM_DNA_G = 'G'; +const char BAM_DNA_R = 'R'; +const char BAM_DNA_S = 'S'; +const char BAM_DNA_V = 'V'; +const char BAM_DNA_T = 'T'; +const char BAM_DNA_W = 'W'; +const char BAM_DNA_Y = 'Y'; +const char BAM_DNA_H = 'H'; +const char BAM_DNA_K = 'K'; +const char BAM_DNA_D = 'D'; +const char BAM_DNA_B = 'B'; +const char BAM_DNA_N = 'N'; +const char BAM_DNA_DEL = '-'; +const char BAM_DNA_PAD = '*'; + +// zlib & BGZF constants +const char GZIP_ID1 = 31; +const char GZIP_ID2 = 139; +const char CM_DEFLATE = 8; +const char FLG_FEXTRA = 4; +const char OS_UNKNOWN = 255; +const char BGZF_XLEN = 6; +const char BGZF_ID1 = 66; +const char BGZF_ID2 = 67; +const char BGZF_LEN = 2; + +const int8_t GZIP_WINDOW_BITS = -15; +//--START EDICO EDITED +//const int8_t Z_DEFAULT_MEM_LEVEL = 8; +const int8_t Z_DEFAULT_MEM_LEVEL = 9; +//--END EDICO EDITED +const uint8_t BGZF_BLOCK_HEADER_LENGTH = 18; +const uint8_t BGZF_BLOCK_FOOTER_LENGTH = 8; +const uint32_t BGZF_MAX_BLOCK_SIZE = 65536; +const uint32_t BGZF_DEFAULT_BLOCK_SIZE = 65536; + +} // namespace Constants + +//! \cond +// ------------------------- +// tag-type helper structs +// ------------------------- + +// fail on any types not specified below +template +struct TagTypeHelper { + static bool CanConvertFrom(const char) { assert(false); return false; } + static bool CanConvertTo(const char) { assert(false); return false; } + static char TypeCode(void) { assert(false); return 0; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_UINT8 ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_UINT8 || + c == Constants::BAM_TAG_TYPE_UINT16 || + c == Constants::BAM_TAG_TYPE_UINT32 ); + } + + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_UINT8; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_INT8 ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_INT8 || + c == Constants::BAM_TAG_TYPE_INT16 || + c == Constants::BAM_TAG_TYPE_INT32 ); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_INT8; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_UINT8 || + c == Constants::BAM_TAG_TYPE_UINT16 ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_UINT16 || + c == Constants::BAM_TAG_TYPE_UINT32); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_UINT16; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_INT8 || + c == Constants::BAM_TAG_TYPE_INT16 ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_INT16 || + c == Constants::BAM_TAG_TYPE_INT32); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_INT16; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_UINT8 || + c == Constants::BAM_TAG_TYPE_UINT16 || + c == Constants::BAM_TAG_TYPE_UINT32 ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_UINT32 ); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_UINT32; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_INT8 || + c == Constants::BAM_TAG_TYPE_INT16 || + c == Constants::BAM_TAG_TYPE_INT32 ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_INT32 ); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_INT32; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_ASCII || + c == Constants::BAM_TAG_TYPE_UINT8 || + c == Constants::BAM_TAG_TYPE_INT8 || + c == Constants::BAM_TAG_TYPE_UINT16 || + c == Constants::BAM_TAG_TYPE_INT16 || + c == Constants::BAM_TAG_TYPE_UINT32 || + c == Constants::BAM_TAG_TYPE_INT32 || + c == Constants::BAM_TAG_TYPE_FLOAT); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_FLOAT ); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_FLOAT; } +}; + +template<> +struct TagTypeHelper { + static bool CanConvertFrom(const char c) { + return ( c == Constants::BAM_TAG_TYPE_HEX || + c == Constants::BAM_TAG_TYPE_STRING ); + } + static bool CanConvertTo(const char c) { + return ( c == Constants::BAM_TAG_TYPE_HEX || + c == Constants::BAM_TAG_TYPE_STRING ); + } + static char TypeCode(void) { return Constants::BAM_TAG_TYPE_STRING; } +}; + +//! \endcond + +} // namespace BamTools + +#endif // BAM_CONSTANTS_H diff --git a/stubs/dragen/src/host/dragen_api/dbam/output_dbam_header.hpp b/stubs/dragen/src/host/dragen_api/dbam/output_dbam_header.hpp index be42eb8..39b1dac 100644 --- a/stubs/dragen/src/host/dragen_api/dbam/output_dbam_header.hpp +++ b/stubs/dragen/src/host/dragen_api/dbam/output_dbam_header.hpp @@ -13,38 +13,11 @@ #ifndef __OUTPUT_DBAM_HEADER_HPP__ #define __OUTPUT_DBAM_HEADER_HPP__ +#include "api/BamConstants.h" + #include "align/Alignment.hpp" #include "align/Cigar.hpp" -namespace BamTools { -namespace Constants { - -const uint8_t BAM_SIZEOF_INT = 4; - -// header magic number -const char *const BAM_HEADER_MAGIC = "BAM\1"; -const uint8_t BAM_HEADER_MAGIC_LENGTH = 4; - -// BAM alignment core size -const uint8_t BAM_CORE_SIZE = 32; -const uint8_t BAM_CORE_BUFFER_SIZE = 8; - -// BAM alignment flags -const int BAM_ALIGNMENT_PAIRED = 0x0001; -const int BAM_ALIGNMENT_PROPER_PAIR = 0x0002; -const int BAM_ALIGNMENT_UNMAPPED = 0x0004; -const int BAM_ALIGNMENT_MATE_UNMAPPED = 0x0008; -const int BAM_ALIGNMENT_REVERSE_STRAND = 0x0010; -const int BAM_ALIGNMENT_MATE_REVERSE_STRAND = 0x0020; -const int BAM_ALIGNMENT_READ_1 = 0x0040; -const int BAM_ALIGNMENT_READ_2 = 0x0080; -const int BAM_ALIGNMENT_SECONDARY = 0x0100; -const int BAM_ALIGNMENT_QC_FAILED = 0x0200; -const int BAM_ALIGNMENT_DUPLICATE = 0x0400; - -} // namespace Constants -} // namespace BamTools - class DbamHeader { const dragenos::align::SerializedAlignment &alignment_; uint8_t peStatsInterval_ = 0; diff --git a/stubs/dragen/src/host/infra/public/time_to_str.hpp b/stubs/dragen/src/host/infra/public/time_to_str.hpp new file mode 100644 index 0000000..c482c21 --- /dev/null +++ b/stubs/dragen/src/host/infra/public/time_to_str.hpp @@ -0,0 +1 @@ +#include "elapsed_timer.hpp" diff --git a/stubs/dragen/src/host/metrics/public/run_stats.hpp b/stubs/dragen/src/host/metrics/public/run_stats.hpp index 13561fd..998fe4e 100644 --- a/stubs/dragen/src/host/metrics/public/run_stats.hpp +++ b/stubs/dragen/src/host/metrics/public/run_stats.hpp @@ -9,6 +9,7 @@ #include #include +#include // // RP: HA! HA! HA! That's what you get when you write code logging to cout all // over the place! @@ -35,6 +36,7 @@ class RunStats { }; void addInsertSizeRG(RGinsertSizeStats &other) {} + void addInsertSizeHistogram(const std::vector &){} static RunStats *Instance(); static RunStats *m_instance; diff --git a/tests/HashtableGtest.cpp b/tests/HashtableGtest.cpp index dc51b49..3d68c20 100644 --- a/tests/HashtableGtest.cpp +++ b/tests/HashtableGtest.cpp @@ -132,22 +132,22 @@ TEST_F(HashtableFixture, getBits) using namespace dragenos::common::bits; const uint64_t v = 0xFEDCBA9876543210; ASSERT_EQ(v, (getBits<0, 64>(v))); - ASSERT_EQ(0, (getBits<0, 4>(v))); - ASSERT_EQ(1, (getBits<4, 4>(v))); - ASSERT_EQ(2, (getBits<8, 4>(v))); - ASSERT_EQ(3, (getBits<12, 4>(v))); - ASSERT_EQ(4, (getBits<16, 4>(v))); - ASSERT_EQ(5, (getBits<20, 4>(v))); - ASSERT_EQ(6, (getBits<24, 4>(v))); - ASSERT_EQ(7, (getBits<28, 4>(v))); - ASSERT_EQ(8, (getBits<32, 4>(v))); - ASSERT_EQ(9, (getBits<36, 4>(v))); - ASSERT_EQ(10, (getBits<40, 4>(v))); - ASSERT_EQ(11, (getBits<44, 4>(v))); - ASSERT_EQ(12, (getBits<48, 4>(v))); - ASSERT_EQ(13, (getBits<52, 4>(v))); - ASSERT_EQ(14, (getBits<56, 4>(v))); - ASSERT_EQ(15, (getBits<60, 4>(v))); + ASSERT_EQ(0u, (getBits<0, 4>(v))); + ASSERT_EQ(1u, (getBits<4, 4>(v))); + ASSERT_EQ(2u, (getBits<8, 4>(v))); + ASSERT_EQ(3u, (getBits<12, 4>(v))); + ASSERT_EQ(4u, (getBits<16, 4>(v))); + ASSERT_EQ(5u, (getBits<20, 4>(v))); + ASSERT_EQ(6u, (getBits<24, 4>(v))); + ASSERT_EQ(7u, (getBits<28, 4>(v))); + ASSERT_EQ(8u, (getBits<32, 4>(v))); + ASSERT_EQ(9u, (getBits<36, 4>(v))); + ASSERT_EQ(10u, (getBits<40, 4>(v))); + ASSERT_EQ(11u, (getBits<44, 4>(v))); + ASSERT_EQ(12u, (getBits<48, 4>(v))); + ASSERT_EQ(13u, (getBits<52, 4>(v))); + ASSERT_EQ(14u, (getBits<56, 4>(v))); + ASSERT_EQ(15u, (getBits<60, 4>(v))); } TEST_F(HashtableFixture, DISABLED_ExploreHhashtablev8) @@ -474,7 +474,7 @@ std::cerr << "\n---------------------------" << std::endl; ASSERT_TRUE(secCrcPolynomial == "1524CA66E8D39"); // the value from hash_table.cfg CrcHasher priCrcHasher(priCrcPolynomial); CrcHasher secCrcHasher(secCrcPolynomial); - ASSERT_EQ(21, hashtableConfig->getPrimarySeedBases()); + ASSERT_EQ(21u, hashtableConfig->getPrimarySeedBases()); } std::ostream &printBases(std::ostream &os, const dragenos::sequences::Read &read) @@ -520,8 +520,8 @@ std::vector encode4bpbTo2bpb(const std::vector sequence) TEST_F(HashtableFixture, CheckReferenceBasesHashtableV8) { //Chr1 starts at position 163840 - 9984 first bases (Ns) are trimmed. - ASSERT_EQ(163840, hashtableConfig->getSequences()[0].seqStart); - ASSERT_EQ(9984, hashtableConfig->getSequences()[0].begTrim); + ASSERT_EQ(163840u, hashtableConfig->getSequences()[0].seqStart); + ASSERT_EQ(9984u, hashtableConfig->getSequences()[0].begTrim); // Beginning of the untrimmed sequence from FASTA: // NNNNNNNNNNNNNNNNTAACCCTAAC // CCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTAACCCTA @@ -553,7 +553,7 @@ TEST_F(HashtableFixture, CheckReferenceBasesHashtableV8) ASSERT_EQ(0x35, encoded2bpb[5]); // 22, 18: CCTA: 00110101 ASSERT_EQ(0x54, encoded2bpb[6]); // 21, 22: ACCC: 01010100 - ASSERT_EQ(128, sequence.size()); + ASSERT_EQ(128u, sequence.size()); ASSERT_EQ(0x00014000 * 2, 163840); for (size_t i = 0; 0x14000 > i; ++i) { @@ -584,26 +584,26 @@ TEST_F(HashtableFixture, CheckReferenceBasesHashtableV8) // Generate the seeds from a few bases before to a few bases after and hash them // start at offset ((175/4) * 4)==172 and do 32 primary seeds const unsigned seedLength = hashtableConfig->getPrimarySeedBases(); - ASSERT_EQ(21, seedLength); + ASSERT_EQ(21u, seedLength); const uint64_t seedMask = (((uint64_t)1) << (seedLength * 2)) - 1; // check that the mask has 2 * seedLength LSB set for (unsigned i = 0; 2 * seedLength > i; ++i) { - ASSERT_EQ(1, (seedMask >> i) & 1) << "i: " << i; + ASSERT_EQ(1u, (seedMask >> i) & 1) << "i: " << i; } // check that the mask bits after that al 0 - ASSERT_EQ(0, seedMask >> (2 * seedLength)); + ASSERT_EQ(0u, seedMask >> (2 * seedLength)); const unsigned newBaseShift = 2 * seedLength - 2; using dragenos::sequences::CrcPolynomial; CrcPolynomial priCrcPolynomial(hashtableConfig->getPrimaryCrcBits(), hashtableConfig->getPriCrcPoly()); ASSERT_TRUE(priCrcPolynomial == "2C991CE6A8DD55"); // the value from hash_table.cfg - ASSERT_EQ(54, hashtableConfig->getPrimaryCrcBits()); + ASSERT_EQ(54u, hashtableConfig->getPrimaryCrcBits()); // void* crcHash64Init(int bits, void const* poly); const uint64_t poly = 0x2C991CE6A8DD55; uint64_t *init = reinterpret_cast(crcHash64Init(54, &poly)); - ASSERT_EQ(encoded2bpb.size(), 64); + ASSERT_EQ(encoded2bpb.size(), 64u); const size_t begin = 175 / 4; - ASSERT_GT(64, begin + 8 + 5); // enough space to get 32 deeds of 21 bases + ASSERT_GT(64u, begin + 8 + 5); // enough space to get 32 deeds of 21 bases uint64_t seedValue = (*reinterpret_cast(encoded2bpb.data() + begin)) & seedMask; const uint8_t *bytePtr = encoded2bpb.data() + begin + 5; // pointer to the byte that contains the next bases uint8_t byte = (*bytePtr) >> 2; @@ -667,7 +667,7 @@ TEST_F(HashtableFixture, DISABLED_CheckReferenceBasesHashtableV7) const std::vector sequence {1,4, 2,8, 2,1, 4,1, 8,4, 8,2, 8,1, 1,2, 2,2, 8,2, 8,1, 1,8, 2,1, 1,2, 8,2, 1,2, 4,2, 4,4, 4,1, 8,2, 8,2, 2,2, 8,1, 2,4, 8,1, 8,8, 4,4, 1,8, 8,8, 8,8, 4,2, 2,8 }; - ASSERT_EQ(64, sequence.size()); + ASSERT_EQ(64u, sequence.size()); for(auto s: sequence) { ASSERT_EQ(s, referenceSequence.getBase(position)); @@ -888,7 +888,7 @@ TEST_F(HashtableFixture, DISABLED_Config) getline(is, line); // 2nd line is command line getline(is, line); ASSERT_EQ(std::string("# Hash table version 7"), line); - ASSERT_LE(7, hashtableConfig->getHashtableVersion()); + ASSERT_LE(7u, hashtableConfig->getHashtableVersion()); getline(is, line); // 4th line is "#" getline(is, line); // 5th line is "# Do not modify. getline(is, line); // 6th line is empty @@ -899,8 +899,8 @@ TEST_F(HashtableFixture, DISABLED_Config) } const std::map keyValuesMap(keyValues.begin(), keyValues.end()); ASSERT_EQ(keyValuesMap.size(), keyValues.size()); // check that all keys are unique - ASSERT_EQ(stol(keyValuesMap.at("reference_len_raw")), hashtableConfig->getReferenceLength()); - ASSERT_EQ(stoi(keyValuesMap.at("reference_sequences")), hashtableConfig->getNumberOfSequences()); + ASSERT_EQ((unsigned long)stol(keyValuesMap.at("reference_len_raw")), hashtableConfig->getReferenceLength()); + ASSERT_EQ((unsigned)stoi(keyValuesMap.at("reference_sequences")), hashtableConfig->getNumberOfSequences()); ASSERT_LT(5 * hashtableConfig->getNumberOfSequences(), keyValues.size()); // at least 5 entries per sequence for(unsigned i = 0; hashtableConfig->getNumberOfSequences() > i; ++i) { diff --git a/thirdparty/dragen/src/common/hash_generation/hash_cfg_file.c b/thirdparty/dragen/src/common/hash_generation/hash_cfg_file.c index fed9ea7..063ab3c 100644 --- a/thirdparty/dragen/src/common/hash_generation/hash_cfg_file.c +++ b/thirdparty/dragen/src/common/hash_generation/hash_cfg_file.c @@ -490,7 +490,7 @@ void regenHashTableError(const char* binFile, const char* liftoverFile) sprintf(errorMsg + strlen(errorMsg), "--ht-alt-liftover %s ", liftoverFile); } if (restOfArgs) { - sprintf(errorMsg + strlen(errorMsg), restOfArgs); + strncat(errorMsg + strlen(errorMsg), restOfArgs, 2048 - strlen(errorMsg) - 1); } else { sprintf(errorMsg + strlen(errorMsg), "\n"); } @@ -539,7 +539,12 @@ int readHashCfgBin(const char* filename, hashTableConfig_t* config) } config->readBuf = (uint8_t*)malloc(fileSize); - fread(config->readBuf, fileSize, 1, fp); + if (fread(config->readBuf, fileSize, 1, fp) != fileSize) + { + sprintf(errorMsg, "failed to read %lu bytes from %s: %s\n", fileSize, filename, (feof(fp) ? "EOF" : strerror(errno))); + fclose(fp); + return 0; + } config->hdr = (hashTableHeader_t*)config->readBuf; // size_t bufOffset = sizeof(hashTableHeader_t); diff --git a/src/lib/common/Crc32Hw.cpp b/thirdparty/dragen/src/host/infra/crypto/crc32_hw.c similarity index 93% rename from src/lib/common/Crc32Hw.cpp rename to thirdparty/dragen/src/host/infra/crypto/crc32_hw.c index e1e7bc8..0feeb27 100644 --- a/src/lib/common/Crc32Hw.cpp +++ b/thirdparty/dragen/src/host/infra/crypto/crc32_hw.c @@ -32,30 +32,17 @@ 1.0 10 Feb 2013 First version 1.1 1 Aug 2013 Correct comments on why three crc instructions in parallel */ -#include "common/Crc32Hw.hpp" #include -//#include +#include #include #include #include -/* ============ end of #include directives ============ */ -//#include "edico_memdebug.h" - -namespace dragenos { -namespace common { - /* CRC-32C (iSCSI) polynomial in reversed bit order. */ #define POLY 0x82f63b78 -#if defined(__x86_64) -#define _TARGET_X86_ 1 -#endif - -// this should probably test for the __SSE2__ macro instead #if !defined(_TARGET_X86_) -#error "Only x85_64 architecture supported" #include "fast_nonvector_crc32c.h" #endif @@ -94,7 +81,7 @@ static void crc32c_init_sw(void) /* Table-driven software version as a fall-back. This is about 15 times slower than using the hardware instructions. This assumes little-endian integers, as is the case on Intel processors that the assembler code here is for. */ -static uint32_t crc32c_sw(uint32_t crci, const void* buf, std::size_t len) +static uint32_t crc32c_sw(uint32_t crci, const void* buf, size_t len) { const unsigned char* next = (const unsigned char*)buf; uint64_t crc; @@ -158,7 +145,7 @@ static inline void gf2_matrix_square(uint32_t* square, uint32_t* mat) largest power of two less than len. The result for len == 0 is the same as for len == 1. A version of this routine could be easily written for any len, but that is not needed for this application. */ -static void crc32c_zeros_op(uint32_t* even, std::size_t len) +static void crc32c_zeros_op(uint32_t* even, size_t len) { int n; uint32_t row; @@ -195,7 +182,7 @@ static void crc32c_zeros_op(uint32_t* even, std::size_t len) /* Take a length and build four lookup tables for applying the zeros operator for that length, byte-by-byte on the operand. */ -static void crc32c_zeros(uint32_t zeros[][256], std::size_t len) +static void crc32c_zeros(uint32_t zeros[][256], size_t len) { uint32_t n; uint32_t op[32]; @@ -239,7 +226,7 @@ static void crc32c_init_hw(void) } /* Compute CRC-32C using the Intel hardware instruction. */ -static uint32_t crc32c_hw_impl(uint32_t crc, const void* buf, std::size_t len) +static uint32_t crc32c_hw_impl(uint32_t crc, const void* buf, size_t len) { const unsigned char* next = (const unsigned char*)buf; const unsigned char* end; @@ -367,7 +354,7 @@ static void init_sse42(void) } /* Read the state of sse42 from hw only once * Return a variable on subsequent calls */ -bool machine_has_sse42() +int machine_has_sse42() { pthread_once(&sse42_rd_hw_once, init_sse42); return has_sse42; @@ -375,7 +362,7 @@ bool machine_has_sse42() #if !defined(_TARGET_X86_) /* Compute CRC32C using optimized SW implementation */ -static uint32_t crc32c_sw_impl(uint32_t crc, const void* buf, std::size_t len) +static uint32_t crc32c_sw_impl(uint32_t crc, const void* buf, size_t len) { uint64_t crc0; const unsigned char* next = (const unsigned char*)buf; @@ -412,7 +399,7 @@ static uint32_t crc32c_sw_impl(uint32_t crc, const void* buf, std::size_t len) /* Compute a CRC-32C. If the crc32 instruction is available, use the hardware version. Otherwise, use the software version. */ -uint32_t crc32c_hw(uint32_t crc, const void* buf, std::size_t len) +uint32_t crc32c_hw(uint32_t crc, const void* buf, size_t len) { #if defined(_TARGET_X86_) return crc32c_hw_impl(crc, buf, len); @@ -421,9 +408,6 @@ uint32_t crc32c_hw(uint32_t crc, const void* buf, std::size_t len) #endif } -} // namespace common -} // namespace dragenos - #if 0 #define SIZE (262144 * 3) diff --git a/thirdparty/dragen/src/host/infra/crypto/fast_nonvector_crc32c.c b/thirdparty/dragen/src/host/infra/crypto/fast_nonvector_crc32c.c new file mode 100644 index 0000000..dee92d3 --- /dev/null +++ b/thirdparty/dragen/src/host/infra/crypto/fast_nonvector_crc32c.c @@ -0,0 +1,1815 @@ +// Copyright 2014-2016 Edico Genome Corporation. All rights reserved. +// +// This file contains confidential and proprietary information of the Edico Genome +// Corporation and is protected under the U.S. and international copyright and other +// intellectual property laws. +// +// $Id$ +// $Author$ +// $Change$ +// $DateTime$ +// +#include + +#define ENABLE_1B 1 +#define ENABLE_2B 1 +#define ENABLE_4B 1 +#define ENABLE_8B 1 +#define ENABLE_16B 1 + +#if ENABLE_1B +static const uint32_t crc32cTable1[256 * (4 + 1)] = { + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, + 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, + 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, + 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, + 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F, + 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, + 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F, + 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, + 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D, 0x0000003E, 0x0000003F, + 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, + 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F, + 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, + 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F, + 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, + 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F, + 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, + 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, 0x0000007D, 0x0000007E, 0x0000007F, + 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087, + 0x00000088, 0x00000089, 0x0000008A, 0x0000008B, 0x0000008C, 0x0000008D, 0x0000008E, 0x0000008F, + 0x00000090, 0x00000091, 0x00000092, 0x00000093, 0x00000094, 0x00000095, 0x00000096, 0x00000097, + 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, 0x0000009D, 0x0000009E, 0x0000009F, + 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, 0x000000A5, 0x000000A6, 0x000000A7, + 0x000000A8, 0x000000A9, 0x000000AA, 0x000000AB, 0x000000AC, 0x000000AD, 0x000000AE, 0x000000AF, + 0x000000B0, 0x000000B1, 0x000000B2, 0x000000B3, 0x000000B4, 0x000000B5, 0x000000B6, 0x000000B7, + 0x000000B8, 0x000000B9, 0x000000BA, 0x000000BB, 0x000000BC, 0x000000BD, 0x000000BE, 0x000000BF, + 0x000000C0, 0x000000C1, 0x000000C2, 0x000000C3, 0x000000C4, 0x000000C5, 0x000000C6, 0x000000C7, + 0x000000C8, 0x000000C9, 0x000000CA, 0x000000CB, 0x000000CC, 0x000000CD, 0x000000CE, 0x000000CF, + 0x000000D0, 0x000000D1, 0x000000D2, 0x000000D3, 0x000000D4, 0x000000D5, 0x000000D6, 0x000000D7, + 0x000000D8, 0x000000D9, 0x000000DA, 0x000000DB, 0x000000DC, 0x000000DD, 0x000000DE, 0x000000DF, + 0x000000E0, 0x000000E1, 0x000000E2, 0x000000E3, 0x000000E4, 0x000000E5, 0x000000E6, 0x000000E7, + 0x000000E8, 0x000000E9, 0x000000EA, 0x000000EB, 0x000000EC, 0x000000ED, 0x000000EE, 0x000000EF, + 0x000000F0, 0x000000F1, 0x000000F2, 0x000000F3, 0x000000F4, 0x000000F5, 0x000000F6, 0x000000F7, + 0x000000F8, 0x000000F9, 0x000000FA, 0x000000FB, 0x000000FC, 0x000000FD, 0x000000FE, 0x000000FF, + 0x00000000, 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, + 0x00000800, 0x00000900, 0x00000A00, 0x00000B00, 0x00000C00, 0x00000D00, 0x00000E00, 0x00000F00, + 0x00001000, 0x00001100, 0x00001200, 0x00001300, 0x00001400, 0x00001500, 0x00001600, 0x00001700, + 0x00001800, 0x00001900, 0x00001A00, 0x00001B00, 0x00001C00, 0x00001D00, 0x00001E00, 0x00001F00, + 0x00002000, 0x00002100, 0x00002200, 0x00002300, 0x00002400, 0x00002500, 0x00002600, 0x00002700, + 0x00002800, 0x00002900, 0x00002A00, 0x00002B00, 0x00002C00, 0x00002D00, 0x00002E00, 0x00002F00, + 0x00003000, 0x00003100, 0x00003200, 0x00003300, 0x00003400, 0x00003500, 0x00003600, 0x00003700, + 0x00003800, 0x00003900, 0x00003A00, 0x00003B00, 0x00003C00, 0x00003D00, 0x00003E00, 0x00003F00, + 0x00004000, 0x00004100, 0x00004200, 0x00004300, 0x00004400, 0x00004500, 0x00004600, 0x00004700, + 0x00004800, 0x00004900, 0x00004A00, 0x00004B00, 0x00004C00, 0x00004D00, 0x00004E00, 0x00004F00, + 0x00005000, 0x00005100, 0x00005200, 0x00005300, 0x00005400, 0x00005500, 0x00005600, 0x00005700, + 0x00005800, 0x00005900, 0x00005A00, 0x00005B00, 0x00005C00, 0x00005D00, 0x00005E00, 0x00005F00, + 0x00006000, 0x00006100, 0x00006200, 0x00006300, 0x00006400, 0x00006500, 0x00006600, 0x00006700, + 0x00006800, 0x00006900, 0x00006A00, 0x00006B00, 0x00006C00, 0x00006D00, 0x00006E00, 0x00006F00, + 0x00007000, 0x00007100, 0x00007200, 0x00007300, 0x00007400, 0x00007500, 0x00007600, 0x00007700, + 0x00007800, 0x00007900, 0x00007A00, 0x00007B00, 0x00007C00, 0x00007D00, 0x00007E00, 0x00007F00, + 0x00008000, 0x00008100, 0x00008200, 0x00008300, 0x00008400, 0x00008500, 0x00008600, 0x00008700, + 0x00008800, 0x00008900, 0x00008A00, 0x00008B00, 0x00008C00, 0x00008D00, 0x00008E00, 0x00008F00, + 0x00009000, 0x00009100, 0x00009200, 0x00009300, 0x00009400, 0x00009500, 0x00009600, 0x00009700, + 0x00009800, 0x00009900, 0x00009A00, 0x00009B00, 0x00009C00, 0x00009D00, 0x00009E00, 0x00009F00, + 0x0000A000, 0x0000A100, 0x0000A200, 0x0000A300, 0x0000A400, 0x0000A500, 0x0000A600, 0x0000A700, + 0x0000A800, 0x0000A900, 0x0000AA00, 0x0000AB00, 0x0000AC00, 0x0000AD00, 0x0000AE00, 0x0000AF00, + 0x0000B000, 0x0000B100, 0x0000B200, 0x0000B300, 0x0000B400, 0x0000B500, 0x0000B600, 0x0000B700, + 0x0000B800, 0x0000B900, 0x0000BA00, 0x0000BB00, 0x0000BC00, 0x0000BD00, 0x0000BE00, 0x0000BF00, + 0x0000C000, 0x0000C100, 0x0000C200, 0x0000C300, 0x0000C400, 0x0000C500, 0x0000C600, 0x0000C700, + 0x0000C800, 0x0000C900, 0x0000CA00, 0x0000CB00, 0x0000CC00, 0x0000CD00, 0x0000CE00, 0x0000CF00, + 0x0000D000, 0x0000D100, 0x0000D200, 0x0000D300, 0x0000D400, 0x0000D500, 0x0000D600, 0x0000D700, + 0x0000D800, 0x0000D900, 0x0000DA00, 0x0000DB00, 0x0000DC00, 0x0000DD00, 0x0000DE00, 0x0000DF00, + 0x0000E000, 0x0000E100, 0x0000E200, 0x0000E300, 0x0000E400, 0x0000E500, 0x0000E600, 0x0000E700, + 0x0000E800, 0x0000E900, 0x0000EA00, 0x0000EB00, 0x0000EC00, 0x0000ED00, 0x0000EE00, 0x0000EF00, + 0x0000F000, 0x0000F100, 0x0000F200, 0x0000F300, 0x0000F400, 0x0000F500, 0x0000F600, 0x0000F700, + 0x0000F800, 0x0000F900, 0x0000FA00, 0x0000FB00, 0x0000FC00, 0x0000FD00, 0x0000FE00, 0x0000FF00, + 0x00000000, 0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000, 0x00070000, + 0x00080000, 0x00090000, 0x000A0000, 0x000B0000, 0x000C0000, 0x000D0000, 0x000E0000, 0x000F0000, + 0x00100000, 0x00110000, 0x00120000, 0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, + 0x00180000, 0x00190000, 0x001A0000, 0x001B0000, 0x001C0000, 0x001D0000, 0x001E0000, 0x001F0000, + 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000, 0x00250000, 0x00260000, 0x00270000, + 0x00280000, 0x00290000, 0x002A0000, 0x002B0000, 0x002C0000, 0x002D0000, 0x002E0000, 0x002F0000, + 0x00300000, 0x00310000, 0x00320000, 0x00330000, 0x00340000, 0x00350000, 0x00360000, 0x00370000, + 0x00380000, 0x00390000, 0x003A0000, 0x003B0000, 0x003C0000, 0x003D0000, 0x003E0000, 0x003F0000, + 0x00400000, 0x00410000, 0x00420000, 0x00430000, 0x00440000, 0x00450000, 0x00460000, 0x00470000, + 0x00480000, 0x00490000, 0x004A0000, 0x004B0000, 0x004C0000, 0x004D0000, 0x004E0000, 0x004F0000, + 0x00500000, 0x00510000, 0x00520000, 0x00530000, 0x00540000, 0x00550000, 0x00560000, 0x00570000, + 0x00580000, 0x00590000, 0x005A0000, 0x005B0000, 0x005C0000, 0x005D0000, 0x005E0000, 0x005F0000, + 0x00600000, 0x00610000, 0x00620000, 0x00630000, 0x00640000, 0x00650000, 0x00660000, 0x00670000, + 0x00680000, 0x00690000, 0x006A0000, 0x006B0000, 0x006C0000, 0x006D0000, 0x006E0000, 0x006F0000, + 0x00700000, 0x00710000, 0x00720000, 0x00730000, 0x00740000, 0x00750000, 0x00760000, 0x00770000, + 0x00780000, 0x00790000, 0x007A0000, 0x007B0000, 0x007C0000, 0x007D0000, 0x007E0000, 0x007F0000, + 0x00800000, 0x00810000, 0x00820000, 0x00830000, 0x00840000, 0x00850000, 0x00860000, 0x00870000, + 0x00880000, 0x00890000, 0x008A0000, 0x008B0000, 0x008C0000, 0x008D0000, 0x008E0000, 0x008F0000, + 0x00900000, 0x00910000, 0x00920000, 0x00930000, 0x00940000, 0x00950000, 0x00960000, 0x00970000, + 0x00980000, 0x00990000, 0x009A0000, 0x009B0000, 0x009C0000, 0x009D0000, 0x009E0000, 0x009F0000, + 0x00A00000, 0x00A10000, 0x00A20000, 0x00A30000, 0x00A40000, 0x00A50000, 0x00A60000, 0x00A70000, + 0x00A80000, 0x00A90000, 0x00AA0000, 0x00AB0000, 0x00AC0000, 0x00AD0000, 0x00AE0000, 0x00AF0000, + 0x00B00000, 0x00B10000, 0x00B20000, 0x00B30000, 0x00B40000, 0x00B50000, 0x00B60000, 0x00B70000, + 0x00B80000, 0x00B90000, 0x00BA0000, 0x00BB0000, 0x00BC0000, 0x00BD0000, 0x00BE0000, 0x00BF0000, + 0x00C00000, 0x00C10000, 0x00C20000, 0x00C30000, 0x00C40000, 0x00C50000, 0x00C60000, 0x00C70000, + 0x00C80000, 0x00C90000, 0x00CA0000, 0x00CB0000, 0x00CC0000, 0x00CD0000, 0x00CE0000, 0x00CF0000, + 0x00D00000, 0x00D10000, 0x00D20000, 0x00D30000, 0x00D40000, 0x00D50000, 0x00D60000, 0x00D70000, + 0x00D80000, 0x00D90000, 0x00DA0000, 0x00DB0000, 0x00DC0000, 0x00DD0000, 0x00DE0000, 0x00DF0000, + 0x00E00000, 0x00E10000, 0x00E20000, 0x00E30000, 0x00E40000, 0x00E50000, 0x00E60000, 0x00E70000, + 0x00E80000, 0x00E90000, 0x00EA0000, 0x00EB0000, 0x00EC0000, 0x00ED0000, 0x00EE0000, 0x00EF0000, + 0x00F00000, 0x00F10000, 0x00F20000, 0x00F30000, 0x00F40000, 0x00F50000, 0x00F60000, 0x00F70000, + 0x00F80000, 0x00F90000, 0x00FA0000, 0x00FB0000, 0x00FC0000, 0x00FD0000, 0x00FE0000, 0x00FF0000, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}; +#endif // ENABLE_1B + +#if ENABLE_2B +static const uint32_t crc32cTable2[256 * (4 + 2)] = { + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, + 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, + 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F, + 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, + 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F, + 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, + 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F, + 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, + 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D, 0x0000003E, 0x0000003F, + 0x00000040, 0x00000041, 0x00000042, 0x00000043, 0x00000044, 0x00000045, 0x00000046, 0x00000047, + 0x00000048, 0x00000049, 0x0000004A, 0x0000004B, 0x0000004C, 0x0000004D, 0x0000004E, 0x0000004F, + 0x00000050, 0x00000051, 0x00000052, 0x00000053, 0x00000054, 0x00000055, 0x00000056, 0x00000057, + 0x00000058, 0x00000059, 0x0000005A, 0x0000005B, 0x0000005C, 0x0000005D, 0x0000005E, 0x0000005F, + 0x00000060, 0x00000061, 0x00000062, 0x00000063, 0x00000064, 0x00000065, 0x00000066, 0x00000067, + 0x00000068, 0x00000069, 0x0000006A, 0x0000006B, 0x0000006C, 0x0000006D, 0x0000006E, 0x0000006F, + 0x00000070, 0x00000071, 0x00000072, 0x00000073, 0x00000074, 0x00000075, 0x00000076, 0x00000077, + 0x00000078, 0x00000079, 0x0000007A, 0x0000007B, 0x0000007C, 0x0000007D, 0x0000007E, 0x0000007F, + 0x00000080, 0x00000081, 0x00000082, 0x00000083, 0x00000084, 0x00000085, 0x00000086, 0x00000087, + 0x00000088, 0x00000089, 0x0000008A, 0x0000008B, 0x0000008C, 0x0000008D, 0x0000008E, 0x0000008F, + 0x00000090, 0x00000091, 0x00000092, 0x00000093, 0x00000094, 0x00000095, 0x00000096, 0x00000097, + 0x00000098, 0x00000099, 0x0000009A, 0x0000009B, 0x0000009C, 0x0000009D, 0x0000009E, 0x0000009F, + 0x000000A0, 0x000000A1, 0x000000A2, 0x000000A3, 0x000000A4, 0x000000A5, 0x000000A6, 0x000000A7, + 0x000000A8, 0x000000A9, 0x000000AA, 0x000000AB, 0x000000AC, 0x000000AD, 0x000000AE, 0x000000AF, + 0x000000B0, 0x000000B1, 0x000000B2, 0x000000B3, 0x000000B4, 0x000000B5, 0x000000B6, 0x000000B7, + 0x000000B8, 0x000000B9, 0x000000BA, 0x000000BB, 0x000000BC, 0x000000BD, 0x000000BE, 0x000000BF, + 0x000000C0, 0x000000C1, 0x000000C2, 0x000000C3, 0x000000C4, 0x000000C5, 0x000000C6, 0x000000C7, + 0x000000C8, 0x000000C9, 0x000000CA, 0x000000CB, 0x000000CC, 0x000000CD, 0x000000CE, 0x000000CF, + 0x000000D0, 0x000000D1, 0x000000D2, 0x000000D3, 0x000000D4, 0x000000D5, 0x000000D6, 0x000000D7, + 0x000000D8, 0x000000D9, 0x000000DA, 0x000000DB, 0x000000DC, 0x000000DD, 0x000000DE, 0x000000DF, + 0x000000E0, 0x000000E1, 0x000000E2, 0x000000E3, 0x000000E4, 0x000000E5, 0x000000E6, 0x000000E7, + 0x000000E8, 0x000000E9, 0x000000EA, 0x000000EB, 0x000000EC, 0x000000ED, 0x000000EE, 0x000000EF, + 0x000000F0, 0x000000F1, 0x000000F2, 0x000000F3, 0x000000F4, 0x000000F5, 0x000000F6, 0x000000F7, + 0x000000F8, 0x000000F9, 0x000000FA, 0x000000FB, 0x000000FC, 0x000000FD, 0x000000FE, 0x000000FF, + 0x00000000, 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, + 0x00000800, 0x00000900, 0x00000A00, 0x00000B00, 0x00000C00, 0x00000D00, 0x00000E00, 0x00000F00, + 0x00001000, 0x00001100, 0x00001200, 0x00001300, 0x00001400, 0x00001500, 0x00001600, 0x00001700, + 0x00001800, 0x00001900, 0x00001A00, 0x00001B00, 0x00001C00, 0x00001D00, 0x00001E00, 0x00001F00, + 0x00002000, 0x00002100, 0x00002200, 0x00002300, 0x00002400, 0x00002500, 0x00002600, 0x00002700, + 0x00002800, 0x00002900, 0x00002A00, 0x00002B00, 0x00002C00, 0x00002D00, 0x00002E00, 0x00002F00, + 0x00003000, 0x00003100, 0x00003200, 0x00003300, 0x00003400, 0x00003500, 0x00003600, 0x00003700, + 0x00003800, 0x00003900, 0x00003A00, 0x00003B00, 0x00003C00, 0x00003D00, 0x00003E00, 0x00003F00, + 0x00004000, 0x00004100, 0x00004200, 0x00004300, 0x00004400, 0x00004500, 0x00004600, 0x00004700, + 0x00004800, 0x00004900, 0x00004A00, 0x00004B00, 0x00004C00, 0x00004D00, 0x00004E00, 0x00004F00, + 0x00005000, 0x00005100, 0x00005200, 0x00005300, 0x00005400, 0x00005500, 0x00005600, 0x00005700, + 0x00005800, 0x00005900, 0x00005A00, 0x00005B00, 0x00005C00, 0x00005D00, 0x00005E00, 0x00005F00, + 0x00006000, 0x00006100, 0x00006200, 0x00006300, 0x00006400, 0x00006500, 0x00006600, 0x00006700, + 0x00006800, 0x00006900, 0x00006A00, 0x00006B00, 0x00006C00, 0x00006D00, 0x00006E00, 0x00006F00, + 0x00007000, 0x00007100, 0x00007200, 0x00007300, 0x00007400, 0x00007500, 0x00007600, 0x00007700, + 0x00007800, 0x00007900, 0x00007A00, 0x00007B00, 0x00007C00, 0x00007D00, 0x00007E00, 0x00007F00, + 0x00008000, 0x00008100, 0x00008200, 0x00008300, 0x00008400, 0x00008500, 0x00008600, 0x00008700, + 0x00008800, 0x00008900, 0x00008A00, 0x00008B00, 0x00008C00, 0x00008D00, 0x00008E00, 0x00008F00, + 0x00009000, 0x00009100, 0x00009200, 0x00009300, 0x00009400, 0x00009500, 0x00009600, 0x00009700, + 0x00009800, 0x00009900, 0x00009A00, 0x00009B00, 0x00009C00, 0x00009D00, 0x00009E00, 0x00009F00, + 0x0000A000, 0x0000A100, 0x0000A200, 0x0000A300, 0x0000A400, 0x0000A500, 0x0000A600, 0x0000A700, + 0x0000A800, 0x0000A900, 0x0000AA00, 0x0000AB00, 0x0000AC00, 0x0000AD00, 0x0000AE00, 0x0000AF00, + 0x0000B000, 0x0000B100, 0x0000B200, 0x0000B300, 0x0000B400, 0x0000B500, 0x0000B600, 0x0000B700, + 0x0000B800, 0x0000B900, 0x0000BA00, 0x0000BB00, 0x0000BC00, 0x0000BD00, 0x0000BE00, 0x0000BF00, + 0x0000C000, 0x0000C100, 0x0000C200, 0x0000C300, 0x0000C400, 0x0000C500, 0x0000C600, 0x0000C700, + 0x0000C800, 0x0000C900, 0x0000CA00, 0x0000CB00, 0x0000CC00, 0x0000CD00, 0x0000CE00, 0x0000CF00, + 0x0000D000, 0x0000D100, 0x0000D200, 0x0000D300, 0x0000D400, 0x0000D500, 0x0000D600, 0x0000D700, + 0x0000D800, 0x0000D900, 0x0000DA00, 0x0000DB00, 0x0000DC00, 0x0000DD00, 0x0000DE00, 0x0000DF00, + 0x0000E000, 0x0000E100, 0x0000E200, 0x0000E300, 0x0000E400, 0x0000E500, 0x0000E600, 0x0000E700, + 0x0000E800, 0x0000E900, 0x0000EA00, 0x0000EB00, 0x0000EC00, 0x0000ED00, 0x0000EE00, 0x0000EF00, + 0x0000F000, 0x0000F100, 0x0000F200, 0x0000F300, 0x0000F400, 0x0000F500, 0x0000F600, 0x0000F700, + 0x0000F800, 0x0000F900, 0x0000FA00, 0x0000FB00, 0x0000FC00, 0x0000FD00, 0x0000FE00, 0x0000FF00, + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}; +#endif // ENABLE_2B + +#if ENABLE_4B +static const uint32_t crc32cTable4[256 * (4 + 4)] = { + 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, + 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, + 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, + 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, + 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, + 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, + 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, + 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, + 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, + 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, + 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, + 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, + 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, + 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, + 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, + 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, + 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, + 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, + 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, + 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, + 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, + 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, + 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, + 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, + 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, + 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, + 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, + 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, + 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, + 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, + 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, + 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842, + 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, + 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, + 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, + 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, + 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, + 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, + 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, + 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, + 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, + 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, + 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, + 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, + 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, + 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, + 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, + 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, + 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, + 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, + 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, + 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, + 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, + 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, + 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, + 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, + 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, + 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, + 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, + 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, + 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, + 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, + 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, + 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8, + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, + 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, + 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, + 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, + 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, + 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, + 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, + 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, + 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, + 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, + 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, + 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, + 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, + 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, + 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, + 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, + 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, + 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, + 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, + 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, + 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, + 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, + 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, + 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, + 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, + 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, + 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, + 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, + 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, + 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, + 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, + 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, + 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842, + 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, + 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, + 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, + 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, + 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, + 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, + 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, + 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, + 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, + 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, + 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, + 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, + 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, + 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, + 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, + 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, + 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, + 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, + 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, + 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, + 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, + 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, + 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, + 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, + 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, + 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, + 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, + 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, + 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, + 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, + 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, + 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8, + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}; +#endif // ENABLE_4B + +#if ENABLE_8B +static const uint32_t crc32cTable8[256 * (4 + 8)] = { + 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504, + 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, + 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0, + 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A, + 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, + 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447, + 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929, + 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, + 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36, + 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC, + 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, + 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358, + 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF, + 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, + 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B, + 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1, + 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, + 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA, + 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4, + 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, + 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9, + 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223, + 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, + 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97, + 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852, + 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, + 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6, + 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C, + 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, + 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911, + 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F, + 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5, + 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089, + 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, + 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F, + 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C, + 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, + 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67, + 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992, + 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, + 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3, + 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0, + 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, + 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006, + 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E, + 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, + 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8, + 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB, + 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, + 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E, + 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB, + 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, + 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0, + 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093, + 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, + 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35, + 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907, + 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, + 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1, + 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2, + 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, + 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9, + 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C, + 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F, + 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD, + 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, + 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93, + 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C, + 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, + 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F, + 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E, + 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, + 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746, + 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59, + 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, + 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67, + 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB, + 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, + 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5, + 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA, + 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, + 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364, + 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45, + 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, + 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6, + 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9, + 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, + 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7, + 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090, + 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, + 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE, + 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1, + 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, + 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02, + 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623, + 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C, + 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44, + 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, + 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97, + 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406, + 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, + 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082, + 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0, + 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, + 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA, + 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B, + 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, + 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8, + 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD, + 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, + 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E, + 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF, + 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, + 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089, + 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB, + 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, + 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F, + 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE, + 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, + 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D, + 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6, + 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, + 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065, + 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4, + 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, + 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70, + 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532, + 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3, + 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504, + 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, + 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0, + 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A, + 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, + 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447, + 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929, + 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, + 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36, + 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC, + 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, + 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358, + 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF, + 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, + 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B, + 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1, + 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, + 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA, + 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4, + 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, + 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9, + 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223, + 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, + 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97, + 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852, + 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, + 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6, + 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C, + 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, + 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911, + 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F, + 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5, + 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089, + 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, + 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F, + 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C, + 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, + 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67, + 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992, + 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, + 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3, + 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0, + 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, + 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006, + 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E, + 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, + 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8, + 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB, + 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, + 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E, + 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB, + 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, + 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0, + 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093, + 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, + 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35, + 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907, + 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, + 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1, + 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2, + 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, + 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9, + 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C, + 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F, + 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD, + 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, + 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93, + 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C, + 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, + 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F, + 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E, + 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, + 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746, + 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59, + 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, + 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67, + 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB, + 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, + 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5, + 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA, + 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, + 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364, + 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45, + 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, + 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6, + 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9, + 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, + 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7, + 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090, + 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, + 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE, + 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1, + 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, + 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02, + 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623, + 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C, + 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44, + 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, + 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97, + 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406, + 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, + 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082, + 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0, + 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, + 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA, + 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B, + 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, + 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8, + 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD, + 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, + 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E, + 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF, + 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, + 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089, + 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB, + 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, + 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F, + 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE, + 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, + 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D, + 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6, + 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, + 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065, + 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4, + 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, + 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70, + 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532, + 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3, + 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, + 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, + 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, + 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, + 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, + 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, + 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, + 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, + 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, + 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, + 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, + 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, + 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, + 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, + 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, + 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, + 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, + 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, + 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, + 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, + 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, + 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, + 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, + 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, + 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, + 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, + 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, + 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, + 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, + 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, + 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, + 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842, + 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, + 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, + 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, + 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, + 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, + 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, + 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, + 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, + 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, + 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, + 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, + 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, + 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, + 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, + 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, + 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, + 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, + 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, + 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, + 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, + 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, + 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, + 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, + 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, + 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, + 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, + 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, + 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, + 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, + 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, + 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, + 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8, + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}; +#endif // ENABLE_8B + +#if ENABLE_16B +static const uint32_t crc32cTable16[256 * (4 + 16)] = { + 0x00000000, 0xF20C0DFE, 0xE1F46D0D, 0x13F860F3, 0xC604ACEB, 0x3408A115, 0x27F0C1E6, 0xD5FCCC18, + 0x89E52F27, 0x7BE922D9, 0x6811422A, 0x9A1D4FD4, 0x4FE183CC, 0xBDED8E32, 0xAE15EEC1, 0x5C19E33F, + 0x162628BF, 0xE42A2541, 0xF7D245B2, 0x05DE484C, 0xD0228454, 0x222E89AA, 0x31D6E959, 0xC3DAE4A7, + 0x9FC30798, 0x6DCF0A66, 0x7E376A95, 0x8C3B676B, 0x59C7AB73, 0xABCBA68D, 0xB833C67E, 0x4A3FCB80, + 0x2C4C517E, 0xDE405C80, 0xCDB83C73, 0x3FB4318D, 0xEA48FD95, 0x1844F06B, 0x0BBC9098, 0xF9B09D66, + 0xA5A97E59, 0x57A573A7, 0x445D1354, 0xB6511EAA, 0x63ADD2B2, 0x91A1DF4C, 0x8259BFBF, 0x7055B241, + 0x3A6A79C1, 0xC866743F, 0xDB9E14CC, 0x29921932, 0xFC6ED52A, 0x0E62D8D4, 0x1D9AB827, 0xEF96B5D9, + 0xB38F56E6, 0x41835B18, 0x527B3BEB, 0xA0773615, 0x758BFA0D, 0x8787F7F3, 0x947F9700, 0x66739AFE, + 0x5898A2FC, 0xAA94AF02, 0xB96CCFF1, 0x4B60C20F, 0x9E9C0E17, 0x6C9003E9, 0x7F68631A, 0x8D646EE4, + 0xD17D8DDB, 0x23718025, 0x3089E0D6, 0xC285ED28, 0x17792130, 0xE5752CCE, 0xF68D4C3D, 0x048141C3, + 0x4EBE8A43, 0xBCB287BD, 0xAF4AE74E, 0x5D46EAB0, 0x88BA26A8, 0x7AB62B56, 0x694E4BA5, 0x9B42465B, + 0xC75BA564, 0x3557A89A, 0x26AFC869, 0xD4A3C597, 0x015F098F, 0xF3530471, 0xE0AB6482, 0x12A7697C, + 0x74D4F382, 0x86D8FE7C, 0x95209E8F, 0x672C9371, 0xB2D05F69, 0x40DC5297, 0x53243264, 0xA1283F9A, + 0xFD31DCA5, 0x0F3DD15B, 0x1CC5B1A8, 0xEEC9BC56, 0x3B35704E, 0xC9397DB0, 0xDAC11D43, 0x28CD10BD, + 0x62F2DB3D, 0x90FED6C3, 0x8306B630, 0x710ABBCE, 0xA4F677D6, 0x56FA7A28, 0x45021ADB, 0xB70E1725, + 0xEB17F41A, 0x191BF9E4, 0x0AE39917, 0xF8EF94E9, 0x2D1358F1, 0xDF1F550F, 0xCCE735FC, 0x3EEB3802, + 0xB13145F8, 0x433D4806, 0x50C528F5, 0xA2C9250B, 0x7735E913, 0x8539E4ED, 0x96C1841E, 0x64CD89E0, + 0x38D46ADF, 0xCAD86721, 0xD92007D2, 0x2B2C0A2C, 0xFED0C634, 0x0CDCCBCA, 0x1F24AB39, 0xED28A6C7, + 0xA7176D47, 0x551B60B9, 0x46E3004A, 0xB4EF0DB4, 0x6113C1AC, 0x931FCC52, 0x80E7ACA1, 0x72EBA15F, + 0x2EF24260, 0xDCFE4F9E, 0xCF062F6D, 0x3D0A2293, 0xE8F6EE8B, 0x1AFAE375, 0x09028386, 0xFB0E8E78, + 0x9D7D1486, 0x6F711978, 0x7C89798B, 0x8E857475, 0x5B79B86D, 0xA975B593, 0xBA8DD560, 0x4881D89E, + 0x14983BA1, 0xE694365F, 0xF56C56AC, 0x07605B52, 0xD29C974A, 0x20909AB4, 0x3368FA47, 0xC164F7B9, + 0x8B5B3C39, 0x795731C7, 0x6AAF5134, 0x98A35CCA, 0x4D5F90D2, 0xBF539D2C, 0xACABFDDF, 0x5EA7F021, + 0x02BE131E, 0xF0B21EE0, 0xE34A7E13, 0x114673ED, 0xC4BABFF5, 0x36B6B20B, 0x254ED2F8, 0xD742DF06, + 0xE9A9E704, 0x1BA5EAFA, 0x085D8A09, 0xFA5187F7, 0x2FAD4BEF, 0xDDA14611, 0xCE5926E2, 0x3C552B1C, + 0x604CC823, 0x9240C5DD, 0x81B8A52E, 0x73B4A8D0, 0xA64864C8, 0x54446936, 0x47BC09C5, 0xB5B0043B, + 0xFF8FCFBB, 0x0D83C245, 0x1E7BA2B6, 0xEC77AF48, 0x398B6350, 0xCB876EAE, 0xD87F0E5D, 0x2A7303A3, + 0x766AE09C, 0x8466ED62, 0x979E8D91, 0x6592806F, 0xB06E4C77, 0x42624189, 0x519A217A, 0xA3962C84, + 0xC5E5B67A, 0x37E9BB84, 0x2411DB77, 0xD61DD689, 0x03E11A91, 0xF1ED176F, 0xE215779C, 0x10197A62, + 0x4C00995D, 0xBE0C94A3, 0xADF4F450, 0x5FF8F9AE, 0x8A0435B6, 0x78083848, 0x6BF058BB, 0x99FC5545, + 0xD3C39EC5, 0x21CF933B, 0x3237F3C8, 0xC03BFE36, 0x15C7322E, 0xE7CB3FD0, 0xF4335F23, 0x063F52DD, + 0x5A26B1E2, 0xA82ABC1C, 0xBBD2DCEF, 0x49DED111, 0x9C221D09, 0x6E2E10F7, 0x7DD67004, 0x8FDA7DFA, + 0x00000000, 0x678EFD01, 0xCF1DFA02, 0xA8930703, 0x9BD782F5, 0xFC597FF4, 0x54CA78F7, 0x334485F6, + 0x3243731B, 0x55CD8E1A, 0xFD5E8919, 0x9AD07418, 0xA994F1EE, 0xCE1A0CEF, 0x66890BEC, 0x0107F6ED, + 0x6486E636, 0x03081B37, 0xAB9B1C34, 0xCC15E135, 0xFF5164C3, 0x98DF99C2, 0x304C9EC1, 0x57C263C0, + 0x56C5952D, 0x314B682C, 0x99D86F2F, 0xFE56922E, 0xCD1217D8, 0xAA9CEAD9, 0x020FEDDA, 0x658110DB, + 0xC90DCC6C, 0xAE83316D, 0x0610366E, 0x619ECB6F, 0x52DA4E99, 0x3554B398, 0x9DC7B49B, 0xFA49499A, + 0xFB4EBF77, 0x9CC04276, 0x34534575, 0x53DDB874, 0x60993D82, 0x0717C083, 0xAF84C780, 0xC80A3A81, + 0xAD8B2A5A, 0xCA05D75B, 0x6296D058, 0x05182D59, 0x365CA8AF, 0x51D255AE, 0xF94152AD, 0x9ECFAFAC, + 0x9FC85941, 0xF846A440, 0x50D5A343, 0x375B5E42, 0x041FDBB4, 0x639126B5, 0xCB0221B6, 0xAC8CDCB7, + 0x97F7EE29, 0xF0791328, 0x58EA142B, 0x3F64E92A, 0x0C206CDC, 0x6BAE91DD, 0xC33D96DE, 0xA4B36BDF, + 0xA5B49D32, 0xC23A6033, 0x6AA96730, 0x0D279A31, 0x3E631FC7, 0x59EDE2C6, 0xF17EE5C5, 0x96F018C4, + 0xF371081F, 0x94FFF51E, 0x3C6CF21D, 0x5BE20F1C, 0x68A68AEA, 0x0F2877EB, 0xA7BB70E8, 0xC0358DE9, + 0xC1327B04, 0xA6BC8605, 0x0E2F8106, 0x69A17C07, 0x5AE5F9F1, 0x3D6B04F0, 0x95F803F3, 0xF276FEF2, + 0x5EFA2245, 0x3974DF44, 0x91E7D847, 0xF6692546, 0xC52DA0B0, 0xA2A35DB1, 0x0A305AB2, 0x6DBEA7B3, + 0x6CB9515E, 0x0B37AC5F, 0xA3A4AB5C, 0xC42A565D, 0xF76ED3AB, 0x90E02EAA, 0x387329A9, 0x5FFDD4A8, + 0x3A7CC473, 0x5DF23972, 0xF5613E71, 0x92EFC370, 0xA1AB4686, 0xC625BB87, 0x6EB6BC84, 0x09384185, + 0x083FB768, 0x6FB14A69, 0xC7224D6A, 0xA0ACB06B, 0x93E8359D, 0xF466C89C, 0x5CF5CF9F, 0x3B7B329E, + 0x2A03AAA3, 0x4D8D57A2, 0xE51E50A1, 0x8290ADA0, 0xB1D42856, 0xD65AD557, 0x7EC9D254, 0x19472F55, + 0x1840D9B8, 0x7FCE24B9, 0xD75D23BA, 0xB0D3DEBB, 0x83975B4D, 0xE419A64C, 0x4C8AA14F, 0x2B045C4E, + 0x4E854C95, 0x290BB194, 0x8198B697, 0xE6164B96, 0xD552CE60, 0xB2DC3361, 0x1A4F3462, 0x7DC1C963, + 0x7CC63F8E, 0x1B48C28F, 0xB3DBC58C, 0xD455388D, 0xE711BD7B, 0x809F407A, 0x280C4779, 0x4F82BA78, + 0xE30E66CF, 0x84809BCE, 0x2C139CCD, 0x4B9D61CC, 0x78D9E43A, 0x1F57193B, 0xB7C41E38, 0xD04AE339, + 0xD14D15D4, 0xB6C3E8D5, 0x1E50EFD6, 0x79DE12D7, 0x4A9A9721, 0x2D146A20, 0x85876D23, 0xE2099022, + 0x878880F9, 0xE0067DF8, 0x48957AFB, 0x2F1B87FA, 0x1C5F020C, 0x7BD1FF0D, 0xD342F80E, 0xB4CC050F, + 0xB5CBF3E2, 0xD2450EE3, 0x7AD609E0, 0x1D58F4E1, 0x2E1C7117, 0x49928C16, 0xE1018B15, 0x868F7614, + 0xBDF4448A, 0xDA7AB98B, 0x72E9BE88, 0x15674389, 0x2623C67F, 0x41AD3B7E, 0xE93E3C7D, 0x8EB0C17C, + 0x8FB73791, 0xE839CA90, 0x40AACD93, 0x27243092, 0x1460B564, 0x73EE4865, 0xDB7D4F66, 0xBCF3B267, + 0xD972A2BC, 0xBEFC5FBD, 0x166F58BE, 0x71E1A5BF, 0x42A52049, 0x252BDD48, 0x8DB8DA4B, 0xEA36274A, + 0xEB31D1A7, 0x8CBF2CA6, 0x242C2BA5, 0x43A2D6A4, 0x70E65352, 0x1768AE53, 0xBFFBA950, 0xD8755451, + 0x74F988E6, 0x137775E7, 0xBBE472E4, 0xDC6A8FE5, 0xEF2E0A13, 0x88A0F712, 0x2033F011, 0x47BD0D10, + 0x46BAFBFD, 0x213406FC, 0x89A701FF, 0xEE29FCFE, 0xDD6D7908, 0xBAE38409, 0x1270830A, 0x75FE7E0B, + 0x107F6ED0, 0x77F193D1, 0xDF6294D2, 0xB8EC69D3, 0x8BA8EC25, 0xEC261124, 0x44B51627, 0x233BEB26, + 0x223C1DCB, 0x45B2E0CA, 0xED21E7C9, 0x8AAF1AC8, 0xB9EB9F3E, 0xDE65623F, 0x76F6653C, 0x1178983D, + 0x00000000, 0x54075546, 0xA80EAA8C, 0xFC09FFCA, 0x55F123E9, 0x01F676AF, 0xFDFF8965, 0xA9F8DC23, + 0xABE247D2, 0xFFE51294, 0x03ECED5E, 0x57EBB818, 0xFE13643B, 0xAA14317D, 0x561DCEB7, 0x021A9BF1, + 0x5228F955, 0x062FAC13, 0xFA2653D9, 0xAE21069F, 0x07D9DABC, 0x53DE8FFA, 0xAFD77030, 0xFBD02576, + 0xF9CABE87, 0xADCDEBC1, 0x51C4140B, 0x05C3414D, 0xAC3B9D6E, 0xF83CC828, 0x043537E2, 0x503262A4, + 0xA451F2AA, 0xF056A7EC, 0x0C5F5826, 0x58580D60, 0xF1A0D143, 0xA5A78405, 0x59AE7BCF, 0x0DA92E89, + 0x0FB3B578, 0x5BB4E03E, 0xA7BD1FF4, 0xF3BA4AB2, 0x5A429691, 0x0E45C3D7, 0xF24C3C1D, 0xA64B695B, + 0xF6790BFF, 0xA27E5EB9, 0x5E77A173, 0x0A70F435, 0xA3882816, 0xF78F7D50, 0x0B86829A, 0x5F81D7DC, + 0x5D9B4C2D, 0x099C196B, 0xF595E6A1, 0xA192B3E7, 0x086A6FC4, 0x5C6D3A82, 0xA064C548, 0xF463900E, + 0x4D4F93A5, 0x1948C6E3, 0xE5413929, 0xB1466C6F, 0x18BEB04C, 0x4CB9E50A, 0xB0B01AC0, 0xE4B74F86, + 0xE6ADD477, 0xB2AA8131, 0x4EA37EFB, 0x1AA42BBD, 0xB35CF79E, 0xE75BA2D8, 0x1B525D12, 0x4F550854, + 0x1F676AF0, 0x4B603FB6, 0xB769C07C, 0xE36E953A, 0x4A964919, 0x1E911C5F, 0xE298E395, 0xB69FB6D3, + 0xB4852D22, 0xE0827864, 0x1C8B87AE, 0x488CD2E8, 0xE1740ECB, 0xB5735B8D, 0x497AA447, 0x1D7DF101, + 0xE91E610F, 0xBD193449, 0x4110CB83, 0x15179EC5, 0xBCEF42E6, 0xE8E817A0, 0x14E1E86A, 0x40E6BD2C, + 0x42FC26DD, 0x16FB739B, 0xEAF28C51, 0xBEF5D917, 0x170D0534, 0x430A5072, 0xBF03AFB8, 0xEB04FAFE, + 0xBB36985A, 0xEF31CD1C, 0x133832D6, 0x473F6790, 0xEEC7BBB3, 0xBAC0EEF5, 0x46C9113F, 0x12CE4479, + 0x10D4DF88, 0x44D38ACE, 0xB8DA7504, 0xECDD2042, 0x4525FC61, 0x1122A927, 0xED2B56ED, 0xB92C03AB, + 0x9A9F274A, 0xCE98720C, 0x32918DC6, 0x6696D880, 0xCF6E04A3, 0x9B6951E5, 0x6760AE2F, 0x3367FB69, + 0x317D6098, 0x657A35DE, 0x9973CA14, 0xCD749F52, 0x648C4371, 0x308B1637, 0xCC82E9FD, 0x9885BCBB, + 0xC8B7DE1F, 0x9CB08B59, 0x60B97493, 0x34BE21D5, 0x9D46FDF6, 0xC941A8B0, 0x3548577A, 0x614F023C, + 0x635599CD, 0x3752CC8B, 0xCB5B3341, 0x9F5C6607, 0x36A4BA24, 0x62A3EF62, 0x9EAA10A8, 0xCAAD45EE, + 0x3ECED5E0, 0x6AC980A6, 0x96C07F6C, 0xC2C72A2A, 0x6B3FF609, 0x3F38A34F, 0xC3315C85, 0x973609C3, + 0x952C9232, 0xC12BC774, 0x3D2238BE, 0x69256DF8, 0xC0DDB1DB, 0x94DAE49D, 0x68D31B57, 0x3CD44E11, + 0x6CE62CB5, 0x38E179F3, 0xC4E88639, 0x90EFD37F, 0x39170F5C, 0x6D105A1A, 0x9119A5D0, 0xC51EF096, + 0xC7046B67, 0x93033E21, 0x6F0AC1EB, 0x3B0D94AD, 0x92F5488E, 0xC6F21DC8, 0x3AFBE202, 0x6EFCB744, + 0xD7D0B4EF, 0x83D7E1A9, 0x7FDE1E63, 0x2BD94B25, 0x82219706, 0xD626C240, 0x2A2F3D8A, 0x7E2868CC, + 0x7C32F33D, 0x2835A67B, 0xD43C59B1, 0x803B0CF7, 0x29C3D0D4, 0x7DC48592, 0x81CD7A58, 0xD5CA2F1E, + 0x85F84DBA, 0xD1FF18FC, 0x2DF6E736, 0x79F1B270, 0xD0096E53, 0x840E3B15, 0x7807C4DF, 0x2C009199, + 0x2E1A0A68, 0x7A1D5F2E, 0x8614A0E4, 0xD213F5A2, 0x7BEB2981, 0x2FEC7CC7, 0xD3E5830D, 0x87E2D64B, + 0x73814645, 0x27861303, 0xDB8FECC9, 0x8F88B98F, 0x267065AC, 0x727730EA, 0x8E7ECF20, 0xDA799A66, + 0xD8630197, 0x8C6454D1, 0x706DAB1B, 0x246AFE5D, 0x8D92227E, 0xD9957738, 0x259C88F2, 0x719BDDB4, + 0x21A9BF10, 0x75AEEA56, 0x89A7159C, 0xDDA040DA, 0x74589CF9, 0x205FC9BF, 0xDC563675, 0x88516333, + 0x8A4BF8C2, 0xDE4CAD84, 0x2245524E, 0x76420708, 0xDFBADB2B, 0x8BBD8E6D, 0x77B471A7, 0x23B324E1, + 0x00000000, 0x30D23865, 0x61A470CA, 0x517648AF, 0xC348E194, 0xF39AD9F1, 0xA2EC915E, 0x923EA93B, + 0x837DB5D9, 0xB3AF8DBC, 0xE2D9C513, 0xD20BFD76, 0x4035544D, 0x70E76C28, 0x21912487, 0x11431CE2, + 0x03171D43, 0x33C52526, 0x62B36D89, 0x526155EC, 0xC05FFCD7, 0xF08DC4B2, 0xA1FB8C1D, 0x9129B478, + 0x806AA89A, 0xB0B890FF, 0xE1CED850, 0xD11CE035, 0x4322490E, 0x73F0716B, 0x228639C4, 0x125401A1, + 0x062E3A86, 0x36FC02E3, 0x678A4A4C, 0x57587229, 0xC566DB12, 0xF5B4E377, 0xA4C2ABD8, 0x941093BD, + 0x85538F5F, 0xB581B73A, 0xE4F7FF95, 0xD425C7F0, 0x461B6ECB, 0x76C956AE, 0x27BF1E01, 0x176D2664, + 0x053927C5, 0x35EB1FA0, 0x649D570F, 0x544F6F6A, 0xC671C651, 0xF6A3FE34, 0xA7D5B69B, 0x97078EFE, + 0x8644921C, 0xB696AA79, 0xE7E0E2D6, 0xD732DAB3, 0x450C7388, 0x75DE4BED, 0x24A80342, 0x147A3B27, + 0x0C5C750C, 0x3C8E4D69, 0x6DF805C6, 0x5D2A3DA3, 0xCF149498, 0xFFC6ACFD, 0xAEB0E452, 0x9E62DC37, + 0x8F21C0D5, 0xBFF3F8B0, 0xEE85B01F, 0xDE57887A, 0x4C692141, 0x7CBB1924, 0x2DCD518B, 0x1D1F69EE, + 0x0F4B684F, 0x3F99502A, 0x6EEF1885, 0x5E3D20E0, 0xCC0389DB, 0xFCD1B1BE, 0xADA7F911, 0x9D75C174, + 0x8C36DD96, 0xBCE4E5F3, 0xED92AD5C, 0xDD409539, 0x4F7E3C02, 0x7FAC0467, 0x2EDA4CC8, 0x1E0874AD, + 0x0A724F8A, 0x3AA077EF, 0x6BD63F40, 0x5B040725, 0xC93AAE1E, 0xF9E8967B, 0xA89EDED4, 0x984CE6B1, + 0x890FFA53, 0xB9DDC236, 0xE8AB8A99, 0xD879B2FC, 0x4A471BC7, 0x7A9523A2, 0x2BE36B0D, 0x1B315368, + 0x096552C9, 0x39B76AAC, 0x68C12203, 0x58131A66, 0xCA2DB35D, 0xFAFF8B38, 0xAB89C397, 0x9B5BFBF2, + 0x8A18E710, 0xBACADF75, 0xEBBC97DA, 0xDB6EAFBF, 0x49500684, 0x79823EE1, 0x28F4764E, 0x18264E2B, + 0x18B8EA18, 0x286AD27D, 0x791C9AD2, 0x49CEA2B7, 0xDBF00B8C, 0xEB2233E9, 0xBA547B46, 0x8A864323, + 0x9BC55FC1, 0xAB1767A4, 0xFA612F0B, 0xCAB3176E, 0x588DBE55, 0x685F8630, 0x3929CE9F, 0x09FBF6FA, + 0x1BAFF75B, 0x2B7DCF3E, 0x7A0B8791, 0x4AD9BFF4, 0xD8E716CF, 0xE8352EAA, 0xB9436605, 0x89915E60, + 0x98D24282, 0xA8007AE7, 0xF9763248, 0xC9A40A2D, 0x5B9AA316, 0x6B489B73, 0x3A3ED3DC, 0x0AECEBB9, + 0x1E96D09E, 0x2E44E8FB, 0x7F32A054, 0x4FE09831, 0xDDDE310A, 0xED0C096F, 0xBC7A41C0, 0x8CA879A5, + 0x9DEB6547, 0xAD395D22, 0xFC4F158D, 0xCC9D2DE8, 0x5EA384D3, 0x6E71BCB6, 0x3F07F419, 0x0FD5CC7C, + 0x1D81CDDD, 0x2D53F5B8, 0x7C25BD17, 0x4CF78572, 0xDEC92C49, 0xEE1B142C, 0xBF6D5C83, 0x8FBF64E6, + 0x9EFC7804, 0xAE2E4061, 0xFF5808CE, 0xCF8A30AB, 0x5DB49990, 0x6D66A1F5, 0x3C10E95A, 0x0CC2D13F, + 0x14E49F14, 0x2436A771, 0x7540EFDE, 0x4592D7BB, 0xD7AC7E80, 0xE77E46E5, 0xB6080E4A, 0x86DA362F, + 0x97992ACD, 0xA74B12A8, 0xF63D5A07, 0xC6EF6262, 0x54D1CB59, 0x6403F33C, 0x3575BB93, 0x05A783F6, + 0x17F38257, 0x2721BA32, 0x7657F29D, 0x4685CAF8, 0xD4BB63C3, 0xE4695BA6, 0xB51F1309, 0x85CD2B6C, + 0x948E378E, 0xA45C0FEB, 0xF52A4744, 0xC5F87F21, 0x57C6D61A, 0x6714EE7F, 0x3662A6D0, 0x06B09EB5, + 0x12CAA592, 0x22189DF7, 0x736ED558, 0x43BCED3D, 0xD1824406, 0xE1507C63, 0xB02634CC, 0x80F40CA9, + 0x91B7104B, 0xA165282E, 0xF0136081, 0xC0C158E4, 0x52FFF1DF, 0x622DC9BA, 0x335B8115, 0x0389B970, + 0x11DDB8D1, 0x210F80B4, 0x7079C81B, 0x40ABF07E, 0xD2955945, 0xE2476120, 0xB331298F, 0x83E311EA, + 0x92A00D08, 0xA272356D, 0xF3047DC2, 0xC3D645A7, 0x51E8EC9C, 0x613AD4F9, 0x304C9C56, 0x009EA433, + 0x00000000, 0xF20C0DFE, 0xE1F46D0D, 0x13F860F3, 0xC604ACEB, 0x3408A115, 0x27F0C1E6, 0xD5FCCC18, + 0x89E52F27, 0x7BE922D9, 0x6811422A, 0x9A1D4FD4, 0x4FE183CC, 0xBDED8E32, 0xAE15EEC1, 0x5C19E33F, + 0x162628BF, 0xE42A2541, 0xF7D245B2, 0x05DE484C, 0xD0228454, 0x222E89AA, 0x31D6E959, 0xC3DAE4A7, + 0x9FC30798, 0x6DCF0A66, 0x7E376A95, 0x8C3B676B, 0x59C7AB73, 0xABCBA68D, 0xB833C67E, 0x4A3FCB80, + 0x2C4C517E, 0xDE405C80, 0xCDB83C73, 0x3FB4318D, 0xEA48FD95, 0x1844F06B, 0x0BBC9098, 0xF9B09D66, + 0xA5A97E59, 0x57A573A7, 0x445D1354, 0xB6511EAA, 0x63ADD2B2, 0x91A1DF4C, 0x8259BFBF, 0x7055B241, + 0x3A6A79C1, 0xC866743F, 0xDB9E14CC, 0x29921932, 0xFC6ED52A, 0x0E62D8D4, 0x1D9AB827, 0xEF96B5D9, + 0xB38F56E6, 0x41835B18, 0x527B3BEB, 0xA0773615, 0x758BFA0D, 0x8787F7F3, 0x947F9700, 0x66739AFE, + 0x5898A2FC, 0xAA94AF02, 0xB96CCFF1, 0x4B60C20F, 0x9E9C0E17, 0x6C9003E9, 0x7F68631A, 0x8D646EE4, + 0xD17D8DDB, 0x23718025, 0x3089E0D6, 0xC285ED28, 0x17792130, 0xE5752CCE, 0xF68D4C3D, 0x048141C3, + 0x4EBE8A43, 0xBCB287BD, 0xAF4AE74E, 0x5D46EAB0, 0x88BA26A8, 0x7AB62B56, 0x694E4BA5, 0x9B42465B, + 0xC75BA564, 0x3557A89A, 0x26AFC869, 0xD4A3C597, 0x015F098F, 0xF3530471, 0xE0AB6482, 0x12A7697C, + 0x74D4F382, 0x86D8FE7C, 0x95209E8F, 0x672C9371, 0xB2D05F69, 0x40DC5297, 0x53243264, 0xA1283F9A, + 0xFD31DCA5, 0x0F3DD15B, 0x1CC5B1A8, 0xEEC9BC56, 0x3B35704E, 0xC9397DB0, 0xDAC11D43, 0x28CD10BD, + 0x62F2DB3D, 0x90FED6C3, 0x8306B630, 0x710ABBCE, 0xA4F677D6, 0x56FA7A28, 0x45021ADB, 0xB70E1725, + 0xEB17F41A, 0x191BF9E4, 0x0AE39917, 0xF8EF94E9, 0x2D1358F1, 0xDF1F550F, 0xCCE735FC, 0x3EEB3802, + 0xB13145F8, 0x433D4806, 0x50C528F5, 0xA2C9250B, 0x7735E913, 0x8539E4ED, 0x96C1841E, 0x64CD89E0, + 0x38D46ADF, 0xCAD86721, 0xD92007D2, 0x2B2C0A2C, 0xFED0C634, 0x0CDCCBCA, 0x1F24AB39, 0xED28A6C7, + 0xA7176D47, 0x551B60B9, 0x46E3004A, 0xB4EF0DB4, 0x6113C1AC, 0x931FCC52, 0x80E7ACA1, 0x72EBA15F, + 0x2EF24260, 0xDCFE4F9E, 0xCF062F6D, 0x3D0A2293, 0xE8F6EE8B, 0x1AFAE375, 0x09028386, 0xFB0E8E78, + 0x9D7D1486, 0x6F711978, 0x7C89798B, 0x8E857475, 0x5B79B86D, 0xA975B593, 0xBA8DD560, 0x4881D89E, + 0x14983BA1, 0xE694365F, 0xF56C56AC, 0x07605B52, 0xD29C974A, 0x20909AB4, 0x3368FA47, 0xC164F7B9, + 0x8B5B3C39, 0x795731C7, 0x6AAF5134, 0x98A35CCA, 0x4D5F90D2, 0xBF539D2C, 0xACABFDDF, 0x5EA7F021, + 0x02BE131E, 0xF0B21EE0, 0xE34A7E13, 0x114673ED, 0xC4BABFF5, 0x36B6B20B, 0x254ED2F8, 0xD742DF06, + 0xE9A9E704, 0x1BA5EAFA, 0x085D8A09, 0xFA5187F7, 0x2FAD4BEF, 0xDDA14611, 0xCE5926E2, 0x3C552B1C, + 0x604CC823, 0x9240C5DD, 0x81B8A52E, 0x73B4A8D0, 0xA64864C8, 0x54446936, 0x47BC09C5, 0xB5B0043B, + 0xFF8FCFBB, 0x0D83C245, 0x1E7BA2B6, 0xEC77AF48, 0x398B6350, 0xCB876EAE, 0xD87F0E5D, 0x2A7303A3, + 0x766AE09C, 0x8466ED62, 0x979E8D91, 0x6592806F, 0xB06E4C77, 0x42624189, 0x519A217A, 0xA3962C84, + 0xC5E5B67A, 0x37E9BB84, 0x2411DB77, 0xD61DD689, 0x03E11A91, 0xF1ED176F, 0xE215779C, 0x10197A62, + 0x4C00995D, 0xBE0C94A3, 0xADF4F450, 0x5FF8F9AE, 0x8A0435B6, 0x78083848, 0x6BF058BB, 0x99FC5545, + 0xD3C39EC5, 0x21CF933B, 0x3237F3C8, 0xC03BFE36, 0x15C7322E, 0xE7CB3FD0, 0xF4335F23, 0x063F52DD, + 0x5A26B1E2, 0xA82ABC1C, 0xBBD2DCEF, 0x49DED111, 0x9C221D09, 0x6E2E10F7, 0x7DD67004, 0x8FDA7DFA, + 0x00000000, 0x678EFD01, 0xCF1DFA02, 0xA8930703, 0x9BD782F5, 0xFC597FF4, 0x54CA78F7, 0x334485F6, + 0x3243731B, 0x55CD8E1A, 0xFD5E8919, 0x9AD07418, 0xA994F1EE, 0xCE1A0CEF, 0x66890BEC, 0x0107F6ED, + 0x6486E636, 0x03081B37, 0xAB9B1C34, 0xCC15E135, 0xFF5164C3, 0x98DF99C2, 0x304C9EC1, 0x57C263C0, + 0x56C5952D, 0x314B682C, 0x99D86F2F, 0xFE56922E, 0xCD1217D8, 0xAA9CEAD9, 0x020FEDDA, 0x658110DB, + 0xC90DCC6C, 0xAE83316D, 0x0610366E, 0x619ECB6F, 0x52DA4E99, 0x3554B398, 0x9DC7B49B, 0xFA49499A, + 0xFB4EBF77, 0x9CC04276, 0x34534575, 0x53DDB874, 0x60993D82, 0x0717C083, 0xAF84C780, 0xC80A3A81, + 0xAD8B2A5A, 0xCA05D75B, 0x6296D058, 0x05182D59, 0x365CA8AF, 0x51D255AE, 0xF94152AD, 0x9ECFAFAC, + 0x9FC85941, 0xF846A440, 0x50D5A343, 0x375B5E42, 0x041FDBB4, 0x639126B5, 0xCB0221B6, 0xAC8CDCB7, + 0x97F7EE29, 0xF0791328, 0x58EA142B, 0x3F64E92A, 0x0C206CDC, 0x6BAE91DD, 0xC33D96DE, 0xA4B36BDF, + 0xA5B49D32, 0xC23A6033, 0x6AA96730, 0x0D279A31, 0x3E631FC7, 0x59EDE2C6, 0xF17EE5C5, 0x96F018C4, + 0xF371081F, 0x94FFF51E, 0x3C6CF21D, 0x5BE20F1C, 0x68A68AEA, 0x0F2877EB, 0xA7BB70E8, 0xC0358DE9, + 0xC1327B04, 0xA6BC8605, 0x0E2F8106, 0x69A17C07, 0x5AE5F9F1, 0x3D6B04F0, 0x95F803F3, 0xF276FEF2, + 0x5EFA2245, 0x3974DF44, 0x91E7D847, 0xF6692546, 0xC52DA0B0, 0xA2A35DB1, 0x0A305AB2, 0x6DBEA7B3, + 0x6CB9515E, 0x0B37AC5F, 0xA3A4AB5C, 0xC42A565D, 0xF76ED3AB, 0x90E02EAA, 0x387329A9, 0x5FFDD4A8, + 0x3A7CC473, 0x5DF23972, 0xF5613E71, 0x92EFC370, 0xA1AB4686, 0xC625BB87, 0x6EB6BC84, 0x09384185, + 0x083FB768, 0x6FB14A69, 0xC7224D6A, 0xA0ACB06B, 0x93E8359D, 0xF466C89C, 0x5CF5CF9F, 0x3B7B329E, + 0x2A03AAA3, 0x4D8D57A2, 0xE51E50A1, 0x8290ADA0, 0xB1D42856, 0xD65AD557, 0x7EC9D254, 0x19472F55, + 0x1840D9B8, 0x7FCE24B9, 0xD75D23BA, 0xB0D3DEBB, 0x83975B4D, 0xE419A64C, 0x4C8AA14F, 0x2B045C4E, + 0x4E854C95, 0x290BB194, 0x8198B697, 0xE6164B96, 0xD552CE60, 0xB2DC3361, 0x1A4F3462, 0x7DC1C963, + 0x7CC63F8E, 0x1B48C28F, 0xB3DBC58C, 0xD455388D, 0xE711BD7B, 0x809F407A, 0x280C4779, 0x4F82BA78, + 0xE30E66CF, 0x84809BCE, 0x2C139CCD, 0x4B9D61CC, 0x78D9E43A, 0x1F57193B, 0xB7C41E38, 0xD04AE339, + 0xD14D15D4, 0xB6C3E8D5, 0x1E50EFD6, 0x79DE12D7, 0x4A9A9721, 0x2D146A20, 0x85876D23, 0xE2099022, + 0x878880F9, 0xE0067DF8, 0x48957AFB, 0x2F1B87FA, 0x1C5F020C, 0x7BD1FF0D, 0xD342F80E, 0xB4CC050F, + 0xB5CBF3E2, 0xD2450EE3, 0x7AD609E0, 0x1D58F4E1, 0x2E1C7117, 0x49928C16, 0xE1018B15, 0x868F7614, + 0xBDF4448A, 0xDA7AB98B, 0x72E9BE88, 0x15674389, 0x2623C67F, 0x41AD3B7E, 0xE93E3C7D, 0x8EB0C17C, + 0x8FB73791, 0xE839CA90, 0x40AACD93, 0x27243092, 0x1460B564, 0x73EE4865, 0xDB7D4F66, 0xBCF3B267, + 0xD972A2BC, 0xBEFC5FBD, 0x166F58BE, 0x71E1A5BF, 0x42A52049, 0x252BDD48, 0x8DB8DA4B, 0xEA36274A, + 0xEB31D1A7, 0x8CBF2CA6, 0x242C2BA5, 0x43A2D6A4, 0x70E65352, 0x1768AE53, 0xBFFBA950, 0xD8755451, + 0x74F988E6, 0x137775E7, 0xBBE472E4, 0xDC6A8FE5, 0xEF2E0A13, 0x88A0F712, 0x2033F011, 0x47BD0D10, + 0x46BAFBFD, 0x213406FC, 0x89A701FF, 0xEE29FCFE, 0xDD6D7908, 0xBAE38409, 0x1270830A, 0x75FE7E0B, + 0x107F6ED0, 0x77F193D1, 0xDF6294D2, 0xB8EC69D3, 0x8BA8EC25, 0xEC261124, 0x44B51627, 0x233BEB26, + 0x223C1DCB, 0x45B2E0CA, 0xED21E7C9, 0x8AAF1AC8, 0xB9EB9F3E, 0xDE65623F, 0x76F6653C, 0x1178983D, + 0x00000000, 0x54075546, 0xA80EAA8C, 0xFC09FFCA, 0x55F123E9, 0x01F676AF, 0xFDFF8965, 0xA9F8DC23, + 0xABE247D2, 0xFFE51294, 0x03ECED5E, 0x57EBB818, 0xFE13643B, 0xAA14317D, 0x561DCEB7, 0x021A9BF1, + 0x5228F955, 0x062FAC13, 0xFA2653D9, 0xAE21069F, 0x07D9DABC, 0x53DE8FFA, 0xAFD77030, 0xFBD02576, + 0xF9CABE87, 0xADCDEBC1, 0x51C4140B, 0x05C3414D, 0xAC3B9D6E, 0xF83CC828, 0x043537E2, 0x503262A4, + 0xA451F2AA, 0xF056A7EC, 0x0C5F5826, 0x58580D60, 0xF1A0D143, 0xA5A78405, 0x59AE7BCF, 0x0DA92E89, + 0x0FB3B578, 0x5BB4E03E, 0xA7BD1FF4, 0xF3BA4AB2, 0x5A429691, 0x0E45C3D7, 0xF24C3C1D, 0xA64B695B, + 0xF6790BFF, 0xA27E5EB9, 0x5E77A173, 0x0A70F435, 0xA3882816, 0xF78F7D50, 0x0B86829A, 0x5F81D7DC, + 0x5D9B4C2D, 0x099C196B, 0xF595E6A1, 0xA192B3E7, 0x086A6FC4, 0x5C6D3A82, 0xA064C548, 0xF463900E, + 0x4D4F93A5, 0x1948C6E3, 0xE5413929, 0xB1466C6F, 0x18BEB04C, 0x4CB9E50A, 0xB0B01AC0, 0xE4B74F86, + 0xE6ADD477, 0xB2AA8131, 0x4EA37EFB, 0x1AA42BBD, 0xB35CF79E, 0xE75BA2D8, 0x1B525D12, 0x4F550854, + 0x1F676AF0, 0x4B603FB6, 0xB769C07C, 0xE36E953A, 0x4A964919, 0x1E911C5F, 0xE298E395, 0xB69FB6D3, + 0xB4852D22, 0xE0827864, 0x1C8B87AE, 0x488CD2E8, 0xE1740ECB, 0xB5735B8D, 0x497AA447, 0x1D7DF101, + 0xE91E610F, 0xBD193449, 0x4110CB83, 0x15179EC5, 0xBCEF42E6, 0xE8E817A0, 0x14E1E86A, 0x40E6BD2C, + 0x42FC26DD, 0x16FB739B, 0xEAF28C51, 0xBEF5D917, 0x170D0534, 0x430A5072, 0xBF03AFB8, 0xEB04FAFE, + 0xBB36985A, 0xEF31CD1C, 0x133832D6, 0x473F6790, 0xEEC7BBB3, 0xBAC0EEF5, 0x46C9113F, 0x12CE4479, + 0x10D4DF88, 0x44D38ACE, 0xB8DA7504, 0xECDD2042, 0x4525FC61, 0x1122A927, 0xED2B56ED, 0xB92C03AB, + 0x9A9F274A, 0xCE98720C, 0x32918DC6, 0x6696D880, 0xCF6E04A3, 0x9B6951E5, 0x6760AE2F, 0x3367FB69, + 0x317D6098, 0x657A35DE, 0x9973CA14, 0xCD749F52, 0x648C4371, 0x308B1637, 0xCC82E9FD, 0x9885BCBB, + 0xC8B7DE1F, 0x9CB08B59, 0x60B97493, 0x34BE21D5, 0x9D46FDF6, 0xC941A8B0, 0x3548577A, 0x614F023C, + 0x635599CD, 0x3752CC8B, 0xCB5B3341, 0x9F5C6607, 0x36A4BA24, 0x62A3EF62, 0x9EAA10A8, 0xCAAD45EE, + 0x3ECED5E0, 0x6AC980A6, 0x96C07F6C, 0xC2C72A2A, 0x6B3FF609, 0x3F38A34F, 0xC3315C85, 0x973609C3, + 0x952C9232, 0xC12BC774, 0x3D2238BE, 0x69256DF8, 0xC0DDB1DB, 0x94DAE49D, 0x68D31B57, 0x3CD44E11, + 0x6CE62CB5, 0x38E179F3, 0xC4E88639, 0x90EFD37F, 0x39170F5C, 0x6D105A1A, 0x9119A5D0, 0xC51EF096, + 0xC7046B67, 0x93033E21, 0x6F0AC1EB, 0x3B0D94AD, 0x92F5488E, 0xC6F21DC8, 0x3AFBE202, 0x6EFCB744, + 0xD7D0B4EF, 0x83D7E1A9, 0x7FDE1E63, 0x2BD94B25, 0x82219706, 0xD626C240, 0x2A2F3D8A, 0x7E2868CC, + 0x7C32F33D, 0x2835A67B, 0xD43C59B1, 0x803B0CF7, 0x29C3D0D4, 0x7DC48592, 0x81CD7A58, 0xD5CA2F1E, + 0x85F84DBA, 0xD1FF18FC, 0x2DF6E736, 0x79F1B270, 0xD0096E53, 0x840E3B15, 0x7807C4DF, 0x2C009199, + 0x2E1A0A68, 0x7A1D5F2E, 0x8614A0E4, 0xD213F5A2, 0x7BEB2981, 0x2FEC7CC7, 0xD3E5830D, 0x87E2D64B, + 0x73814645, 0x27861303, 0xDB8FECC9, 0x8F88B98F, 0x267065AC, 0x727730EA, 0x8E7ECF20, 0xDA799A66, + 0xD8630197, 0x8C6454D1, 0x706DAB1B, 0x246AFE5D, 0x8D92227E, 0xD9957738, 0x259C88F2, 0x719BDDB4, + 0x21A9BF10, 0x75AEEA56, 0x89A7159C, 0xDDA040DA, 0x74589CF9, 0x205FC9BF, 0xDC563675, 0x88516333, + 0x8A4BF8C2, 0xDE4CAD84, 0x2245524E, 0x76420708, 0xDFBADB2B, 0x8BBD8E6D, 0x77B471A7, 0x23B324E1, + 0x00000000, 0x30D23865, 0x61A470CA, 0x517648AF, 0xC348E194, 0xF39AD9F1, 0xA2EC915E, 0x923EA93B, + 0x837DB5D9, 0xB3AF8DBC, 0xE2D9C513, 0xD20BFD76, 0x4035544D, 0x70E76C28, 0x21912487, 0x11431CE2, + 0x03171D43, 0x33C52526, 0x62B36D89, 0x526155EC, 0xC05FFCD7, 0xF08DC4B2, 0xA1FB8C1D, 0x9129B478, + 0x806AA89A, 0xB0B890FF, 0xE1CED850, 0xD11CE035, 0x4322490E, 0x73F0716B, 0x228639C4, 0x125401A1, + 0x062E3A86, 0x36FC02E3, 0x678A4A4C, 0x57587229, 0xC566DB12, 0xF5B4E377, 0xA4C2ABD8, 0x941093BD, + 0x85538F5F, 0xB581B73A, 0xE4F7FF95, 0xD425C7F0, 0x461B6ECB, 0x76C956AE, 0x27BF1E01, 0x176D2664, + 0x053927C5, 0x35EB1FA0, 0x649D570F, 0x544F6F6A, 0xC671C651, 0xF6A3FE34, 0xA7D5B69B, 0x97078EFE, + 0x8644921C, 0xB696AA79, 0xE7E0E2D6, 0xD732DAB3, 0x450C7388, 0x75DE4BED, 0x24A80342, 0x147A3B27, + 0x0C5C750C, 0x3C8E4D69, 0x6DF805C6, 0x5D2A3DA3, 0xCF149498, 0xFFC6ACFD, 0xAEB0E452, 0x9E62DC37, + 0x8F21C0D5, 0xBFF3F8B0, 0xEE85B01F, 0xDE57887A, 0x4C692141, 0x7CBB1924, 0x2DCD518B, 0x1D1F69EE, + 0x0F4B684F, 0x3F99502A, 0x6EEF1885, 0x5E3D20E0, 0xCC0389DB, 0xFCD1B1BE, 0xADA7F911, 0x9D75C174, + 0x8C36DD96, 0xBCE4E5F3, 0xED92AD5C, 0xDD409539, 0x4F7E3C02, 0x7FAC0467, 0x2EDA4CC8, 0x1E0874AD, + 0x0A724F8A, 0x3AA077EF, 0x6BD63F40, 0x5B040725, 0xC93AAE1E, 0xF9E8967B, 0xA89EDED4, 0x984CE6B1, + 0x890FFA53, 0xB9DDC236, 0xE8AB8A99, 0xD879B2FC, 0x4A471BC7, 0x7A9523A2, 0x2BE36B0D, 0x1B315368, + 0x096552C9, 0x39B76AAC, 0x68C12203, 0x58131A66, 0xCA2DB35D, 0xFAFF8B38, 0xAB89C397, 0x9B5BFBF2, + 0x8A18E710, 0xBACADF75, 0xEBBC97DA, 0xDB6EAFBF, 0x49500684, 0x79823EE1, 0x28F4764E, 0x18264E2B, + 0x18B8EA18, 0x286AD27D, 0x791C9AD2, 0x49CEA2B7, 0xDBF00B8C, 0xEB2233E9, 0xBA547B46, 0x8A864323, + 0x9BC55FC1, 0xAB1767A4, 0xFA612F0B, 0xCAB3176E, 0x588DBE55, 0x685F8630, 0x3929CE9F, 0x09FBF6FA, + 0x1BAFF75B, 0x2B7DCF3E, 0x7A0B8791, 0x4AD9BFF4, 0xD8E716CF, 0xE8352EAA, 0xB9436605, 0x89915E60, + 0x98D24282, 0xA8007AE7, 0xF9763248, 0xC9A40A2D, 0x5B9AA316, 0x6B489B73, 0x3A3ED3DC, 0x0AECEBB9, + 0x1E96D09E, 0x2E44E8FB, 0x7F32A054, 0x4FE09831, 0xDDDE310A, 0xED0C096F, 0xBC7A41C0, 0x8CA879A5, + 0x9DEB6547, 0xAD395D22, 0xFC4F158D, 0xCC9D2DE8, 0x5EA384D3, 0x6E71BCB6, 0x3F07F419, 0x0FD5CC7C, + 0x1D81CDDD, 0x2D53F5B8, 0x7C25BD17, 0x4CF78572, 0xDEC92C49, 0xEE1B142C, 0xBF6D5C83, 0x8FBF64E6, + 0x9EFC7804, 0xAE2E4061, 0xFF5808CE, 0xCF8A30AB, 0x5DB49990, 0x6D66A1F5, 0x3C10E95A, 0x0CC2D13F, + 0x14E49F14, 0x2436A771, 0x7540EFDE, 0x4592D7BB, 0xD7AC7E80, 0xE77E46E5, 0xB6080E4A, 0x86DA362F, + 0x97992ACD, 0xA74B12A8, 0xF63D5A07, 0xC6EF6262, 0x54D1CB59, 0x6403F33C, 0x3575BB93, 0x05A783F6, + 0x17F38257, 0x2721BA32, 0x7657F29D, 0x4685CAF8, 0xD4BB63C3, 0xE4695BA6, 0xB51F1309, 0x85CD2B6C, + 0x948E378E, 0xA45C0FEB, 0xF52A4744, 0xC5F87F21, 0x57C6D61A, 0x6714EE7F, 0x3662A6D0, 0x06B09EB5, + 0x12CAA592, 0x22189DF7, 0x736ED558, 0x43BCED3D, 0xD1824406, 0xE1507C63, 0xB02634CC, 0x80F40CA9, + 0x91B7104B, 0xA165282E, 0xF0136081, 0xC0C158E4, 0x52FFF1DF, 0x622DC9BA, 0x335B8115, 0x0389B970, + 0x11DDB8D1, 0x210F80B4, 0x7079C81B, 0x40ABF07E, 0xD2955945, 0xE2476120, 0xB331298F, 0x83E311EA, + 0x92A00D08, 0xA272356D, 0xF3047DC2, 0xC3D645A7, 0x51E8EC9C, 0x613AD4F9, 0x304C9C56, 0x009EA433, + 0x00000000, 0x3171D430, 0x62E3A860, 0x53927C50, 0xC5C750C0, 0xF4B684F0, 0xA724F8A0, 0x96552C90, + 0x8E62D771, 0xBF130341, 0xEC817F11, 0xDDF0AB21, 0x4BA587B1, 0x7AD45381, 0x29462FD1, 0x1837FBE1, + 0x1929D813, 0x28580C23, 0x7BCA7073, 0x4ABBA443, 0xDCEE88D3, 0xED9F5CE3, 0xBE0D20B3, 0x8F7CF483, + 0x974B0F62, 0xA63ADB52, 0xF5A8A702, 0xC4D97332, 0x528C5FA2, 0x63FD8B92, 0x306FF7C2, 0x011E23F2, + 0x3253B026, 0x03226416, 0x50B01846, 0x61C1CC76, 0xF794E0E6, 0xC6E534D6, 0x95774886, 0xA4069CB6, + 0xBC316757, 0x8D40B367, 0xDED2CF37, 0xEFA31B07, 0x79F63797, 0x4887E3A7, 0x1B159FF7, 0x2A644BC7, + 0x2B7A6835, 0x1A0BBC05, 0x4999C055, 0x78E81465, 0xEEBD38F5, 0xDFCCECC5, 0x8C5E9095, 0xBD2F44A5, + 0xA518BF44, 0x94696B74, 0xC7FB1724, 0xF68AC314, 0x60DFEF84, 0x51AE3BB4, 0x023C47E4, 0x334D93D4, + 0x64A7604C, 0x55D6B47C, 0x0644C82C, 0x37351C1C, 0xA160308C, 0x9011E4BC, 0xC38398EC, 0xF2F24CDC, + 0xEAC5B73D, 0xDBB4630D, 0x88261F5D, 0xB957CB6D, 0x2F02E7FD, 0x1E7333CD, 0x4DE14F9D, 0x7C909BAD, + 0x7D8EB85F, 0x4CFF6C6F, 0x1F6D103F, 0x2E1CC40F, 0xB849E89F, 0x89383CAF, 0xDAAA40FF, 0xEBDB94CF, + 0xF3EC6F2E, 0xC29DBB1E, 0x910FC74E, 0xA07E137E, 0x362B3FEE, 0x075AEBDE, 0x54C8978E, 0x65B943BE, + 0x56F4D06A, 0x6785045A, 0x3417780A, 0x0566AC3A, 0x933380AA, 0xA242549A, 0xF1D028CA, 0xC0A1FCFA, + 0xD896071B, 0xE9E7D32B, 0xBA75AF7B, 0x8B047B4B, 0x1D5157DB, 0x2C2083EB, 0x7FB2FFBB, 0x4EC32B8B, + 0x4FDD0879, 0x7EACDC49, 0x2D3EA019, 0x1C4F7429, 0x8A1A58B9, 0xBB6B8C89, 0xE8F9F0D9, 0xD98824E9, + 0xC1BFDF08, 0xF0CE0B38, 0xA35C7768, 0x922DA358, 0x04788FC8, 0x35095BF8, 0x669B27A8, 0x57EAF398, + 0xC94EC098, 0xF83F14A8, 0xABAD68F8, 0x9ADCBCC8, 0x0C899058, 0x3DF84468, 0x6E6A3838, 0x5F1BEC08, + 0x472C17E9, 0x765DC3D9, 0x25CFBF89, 0x14BE6BB9, 0x82EB4729, 0xB39A9319, 0xE008EF49, 0xD1793B79, + 0xD067188B, 0xE116CCBB, 0xB284B0EB, 0x83F564DB, 0x15A0484B, 0x24D19C7B, 0x7743E02B, 0x4632341B, + 0x5E05CFFA, 0x6F741BCA, 0x3CE6679A, 0x0D97B3AA, 0x9BC29F3A, 0xAAB34B0A, 0xF921375A, 0xC850E36A, + 0xFB1D70BE, 0xCA6CA48E, 0x99FED8DE, 0xA88F0CEE, 0x3EDA207E, 0x0FABF44E, 0x5C39881E, 0x6D485C2E, + 0x757FA7CF, 0x440E73FF, 0x179C0FAF, 0x26EDDB9F, 0xB0B8F70F, 0x81C9233F, 0xD25B5F6F, 0xE32A8B5F, + 0xE234A8AD, 0xD3457C9D, 0x80D700CD, 0xB1A6D4FD, 0x27F3F86D, 0x16822C5D, 0x4510500D, 0x7461843D, + 0x6C567FDC, 0x5D27ABEC, 0x0EB5D7BC, 0x3FC4038C, 0xA9912F1C, 0x98E0FB2C, 0xCB72877C, 0xFA03534C, + 0xADE9A0D4, 0x9C9874E4, 0xCF0A08B4, 0xFE7BDC84, 0x682EF014, 0x595F2424, 0x0ACD5874, 0x3BBC8C44, + 0x238B77A5, 0x12FAA395, 0x4168DFC5, 0x70190BF5, 0xE64C2765, 0xD73DF355, 0x84AF8F05, 0xB5DE5B35, + 0xB4C078C7, 0x85B1ACF7, 0xD623D0A7, 0xE7520497, 0x71072807, 0x4076FC37, 0x13E48067, 0x22955457, + 0x3AA2AFB6, 0x0BD37B86, 0x584107D6, 0x6930D3E6, 0xFF65FF76, 0xCE142B46, 0x9D865716, 0xACF78326, + 0x9FBA10F2, 0xAECBC4C2, 0xFD59B892, 0xCC286CA2, 0x5A7D4032, 0x6B0C9402, 0x389EE852, 0x09EF3C62, + 0x11D8C783, 0x20A913B3, 0x733B6FE3, 0x424ABBD3, 0xD41F9743, 0xE56E4373, 0xB6FC3F23, 0x878DEB13, + 0x8693C8E1, 0xB7E21CD1, 0xE4706081, 0xD501B4B1, 0x43549821, 0x72254C11, 0x21B73041, 0x10C6E471, + 0x08F11F90, 0x3980CBA0, 0x6A12B7F0, 0x5B6363C0, 0xCD364F50, 0xFC479B60, 0xAFD5E730, 0x9EA43300, + 0x00000000, 0x9771F7C1, 0x2B0F9973, 0xBC7E6EB2, 0x561F32E6, 0xC16EC527, 0x7D10AB95, 0xEA615C54, + 0xAC3E65CC, 0x3B4F920D, 0x8731FCBF, 0x10400B7E, 0xFA21572A, 0x6D50A0EB, 0xD12ECE59, 0x465F3998, + 0x5D90BD69, 0xCAE14AA8, 0x769F241A, 0xE1EED3DB, 0x0B8F8F8F, 0x9CFE784E, 0x208016FC, 0xB7F1E13D, + 0xF1AED8A5, 0x66DF2F64, 0xDAA141D6, 0x4DD0B617, 0xA7B1EA43, 0x30C01D82, 0x8CBE7330, 0x1BCF84F1, + 0xBB217AD2, 0x2C508D13, 0x902EE3A1, 0x075F1460, 0xED3E4834, 0x7A4FBFF5, 0xC631D147, 0x51402686, + 0x171F1F1E, 0x806EE8DF, 0x3C10866D, 0xAB6171AC, 0x41002DF8, 0xD671DA39, 0x6A0FB48B, 0xFD7E434A, + 0xE6B1C7BB, 0x71C0307A, 0xCDBE5EC8, 0x5ACFA909, 0xB0AEF55D, 0x27DF029C, 0x9BA16C2E, 0x0CD09BEF, + 0x4A8FA277, 0xDDFE55B6, 0x61803B04, 0xF6F1CCC5, 0x1C909091, 0x8BE16750, 0x379F09E2, 0xA0EEFE23, + 0x73AE8355, 0xE4DF7494, 0x58A11A26, 0xCFD0EDE7, 0x25B1B1B3, 0xB2C04672, 0x0EBE28C0, 0x99CFDF01, + 0xDF90E699, 0x48E11158, 0xF49F7FEA, 0x63EE882B, 0x898FD47F, 0x1EFE23BE, 0xA2804D0C, 0x35F1BACD, + 0x2E3E3E3C, 0xB94FC9FD, 0x0531A74F, 0x9240508E, 0x78210CDA, 0xEF50FB1B, 0x532E95A9, 0xC45F6268, + 0x82005BF0, 0x1571AC31, 0xA90FC283, 0x3E7E3542, 0xD41F6916, 0x436E9ED7, 0xFF10F065, 0x686107A4, + 0xC88FF987, 0x5FFE0E46, 0xE38060F4, 0x74F19735, 0x9E90CB61, 0x09E13CA0, 0xB59F5212, 0x22EEA5D3, + 0x64B19C4B, 0xF3C06B8A, 0x4FBE0538, 0xD8CFF2F9, 0x32AEAEAD, 0xA5DF596C, 0x19A137DE, 0x8ED0C01F, + 0x951F44EE, 0x026EB32F, 0xBE10DD9D, 0x29612A5C, 0xC3007608, 0x547181C9, 0xE80FEF7B, 0x7F7E18BA, + 0x39212122, 0xAE50D6E3, 0x122EB851, 0x855F4F90, 0x6F3E13C4, 0xF84FE405, 0x44318AB7, 0xD3407D76, + 0xE75D06AA, 0x702CF16B, 0xCC529FD9, 0x5B236818, 0xB142344C, 0x2633C38D, 0x9A4DAD3F, 0x0D3C5AFE, + 0x4B636366, 0xDC1294A7, 0x606CFA15, 0xF71D0DD4, 0x1D7C5180, 0x8A0DA641, 0x3673C8F3, 0xA1023F32, + 0xBACDBBC3, 0x2DBC4C02, 0x91C222B0, 0x06B3D571, 0xECD28925, 0x7BA37EE4, 0xC7DD1056, 0x50ACE797, + 0x16F3DE0F, 0x818229CE, 0x3DFC477C, 0xAA8DB0BD, 0x40ECECE9, 0xD79D1B28, 0x6BE3759A, 0xFC92825B, + 0x5C7C7C78, 0xCB0D8BB9, 0x7773E50B, 0xE00212CA, 0x0A634E9E, 0x9D12B95F, 0x216CD7ED, 0xB61D202C, + 0xF04219B4, 0x6733EE75, 0xDB4D80C7, 0x4C3C7706, 0xA65D2B52, 0x312CDC93, 0x8D52B221, 0x1A2345E0, + 0x01ECC111, 0x969D36D0, 0x2AE35862, 0xBD92AFA3, 0x57F3F3F7, 0xC0820436, 0x7CFC6A84, 0xEB8D9D45, + 0xADD2A4DD, 0x3AA3531C, 0x86DD3DAE, 0x11ACCA6F, 0xFBCD963B, 0x6CBC61FA, 0xD0C20F48, 0x47B3F889, + 0x94F385FF, 0x0382723E, 0xBFFC1C8C, 0x288DEB4D, 0xC2ECB719, 0x559D40D8, 0xE9E32E6A, 0x7E92D9AB, + 0x38CDE033, 0xAFBC17F2, 0x13C27940, 0x84B38E81, 0x6ED2D2D5, 0xF9A32514, 0x45DD4BA6, 0xD2ACBC67, + 0xC9633896, 0x5E12CF57, 0xE26CA1E5, 0x751D5624, 0x9F7C0A70, 0x080DFDB1, 0xB4739303, 0x230264C2, + 0x655D5D5A, 0xF22CAA9B, 0x4E52C429, 0xD92333E8, 0x33426FBC, 0xA433987D, 0x184DF6CF, 0x8F3C010E, + 0x2FD2FF2D, 0xB8A308EC, 0x04DD665E, 0x93AC919F, 0x79CDCDCB, 0xEEBC3A0A, 0x52C254B8, 0xC5B3A379, + 0x83EC9AE1, 0x149D6D20, 0xA8E30392, 0x3F92F453, 0xD5F3A807, 0x42825FC6, 0xFEFC3174, 0x698DC6B5, + 0x72424244, 0xE533B585, 0x594DDB37, 0xCE3C2CF6, 0x245D70A2, 0xB32C8763, 0x0F52E9D1, 0x98231E10, + 0xDE7C2788, 0x490DD049, 0xF573BEFB, 0x6202493A, 0x8863156E, 0x1F12E2AF, 0xA36C8C1D, 0x341D7BDC, + 0x00000000, 0xCB567BA5, 0x934081BB, 0x5816FA1E, 0x236D7587, 0xE83B0E22, 0xB02DF43C, 0x7B7B8F99, + 0x46DAEB0E, 0x8D8C90AB, 0xD59A6AB5, 0x1ECC1110, 0x65B79E89, 0xAEE1E52C, 0xF6F71F32, 0x3DA16497, + 0x8DB5D61C, 0x46E3ADB9, 0x1EF557A7, 0xD5A32C02, 0xAED8A39B, 0x658ED83E, 0x3D982220, 0xF6CE5985, + 0xCB6F3D12, 0x003946B7, 0x582FBCA9, 0x9379C70C, 0xE8024895, 0x23543330, 0x7B42C92E, 0xB014B28B, + 0x1E87DAC9, 0xD5D1A16C, 0x8DC75B72, 0x469120D7, 0x3DEAAF4E, 0xF6BCD4EB, 0xAEAA2EF5, 0x65FC5550, + 0x585D31C7, 0x930B4A62, 0xCB1DB07C, 0x004BCBD9, 0x7B304440, 0xB0663FE5, 0xE870C5FB, 0x2326BE5E, + 0x93320CD5, 0x58647770, 0x00728D6E, 0xCB24F6CB, 0xB05F7952, 0x7B0902F7, 0x231FF8E9, 0xE849834C, + 0xD5E8E7DB, 0x1EBE9C7E, 0x46A86660, 0x8DFE1DC5, 0xF685925C, 0x3DD3E9F9, 0x65C513E7, 0xAE936842, + 0x3D0FB592, 0xF659CE37, 0xAE4F3429, 0x65194F8C, 0x1E62C015, 0xD534BBB0, 0x8D2241AE, 0x46743A0B, + 0x7BD55E9C, 0xB0832539, 0xE895DF27, 0x23C3A482, 0x58B82B1B, 0x93EE50BE, 0xCBF8AAA0, 0x00AED105, + 0xB0BA638E, 0x7BEC182B, 0x23FAE235, 0xE8AC9990, 0x93D71609, 0x58816DAC, 0x009797B2, 0xCBC1EC17, + 0xF6608880, 0x3D36F325, 0x6520093B, 0xAE76729E, 0xD50DFD07, 0x1E5B86A2, 0x464D7CBC, 0x8D1B0719, + 0x23886F5B, 0xE8DE14FE, 0xB0C8EEE0, 0x7B9E9545, 0x00E51ADC, 0xCBB36179, 0x93A59B67, 0x58F3E0C2, + 0x65528455, 0xAE04FFF0, 0xF61205EE, 0x3D447E4B, 0x463FF1D2, 0x8D698A77, 0xD57F7069, 0x1E290BCC, + 0xAE3DB947, 0x656BC2E2, 0x3D7D38FC, 0xF62B4359, 0x8D50CCC0, 0x4606B765, 0x1E104D7B, 0xD54636DE, + 0xE8E75249, 0x23B129EC, 0x7BA7D3F2, 0xB0F1A857, 0xCB8A27CE, 0x00DC5C6B, 0x58CAA675, 0x939CDDD0, + 0x7A1F6B24, 0xB1491081, 0xE95FEA9F, 0x2209913A, 0x59721EA3, 0x92246506, 0xCA329F18, 0x0164E4BD, + 0x3CC5802A, 0xF793FB8F, 0xAF850191, 0x64D37A34, 0x1FA8F5AD, 0xD4FE8E08, 0x8CE87416, 0x47BE0FB3, + 0xF7AABD38, 0x3CFCC69D, 0x64EA3C83, 0xAFBC4726, 0xD4C7C8BF, 0x1F91B31A, 0x47874904, 0x8CD132A1, + 0xB1705636, 0x7A262D93, 0x2230D78D, 0xE966AC28, 0x921D23B1, 0x594B5814, 0x015DA20A, 0xCA0BD9AF, + 0x6498B1ED, 0xAFCECA48, 0xF7D83056, 0x3C8E4BF3, 0x47F5C46A, 0x8CA3BFCF, 0xD4B545D1, 0x1FE33E74, + 0x22425AE3, 0xE9142146, 0xB102DB58, 0x7A54A0FD, 0x012F2F64, 0xCA7954C1, 0x926FAEDF, 0x5939D57A, + 0xE92D67F1, 0x227B1C54, 0x7A6DE64A, 0xB13B9DEF, 0xCA401276, 0x011669D3, 0x590093CD, 0x9256E868, + 0xAFF78CFF, 0x64A1F75A, 0x3CB70D44, 0xF7E176E1, 0x8C9AF978, 0x47CC82DD, 0x1FDA78C3, 0xD48C0366, + 0x4710DEB6, 0x8C46A513, 0xD4505F0D, 0x1F0624A8, 0x647DAB31, 0xAF2BD094, 0xF73D2A8A, 0x3C6B512F, + 0x01CA35B8, 0xCA9C4E1D, 0x928AB403, 0x59DCCFA6, 0x22A7403F, 0xE9F13B9A, 0xB1E7C184, 0x7AB1BA21, + 0xCAA508AA, 0x01F3730F, 0x59E58911, 0x92B3F2B4, 0xE9C87D2D, 0x229E0688, 0x7A88FC96, 0xB1DE8733, + 0x8C7FE3A4, 0x47299801, 0x1F3F621F, 0xD46919BA, 0xAF129623, 0x6444ED86, 0x3C521798, 0xF7046C3D, + 0x5997047F, 0x92C17FDA, 0xCAD785C4, 0x0181FE61, 0x7AFA71F8, 0xB1AC0A5D, 0xE9BAF043, 0x22EC8BE6, + 0x1F4DEF71, 0xD41B94D4, 0x8C0D6ECA, 0x475B156F, 0x3C209AF6, 0xF776E153, 0xAF601B4D, 0x643660E8, + 0xD422D263, 0x1F74A9C6, 0x476253D8, 0x8C34287D, 0xF74FA7E4, 0x3C19DC41, 0x640F265F, 0xAF595DFA, + 0x92F8396D, 0x59AE42C8, 0x01B8B8D6, 0xCAEEC373, 0xB1954CEA, 0x7AC3374F, 0x22D5CD51, 0xE983B6F4, + 0x00000000, 0xF43ED648, 0xED91DA61, 0x19AF0C29, 0xDECFC233, 0x2AF1147B, 0x335E1852, 0xC760CE1A, + 0xB873F297, 0x4C4D24DF, 0x55E228F6, 0xA1DCFEBE, 0x66BC30A4, 0x9282E6EC, 0x8B2DEAC5, 0x7F133C8D, + 0x750B93DF, 0x81354597, 0x989A49BE, 0x6CA49FF6, 0xABC451EC, 0x5FFA87A4, 0x46558B8D, 0xB26B5DC5, + 0xCD786148, 0x3946B700, 0x20E9BB29, 0xD4D76D61, 0x13B7A37B, 0xE7897533, 0xFE26791A, 0x0A18AF52, + 0xEA1727BE, 0x1E29F1F6, 0x0786FDDF, 0xF3B82B97, 0x34D8E58D, 0xC0E633C5, 0xD9493FEC, 0x2D77E9A4, + 0x5264D529, 0xA65A0361, 0xBFF50F48, 0x4BCBD900, 0x8CAB171A, 0x7895C152, 0x613ACD7B, 0x95041B33, + 0x9F1CB461, 0x6B226229, 0x728D6E00, 0x86B3B848, 0x41D37652, 0xB5EDA01A, 0xAC42AC33, 0x587C7A7B, + 0x276F46F6, 0xD35190BE, 0xCAFE9C97, 0x3EC04ADF, 0xF9A084C5, 0x0D9E528D, 0x14315EA4, 0xE00F88EC, + 0xD1C2398D, 0x25FCEFC5, 0x3C53E3EC, 0xC86D35A4, 0x0F0DFBBE, 0xFB332DF6, 0xE29C21DF, 0x16A2F797, + 0x69B1CB1A, 0x9D8F1D52, 0x8420117B, 0x701EC733, 0xB77E0929, 0x4340DF61, 0x5AEFD348, 0xAED10500, + 0xA4C9AA52, 0x50F77C1A, 0x49587033, 0xBD66A67B, 0x7A066861, 0x8E38BE29, 0x9797B200, 0x63A96448, + 0x1CBA58C5, 0xE8848E8D, 0xF12B82A4, 0x051554EC, 0xC2759AF6, 0x364B4CBE, 0x2FE44097, 0xDBDA96DF, + 0x3BD51E33, 0xCFEBC87B, 0xD644C452, 0x227A121A, 0xE51ADC00, 0x11240A48, 0x088B0661, 0xFCB5D029, + 0x83A6ECA4, 0x77983AEC, 0x6E3736C5, 0x9A09E08D, 0x5D692E97, 0xA957F8DF, 0xB0F8F4F6, 0x44C622BE, + 0x4EDE8DEC, 0xBAE05BA4, 0xA34F578D, 0x577181C5, 0x90114FDF, 0x642F9997, 0x7D8095BE, 0x89BE43F6, + 0xF6AD7F7B, 0x0293A933, 0x1B3CA51A, 0xEF027352, 0x2862BD48, 0xDC5C6B00, 0xC5F36729, 0x31CDB161, + 0xA66805EB, 0x5256D3A3, 0x4BF9DF8A, 0xBFC709C2, 0x78A7C7D8, 0x8C991190, 0x95361DB9, 0x6108CBF1, + 0x1E1BF77C, 0xEA252134, 0xF38A2D1D, 0x07B4FB55, 0xC0D4354F, 0x34EAE307, 0x2D45EF2E, 0xD97B3966, + 0xD3639634, 0x275D407C, 0x3EF24C55, 0xCACC9A1D, 0x0DAC5407, 0xF992824F, 0xE03D8E66, 0x1403582E, + 0x6B1064A3, 0x9F2EB2EB, 0x8681BEC2, 0x72BF688A, 0xB5DFA690, 0x41E170D8, 0x584E7CF1, 0xAC70AAB9, + 0x4C7F2255, 0xB841F41D, 0xA1EEF834, 0x55D02E7C, 0x92B0E066, 0x668E362E, 0x7F213A07, 0x8B1FEC4F, + 0xF40CD0C2, 0x0032068A, 0x199D0AA3, 0xEDA3DCEB, 0x2AC312F1, 0xDEFDC4B9, 0xC752C890, 0x336C1ED8, + 0x3974B18A, 0xCD4A67C2, 0xD4E56BEB, 0x20DBBDA3, 0xE7BB73B9, 0x1385A5F1, 0x0A2AA9D8, 0xFE147F90, + 0x8107431D, 0x75399555, 0x6C96997C, 0x98A84F34, 0x5FC8812E, 0xABF65766, 0xB2595B4F, 0x46678D07, + 0x77AA3C66, 0x8394EA2E, 0x9A3BE607, 0x6E05304F, 0xA965FE55, 0x5D5B281D, 0x44F42434, 0xB0CAF27C, + 0xCFD9CEF1, 0x3BE718B9, 0x22481490, 0xD676C2D8, 0x11160CC2, 0xE528DA8A, 0xFC87D6A3, 0x08B900EB, + 0x02A1AFB9, 0xF69F79F1, 0xEF3075D8, 0x1B0EA390, 0xDC6E6D8A, 0x2850BBC2, 0x31FFB7EB, 0xC5C161A3, + 0xBAD25D2E, 0x4EEC8B66, 0x5743874F, 0xA37D5107, 0x641D9F1D, 0x90234955, 0x898C457C, 0x7DB29334, + 0x9DBD1BD8, 0x6983CD90, 0x702CC1B9, 0x841217F1, 0x4372D9EB, 0xB74C0FA3, 0xAEE3038A, 0x5ADDD5C2, + 0x25CEE94F, 0xD1F03F07, 0xC85F332E, 0x3C61E566, 0xFB012B7C, 0x0F3FFD34, 0x1690F11D, 0xE2AE2755, + 0xE8B68807, 0x1C885E4F, 0x05275266, 0xF119842E, 0x36794A34, 0xC2479C7C, 0xDBE89055, 0x2FD6461D, + 0x50C57A90, 0xA4FBACD8, 0xBD54A0F1, 0x496A76B9, 0x8E0AB8A3, 0x7A346EEB, 0x639B62C2, 0x97A5B48A, + 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504, + 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, + 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0, + 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A, + 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, + 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447, + 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929, + 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, + 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36, + 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC, + 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, + 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358, + 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF, + 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, + 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B, + 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1, + 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, + 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA, + 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4, + 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, + 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9, + 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223, + 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, + 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97, + 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852, + 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, + 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6, + 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C, + 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, + 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911, + 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F, + 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5, + 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089, + 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, + 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F, + 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C, + 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, + 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67, + 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992, + 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, + 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3, + 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0, + 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, + 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006, + 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E, + 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, + 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8, + 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB, + 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, + 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E, + 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB, + 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, + 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0, + 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093, + 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, + 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35, + 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907, + 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, + 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1, + 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2, + 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, + 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9, + 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C, + 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F, + 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD, + 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, + 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93, + 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C, + 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, + 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F, + 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E, + 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, + 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746, + 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59, + 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, + 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67, + 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB, + 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, + 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5, + 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA, + 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, + 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364, + 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45, + 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, + 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6, + 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9, + 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, + 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7, + 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090, + 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, + 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE, + 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1, + 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, + 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02, + 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623, + 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C, + 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44, + 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, + 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97, + 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406, + 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, + 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082, + 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0, + 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, + 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA, + 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B, + 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, + 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8, + 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD, + 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, + 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E, + 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF, + 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, + 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089, + 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB, + 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, + 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F, + 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE, + 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, + 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D, + 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6, + 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, + 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065, + 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4, + 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, + 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70, + 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532, + 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3, + 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, + 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, + 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, + 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, + 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, + 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, + 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, + 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, + 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, + 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, + 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, + 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, + 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, + 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, + 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, + 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, + 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, + 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, + 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, + 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, + 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, + 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, + 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, + 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, + 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, + 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, + 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, + 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, + 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, + 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, + 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, + 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842, + 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, + 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, + 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, + 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, + 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, + 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, + 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, + 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, + 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, + 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, + 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, + 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, + 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, + 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, + 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, + 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, + 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, + 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, + 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, + 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, + 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, + 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, + 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, + 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, + 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, + 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, + 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, + 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, + 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, + 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, + 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, + 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8, + 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, + 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, + 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, + 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, + 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, + 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, + 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, + 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, + 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, + 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, + 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, + 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, + 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, + 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, + 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, + 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, + 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, + 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, + 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, + 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, + 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, + 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, + 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, + 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, + 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, + 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, + 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, + 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, + 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, + 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, + 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, + 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483, + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}; +#endif // ENABLE_16B +/* + * These functions take advantage of fixed input sizes to + * calculate CRCs with simple table lookups and no bit-shifting. + * The faster single-argument versions ('f' suffix) can be used + * on the first (or only) word of a message. + */ +#define pCRC ((uint8_t*)&crc) +#if ENABLE_1B +uint32_t fastCrc32c1(uint32_t crc, const uint8_t* data) +{ + return (crc32cTable1[pCRC[0] + 256 * 0] ^ crc32cTable1[pCRC[1] + 256 * 1]) ^ + (crc32cTable1[pCRC[2] + 256 * 2] ^ crc32cTable1[pCRC[3] + 256 * 3]) ^ + (crc32cTable1[data[0] + 256 * 4]); +} + +uint32_t fastCrc32c1f(const uint8_t* data) +{ + return (crc32cTable1[data[0] + 256 * 4]); +} +#endif // ENABLE_1B + +#if ENABLE_2B +uint32_t fastCrc32c2(uint32_t crc, const uint8_t* data) +{ + return (crc32cTable2[pCRC[0] + 256 * 0] ^ crc32cTable2[pCRC[1] + 256 * 1]) ^ + (crc32cTable2[pCRC[2] + 256 * 2] ^ crc32cTable2[pCRC[3] + 256 * 3]) ^ + (crc32cTable2[data[0] + 256 * 4] ^ crc32cTable2[data[1] + 256 * 5]); +} + +uint32_t fastCrc32c2f(const uint8_t* data) +{ + return (crc32cTable2[data[0] + 256 * 4] ^ crc32cTable2[data[1] + 256 * 5]); +} +#endif // ENABLE_2B + +#if ENABLE_4B +uint32_t fastCrc32c4(uint32_t crc, const uint8_t* data) +{ + return (crc32cTable4[pCRC[0] + 256 * 0] ^ crc32cTable4[pCRC[1] + 256 * 1]) ^ + (crc32cTable4[pCRC[2] + 256 * 2] ^ crc32cTable4[pCRC[3] + 256 * 3]) ^ + (crc32cTable4[data[0] + 256 * 4] ^ crc32cTable4[data[1] + 256 * 5]) ^ + (crc32cTable4[data[2] + 256 * 6] ^ crc32cTable4[data[3] + 256 * 7]); +} + +uint32_t fastCrc32c4f(const uint8_t* data) +{ + return (crc32cTable4[data[0] + 256 * 4] ^ crc32cTable4[data[1] + 256 * 5]) ^ + (crc32cTable4[data[2] + 256 * 6] ^ crc32cTable4[data[3] + 256 * 7]); +} +#endif // ENABLE_4B + +#if ENABLE_8B +uint32_t fastCrc32c8(uint32_t crc, const uint8_t* data) +{ + return (crc32cTable8[pCRC[0] + 256 * 0] ^ crc32cTable8[pCRC[1] + 256 * 1]) ^ + (crc32cTable8[pCRC[2] + 256 * 2] ^ crc32cTable8[pCRC[3] + 256 * 3]) ^ + (crc32cTable8[data[0] + 256 * 4] ^ crc32cTable8[data[1] + 256 * 5]) ^ + (crc32cTable8[data[2] + 256 * 6] ^ crc32cTable8[data[3] + 256 * 7]) ^ + (crc32cTable8[data[4] + 256 * 8] ^ crc32cTable8[data[5] + 256 * 9]) ^ + (crc32cTable8[data[6] + 256 * 10] ^ crc32cTable8[data[7] + 256 * 11]); +} +uint32_t fastCrc32c8f(const uint8_t* data) +{ + return (crc32cTable8[data[0] + 256 * 4] ^ crc32cTable8[data[1] + 256 * 5]) ^ + (crc32cTable8[data[2] + 256 * 6] ^ crc32cTable8[data[3] + 256 * 7]) ^ + (crc32cTable8[data[4] + 256 * 8] ^ crc32cTable8[data[5] + 256 * 9]) ^ + (crc32cTable8[data[6] + 256 * 10] ^ crc32cTable8[data[7] + 256 * 11]); +} +#endif // ENABLE_8B + +#if ENABLE_16B +uint32_t fastCrc32c16(uint32_t crc, const uint8_t* data) +{ + return (crc32cTable16[pCRC[0] + 256 * 0] ^ crc32cTable16[pCRC[1] + 256 * 1]) ^ + (crc32cTable16[pCRC[2] + 256 * 2] ^ crc32cTable16[pCRC[3] + 256 * 3]) ^ + (crc32cTable16[data[0] + 256 * 4] ^ crc32cTable16[data[1] + 256 * 5]) ^ + (crc32cTable16[data[2] + 256 * 6] ^ crc32cTable16[data[3] + 256 * 7]) ^ + (crc32cTable16[data[4] + 256 * 8] ^ crc32cTable16[data[5] + 256 * 9]) ^ + (crc32cTable16[data[6] + 256 * 10] ^ crc32cTable16[data[7] + 256 * 11]) ^ + (crc32cTable16[data[8] + 256 * 12] ^ crc32cTable16[data[9] + 256 * 13]) ^ + (crc32cTable16[data[10] + 256 * 14] ^ crc32cTable16[data[11] + 256 * 15]) ^ + (crc32cTable16[data[12] + 256 * 16] ^ crc32cTable16[data[13] + 256 * 17]) ^ + (crc32cTable16[data[14] + 256 * 18] ^ crc32cTable16[data[15] + 256 * 19]); +} + +uint32_t fastCrc32c16f(const uint8_t* data) +{ + return (crc32cTable16[data[0] + 256 * 4] ^ crc32cTable16[data[1] + 256 * 5]) ^ + (crc32cTable16[data[2] + 256 * 6] ^ crc32cTable16[data[3] + 256 * 7]) ^ + (crc32cTable16[data[4] + 256 * 8] ^ crc32cTable16[data[5] + 256 * 9]) ^ + (crc32cTable16[data[6] + 256 * 10] ^ crc32cTable16[data[7] + 256 * 11]) ^ + (crc32cTable16[data[8] + 256 * 12] ^ crc32cTable16[data[9] + 256 * 13]) ^ + (crc32cTable16[data[10] + 256 * 14] ^ crc32cTable16[data[11] + 256 * 15]) ^ + (crc32cTable16[data[12] + 256 * 16] ^ crc32cTable16[data[13] + 256 * 17]) ^ + (crc32cTable16[data[14] + 256 * 18] ^ crc32cTable16[data[15] + 256 * 19]); +} +#endif // ENABLE_16B +#undef pCRC + +#if 0 +// This function was used to generate crc32cTable* and fastCrc32c* above +void optimizeFixedLenCrc32c(int len) { + uint8_t buf[len+4]; + int b, i; + uint32_t *init = (uint32_t*)buf; + uint32_t crc; + uint8_t *msg = buf + 4; + printf("static const uint32_t crc32cTable%d[256*(4+%d)] = {\n",len,len); + printf(" "); + for(b = 0; b < len+4; b++) { + memset(buf,0,sizeof(buf)); + for(i = 0; i < 256; i++) { + buf[b] = i; + crc = singletable_crc32c(*init, msg, len); + printf(" 0x%08lX",(long unsigned int)crc); + if(b==len+3 && i==255) + printf("\n};\n"); + else if((i+1) % 8 == 0) + printf(",\n "); + else + printf(","); + } + } + printf("\n"); + printf("#define pCRC ((uint8_t*)&crc)\n"); + printf("inline uint32_t fastCrc32c%d(uint32_t crc, const uint8_t *data) {\n",len); + printf(" return (crc32cTable%d[pCRC[ 0] + 256 * 0] ^ crc32cTable%d[pCRC[ 1] + 256 * 1])\n",len,len); + printf(" ^ (crc32cTable%d[pCRC[ 2] + 256 * 2] ^ crc32cTable%d[pCRC[ 3] + 256 * 3])",len,len); + for(b = 0; b < len-1; b+=2) { + printf("\n ^ (crc32cTable%d[data[%2d] + 256 * %2d] ^ crc32cTable%d[data[%2d] + 256 * %2d])",len,b,b+4,len,b+1,b+5); + } + if(b < len) + printf("\n ^ (crc32cTable%d[data[%2d] + 256 * %2d])",len,b,b+4); + printf(";\n}\n"); + printf("\n"); + printf("inline uint32_t fastCrc32c%df(const uint8_t *data) {",len); + for(b = 0; b < len-1; b+=2) { + printf("\n %s (crc32cTable%d[data[%2d] + 256 * %2d] ^ crc32cTable%d[data[%2d] + 256 * %2d])",b?" ^":"return",len,b,b+4,len,b+1,b+5); + } + if(b < len) + printf("\n %s (crc32cTable%d[data[%2d] + 256 * %2d])",b?" ^":"return",len,b,b+4); + printf(";\n}\n"); + printf("#undef pCRC\n"); +} +#endif diff --git a/thirdparty/dragen/src/host/infra/public/crc32_hw.h b/thirdparty/dragen/src/host/infra/public/crc32_hw.h new file mode 100644 index 0000000..6733700 --- /dev/null +++ b/thirdparty/dragen/src/host/infra/public/crc32_hw.h @@ -0,0 +1,17 @@ +#ifndef __CRC32_HW_H__ +#define __CRC32_HW_H__ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t crc32c_hw(uint32_t crc, const void* buf, size_t len); +bool machine_has_sse42(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/dragen/src/host/infra/public/fast_nonvector_crc32c.h b/thirdparty/dragen/src/host/infra/public/fast_nonvector_crc32c.h new file mode 100644 index 0000000..039e09e --- /dev/null +++ b/thirdparty/dragen/src/host/infra/public/fast_nonvector_crc32c.h @@ -0,0 +1,23 @@ +#ifndef __FAST_NONVECTOR_CRC32C_H__ +#define __FAST_NONVECTOR_CRC32C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t fastCrc32c1(uint32_t crc, const uint8_t* data); +uint32_t fastCrc32c1f(const uint8_t* data); +uint32_t fastCrc32c2(uint32_t crc, const uint8_t* data); +uint32_t fastCrc32c2f(const uint8_t* data); +uint32_t fastCrc32c4(uint32_t crc, const uint8_t* data); +uint32_t fastCrc32c4f(const uint8_t* data); +uint32_t fastCrc32c8(uint32_t crc, const uint8_t* data); +uint32_t fastCrc32c8f(const uint8_t* data); +uint32_t fastCrc32c16(uint32_t crc, const uint8_t* data); +uint32_t fastCrc32c16f(const uint8_t* data); + +#ifdef __cplusplus +} +#endif + +#endif // __FAST_NONVECTOR_CRC32C_H__ diff --git a/thirdparty/dragen/update.mk b/thirdparty/dragen/update.mk new file mode 100644 index 0000000..a009136 --- /dev/null +++ b/thirdparty/dragen/update.mk @@ -0,0 +1,18 @@ +FIND:=find +GREP:=grep +CP:=cp + +ifeq (,$(DRAGEN_SRC)) +$(error Please set DRAGEN_SRC to the location of dragen repository root folder) +endif + +DRAGMAP_FILES:=$(shell $(FIND) . -type f |$(GREP) -v $(lastword $(MAKEFILE_LIST)) | $(GREP) -v mapping_stats) + +all: $(DRAGMAP_FILES) + +.SECONDEXPANSION: +$(DRAGMAP_FILES) : $(DRAGEN_SRC)/$$@ + $(CP) $< $@.tmp && \ + sed -i '/^\#ifndef OPEN_SOURCE/,/^\#endif \/\/ OPEN_SOURCE/{d}' $@.tmp && \ + mv $@.tmp $@ \ + diff --git a/thirdparty/sswlib/ssw/ssw.c b/thirdparty/sswlib/ssw/ssw.c deleted file mode 100644 index 6945cf3..0000000 --- a/thirdparty/sswlib/ssw/ssw.c +++ /dev/null @@ -1,1142 +0,0 @@ -/* The MIT License - - Copyright (c) 2012-1015 Boston College. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -/* Contact: Mengyao Zhao */ - -/* - * ssw.c - * - * Created by Mengyao Zhao on 6/22/10. - * Copyright 2010 Boston College. All rights reserved. - * Version 0.1.4 - * Last revision by Mengyao Zhao on 07/19/16. - * - */ - -#include -#include -#include -#include -#include -#include -#include "ssw.h" - -#ifdef __GNUC__ -#define LIKELY(x) __builtin_expect((x),1) -#define UNLIKELY(x) __builtin_expect((x),0) -#else -#define LIKELY(x) (x) -#define UNLIKELY(x) (x) -#endif - -#define UNCLIP_BONUS 5 -/* Convert the coordinate in the scoring matrix into the coordinate in one line of the band. */ -#define set_u(u, w, i, j) { int x=(i)-(w); x=x>0?x:0; (u)=(j)-x+1; } - -/* Convert the coordinate in the direction matrix into the coordinate in one line of the band. */ -#define set_d(u, w, i, j, p) { int x=(i)-(w); x=x>0?x:0; x=(j)-x; (u)=x*3+p; } - -/*! @function - @abstract Round an integer to the next closest power-2 integer. - @param x integer to be rounded (in place) - @discussion x will be modified. - */ -#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) - -typedef struct { - uint16_t score; - int32_t ref; //0-based position - int32_t read; //alignment ending position on read, 0-based -} alignment_end; - -typedef struct { - uint32_t* seq; - int32_t length; -} cigar; - -struct _profile{ - __m128i* profile_byte; // 0: none - __m128i* profile_word; // 0: none - const int8_t* read; - const int8_t* mat; - int32_t readLen; - int32_t n; - uint8_t bias; -}; - -/* Generate query profile rearrange query sequence & calculate the weight of match/mismatch. */ -static __m128i* qP_byte_init (const int8_t* read_num, - const int8_t* mat, - const int32_t readLen, - const int32_t n, /* the edge length of the squre matrix mat */ - uint8_t bias) { - - int32_t segLen = (readLen + 15) / 16; /* Split the 128 bit register into 16 pieces. - Each piece is 8 bit. Split the read into 16 segments. - Calculat 16 segments in parallel. - */ - __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); - int8_t* t = (int8_t*)vProfile; - int32_t nt, i, j, segNum; - - int8_t bonus = 0; - /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ - for (nt = 0; LIKELY(nt < n); nt ++) { - for (i = 0; i < segLen; i ++) { - j = i; - for (segNum = 0; LIKELY(segNum < 16) ; segNum ++) { - bonus = 0; - if(j==0 || j == readLen-1) - { - bonus = UNCLIP_BONUS; - //printf("qp_byte init UB j %i read_num[%i] = %i bias %i bonus %i\n",j,j,read_num[j],bias,bonus); - } - *t++ = j>= readLen ? bias : mat[nt * n + read_num[j]] + bias + bonus; - j += segLen; - } - } - } - return vProfile; -} - - - - - -static __m128i* qP_byte_rev (const int8_t* read_num, - const int8_t* mat, - const int32_t readLen, - const int32_t fullreadLen, - const int32_t n, - uint8_t bias) { -//printf("qp_byte rev readLen %i fullreadLen %i \n",readLen,fullreadLen); - - int32_t segLen = (readLen + 15) / 16; - __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); - int8_t* t = (int8_t*)vProfile; - int32_t nt, i, j, segNum; - - int8_t bonus = 0; - - for (nt = 0; LIKELY(nt < n); nt ++) { - for (i = 0; i < segLen; i ++) { - j = i; - for (segNum = 0; LIKELY(segNum < 16) ; segNum ++) { - bonus = 0; - if( j == readLen-1) { - bonus = UNCLIP_BONUS; - //printf("qp_byte rev UB j %i read_num[%i] = %i bias %i bonus %i\n",j,j,read_num[j],bias,bonus); - } - if( (readLen == fullreadLen) && (j==0)){ - bonus = UNCLIP_BONUS; - //printf("qp_byte init UB j %i read_num[%i] = %i bias %i bonus %i\n",j,j,read_num[j],bias,bonus); - } - *t++ = j>= readLen ? bias : mat[nt * n + read_num[j]] + bias + bonus; - j += segLen; - } - } - } - return vProfile; -} - -static __m128i* qP_byte (const int8_t* read_num, - const int8_t* mat, - const int32_t readLen, - const int32_t n, /* the edge length of the squre matrix mat */ - uint8_t bias) { - int32_t segLen = (readLen + 15) / 16; /* Split the 128 bit register into 16 pieces. - Each piece is 8 bit. Split the read into 16 segments. - Calculat 16 segments in parallel. - */ - __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); - int8_t* t = (int8_t*)vProfile; - int32_t nt, i, j, segNum; - - /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ - for (nt = 0; LIKELY(nt < n); nt ++) { - for (i = 0; i < segLen; i ++) { - j = i; - for (segNum = 0; LIKELY(segNum < 16) ; segNum ++) { - *t++ = j>= readLen ? bias : mat[nt * n + read_num[j]] + bias; - j += segLen; - } - } - } - return vProfile; -} - - -/* Striped Smith-Waterman - Record the highest score of each reference position. - Return the alignment score and ending position of the best alignment, 2nd best alignment, etc. - Gap begin and gap extension are different. - wight_match > 0, all other weights < 0. - The returned positions are 0-based. - */ -static alignment_end* sw_sse2_byte (const int8_t* ref, - int8_t ref_dir, // 0: forward ref; 1: reverse ref - int32_t refLen, - int32_t readLen, - const uint8_t weight_gapO, /* will be used as - */ - const uint8_t weight_gapE, /* will be used as - */ - const __m128i* vProfile, - uint8_t terminate, /* the best alignment score: used to terminate - the matrix calculation when locating the - alignment beginning point. If this score - is set to 0, it will not be used */ - uint8_t bias, /* Shift 0 point to a positive value. */ - int32_t maskLen) { - -#define max16(m, vm) (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 8)); \ - (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 4)); \ - (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 2)); \ - (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 1)); \ - (m) = _mm_extract_epi16((vm), 0) - - uint8_t max = 0; /* the max alignment score */ - int32_t end_read = readLen - 1; - int32_t end_ref = -1; /* 0_based best alignment ending point; Initialized as isn't aligned -1. */ - int32_t segLen = (readLen + 15) / 16; /* number of segment */ - - /* array to record the largest score of each reference position */ - uint8_t* maxColumn = (uint8_t*) calloc(refLen, 1); - - /* array to record the alignment read ending position of the largest score of each reference position */ - int32_t* end_read_column = (int32_t*) calloc(refLen, sizeof(int32_t)); - - /* Define 16 byte 0 vector. */ - __m128i vZero = _mm_set1_epi32(0); - - __m128i* pvHStore = (__m128i*) calloc(segLen, sizeof(__m128i)); - __m128i* pvHLoad = (__m128i*) calloc(segLen, sizeof(__m128i)); - __m128i* pvE = (__m128i*) calloc(segLen, sizeof(__m128i)); - __m128i* pvHmax = (__m128i*) calloc(segLen, sizeof(__m128i)); - - int32_t i, j; - /* 16 byte insertion begin vector */ - __m128i vGapO = _mm_set1_epi8(weight_gapO); - - /* 16 byte insertion extension vector */ - __m128i vGapE = _mm_set1_epi8(weight_gapE); - - /* 16 byte bias vector */ - __m128i vBias = _mm_set1_epi8(bias); - - __m128i vMaxScore = vZero; /* Trace the highest score of the whole SW matrix. */ - __m128i vMaxMark = vZero; /* Trace the highest score till the previous column. */ - __m128i vTemp; - int32_t edge, begin = 0, end = refLen, step = 1; - - /* outer loop to process the reference sequence */ - if (ref_dir == 1) { - begin = refLen - 1; - end = -1; - step = -1; - } - for (i = begin; LIKELY(i != end); i += step) { - int32_t cmp; - __m128i e, vF = vZero, vMaxColumn = vZero; /* Initialize F value to 0. - Any errors to vH values will be corrected in the Lazy_F loop. - */ - - __m128i vH = pvHStore[segLen - 1]; - vH = _mm_slli_si128 (vH, 1); /* Shift the 128-bit value in vH left by 1 byte. */ - const __m128i* vP = vProfile + ref[i] * segLen; /* Right part of the vProfile */ - - /* Swap the 2 H buffers. */ - __m128i* pv = pvHLoad; - pvHLoad = pvHStore; - pvHStore = pv; - - /* inner loop to process the query sequence */ - for (j = 0; LIKELY(j < segLen); ++j) { - vH = _mm_adds_epu8(vH, _mm_load_si128(vP + j)); - vH = _mm_subs_epu8(vH, vBias); /* vH will be always > 0 */ - - /* Get max from vH, vE and vF. */ - e = _mm_load_si128(pvE + j); - vH = _mm_max_epu8(vH, e); - vH = _mm_max_epu8(vH, vF); - vMaxColumn = _mm_max_epu8(vMaxColumn, vH); - - /* Save vH values. */ - _mm_store_si128(pvHStore + j, vH); - - /* Update vE value. */ - vH = _mm_subs_epu8(vH, vGapO); /* saturation arithmetic, result >= 0 */ - e = _mm_subs_epu8(e, vGapE); - e = _mm_max_epu8(e, vH); - _mm_store_si128(pvE + j, e); - - /* Update vF value. */ - vF = _mm_subs_epu8(vF, vGapE); - vF = _mm_max_epu8(vF, vH); - - /* Load the next vH. */ - vH = _mm_load_si128(pvHLoad + j); - } - - /* Lazy_F loop: has been revised to disallow adjecent insertion and then deletion, so don't update E(i, j), learn from SWPS3 */ - /* reset pointers to the start of the saved data */ - j = 0; - vH = _mm_load_si128 (pvHStore + j); - - /* the computed vF value is for the given column. since */ - /* we are at the end, we need to shift the vF value over */ - /* to the next column. */ - vF = _mm_slli_si128 (vF, 1); - vTemp = _mm_subs_epu8 (vH, vGapO); - vTemp = _mm_subs_epu8 (vF, vTemp); - vTemp = _mm_cmpeq_epi8 (vTemp, vZero); - cmp = _mm_movemask_epi8 (vTemp); - - while (cmp != 0xffff) - { - vH = _mm_max_epu8 (vH, vF); - vMaxColumn = _mm_max_epu8(vMaxColumn, vH); - _mm_store_si128 (pvHStore + j, vH); - vF = _mm_subs_epu8 (vF, vGapE); - j++; - if (j >= segLen) - { - j = 0; - vF = _mm_slli_si128 (vF, 1); - } - vH = _mm_load_si128 (pvHStore + j); - - vTemp = _mm_subs_epu8 (vH, vGapO); - vTemp = _mm_subs_epu8 (vF, vTemp); - vTemp = _mm_cmpeq_epi8 (vTemp, vZero); - cmp = _mm_movemask_epi8 (vTemp); - } - - vMaxScore = _mm_max_epu8(vMaxScore, vMaxColumn); - vTemp = _mm_cmpeq_epi8(vMaxMark, vMaxScore); - cmp = _mm_movemask_epi8(vTemp); - if (cmp != 0xffff) { - uint8_t temp; - vMaxMark = vMaxScore; - max16(temp, vMaxScore); - vMaxScore = vMaxMark; - - if (LIKELY(temp > max)) { - max = temp; - if (max + bias >= 255) break; //overflow - end_ref = i; - - /* Store the column with the highest alignment score in order to trace the alignment ending position on read. */ - for (j = 0; LIKELY(j < segLen); ++j) pvHmax[j] = pvHStore[j]; - } - } - - /* Record the max score of current column. */ - max16(maxColumn[i], vMaxColumn); - if (maxColumn[i] == terminate) break; - } - - /* Trace the alignment ending position on read. */ - uint8_t *t = (uint8_t*)pvHmax; - int32_t column_len = segLen * 16; - for (i = 0; LIKELY(i < column_len); ++i, ++t) { - int32_t temp; - if (*t == max) { - temp = i / 16 + i % 16 * segLen; - if (temp < end_read) end_read = temp; - } - } - - free(pvHmax); - free(pvE); - free(pvHLoad); - free(pvHStore); - - /* Find the most possible 2nd best alignment. */ - alignment_end* bests = (alignment_end*) calloc(2, sizeof(alignment_end)); - bests[0].score = max + bias >= 255 ? 255 : max; - bests[0].ref = end_ref; - bests[0].read = end_read; - - bests[1].score = 0; - bests[1].ref = 0; - bests[1].read = 0; - - edge = (end_ref - maskLen) > 0 ? (end_ref - maskLen) : 0; - for (i = 0; i < edge; i ++) { - if (maxColumn[i] > bests[1].score) { - bests[1].score = maxColumn[i]; - bests[1].ref = i; - } - } - edge = (end_ref + maskLen) > refLen ? refLen : (end_ref + maskLen); - for (i = edge + 1; i < refLen; i ++) { - if (maxColumn[i] > bests[1].score) { - bests[1].score = maxColumn[i]; - bests[1].ref = i; - } - } - - free(maxColumn); - free(end_read_column); - return bests; -} - - -static __m128i* qP_word_rev (const int8_t* read_num, - const int8_t* mat, - const int32_t readLen, - const int32_t fullreadLen, - const int32_t n) { - - int32_t segLen = (readLen + 7) / 8; - __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); - int16_t* t = (int16_t*)vProfile; - int32_t nt, i, j; - int32_t segNum; - - int8_t bonus = 0; - - for (nt = 0; LIKELY(nt < n); nt ++) { - for (i = 0; i < segLen; i ++) { - j = i; - for (segNum = 0; LIKELY(segNum < 8) ; segNum ++) { - bonus = 0; - if( j == readLen-1) bonus = UNCLIP_BONUS; - if( (readLen == fullreadLen) && (j==0)) bonus = UNCLIP_BONUS; - *t++ = j>= readLen ? 0 : mat[nt * n + read_num[j]] + bonus; - - j += segLen; - } - } - } - return vProfile; -} - -static __m128i* qP_word_init (const int8_t* read_num, - const int8_t* mat, - const int32_t readLen, - const int32_t n) { - - int32_t segLen = (readLen + 7) / 8; - __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); - int16_t* t = (int16_t*)vProfile; - int32_t nt, i, j; - int32_t segNum; - int8_t bonus = 0; - /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ - for (nt = 0; LIKELY(nt < n); nt ++) { - for (i = 0; i < segLen; i ++) { - j = i; - for (segNum = 0; LIKELY(segNum < 8) ; segNum ++) { - bonus = 0; - if(j==0 || j == readLen-1) bonus = UNCLIP_BONUS; - - *t++ = j>= readLen ? 0 : mat[nt * n + read_num[j]] + bonus; - j += segLen; - } - } - } - return vProfile; -} - - - - -static __m128i* qP_word (const int8_t* read_num, - const int8_t* mat, - const int32_t readLen, - const int32_t n) { - - int32_t segLen = (readLen + 7) / 8; - __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); - int16_t* t = (int16_t*)vProfile; - int32_t nt, i, j; - int32_t segNum; - - /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ - for (nt = 0; LIKELY(nt < n); nt ++) { - for (i = 0; i < segLen; i ++) { - j = i; - for (segNum = 0; LIKELY(segNum < 8) ; segNum ++) { - *t++ = j>= readLen ? 0 : mat[nt * n + read_num[j]]; - j += segLen; - } - } - } - return vProfile; -} - -static alignment_end* sw_sse2_word (const int8_t* ref, - int8_t ref_dir, // 0: forward ref; 1: reverse ref - int32_t refLen, - int32_t readLen, - const uint8_t weight_gapO, /* will be used as - */ - const uint8_t weight_gapE, /* will be used as - */ - const __m128i* vProfile, - uint16_t terminate, - int32_t maskLen) { - -#define max8(m, vm) (vm) = _mm_max_epi16((vm), _mm_srli_si128((vm), 8)); \ - (vm) = _mm_max_epi16((vm), _mm_srli_si128((vm), 4)); \ - (vm) = _mm_max_epi16((vm), _mm_srli_si128((vm), 2)); \ - (m) = _mm_extract_epi16((vm), 0) - - uint16_t max = 0; /* the max alignment score */ - int32_t end_read = readLen - 1; - int32_t end_ref = 0; /* 1_based best alignment ending point; Initialized as isn't aligned - 0. */ - int32_t segLen = (readLen + 7) / 8; /* number of segment */ - - /* array to record the largest score of each reference position */ - uint16_t* maxColumn = (uint16_t*) calloc(refLen, 2); - - /* array to record the alignment read ending position of the largest score of each reference position */ - int32_t* end_read_column = (int32_t*) calloc(refLen, sizeof(int32_t)); - - /* Define 16 byte 0 vector. */ - __m128i vZero = _mm_set1_epi32(0); - - __m128i* pvHStore = (__m128i*) calloc(segLen, sizeof(__m128i)); - __m128i* pvHLoad = (__m128i*) calloc(segLen, sizeof(__m128i)); - __m128i* pvE = (__m128i*) calloc(segLen, sizeof(__m128i)); - __m128i* pvHmax = (__m128i*) calloc(segLen, sizeof(__m128i)); - - int32_t i, j, k; - /* 16 byte insertion begin vector */ - __m128i vGapO = _mm_set1_epi16(weight_gapO); - - /* 16 byte insertion extension vector */ - __m128i vGapE = _mm_set1_epi16(weight_gapE); - - __m128i vMaxScore = vZero; /* Trace the highest score of the whole SW matrix. */ - __m128i vMaxMark = vZero; /* Trace the highest score till the previous column. */ - __m128i vTemp; - int32_t edge, begin = 0, end = refLen, step = 1; - - /* outer loop to process the reference sequence */ - if (ref_dir == 1) { - begin = refLen - 1; - end = -1; - step = -1; - } - for (i = begin; LIKELY(i != end); i += step) { - int32_t cmp; - __m128i e, vF = vZero; /* Initialize F value to 0. - Any errors to vH values will be corrected in the Lazy_F loop. - */ - __m128i vH = pvHStore[segLen - 1]; - vH = _mm_slli_si128 (vH, 2); /* Shift the 128-bit value in vH left by 2 byte. */ - - /* Swap the 2 H buffers. */ - __m128i* pv = pvHLoad; - - __m128i vMaxColumn = vZero; /* vMaxColumn is used to record the max values of column i. */ - - const __m128i* vP = vProfile + ref[i] * segLen; /* Right part of the vProfile */ - pvHLoad = pvHStore; - pvHStore = pv; - - /* inner loop to process the query sequence */ - for (j = 0; LIKELY(j < segLen); j ++) { - vH = _mm_adds_epi16(vH, _mm_load_si128(vP + j)); - - /* Get max from vH, vE and vF. */ - e = _mm_load_si128(pvE + j); - vH = _mm_max_epi16(vH, e); - vH = _mm_max_epi16(vH, vF); - vMaxColumn = _mm_max_epi16(vMaxColumn, vH); - - /* Save vH values. */ - _mm_store_si128(pvHStore + j, vH); - - /* Update vE value. */ - vH = _mm_subs_epu16(vH, vGapO); /* saturation arithmetic, result >= 0 */ - e = _mm_subs_epu16(e, vGapE); - e = _mm_max_epi16(e, vH); - _mm_store_si128(pvE + j, e); - - /* Update vF value. */ - vF = _mm_subs_epu16(vF, vGapE); - vF = _mm_max_epi16(vF, vH); - - /* Load the next vH. */ - vH = _mm_load_si128(pvHLoad + j); - } - - /* Lazy_F loop: has been revised to disallow adjecent insertion and then deletion, so don't update E(i, j), learn from SWPS3 */ - for (k = 0; LIKELY(k < 8); ++k) { - vF = _mm_slli_si128 (vF, 2); - for (j = 0; LIKELY(j < segLen); ++j) { - vH = _mm_load_si128(pvHStore + j); - vH = _mm_max_epi16(vH, vF); - vMaxColumn = _mm_max_epi16(vMaxColumn, vH); //newly added line - _mm_store_si128(pvHStore + j, vH); - vH = _mm_subs_epu16(vH, vGapO); - vF = _mm_subs_epu16(vF, vGapE); - if (UNLIKELY(! _mm_movemask_epi8(_mm_cmpgt_epi16(vF, vH)))) goto end; - } - } - -end: - vMaxScore = _mm_max_epi16(vMaxScore, vMaxColumn); - vTemp = _mm_cmpeq_epi16(vMaxMark, vMaxScore); - cmp = _mm_movemask_epi8(vTemp); - if (cmp != 0xffff) { - uint16_t temp; - vMaxMark = vMaxScore; - max8(temp, vMaxScore); - vMaxScore = vMaxMark; - - if (LIKELY(temp > max)) { - max = temp; - end_ref = i; - for (j = 0; LIKELY(j < segLen); ++j) pvHmax[j] = pvHStore[j]; - } - } - - /* Record the max score of current column. */ - max8(maxColumn[i], vMaxColumn); - if (maxColumn[i] == terminate) break; - } - - /* Trace the alignment ending position on read. */ - uint16_t *t = (uint16_t*)pvHmax; - int32_t column_len = segLen * 8; - for (i = 0; LIKELY(i < column_len); ++i, ++t) { - int32_t temp; - if (*t == max) { - temp = i / 8 + i % 8 * segLen; - if (temp < end_read) end_read = temp; - } - } - - free(pvHmax); - free(pvE); - free(pvHLoad); - free(pvHStore); - - /* Find the most possible 2nd best alignment. */ - alignment_end* bests = (alignment_end*) calloc(2, sizeof(alignment_end)); - bests[0].score = max; - bests[0].ref = end_ref; - bests[0].read = end_read; - - bests[1].score = 0; - bests[1].ref = 0; - bests[1].read = 0; - - edge = (end_ref - maskLen) > 0 ? (end_ref - maskLen) : 0; - for (i = 0; i < edge; i ++) { - if (maxColumn[i] > bests[1].score) { - bests[1].score = maxColumn[i]; - bests[1].ref = i; - } - } - edge = (end_ref + maskLen) > refLen ? refLen : (end_ref + maskLen); - for (i = edge; i < refLen; i ++) { - if (maxColumn[i] > bests[1].score) { - bests[1].score = maxColumn[i]; - bests[1].ref = i; - } - } - - free(maxColumn); - free(end_read_column); - return bests; -} - -/*! @function Produce CIGAR 32-bit unsigned integer from CIGAR operation and CIGAR length - @param length length of CIGAR - @param op_letter CIGAR operation character ('M', 'I', etc) - @return 32-bit unsigned integer, representing encoded CIGAR operation and length -*/ -uint32_t to_cigar_int (uint32_t length, char op_letter) -{ - switch (op_letter) { - case 'M': /* alignment match (can be a sequence match or mismatch */ - default: - return length << BAM_CIGAR_SHIFT; - case 'S': /* soft clipping (clipped sequences present in SEQ) */ - return (length << BAM_CIGAR_SHIFT) | (4u); - case 'D': /* deletion from the reference */ - return (length << BAM_CIGAR_SHIFT) | (2u); - case 'I': /* insertion to the reference */ - return (length << BAM_CIGAR_SHIFT) | (1u); - case 'H': /* hard clipping (clipped sequences NOT present in SEQ) */ - return (length << BAM_CIGAR_SHIFT) | (5u); - case 'N': /* skipped region from the reference */ - return (length << BAM_CIGAR_SHIFT) | (3u); - case 'P': /* padding (silent deletion from padded reference) */ - return (length << BAM_CIGAR_SHIFT) | (6u); - case '=': /* sequence match */ - return (length << BAM_CIGAR_SHIFT) | (7u); - case 'X': /* sequence mismatch */ - return (length << BAM_CIGAR_SHIFT) | (8u); - } - return (uint32_t)-1; // This never happens -} - -static cigar* banded_sw (const int8_t* ref, - const int8_t* read, - int32_t refLen, - int32_t readLen, - int32_t score, - const uint32_t weight_gapO, /* will be used as - */ - const uint32_t weight_gapE, /* will be used as - */ - int32_t band_width, - const int8_t* mat, /* pointer to the weight matrix */ - int32_t n, - int32_t read_begin, - int32_t unclippedReadLen -) { - -//printf("banded_sw read %p, readLen %i begin %i fulllen %i \n",read,readLen,read_begin,unclippedReadLen); - - uint32_t *c = (uint32_t*)malloc(16 * sizeof(uint32_t)), *c1; - int32_t i, j, e, f, temp1, temp2, s = 16, s1 = 8, l, max = 0; - int64_t s2 = 1024; - char op, prev_op; - int32_t width, width_d, *h_b, *e_b, *h_c; - int8_t *direction, *direction_line; - cigar* result = (cigar*)malloc(sizeof(cigar)); - h_b = (int32_t*)malloc(s1 * sizeof(int32_t)); - e_b = (int32_t*)malloc(s1 * sizeof(int32_t)); - h_c = (int32_t*)malloc(s1 * sizeof(int32_t)); - direction = (int8_t*)malloc(s2 * sizeof(int8_t)); - - do { - width = band_width * 2 + 3, width_d = band_width * 2 + 1; - while (width >= s1) { - ++s1; - kroundup32(s1); - h_b = (int32_t*)realloc(h_b, s1 * sizeof(int32_t)); - e_b = (int32_t*)realloc(e_b, s1 * sizeof(int32_t)); - h_c = (int32_t*)realloc(h_c, s1 * sizeof(int32_t)); - } - while (width_d * readLen * 3 >= s2) { - ++s2; - kroundup32(s2); - if (s2 < 0) { - fprintf(stderr, "Alignment score and position are not consensus.\n"); - exit(1); - } - direction = (int8_t*)realloc(direction, s2 * sizeof(int8_t)); - } - direction_line = direction; - for (j = 1; LIKELY(j < width - 1); j ++) h_b[j] = 0; - for (i = 0; LIKELY(i < readLen); i ++) { - int32_t beg = 0, end = refLen - 1, u = 0, edge; - j = i - band_width; beg = beg > j ? beg : j; // band start - j = i + band_width; end = end < j ? end : j; // band end - edge = end + 1 < width - 1 ? end + 1 : width - 1; - f = h_b[0] = e_b[0] = h_b[edge] = e_b[edge] = h_c[0] = 0; - direction_line = direction + width_d * i * 3; - - int8_t bonus = 0; - for (j = beg; LIKELY(j <= end); j ++) { - int32_t b, e1, f1, d, de, df, dh; - set_u(u, band_width, i, j); set_u(e, band_width, i - 1, j); - set_u(b, band_width, i, j - 1); set_u(d, band_width, i - 1, j - 1); - set_d(de, band_width, i, j, 0); - set_d(df, band_width, i, j, 1); - set_d(dh, band_width, i, j, 2); - - temp1 = i == 0 ? -weight_gapO : h_b[e] - weight_gapO; - temp2 = i == 0 ? -weight_gapE : e_b[e] - weight_gapE; - e_b[u] = temp1 > temp2 ? temp1 : temp2; - direction_line[de] = temp1 > temp2 ? 3 : 2; - - temp1 = h_c[b] - weight_gapO; - temp2 = f - weight_gapE; - f = temp1 > temp2 ? temp1 : temp2; - direction_line[df] = temp1 > temp2 ? 5 : 4; - - e1 = e_b[u] > 0 ? e_b[u] : 0; - f1 = f > 0 ? f : 0; - temp1 = e1 > f1 ? e1 : f1; - bonus=0; - if( (i+read_begin) ==0 || (i+read_begin)== (unclippedReadLen -1)) - { - bonus = UNCLIP_BONUS; -//printf("traceback UB readLen %i unclippedReadLen %i read_begin %i i %i read_num[%i] = %i bonus %i\n",readLen,unclippedReadLen,read_begin,i,i,read[i],bonus); - - } - temp2 = h_b[d] + mat[ref[j] * n + read[i]] + bonus; - h_c[u] = temp1 > temp2 ? temp1 : temp2; - - if (h_c[u] > max) max = h_c[u]; - - if (temp1 <= temp2) direction_line[dh] = 1; - else direction_line[dh] = e1 > f1 ? direction_line[de] : direction_line[df]; - } - for (j = 1; j <= u; j ++) h_b[j] = h_c[j]; - } - band_width *= 2; - } while (LIKELY(max < score)); - band_width /= 2; - - // trace back - i = readLen - 1; - j = refLen - 1; - e = 0; // Count the number of M, D or I. - l = 0; // record length of current cigar - op = prev_op = 'M'; - temp2 = 2; // h - while (LIKELY(i > 0)) { - set_d(temp1, band_width, i, j, temp2); - switch (direction_line[temp1]) { - case 1: - --i; - --j; - temp2 = 2; - direction_line -= width_d * 3; - op = 'M'; - break; - case 2: - --i; - temp2 = 0; // e - direction_line -= width_d * 3; - op = 'I'; - break; - case 3: - --i; - temp2 = 2; - direction_line -= width_d * 3; - op = 'I'; - break; - case 4: - --j; - temp2 = 1; - op = 'D'; - break; - case 5: - --j; - temp2 = 2; - op = 'D'; - break; - default: - fprintf(stderr, "Trace back error: %d.\n", direction_line[temp1 - 1]); - free(direction); - free(h_c); - free(e_b); - free(h_b); - free(c); - free(result); - return 0; - } - if (op == prev_op) ++e; - else { - ++l; - while (l >= s) { - ++s; - kroundup32(s); - c = (uint32_t*)realloc(c, s * sizeof(uint32_t)); - } - c[l - 1] = to_cigar_int(e, prev_op); - prev_op = op; - e = 1; - } - } - if (op == 'M') { - ++l; - while (l >= s) { - ++s; - kroundup32(s); - c = (uint32_t*)realloc(c, s * sizeof(uint32_t)); - } - c[l - 1] = to_cigar_int(e + 1, op); - }else { - l += 2; - while (l >= s) { - ++s; - kroundup32(s); - c = (uint32_t*)realloc(c, s * sizeof(uint32_t)); - } - c[l - 2] = to_cigar_int(e, op); - c[l - 1] = to_cigar_int(1, 'M'); - } - - // reverse cigar - c1 = (uint32_t*)malloc(l * sizeof(uint32_t)); - s = 0; - e = l - 1; - while (LIKELY(s <= e)) { - c1[s] = c[e]; - c1[e] = c[s]; - ++ s; - -- e; - } - result->seq = c1; - result->length = l; - - free(direction); - free(h_c); - free(e_b); - free(h_b); - free(c); - return result; -} - -static int8_t* seq_reverse(const int8_t* seq, int32_t end) /* end is 0-based alignment ending position */ -{ - int8_t* reverse = (int8_t*)calloc(end + 1, sizeof(int8_t)); - int32_t start = 0; - while (LIKELY(start <= end)) { - reverse[start] = seq[end]; - reverse[end] = seq[start]; - ++ start; - -- end; - } - return reverse; -} - -s_profile* ssw_init (const int8_t* read, const int32_t readLen, const int8_t* mat, const int32_t n, const int8_t score_size) { - s_profile* p = (s_profile*)calloc(1, sizeof(struct _profile)); - p->profile_byte = 0; - p->profile_word = 0; - p->bias = 0; - - if (score_size == 0 || score_size == 2) { - /* Find the bias to use in the substitution matrix */ - int32_t bias = 0, i; - for (i = 0; i < n*n; i++) if (mat[i] < bias) bias = mat[i]; - bias = abs(bias); - - p->bias = bias; - - // p->profile_byte = qP_byte (read, mat, readLen, n, bias); - - p->profile_byte = qP_byte_init (read, mat, readLen, n, bias); - } - -// if (score_size == 1 || score_size == 2) p->profile_word = qP_word (read, mat, readLen, n); - - if (score_size == 1 || score_size == 2) p->profile_word = qP_word_init (read, mat, readLen, n); - p->read = read; - p->mat = mat; - p->readLen = readLen; - p->n = n; - return p; -} - -void init_destroy (s_profile* p) { - free(p->profile_byte); - free(p->profile_word); - free(p); -} - -s_align* ssw_align (const s_profile* prof, - const int8_t* ref, - int32_t refLen, - const uint8_t weight_gapO, - const uint8_t weight_gapE, - const uint8_t flag, // (from high to low) bit 5: return the best alignment beginning position; 6: if (ref_end1 - ref_begin1 <= filterd) && (read_end1 - read_begin1 <= filterd), return cigar; 7: if max score >= filters, return cigar; 8: always return cigar; if 6 & 7 are both setted, only return cigar when both filter fulfilled - const uint16_t filters, - const int32_t filterd, - const int32_t maskLen) { -//printf("----- ssw_align readLen %i read %p ------\n",prof->readLen,prof->read); - alignment_end* bests = 0, *bests_reverse = 0; - __m128i* vP = 0; - int32_t word = 0, band_width = 0, readLen = prof->readLen; - int8_t* read_reverse = 0; - cigar* path; - s_align* r = (s_align*)calloc(1, sizeof(s_align)); - r->ref_begin1 = -1; - r->read_begin1 = -1; - r->cigar = 0; - r->cigarLen = 0; - if (maskLen < 15) { - fprintf(stderr, "When maskLen < 15, the function ssw_align doesn't return 2nd best alignment information.\n"); - } - - // Find the alignment scores and ending positions - if (prof->profile_byte) { - bests = sw_sse2_byte(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_byte, -1, prof->bias, maskLen); - if (prof->profile_word && bests[0].score == 255) { - free(bests); - bests = sw_sse2_word(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_word, -1, maskLen); - word = 1; - } else if (bests[0].score == 255) { - fprintf(stderr, "Please set 2 to the score_size parameter of the function ssw_init, otherwise the alignment results will be incorrect.\n"); - free(r); - return NULL; - } - }else if (prof->profile_word) { - bests = sw_sse2_word(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_word, -1, maskLen); - word = 1; - }else { - fprintf(stderr, "Please call the function ssw_init before ssw_align.\n"); - free(r); - return NULL; - } - r->score1 = bests[0].score; - r->ref_end1 = bests[0].ref; - r->read_end1 = bests[0].read; - if (maskLen >= 15) { - r->score2 = bests[1].score; - r->ref_end2 = bests[1].ref; - } else { - r->score2 = 0; - r->ref_end2 = -1; - } - free(bests); - if (flag == 0 || (flag == 2 && r->score1 < filters)) goto end; - - - // Find the beginning position of the best alignment. - read_reverse = seq_reverse(prof->read, r->read_end1); - if (word == 0) { - vP = qP_byte_rev(read_reverse, prof->mat, r->read_end1 + 1,readLen, prof->n, prof->bias); - bests_reverse = sw_sse2_byte(ref, 1, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, prof->bias, maskLen); - } else { - vP = qP_word_rev(read_reverse, prof->mat, r->read_end1 + 1,readLen, prof->n); - bests_reverse = sw_sse2_word(ref, 1, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, maskLen); - } - free(vP); - free(read_reverse); - r->ref_begin1 = bests_reverse[0].ref; - r->read_begin1 = r->read_end1 - bests_reverse[0].read; - free(bests_reverse); - if ((7&flag) == 0 || ((2&flag) != 0 && r->score1 < filters) || ((4&flag) != 0 && (r->ref_end1 - r->ref_begin1 > filterd || r->read_end1 - r->read_begin1 > filterd))) goto end; - - // Generate cigar. - refLen = r->ref_end1 - r->ref_begin1 + 1; - readLen = r->read_end1 - r->read_begin1 + 1; - band_width = abs(refLen - readLen) + 1; - - //printf("begin end %i %i \n",r->read_begin1 ,r->read_end1); - - path = banded_sw(ref + r->ref_begin1, prof->read + r->read_begin1, refLen, readLen, r->score1, weight_gapO, weight_gapE, band_width, prof->mat, prof->n, r->read_begin1 , prof->readLen); - if (path == 0) { - free(r); - r = NULL; - } - else { - r->cigar = path->seq; - r->cigarLen = path->length; - free(path); - } - -end: - return r; -} - -void align_destroy (s_align* a) { - free(a->cigar); - free(a); -} - -uint32_t* add_cigar (uint32_t* new_cigar, int32_t* p, int32_t* s, uint32_t length, char op) { - if ((*p) >= (*s)) { - ++(*s); - kroundup32(*s); - new_cigar = (uint32_t*)realloc(new_cigar, (*s)*sizeof(uint32_t)); - } - new_cigar[(*p) ++] = to_cigar_int(length, op); - return new_cigar; -} - -uint32_t* store_previous_m (int8_t choice, // 0: current not M, 1: current match, 2: current mismatch - uint32_t* length_m, - uint32_t* length_x, - int32_t* p, - int32_t* s, - uint32_t* new_cigar) { - - if ((*length_m) && (choice == 2 || !choice)) { - new_cigar = add_cigar (new_cigar, p, s, (*length_m), '='); - (*length_m) = 0; - } else if ((*length_x) && (choice == 1 || !choice)) { - new_cigar = add_cigar (new_cigar, p, s, (*length_x), 'X'); - (*length_x) = 0; - } - return new_cigar; -} - -/*! @function: - 1. Calculate the number of mismatches. - 2. Modify the cigar string: - differentiate matches (=) and mismatches(X); add softclip(S) at the beginning and ending of the original cigar. - @return: - The number of mismatches. - The cigar and cigarLen are modified. -*/ -int32_t mark_mismatch (int32_t ref_begin1, - int32_t read_begin1, - int32_t read_end1, - const char* ref, - const char* read, - int32_t readLen, - uint32_t** cigar, - int32_t* cigarLen) { - - int32_t mismatch_length = 0, p = 0, i, length, j, s = *cigarLen + 2; - uint32_t *new_cigar = (uint32_t*)malloc(s*sizeof(uint32_t)), length_m = 0, length_x = 0; - char op; - - ref += ref_begin1; - read += read_begin1; - if (read_begin1 > 0) new_cigar[p ++] = to_cigar_int(read_begin1, 'S'); - for (i = 0; i < (*cigarLen); ++i) { - op = cigar_int_to_op((*cigar)[i]); - length = cigar_int_to_len((*cigar)[i]); - if (op == 'M') { - for (j = 0; j < length; ++j) { - fprintf(stderr, "ref[%d]: %c\tread[%d]: %c\n", j, *ref, j, *read); - if (*ref != *read) { - ++ mismatch_length; - fprintf(stderr, "length_m: %d\n", length_m); - // the previous is match; however the current one is mismatche - new_cigar = store_previous_m (2, &length_m, &length_x, &p, &s, new_cigar); - ++ length_x; - } else { - // the previous is mismatch; however the current one is matche - new_cigar = store_previous_m (1, &length_m, &length_x, &p, &s, new_cigar); - ++ length_m; - } - ++ ref; - ++ read; - } - }else if (op == 'I') { - read += length; - mismatch_length += length; - new_cigar = store_previous_m (0, &length_m, &length_x, &p, &s, new_cigar); - new_cigar = add_cigar (new_cigar, &p, &s, length, 'I'); - }else if (op == 'D') { - ref += length; - mismatch_length += length; - new_cigar = store_previous_m (0, &length_m, &length_x, &p, &s, new_cigar); - new_cigar = add_cigar (new_cigar, &p, &s, length, 'D'); - } - } - new_cigar = store_previous_m (0, &length_m, &length_x, &p, &s, new_cigar); - - length = readLen - read_end1 - 1; - if (length > 0) new_cigar = add_cigar(new_cigar, &p, &s, length, 'S'); - - (*cigarLen) = p; - free(*cigar); - (*cigar) = new_cigar; - return mismatch_length; -} - diff --git a/thirdparty/sswlib/ssw/ssw.cpp b/thirdparty/sswlib/ssw/ssw.cpp new file mode 100644 index 0000000..bbe8027 --- /dev/null +++ b/thirdparty/sswlib/ssw/ssw.cpp @@ -0,0 +1,1083 @@ +/** + ** DRAGEN Open Source Software + ** Copyright (c) 2019-2020 Illumina, Inc. + ** All rights reserved. + ** + ** Based on SSW implementation + ** https://github.com/mengyao/Complete-Striped-Smith-Waterman-Library + ** Version 0.1.4 + ** Last revision by Mengyao Zhao on 07/19/16 + ** + ** License: MIT + ** Copyright (c) 2012-2015 Boston College + ** Copyright (c) 2020-2021 Illumina + ** + ** Permission is hereby granted, free of charge, to any person obtaining a copy of this + ** software and associated documentation files (the "Software"), to deal in the Software + ** without restriction, including without limitation the rights to use, copy, modify, + ** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + ** permit persons to whom the Software is furnished to do so, subject to the following + ** conditions: + ** The above copyright notice and this permission notice shall be included in all copies + ** or substantial portions of the Software. + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + ** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + ** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + ** HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + **/ + +// shared and sse2-specific implementations + +#include +#include +#include +#include +#include +#include +#include "ssw.hpp" +#include "ssw_internal.hpp" + +/* Generate query profile rearrange query sequence & calculate the weight of match/mismatch. */ +static __m128i* qP_byte_init (const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t n, /* the edge length of the squre matrix mat */ + uint8_t bias) { + + int32_t segLen = (readLen + 15) / 16; /* Split the 128 bit register into 16 pieces. + Each piece is 8 bit. Split the read into 16 segments. + Calculat 16 segments in parallel. + */ + __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); + int8_t* t = (int8_t*)vProfile; + int32_t nt, i, j, segNum; + + int8_t bonus = 0; + /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + for (segNum = 0; LIKELY(segNum < 16) ; segNum ++) { + bonus = 0; + if(j==0 || j == readLen-1) + { + bonus = UNCLIP_BONUS; + //printf("qp_byte init UB j %i read_num[%i] = %i bias %i bonus %i\n",j,j,read_num[j],bias,bonus); + } + *t++ = + j>= readLen ? + bias : + mat[nt * n + read_num[j]] + bias + bonus; + j += segLen; + } + } + } + + return vProfile; +} + +static __m128i* qP_byte_rev (const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t fullreadLen, + const int32_t n, + uint8_t bias) { + //printf("qp_byte rev readLen %i fullreadLen %i \n",readLen,fullreadLen); + + int32_t segLen = (readLen + 15) / 16; + __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); + int8_t* t = (int8_t*)vProfile; + int32_t nt, i, j, segNum; + + int8_t bonus = 0; + + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + for (segNum = 0; LIKELY(segNum < 16) ; segNum ++) { + bonus = 0; + if( j == readLen-1) { + bonus = UNCLIP_BONUS; + //printf("qp_byte rev UB j %i read_num[%i] = %i bias %i bonus %i\n",j,j,read_num[j],bias,bonus); + } + if( (readLen == fullreadLen) && (j==0)){ + bonus = UNCLIP_BONUS; + //printf("qp_byte init UB j %i read_num[%i] = %i bias %i bonus %i\n",j,j,read_num[j],bias,bonus); + } + *t++ = j>= readLen ? bias : mat[nt * n + read_num[j]] + bias + bonus; + j += segLen; + } + } + } + return vProfile; +} + + +/* Striped Smith-Waterman + Record the highest score of each reference position. + Return the alignment score and ending position of the best alignment, 2nd best alignment, etc. + Gap begin and gap extension are different. + wight_match > 0, all other weights < 0. + The returned positions are 0-based. + */ +static alignment_end* sw_sse2_byte (const int8_t* ref, + int8_t ref_dir, // 0: forward ref; 1: reverse ref + int32_t refLen, + int32_t readLen, + const uint8_t weight_gapO, /* will be used as - */ + const uint8_t weight_gapE, /* will be used as - */ + const __m128i* vProfile, + uint8_t terminate, /* the best alignment score: used to terminate + the matrix calculation when locating the + alignment beginning point. If this score + is set to 0, it will not be used */ + uint8_t bias, /* Shift 0 point to a positive value. */ + int32_t maskLen) { + +#define max16(m, vm) (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 8)); \ + (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 4)); \ + (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 2)); \ + (vm) = _mm_max_epu8((vm), _mm_srli_si128((vm), 1)); \ + (m) = _mm_extract_epi16((vm), 0) + + uint8_t max = 0; /* the max alignment score */ + int32_t end_read = readLen - 1; + int32_t end_ref = -1; /* 0_based best alignment ending point; Initialized as isn't aligned -1. */ + int32_t segLen = (readLen + 15) / 16; /* number of segment */ + + /* array to record the largest score of each reference position */ + uint8_t* maxColumn = (uint8_t*) calloc(refLen, 1); + + /* array to record the alignment read ending position of the largest score of each reference position */ + int32_t* end_read_column = (int32_t*) calloc(refLen, sizeof(int32_t)); + + /* Define 16 byte 0 vector. */ + __m128i vZero = _mm_set1_epi32(0); + + __m128i* pvHStore = (__m128i*) calloc(segLen, sizeof(__m128i)); + __m128i* pvHLoad = (__m128i*) calloc(segLen, sizeof(__m128i)); + __m128i* pvE = (__m128i*) calloc(segLen, sizeof(__m128i)); + __m128i* pvHmax = (__m128i*) calloc(segLen, sizeof(__m128i)); + + int32_t i, j; + /* 16 byte insertion begin vector */ + __m128i vGapO = _mm_set1_epi8(weight_gapO); + + /* 16 byte insertion extension vector */ + __m128i vGapE = _mm_set1_epi8(weight_gapE); + + /* 16 byte bias vector */ + __m128i vBias = _mm_set1_epi8(bias); + + __m128i vMaxScore = vZero; /* Trace the highest score of the whole SW matrix. */ + __m128i vMaxMark = vZero; /* Trace the highest score till the previous column. */ + __m128i vTemp; + int32_t edge, begin = 0, end = refLen, step = 1; + + /* outer loop to process the reference sequence */ + if (ref_dir == 1) { + begin = refLen - 1; + end = -1; + step = -1; + } + for (i = begin; LIKELY(i != end); i += step) { + int32_t cmp; + __m128i e, vF = vZero, vMaxColumn = vZero; /* Initialize F value to 0. + Any errors to vH values will be corrected in the Lazy_F loop. + */ + + __m128i vH = pvHStore[segLen - 1]; + vH = _mm_slli_si128 (vH, 1); /* Shift the 128-bit value in vH left by 1 byte. */ + const __m128i* vP = vProfile + ref[i] * segLen; /* Right part of the vProfile */ + + /* Swap the 2 H buffers. */ + __m128i* pv = pvHLoad; + pvHLoad = pvHStore; + pvHStore = pv; + + /* inner loop to process the query sequence */ + for (j = 0; LIKELY(j < segLen); ++j) { + __m128i p = _mm_load_si128(vP + j); + + vH = _mm_adds_epu8(vH, p); + vH = _mm_subs_epu8(vH, vBias); /* vH will be always > 0 */ + + /* Get max from vH, vE and vF. */ + e = _mm_load_si128(pvE + j); + + vH = _mm_max_epu8(vH, e); + vH = _mm_max_epu8(vH, vF); + + vMaxColumn = _mm_max_epu8(vMaxColumn, vH); + + /* Save vH values. */ + _mm_store_si128(pvHStore + j, vH); + + /* Update vE value. */ + vH = _mm_subs_epu8(vH, vGapO); /* saturation arithmetic, result >= 0 */ + + e = _mm_subs_epu8(e, vGapE); + e = _mm_max_epu8(e, vH); + _mm_store_si128(pvE + j, e); + + /* Update vF value. */ + vF = _mm_subs_epu8(vF, vGapE); + vF = _mm_max_epu8(vF, vH); + + /* Load the next vH. */ + vH = _mm_load_si128(pvHLoad + j); + } + + /* Lazy_F loop: has been revised to disallow adjacent insertion and then deletion, so don't update E(i, j), learn from SWPS3 */ + /* reset pointers to the start of the saved data */ + j = 0; + vH = _mm_load_si128 (pvHStore + j); + + /* the computed vF value is for the given column. since */ + /* we are at the end, we need to shift the vF value over */ + /* to the next column. */ + vF = _mm_slli_si128 (vF, 1); + vTemp = _mm_subs_epu8 (vH, vGapO); + vTemp = _mm_subs_epu8 (vF, vTemp); + vTemp = _mm_cmpeq_epi8 (vTemp, vZero); + cmp = _mm_movemask_epi8 (vTemp); + + while (cmp != 0xffff) + { + vH = _mm_max_epu8 (vH, vF); + vMaxColumn = _mm_max_epu8(vMaxColumn, vH); + _mm_store_si128 (pvHStore + j, vH); + vF = _mm_subs_epu8 (vF, vGapE); + j++; + if (j >= segLen) + { + j = 0; + vF = _mm_slli_si128 (vF, 1); + } + vH = _mm_load_si128 (pvHStore + j); + + vTemp = _mm_subs_epu8 (vH, vGapO); + vTemp = _mm_subs_epu8 (vF, vTemp); + vTemp = _mm_cmpeq_epi8 (vTemp, vZero); + cmp = _mm_movemask_epi8 (vTemp); + } + + vMaxScore = _mm_max_epu8(vMaxScore, vMaxColumn); + vTemp = _mm_cmpeq_epi8(vMaxMark, vMaxScore); + cmp = _mm_movemask_epi8(vTemp); + if (cmp != 0xffff) { + uint8_t temp; + vMaxMark = vMaxScore; + max16(temp, vMaxScore); + vMaxScore = vMaxMark; + + if (LIKELY(temp > max)) { + max = temp; + if (max + bias >= 255) break; //overflow + end_ref = i; + + /* Store the column with the highest alignment score in order to trace the alignment ending position on read. */ + for (j = 0; LIKELY(j < segLen); ++j) pvHmax[j] = pvHStore[j]; + } + } + + /* Record the max score of current column. */ + max16(maxColumn[i], vMaxColumn); + if (maxColumn[i] == terminate) break; + } + + /* Trace the alignment ending position on read. */ + uint8_t *t = (uint8_t*)pvHmax; + int32_t column_len = segLen * 16; + for (i = 0; LIKELY(i < column_len); ++i, ++t) { + int32_t temp; + if (*t == max) { + temp = i / 16 + i % 16 * segLen; + if (temp < end_read) end_read = temp; + } + } + + free(pvHmax); + free(pvE); + free(pvHLoad); + free(pvHStore); + + /* Find the most possible 2nd best alignment. */ + alignment_end* bests = (alignment_end*) calloc(2, sizeof(alignment_end)); + bests[0].score = max + bias >= 255 ? 255 : max; + bests[0].ref = end_ref; + bests[0].read = end_read; + + bests[1].score = 0; + bests[1].ref = 0; + bests[1].read = 0; + + edge = (end_ref - maskLen) > 0 ? (end_ref - maskLen) : 0; + for (i = 0; i < edge; i ++) { + if (maxColumn[i] > bests[1].score) { + bests[1].score = maxColumn[i]; + bests[1].ref = i; + } + } + edge = (end_ref + maskLen) > refLen ? refLen : (end_ref + maskLen); + for (i = edge + 1; i < refLen; i ++) { + if (maxColumn[i] > bests[1].score) { + bests[1].score = maxColumn[i]; + bests[1].ref = i; + } + } + + free(maxColumn); + free(end_read_column); + return bests; +} + + +static __m128i* qP_word_rev (const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t fullreadLen, + const int32_t n) { + + int32_t segLen = (readLen + 7) / 8; + __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); + int16_t* t = (int16_t*)vProfile; + int32_t nt, i, j; + int32_t segNum; + + int8_t bonus = 0; + + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + for (segNum = 0; LIKELY(segNum < 8) ; segNum ++) { + bonus = 0; + if( j == readLen-1) bonus = UNCLIP_BONUS; + if( (readLen == fullreadLen) && (j==0)) bonus = UNCLIP_BONUS; + *t++ = j>= readLen ? 0 : mat[nt * n + read_num[j]] + bonus; + + j += segLen; + } + } + } + return vProfile; +} + +static __m128i* qP_word_init (const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t n) { + + int32_t segLen = (readLen + 7) / 8; + __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); + int16_t* t = (int16_t*)vProfile; + int32_t nt, i, j; + int32_t segNum; + int8_t bonus = 0; + /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + for (segNum = 0; LIKELY(segNum < 8) ; segNum ++) { + bonus = 0; + if(j==0 || j == readLen-1) bonus = UNCLIP_BONUS; + + *t++ = j>= readLen ? 0 : mat[nt * n + read_num[j]] + bonus; + j += segLen; + } + } + } + return vProfile; +} + + + +#if 0 +static __m128i* qP_word (const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t n) { + + int32_t segLen = (readLen + 7) / 8; + __m128i* vProfile = (__m128i*)malloc(n * segLen * sizeof(__m128i)); + int16_t* t = (int16_t*)vProfile; + int32_t nt, i, j; + int32_t segNum; + + /* Generate query profile rearrange query sequence & calculate the weight of match/mismatch */ + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + for (segNum = 0; LIKELY(segNum < 8) ; segNum ++) { + *t++ = j>= readLen ? 0 : mat[nt * n + read_num[j]]; + j += segLen; + } + } + } + return vProfile; +} +#endif + +static alignment_end* sw_sse2_word (const int8_t* ref, + int8_t ref_dir, // 0: forward ref; 1: reverse ref + int32_t refLen, + int32_t readLen, + const uint8_t weight_gapO, /* will be used as - */ + const uint8_t weight_gapE, /* will be used as - */ + const __m128i* vProfile, + uint16_t terminate, + int32_t maskLen) { + +#define max8(m, vm) (vm) = _mm_max_epi16((vm), _mm_srli_si128((vm), 8)); \ + (vm) = _mm_max_epi16((vm), _mm_srli_si128((vm), 4)); \ + (vm) = _mm_max_epi16((vm), _mm_srli_si128((vm), 2)); \ + (m) = _mm_extract_epi16((vm), 0) + + uint16_t max = 0; /* the max alignment score */ + int32_t end_read = readLen - 1; + int32_t end_ref = 0; /* 1_based best alignment ending point; Initialized as isn't aligned - 0. */ + int32_t segLen = (readLen + 7) / 8; /* number of segment */ + + /* array to record the largest score of each reference position */ + uint16_t* maxColumn = (uint16_t*) calloc(refLen, 2); + + /* array to record the alignment read ending position of the largest score of each reference position */ + int32_t* end_read_column = (int32_t*) calloc(refLen, sizeof(int32_t)); + + /* Define 16 byte 0 vector. */ + __m128i vZero = _mm_set1_epi32(0); + + __m128i* pvHStore = (__m128i*) calloc(segLen, sizeof(__m128i)); + __m128i* pvHLoad = (__m128i*) calloc(segLen, sizeof(__m128i)); + __m128i* pvE = (__m128i*) calloc(segLen, sizeof(__m128i)); + __m128i* pvHmax = (__m128i*) calloc(segLen, sizeof(__m128i)); + + int32_t i, j, k; + /* 16 byte insertion begin vector */ + __m128i vGapO = _mm_set1_epi16(weight_gapO); + + /* 16 byte insertion extension vector */ + __m128i vGapE = _mm_set1_epi16(weight_gapE); + + __m128i vMaxScore = vZero; /* Trace the highest score of the whole SW matrix. */ + __m128i vMaxMark = vZero; /* Trace the highest score till the previous column. */ + __m128i vTemp; + int32_t edge, begin = 0, end = refLen, step = 1; + + /* outer loop to process the reference sequence */ + if (ref_dir == 1) { + begin = refLen - 1; + end = -1; + step = -1; + } + for (i = begin; LIKELY(i != end); i += step) { + int32_t cmp; + __m128i e, vF = vZero; /* Initialize F value to 0. + Any errors to vH values will be corrected in the Lazy_F loop. + */ + __m128i vH = pvHStore[segLen - 1]; + vH = _mm_slli_si128 (vH, 2); /* Shift the 128-bit value in vH left by 2 byte. */ + + /* Swap the 2 H buffers. */ + __m128i* pv = pvHLoad; + + __m128i vMaxColumn = vZero; /* vMaxColumn is used to record the max values of column i. */ + + const __m128i* vP = vProfile + ref[i] * segLen; /* Right part of the vProfile */ + pvHLoad = pvHStore; + pvHStore = pv; + + /* inner loop to process the query sequence */ + for (j = 0; LIKELY(j < segLen); j ++) { + vH = _mm_adds_epi16(vH, _mm_load_si128(vP + j)); + + /* Get max from vH, vE and vF. */ + e = _mm_load_si128(pvE + j); + vH = _mm_max_epi16(vH, e); + vH = _mm_max_epi16(vH, vF); + vMaxColumn = _mm_max_epi16(vMaxColumn, vH); + + /* Save vH values. */ + _mm_store_si128(pvHStore + j, vH); + + /* Update vE value. */ + vH = _mm_subs_epu16(vH, vGapO); /* saturation arithmetic, result >= 0 */ + e = _mm_subs_epu16(e, vGapE); + e = _mm_max_epi16(e, vH); + _mm_store_si128(pvE + j, e); + + /* Update vF value. */ + vF = _mm_subs_epu16(vF, vGapE); + vF = _mm_max_epi16(vF, vH); + + /* Load the next vH. */ + vH = _mm_load_si128(pvHLoad + j); + } + + /* Lazy_F loop: has been revised to disallow adjacent insertion and then deletion, so don't update E(i, j), learn from SWPS3 */ + for (k = 0; LIKELY(k < 8); ++k) { + vF = _mm_slli_si128 (vF, 2); + for (j = 0; LIKELY(j < segLen); ++j) { + vH = _mm_load_si128(pvHStore + j); + vH = _mm_max_epi16(vH, vF); + vMaxColumn = _mm_max_epi16(vMaxColumn, vH); //newly added line + _mm_store_si128(pvHStore + j, vH); + vH = _mm_subs_epu16(vH, vGapO); + vF = _mm_subs_epu16(vF, vGapE); + if (UNLIKELY(! _mm_movemask_epi8(_mm_cmpgt_epi16(vF, vH)))) goto end; + } + } + + end: + vMaxScore = _mm_max_epi16(vMaxScore, vMaxColumn); + vTemp = _mm_cmpeq_epi16(vMaxMark, vMaxScore); + cmp = _mm_movemask_epi8(vTemp); + if (cmp != 0xffff) { + uint16_t temp; + vMaxMark = vMaxScore; + max8(temp, vMaxScore); + vMaxScore = vMaxMark; + + if (LIKELY(temp > max)) { + max = temp; + end_ref = i; + for (j = 0; LIKELY(j < segLen); ++j) pvHmax[j] = pvHStore[j]; + } + } + + /* Record the max score of current column. */ + max8(maxColumn[i], vMaxColumn); + if (maxColumn[i] == terminate) break; + } + + /* Trace the alignment ending position on read. */ + uint16_t *t = (uint16_t*)pvHmax; + int32_t column_len = segLen * 8; + for (i = 0; LIKELY(i < column_len); ++i, ++t) { + int32_t temp; + if (*t == max) { + temp = i / 8 + i % 8 * segLen; + if (temp < end_read) end_read = temp; + } + } + + free(pvHmax); + free(pvE); + free(pvHLoad); + free(pvHStore); + + /* Find the most possible 2nd best alignment. */ + alignment_end* bests = (alignment_end*) calloc(2, sizeof(alignment_end)); + bests[0].score = max; + bests[0].ref = end_ref; + bests[0].read = end_read; + + bests[1].score = 0; + bests[1].ref = 0; + bests[1].read = 0; + + edge = (end_ref - maskLen) > 0 ? (end_ref - maskLen) : 0; + for (i = 0; i < edge; i ++) { + if (maxColumn[i] > bests[1].score) { + bests[1].score = maxColumn[i]; + bests[1].ref = i; + } + } + edge = (end_ref + maskLen) > refLen ? refLen : (end_ref + maskLen); + for (i = edge; i < refLen; i ++) { + if (maxColumn[i] > bests[1].score) { + bests[1].score = maxColumn[i]; + bests[1].ref = i; + } + } + + free(maxColumn); + free(end_read_column); + return bests; +} + +/*! @function Produce CIGAR 32-bit unsigned integer from CIGAR operation and CIGAR length + @param length length of CIGAR + @param op_letter CIGAR operation character ('M', 'I', etc) + @return 32-bit unsigned integer, representing encoded CIGAR operation and length + */ +uint32_t to_cigar_int (uint32_t length, char op_letter) +{ + switch (op_letter) { + case 'M': /* alignment match (can be a sequence match or mismatch */ + default: + return length << BAM_CIGAR_SHIFT; + case 'S': /* soft clipping (clipped sequences present in SEQ) */ + return (length << BAM_CIGAR_SHIFT) | (4u); + case 'D': /* deletion from the reference */ + return (length << BAM_CIGAR_SHIFT) | (2u); + case 'I': /* insertion to the reference */ + return (length << BAM_CIGAR_SHIFT) | (1u); + case 'H': /* hard clipping (clipped sequences NOT present in SEQ) */ + return (length << BAM_CIGAR_SHIFT) | (5u); + case 'N': /* skipped region from the reference */ + return (length << BAM_CIGAR_SHIFT) | (3u); + case 'P': /* padding (silent deletion from padded reference) */ + return (length << BAM_CIGAR_SHIFT) | (6u); + case '=': /* sequence match */ + return (length << BAM_CIGAR_SHIFT) | (7u); + case 'X': /* sequence mismatch */ + return (length << BAM_CIGAR_SHIFT) | (8u); + } + return (uint32_t)-1; // This never happens +} + +cigar* banded_sw (const int8_t* ref, + const int8_t* read, + int32_t refLen, + int32_t readLen, + int32_t score, + const uint32_t weight_gapO, /* will be used as - */ + const uint32_t weight_gapE, /* will be used as - */ + int32_t band_width, + const int8_t* mat, /* pointer to the weight matrix */ + int32_t n, + int32_t read_begin, + int32_t unclippedReadLen +) { + + //printf("banded_sw read %p, readLen %i begin %i fulllen %i \n",read,readLen,read_begin,unclippedReadLen); + + uint32_t *c = (uint32_t*)malloc(16 * sizeof(uint32_t)), *c1; + int32_t i, j, e, f, temp1, temp2, s = 16, s1 = 8, l, max = 0; + int64_t s2 = 1024; + char op, prev_op; + int32_t width, width_d, *h_b, *e_b, *h_c; + int8_t *direction, *direction_line; + cigar* result = (cigar*)malloc(sizeof(cigar)); + h_b = (int32_t*)malloc(s1 * sizeof(int32_t)); + e_b = (int32_t*)malloc(s1 * sizeof(int32_t)); + h_c = (int32_t*)malloc(s1 * sizeof(int32_t)); + direction = (int8_t*)malloc(s2 * sizeof(int8_t)); + + do { + width = band_width * 2 + 3, width_d = band_width * 2 + 1; + while (width >= s1) { + ++s1; + kroundup32(s1); + h_b = (int32_t*)realloc(h_b, s1 * sizeof(int32_t)); + e_b = (int32_t*)realloc(e_b, s1 * sizeof(int32_t)); + h_c = (int32_t*)realloc(h_c, s1 * sizeof(int32_t)); + } + while (width_d * readLen * 3 >= s2) { + ++s2; + kroundup32(s2); + if (s2 < 0) { + fprintf(stderr, "Alignment score and position are not consensus.\n"); + exit(1); + } + direction = (int8_t*)realloc(direction, s2 * sizeof(int8_t)); + } + direction_line = direction; + for (j = 1; LIKELY(j < width - 1); j ++) h_b[j] = 0; + for (i = 0; LIKELY(i < readLen); i ++) { + int32_t beg = 0, end = refLen - 1, u = 0, edge; + j = i - band_width; beg = beg > j ? beg : j; // band start + j = i + band_width; end = end < j ? end : j; // band end + edge = end + 1 < width - 1 ? end + 1 : width - 1; + f = h_b[0] = e_b[0] = h_b[edge] = e_b[edge] = h_c[0] = 0; + direction_line = direction + width_d * i * 3; + + int8_t bonus = 0; + for (j = beg; LIKELY(j <= end); j ++) { + int32_t b, e1, f1, d, de, df, dh; + set_u(u, band_width, i, j); set_u(e, band_width, i - 1, j); + set_u(b, band_width, i, j - 1); set_u(d, band_width, i - 1, j - 1); + set_d(de, band_width, i, j, 0); + set_d(df, band_width, i, j, 1); + set_d(dh, band_width, i, j, 2); + + temp1 = i == 0 ? -weight_gapO : h_b[e] - weight_gapO; + temp2 = i == 0 ? -weight_gapE : e_b[e] - weight_gapE; + e_b[u] = temp1 > temp2 ? temp1 : temp2; + direction_line[de] = temp1 > temp2 ? 3 : 2; + + temp1 = h_c[b] - weight_gapO; + temp2 = f - weight_gapE; + f = temp1 > temp2 ? temp1 : temp2; + direction_line[df] = temp1 > temp2 ? 5 : 4; + + e1 = e_b[u] > 0 ? e_b[u] : 0; + f1 = f > 0 ? f : 0; + temp1 = e1 > f1 ? e1 : f1; + bonus=0; + if( (i+read_begin) ==0 || (i+read_begin)== (unclippedReadLen -1)) + { + bonus = UNCLIP_BONUS; + //printf("traceback UB readLen %i unclippedReadLen %i read_begin %i i %i read_num[%i] = %i bonus %i\n",readLen,unclippedReadLen,read_begin,i,i,read[i],bonus); + + } + temp2 = h_b[d] + mat[ref[j] * n + read[i]] + bonus; + h_c[u] = temp1 > temp2 ? temp1 : temp2; + + if (h_c[u] > max) max = h_c[u]; + + if (temp1 <= temp2) direction_line[dh] = 1; + else direction_line[dh] = e1 > f1 ? direction_line[de] : direction_line[df]; + } + for (j = 1; j <= u; j ++) h_b[j] = h_c[j]; + } + band_width *= 2; + } while (LIKELY(max < score)); + band_width /= 2; + + // trace back + i = readLen - 1; + j = refLen - 1; + e = 0; // Count the number of M, D or I. + l = 0; // record length of current cigar + op = prev_op = 'M'; + temp2 = 2; // h + while (LIKELY(i > 0)) { + set_d(temp1, band_width, i, j, temp2); + switch (direction_line[temp1]) { + case 1: + --i; + --j; + temp2 = 2; + direction_line -= width_d * 3; + op = 'M'; + break; + case 2: + --i; + temp2 = 0; // e + direction_line -= width_d * 3; + op = 'I'; + break; + case 3: + --i; + temp2 = 2; + direction_line -= width_d * 3; + op = 'I'; + break; + case 4: + --j; + temp2 = 1; + op = 'D'; + break; + case 5: + --j; + temp2 = 2; + op = 'D'; + break; + default: + fprintf(stderr, "Trace back error: %d.\n", direction_line[temp1 - 1]); + free(direction); + free(h_c); + free(e_b); + free(h_b); + free(c); + free(result); + return 0; + } + if (op == prev_op) ++e; + else { + ++l; + while (l >= s) { + ++s; + kroundup32(s); + c = (uint32_t*)realloc(c, s * sizeof(uint32_t)); + } + c[l - 1] = to_cigar_int(e, prev_op); + prev_op = op; + e = 1; + } + } + if (op == 'M') { + ++l; + while (l >= s) { + ++s; + kroundup32(s); + c = (uint32_t*)realloc(c, s * sizeof(uint32_t)); + } + c[l - 1] = to_cigar_int(e + 1, op); + }else { + l += 2; + while (l >= s) { + ++s; + kroundup32(s); + c = (uint32_t*)realloc(c, s * sizeof(uint32_t)); + } + c[l - 2] = to_cigar_int(e, op); + c[l - 1] = to_cigar_int(1, 'M'); + } + + // reverse cigar + c1 = (uint32_t*)malloc(l * sizeof(uint32_t)); + s = 0; + e = l - 1; + while (LIKELY(s <= e)) { + c1[s] = c[e]; + c1[e] = c[s]; + ++ s; + -- e; + } + result->seq = c1; + result->length = l; + + free(direction); + free(h_c); + free(e_b); + free(h_b); + free(c); + return result; +} + +static int8_t* seq_reverse(const int8_t* seq, int32_t end) /* end is 0-based alignment ending position */ +{ + int8_t* reverse = (int8_t*)calloc(end + 1, sizeof(int8_t)); + int32_t start = 0; + while (LIKELY(start <= end)) { + reverse[start] = seq[end]; + reverse[end] = seq[start]; + ++ start; + -- end; + } + return reverse; +} + +int32_t ssw_get_bias(const int8_t* mat, const int32_t n) { + int32_t bias = 0, i; + for (i = 0; i < n*n; i++) { + if (mat[i] < bias) { + bias = mat[i]; + } + } + bias = abs(bias); + return bias; +} + + +s_profile_sse2* ssw_init_sse2 ( + const int8_t* read, const int32_t readLen, + const int8_t* mat, const int32_t n, const int32_t bias, + const int8_t score_size) { + + s_profile_sse2* p = (s_profile_sse2*)calloc(1, sizeof(struct _profile_sse2)); + p->profile_byte = 0; + p->profile_word = 0; + p->bias = 0; + + if (score_size == 0 || score_size == 2) { + p->bias = bias; + p->profile_byte = qP_byte_init (read, mat, readLen, n, bias); + } + + if (score_size == 1 || score_size == 2) p->profile_word = qP_word_init (read, mat, readLen, n); + p->read = read; + p->mat = mat; + p->readLen = readLen; + p->n = n; + return p; +} + +void init_destroy_sse2 (s_profile_sse2* p) { + if (p != nullptr) { + free(p->profile_byte); + free(p->profile_word); + free(p); + } +} + +s_align* ssw_align_sse2 (const s_profile_sse2* prof, + const int8_t* ref, + int32_t refLen, + const uint8_t weight_gapO, + const uint8_t weight_gapE, + const uint8_t flag, // (from high to low) bit 5: return the best alignment beginning position; 6: if (ref_end1 - ref_begin1 <= filterd) && (read_end1 - read_begin1 <= filterd), return cigar; 7: if max score >= filters, return cigar; 8: always return cigar; if 6 & 7 are both setted, only return cigar when both filter fulfilled + const uint16_t filters, + const int32_t filterd, + const int32_t maskLen) { + //printf("----- ssw_align readLen %i read %p ------\n",prof->readLen,prof->read); + alignment_end* bests = 0, *bests_reverse = 0; + __m128i* vP = 0; + int32_t word = 0, band_width = 0, readLen = prof->readLen; + int8_t* read_reverse = 0; + cigar* path; + s_align* r = (s_align*)calloc(1, sizeof(s_align)); + r->ref_begin1 = -1; + r->read_begin1 = -1; + r->cigar = 0; + r->cigarLen = 0; + if (maskLen < 15) { + //fprintf(stderr, "When maskLen < 15, the function ssw_align doesn't return 2nd best alignment information.\n"); + } + + // Find the alignment scores and ending positions + if (prof->profile_byte) { + bests = sw_sse2_byte(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_byte, -1, prof->bias, maskLen); + if (prof->profile_word && bests[0].score == 255) { + free(bests); + bests = sw_sse2_word(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_word, -1, maskLen); + word = 1; + } else if (bests[0].score == 255) { + fprintf(stderr, "Please set 2 to the score_size parameter of the function ssw_init, otherwise the alignment results will be incorrect.\n"); + free(r); + return NULL; + } + }else if (prof->profile_word) { + bests = sw_sse2_word(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_word, -1, maskLen); + word = 1; + }else { + fprintf(stderr, "Please call the function ssw_init before ssw_align.\n"); + free(r); + return NULL; + } + r->score1 = bests[0].score; + r->ref_end1 = bests[0].ref; + r->read_end1 = bests[0].read; + if (maskLen >= 15) { + r->score2 = bests[1].score; + r->ref_end2 = bests[1].ref; + } else { + r->score2 = 0; + r->ref_end2 = -1; + } + free(bests); + if (flag == 0 || (flag == 2 && r->score1 < filters)) goto end; + + + // Find the beginning position of the best alignment. + read_reverse = seq_reverse(prof->read, r->read_end1); + if (word == 0) { + vP = qP_byte_rev(read_reverse, prof->mat, r->read_end1 + 1,readLen, prof->n, prof->bias); + bests_reverse = sw_sse2_byte(ref, 1, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, prof->bias, maskLen); + } else { + vP = qP_word_rev(read_reverse, prof->mat, r->read_end1 + 1,readLen, prof->n); + bests_reverse = sw_sse2_word(ref, 1, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, maskLen); + } + free(vP); + free(read_reverse); + r->ref_begin1 = bests_reverse[0].ref; + r->read_begin1 = r->read_end1 - bests_reverse[0].read; + free(bests_reverse); + if ((7&flag) == 0 || ((2&flag) != 0 && r->score1 < filters) || ((4&flag) != 0 && (r->ref_end1 - r->ref_begin1 > filterd || r->read_end1 - r->read_begin1 > filterd))) goto end; + + // Generate cigar. + refLen = r->ref_end1 - r->ref_begin1 + 1; + readLen = r->read_end1 - r->read_begin1 + 1; + band_width = abs(refLen - readLen) + 1; + + //printf("begin end %i %i \n",r->read_begin1 ,r->read_end1); + + path = banded_sw(ref + r->ref_begin1, prof->read + r->read_begin1, refLen, readLen, r->score1, weight_gapO, weight_gapE, band_width, prof->mat, prof->n, r->read_begin1 , prof->readLen); + if (path == 0) { + free(r); + r = NULL; + } + else { + r->cigar = path->seq; + r->cigarLen = path->length; + free(path); + } + + end: + return r; +} + +void align_destroy (s_align* a) { + free(a->cigar); + free(a); +} + +uint32_t* add_cigar (uint32_t* new_cigar, int32_t* p, int32_t* s, uint32_t length, char op) { + if ((*p) >= (*s)) { + ++(*s); + kroundup32(*s); + new_cigar = (uint32_t*)realloc(new_cigar, (*s)*sizeof(uint32_t)); + } + new_cigar[(*p) ++] = to_cigar_int(length, op); + return new_cigar; +} + +uint32_t* store_previous_m (int8_t choice, // 0: current not M, 1: current match, 2: current mismatch + uint32_t* length_m, + uint32_t* length_x, + int32_t* p, + int32_t* s, + uint32_t* new_cigar) { + + if ((*length_m) && (choice == 2 || !choice)) { + new_cigar = add_cigar (new_cigar, p, s, (*length_m), '='); + (*length_m) = 0; + } else if ((*length_x) && (choice == 1 || !choice)) { + new_cigar = add_cigar (new_cigar, p, s, (*length_x), 'X'); + (*length_x) = 0; + } + return new_cigar; +} + +/*! @function: + 1. Calculate the number of mismatches. + 2. Modify the cigar string: + differentiate matches (=) and mismatches(X); add softclip(S) at the beginning and ending of the original cigar. + @return: + The number of mismatches. + The cigar and cigarLen are modified. + */ +int32_t mark_mismatch (int32_t ref_begin1, + int32_t read_begin1, + int32_t read_end1, + const char* ref, + const char* read, + int32_t readLen, + uint32_t** cigar, + int32_t* cigarLen) { + + int32_t mismatch_length = 0, p = 0, i, length, j, s = *cigarLen + 2; + uint32_t *new_cigar = (uint32_t*)malloc(s*sizeof(uint32_t)), length_m = 0, length_x = 0; + char op; + + ref += ref_begin1; + read += read_begin1; + if (read_begin1 > 0) new_cigar[p ++] = to_cigar_int(read_begin1, 'S'); + for (i = 0; i < (*cigarLen); ++i) { + op = cigar_int_to_op((*cigar)[i]); + length = cigar_int_to_len((*cigar)[i]); + if (op == 'M') { + for (j = 0; j < length; ++j) { + fprintf(stderr, "ref[%d]: %c\tread[%d]: %c\n", j, *ref, j, *read); + if (*ref != *read) { + ++ mismatch_length; + fprintf(stderr, "length_m: %d\n", length_m); + // the previous is match; however the current one is mismatche + new_cigar = store_previous_m (2, &length_m, &length_x, &p, &s, new_cigar); + ++ length_x; + } else { + // the previous is mismatch; however the current one is matche + new_cigar = store_previous_m (1, &length_m, &length_x, &p, &s, new_cigar); + ++ length_m; + } + ++ ref; + ++ read; + } + }else if (op == 'I') { + read += length; + mismatch_length += length; + new_cigar = store_previous_m (0, &length_m, &length_x, &p, &s, new_cigar); + new_cigar = add_cigar (new_cigar, &p, &s, length, 'I'); + }else if (op == 'D') { + ref += length; + mismatch_length += length; + new_cigar = store_previous_m (0, &length_m, &length_x, &p, &s, new_cigar); + new_cigar = add_cigar (new_cigar, &p, &s, length, 'D'); + } + } + new_cigar = store_previous_m (0, &length_m, &length_x, &p, &s, new_cigar); + + length = readLen - read_end1 - 1; + if (length > 0) new_cigar = add_cigar(new_cigar, &p, &s, length, 'S'); + + (*cigarLen) = p; + free(*cigar); + (*cigar) = new_cigar; + return mismatch_length; +} + diff --git a/thirdparty/sswlib/ssw/ssw.h b/thirdparty/sswlib/ssw/ssw.hpp similarity index 69% rename from thirdparty/sswlib/ssw/ssw.h rename to thirdparty/sswlib/ssw/ssw.hpp index 43653e6..b9b777c 100644 --- a/thirdparty/sswlib/ssw/ssw.h +++ b/thirdparty/sswlib/ssw/ssw.hpp @@ -1,12 +1,32 @@ -/* - * ssw.h - * - * Created by Mengyao Zhao on 6/22/10. - * Copyright 2010 Boston College. All rights reserved. - * Version 0.1.4 - * Last revision by Mengyao Zhao on 07/19/16. - * - */ +/** + ** DRAGEN Open Source Software + ** Copyright (c) 2019-2020 Illumina, Inc. + ** All rights reserved. + ** + ** Based on SSW implementation + ** https://github.com/mengyao/Complete-Striped-Smith-Waterman-Library + ** Version 0.1.4 + ** Last revision by Mengyao Zhao on 07/19/16 + ** + ** License: MIT + ** Copyright (c) 2012-2015 Boston College + ** Copyright (c) 2020-2021 Illumina + ** + ** Permission is hereby granted, free of charge, to any person obtaining a copy of this + ** software and associated documentation files (the "Software"), to deal in the Software + ** without restriction, including without limitation the rights to use, copy, modify, + ** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + ** permit persons to whom the Software is furnished to do so, subject to the following + ** conditions: + ** The above copyright notice and this permission notice shall be included in all copies + ** or substantial portions of the Software. + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + ** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + ** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + ** HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + **/ #ifndef SSW_H #define SSW_H @@ -14,21 +34,20 @@ #include #include #include -#include +#include -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus #define MAPSTR "MIDNSHP=X" -#ifndef BAM_CIGAR_SHIFT #define BAM_CIGAR_SHIFT 4u -#endif +/*! @typedef structure of the query profiles */ +struct _profile_sse2; +typedef struct _profile_sse2 s_profile_sse2; -/*! @typedef structure of the query profile */ -struct _profile; -typedef struct _profile s_profile; +#ifdef __AVX2__ +struct _profile_avx2; +typedef struct _profile_avx2 s_profile_avx2; +#endif /*! @typedef structure of the alignment result @field score1 the best alignment score @@ -56,6 +75,11 @@ typedef struct { int32_t cigarLen; } s_align; + +int32_t ssw_get_bias ( + const int8_t* mat, const int32_t n); + + /*! @function Create the query profile using the query sequence. @param read pointer to the query sequence; the query sequence needs to be numbers @param readLen length of the query sequence @@ -74,12 +98,26 @@ typedef struct { -2 -2 -2 2 //T mat is the pointer to the array {2, -2, -2, -2, -2, 2, -2, -2, -2, -2, 2, -2, -2, -2, -2, 2} */ -s_profile* ssw_init (const int8_t* read, const int32_t readLen, const int8_t* mat, const int32_t n, const int8_t score_size); +s_profile_sse2* ssw_init_sse2 ( + const int8_t* read, const int32_t readLen, + const int8_t* mat, const int32_t n, const int32_t bias, + const int8_t score_size); + +#ifdef __AVX2__ +s_profile_avx2* ssw_init_avx2 ( + const int8_t* read, const int32_t readLen, + const int8_t* mat, const int32_t n, const int32_t bias, + const int8_t score_size); +#endif /*! @function Release the memory allocated by function ssw_init. - @param p pointer to the query profile structure + @param p pointer to the query profile structure, may be nullptr */ -void init_destroy (s_profile* p); +void init_destroy_sse2 (s_profile_sse2* p); + +#ifdef __AVX2__ +void init_destroy_avx2 (s_profile_avx2* p); +#endif // @function ssw alignment. /*! @function Do Striped Smith-Waterman alignment. @@ -114,15 +152,29 @@ void init_destroy (s_profile* p); while bit 8 is not, the function will return cigar only when both criteria are fulfilled. All returned positions are 0-based coordinate. */ -s_align* ssw_align (const s_profile* prof, - const int8_t* ref, - int32_t refLen, - const uint8_t weight_gapO, - const uint8_t weight_gapE, - const uint8_t flag, - const uint16_t filters, - const int32_t filterd, - const int32_t maskLen); +s_align* ssw_align_sse2 ( + const s_profile_sse2* prof, + const int8_t* ref, + int32_t refLen, + const uint8_t weight_gapO, + const uint8_t weight_gapE, + const uint8_t flag, + const uint16_t filters, + const int32_t filterd, + const int32_t maskLen); + +#ifdef __AVX2__ +s_align* ssw_align_avx2 ( + const s_profile_avx2* prof, + const int8_t* ref, + int32_t refLen, + const uint8_t weight_gapO, + const uint8_t weight_gapE, + const uint8_t flag, + const uint16_t filters, + const int32_t filterd, + const int32_t /*maskLen*/); +#endif /*! @function Release the memory allocated by function ssw_align. @param a pointer to the alignment result structure @@ -181,8 +233,27 @@ static inline uint32_t cigar_int_to_len (uint32_t cigar_int) { return cigar_int >> BAM_CIGAR_SHIFT; } -#ifdef __cplusplus -} -#endif // __cplusplus + +typedef struct { + uint32_t* seq; + int32_t length; +} cigar; + +/*! @function Compute banded SMW with a traceback and return CIGAR representation. +*/ +cigar* banded_sw ( + const int8_t* ref, + const int8_t* read, + int32_t refLen, + int32_t readLen, + int32_t score, + const uint32_t weight_gapO, /* will be used as - */ + const uint32_t weight_gapE, /* will be used as - */ + int32_t band_width, + const int8_t* mat, /* pointer to the weight matrix */ + int32_t n, + int32_t read_begin, + int32_t unclippedReadLen +); #endif // SSW_H diff --git a/thirdparty/sswlib/ssw/ssw_avx2.cpp b/thirdparty/sswlib/ssw/ssw_avx2.cpp new file mode 100644 index 0000000..8464392 --- /dev/null +++ b/thirdparty/sswlib/ssw/ssw_avx2.cpp @@ -0,0 +1,510 @@ +/** + ** DRAGEN Open Source Software + ** Copyright (c) 2019-2020 Illumina, Inc. + ** All rights reserved. + ** + ** Based on SSW implementation + ** https://github.com/mengyao/Complete-Striped-Smith-Waterman-Library + ** Version 0.1.4 + ** Last revision by Mengyao Zhao on 07/19/16 + ** + ** License: MIT + ** Copyright (c) 2012-2015 Boston College + ** Copyright (c) 2021 Illumina + ** + ** Permission is hereby granted, free of charge, to any person obtaining a copy of this + ** software and associated documentation files (the "Software"), to deal in the Software + ** without restriction, including without limitation the rights to use, copy, modify, + ** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + ** permit persons to whom the Software is furnished to do so, subject to the following + ** conditions: + ** The above copyright notice and this permission notice shall be included in all copies + ** or substantial portions of the Software. + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + ** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + ** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + ** HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ssw.hpp" +#include "ssw_internal.hpp" + +#ifdef __AVX2__ + +constexpr int AVX2_BYTE_ELEMS = 32; + +static inline __attribute__((always_inline)) void* memalign_local(const size_t alignment, const size_t size) +{ + void* ptr = NULL; + BOOST_ASSERT(0 == posix_memalign(&ptr, alignment, size)); + BOOST_ASSERT(ptr != nullptr); + return ptr; +} + +static inline int32_t getSegLen(const int32_t readLen) +{ + return (readLen + AVX2_BYTE_ELEMS - 1) / AVX2_BYTE_ELEMS; +} + +/* Generate query profile rearrange query sequence & calculate the weight of match/mismatch. */ +static __m256i* qP_byte_init ( + const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t n, /* the edge length of the squre matrix mat */ + uint8_t bias) { + + int32_t segLen = getSegLen(readLen); /* Split the 128 bit register into 16 pieces. + Each piece is 8 bit. Split the read into 16 segments. + Calculate 16 segments in parallel. + */ + __m256i* vProfile = (__m256i*)memalign_local(AVX2_BYTE_ELEMS, n * segLen * sizeof(__m256i)); + int8_t* t = (int8_t*)vProfile; + int32_t nt, i, j, segNum; + + + std::vector bonuses(segLen * AVX2_BYTE_ELEMS, bias); + bonuses[0] = bias + UNCLIP_BONUS; + bonuses[readLen-1] = bias + UNCLIP_BONUS; + + /* Generate query profile, rearrange query sequence & calculate the weight of match/mismatch */ + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + + for (segNum = 0; LIKELY(segNum < AVX2_BYTE_ELEMS) ; segNum ++) { + *t++ = + j>= readLen ? + bias : + mat[nt * n + read_num[j]] + bonuses[j]; + j += segLen; + } + } + } + + return vProfile; +} + +static __m256i* qP_byte_rev ( + const int8_t* read_num, + const int8_t* mat, + const int32_t readLen, + const int32_t fullreadLen, + const int32_t n, + uint8_t bias) { + //printf("qp_byte rev readLen %i fullreadLen %i \n",readLen,fullreadLen); + + constexpr int ELEMS = 32; + + int32_t segLen = getSegLen(readLen); + __m256i* vProfile = (__m256i*)malloc(n * segLen * sizeof(__m256i)); + int8_t* t = (int8_t*)vProfile; + int32_t nt, i, j, segNum; + + std::vector bonuses(segLen * AVX2_BYTE_ELEMS, bias); + if (readLen == fullreadLen) { + bonuses[0] = bias + UNCLIP_BONUS; + } + bonuses[readLen-1] = bias + UNCLIP_BONUS; + + for (nt = 0; LIKELY(nt < n); nt ++) { + for (i = 0; i < segLen; i ++) { + j = i; + for (segNum = 0; LIKELY(segNum < ELEMS) ; segNum ++) { + + *t++ = j>= readLen ? bias : mat[nt * n + read_num[j]] + bonuses[j]; + j += segLen; + } + } + } + return vProfile; +} + + +static inline uint8_t max32fun(__m256i v) +{ + uint8_t* s = (uint8_t*)&v; + uint8_t max = 0; + // recognized by compiler + for (int i = 0; i < 32; i++) { + if (s[i] > max) { + max = s[i]; + } + } + + return max; +} + +// shift left that handles 128-bit lane crossing +template +__m256i _mm256_shift_left(__m256i a) +{ + __m256i mask = _mm256_srli_si256( + _mm256_permute2x128_si256(a, a, _MM_SHUFFLE(0,0,3,0)), 16-N); + return _mm256_or_si256(_mm256_slli_si256(a,N),mask); +} + +/* Striped Smith-Waterman + Record the highest score of each reference position. + Return the alignment score and ending position of the best alignment, 2nd best alignment, etc. + Gap begin and gap extension are different. + wight_match > 0, all other weights < 0. + The returned positions are 0-based. + */ +template +static void sw_avx2_byte (const int8_t* ref, + int32_t refLen, + int32_t readLen, + const uint8_t weight_gapO, /* will be used as - */ + const uint8_t weight_gapE, /* will be used as - */ + const __m256i* vProfile, + uint8_t terminate, /* the best alignment score: used to terminate + the matrix calculation when locating the + alignment beginning point. If this score + is set to 0, it will not be used */ + uint8_t bias, /* Shift 0 point to a positive value. */ + int32_t /*maskLen*/, + alignment_end& best) { + + uint8_t max = 0; /* the max alignment score */ + int32_t end_read = readLen - 1; + int32_t end_ref = -1; /* 0_based best alignment ending point; Initialized as isn't aligned -1. */ + int32_t segLen; + + if (segLenIs5) { + segLen = 5; + } + else { + segLen = (readLen + AVX2_BYTE_ELEMS - 1) / AVX2_BYTE_ELEMS; /* number of segment */ + } + + /* Define 32 byte 0 vector. */ + __m256i vZero = _mm256_set1_epi32(0); + size_t sz = segLen * sizeof(__m256i); + __m256i* pvHStore = (__m256i*) memalign_local(AVX2_BYTE_ELEMS, sz); + __m256i* pvHLoad = (__m256i*) memalign_local(AVX2_BYTE_ELEMS, sz); + __m256i* pvE = (__m256i*) memalign_local(AVX2_BYTE_ELEMS, sz); + __m256i* pvHmax = (__m256i*) memalign_local(AVX2_BYTE_ELEMS, sz); + + // no need to clear pvHLoad and pvHmax + memset(pvHStore, 0, sz); + memset(pvE, 0, sz); + + int32_t i, j; + /* 32 byte insertion begin vector */ + __m256i vGapO = _mm256_set1_epi8(weight_gapO); + + /* 32 byte insertion extension vector */ + __m256i vGapE = _mm256_set1_epi8(weight_gapE); + + /* 32 byte bias vector */ + __m256i vBias = _mm256_set1_epi8(bias); + + + __m256i vTerminate = _mm256_set1_epi8(terminate); + + __m256i vMaxScore = vZero; /* Trace the highest score of the whole SW matrix. */ + __m256i vMaxMark = vZero; /* Trace the highest score till the previous column. */ + __m256i vTemp; + int32_t begin = 0, end = refLen, step = 1; + + /* outer loop to process the reference sequence */ + if (ref_dir == 1) { + begin = refLen - 1; + end = -1; + step = -1; + } + // for reference + for (i = begin; LIKELY(i != end); i += step) { + int32_t cmp; + __m256i e, vF = vZero, vMaxColumn = vZero; /* Initialize F value to 0. + Any errors to vH values will be corrected in the Lazy_F loop. */ + + __m256i vH = _mm256_loadu_si256(&pvHStore[segLen - 1]); + vH = _mm256_shift_left<1>(vH); + + const __m256i* vP = vProfile + ref[i] * segLen; /* Right part of the vProfile */ + + /* Swap the 2 H buffers. */ + __m256i* pv = pvHLoad; + pvHLoad = pvHStore; + pvHStore = pv; + + /* inner loop to process the query sequence */ + for (j = 0; LIKELY(j < segLen); ++j) { + + __m256i p = _mm256_loadu_si256(vP + j); + + vH = _mm256_adds_epu8(vH, p); + vH = _mm256_subs_epu8(vH, vBias); /* vH will be always > 0 */ + + /* Get max from vH, vE and vF. */ + e = _mm256_loadu_si256(pvE + j); // originally _mm256_loadu_si256 + + vH = _mm256_max_epu8(vH, e); + vH = _mm256_max_epu8(vH, vF); + + vMaxColumn = _mm256_max_epu8(vMaxColumn, vH); + + /* Save vH values. */ + _mm256_storeu_si256(pvHStore + j, vH); + + /* Update vE value. */ + vH = _mm256_subs_epu8(vH, vGapO); /* saturation arithmetic, result >= 0 */ + + e = _mm256_subs_epu8(e, vGapE); + e = _mm256_max_epu8(e, vH); + _mm256_storeu_si256(pvE + j, e); + + /* Update vF value. */ + vF = _mm256_subs_epu8(vF, vGapE); + vF = _mm256_max_epu8(vF, vH); + + /* Load the next vH. */ + vH = _mm256_loadu_si256(pvHLoad + j); + } + + /* Lazy_F loop: has been revised to disallow adjacent insertion and then deletion, so don't update E(i, j), learn from SWPS3 */ + /* reset pointers to the start of the saved data */ + j = 0; + vH = _mm256_loadu_si256 (pvHStore + j); + + /* the computed vF value is for the given column. since */ + /* we are at the end, we need to shift the vF value over */ + /* to the next column. */ + vF = _mm256_shift_left<1>(vF); + + vTemp = _mm256_subs_epu8 (vH, vGapO); + vTemp = _mm256_subs_epu8 (vF, vTemp); + vTemp = _mm256_cmpeq_epi8 (vTemp, vZero); + cmp = _mm256_movemask_epi8 (vTemp); + + while ((unsigned int)cmp != 0xffffffff) + { + vH = _mm256_max_epu8 (vH, vF); + vMaxColumn = _mm256_max_epu8(vMaxColumn, vH); + _mm256_storeu_si256 (pvHStore + j, vH); + vF = _mm256_subs_epu8 (vF, vGapE); + j++; + if (j >= segLen) + { + j = 0; + vF = _mm256_shift_left<1>(vF); + } + vH = _mm256_loadu_si256 (pvHStore + j); + + vTemp = _mm256_subs_epu8 (vH, vGapO); + vTemp = _mm256_subs_epu8 (vF, vTemp); + vTemp = _mm256_cmpeq_epi8 (vTemp, vZero); + cmp = _mm256_movemask_epi8 (vTemp); + } + + vMaxScore = _mm256_max_epu8(vMaxScore, vMaxColumn); + vTemp = _mm256_cmpeq_epi8(vMaxMark, vMaxScore); + cmp = _mm256_movemask_epi8(vTemp); + if ((unsigned int)cmp != 0xffffffff) { + uint8_t temp; + vMaxMark = vMaxScore; + temp = max32fun(vMaxScore); + vMaxScore = vMaxMark; + + if (LIKELY(temp > max)) { + max = temp; + if (max + bias >= 255) break; //overflow + end_ref = i; + + /* Store the column with the highest alignment score in order to trace the alignment ending position on read. */ + for (j = 0; LIKELY(j < segLen); ++j) { + __m256i v = _mm256_loadu_si256(&pvHStore[j]); + _mm256_storeu_si256(&pvHmax[j], v); + } + } + } + + vTemp = _mm256_cmpeq_epi8(vTerminate, vMaxColumn); + cmp = _mm256_movemask_epi8(vTemp); + if ((unsigned int)cmp != 0) { + break; + } + } + + /* Trace the alignment ending position on read. */ + uint8_t *t = (uint8_t*)pvHmax; + int32_t column_len = segLen * AVX2_BYTE_ELEMS; + for (i = 0; LIKELY(i < column_len); ++i, ++t) { + int32_t temp; + if (*t == max) { + temp = i / AVX2_BYTE_ELEMS + i % AVX2_BYTE_ELEMS * segLen; + if (temp < end_read) end_read = temp; + } + } + + free(pvHmax); + free(pvE); + free(pvHLoad); + free(pvHStore); + + /* Record the best alignment. */ + best.score = max + bias >= 255 ? 255 : max; + best.ref = end_ref; + best.read = end_read; +} + +s_profile_avx2* ssw_init_avx2 ( + const int8_t* read, const int32_t readLen, + const int8_t* mat, const int32_t n, const int32_t bias, + const int8_t score_size) +{ + BOOST_ASSERT(score_size == 0 && + "The AVX2 SSW variant initializes profile only for 8-bit scoring, " + "16-bit scoring profile is initialized only when needed." + ); + + s_profile_avx2* p = (s_profile_avx2*)calloc(1, sizeof(struct _profile_avx2)); + p->profile_byte = 0; + p->profile_word = 0; + p->bias = bias; + + p->profile_byte = qP_byte_init (read, mat, readLen, n, bias); + + p->read = read; + p->mat = mat; + p->readLen = readLen; + p->n = n; + return p; +} + +void init_destroy_avx2 (s_profile_avx2* p) { + if (p != nullptr) { + free(p->profile_byte); + free(p->profile_word); + free(p); + } +} + +// free +static int8_t* seq_reverse(const int8_t* seq, int32_t end) /* end is 0-based alignment ending position */ +{ + int8_t* reverse = (int8_t*)calloc(end + 1, sizeof(int8_t)); + int32_t start = 0; + while (LIKELY(start <= end)) { + reverse[start] = seq[end]; + reverse[end] = seq[start]; + ++ start; + -- end; + } + return reverse; +} + + +s_align* ssw_align_avx2 ( + const s_profile_avx2* prof, + const int8_t* ref, + int32_t refLen, + const uint8_t weight_gapO, + const uint8_t weight_gapE, + const uint8_t flag, // (from high to low) bit 5: return the best alignment beginning position; 6: if (ref_end1 - ref_begin1 <= filterd) && (read_end1 - read_begin1 <= filterd), return cigar; 7: if max score >= filters, return cigar; 8: always return cigar; if 6 & 7 are both setted, only return cigar when both filter fulfilled + const uint16_t filters, + const int32_t filterd, + const int32_t maskLen) { + //printf("----- ssw_align readLen %i read %p ------\n",prof->readLen,prof->read); + alignment_end best, best_reverse; + int32_t band_width = 0, readLen = prof->readLen; + int8_t* read_reverse = 0; + cigar* path; + s_align* r = (s_align*)calloc(1, sizeof(s_align)); + r->ref_begin1 = -1; + r->read_begin1 = -1; + r->cigar = 0; + r->cigarLen = 0; + + int32_t segLen = (readLen + AVX2_BYTE_ELEMS - 1) / AVX2_BYTE_ELEMS; + + // Find the alignment scores and ending positions + if (prof->profile_byte) { + + if (segLen == 5) { + sw_avx2_byte(ref, refLen, readLen, weight_gapO, weight_gapE, prof->profile_byte, -1, prof->bias, maskLen, best); + } + else { + sw_avx2_byte(ref, refLen, readLen, weight_gapO, weight_gapE, prof->profile_byte, -1, prof->bias, maskLen, best); + } + + if (best.score == 255) { + free(r); + + // use SSW implementation as a fallback when 8-bit scoring overflowed, + // does not happen with ~150 base reads + // there is no overflow check in SSW for the 16-bit scoring + s_profile_sse2* prof_sse2 = ssw_init_sse2 ( + prof->read, prof->readLen, + prof->mat, prof->n, prof->bias, 2); + + s_align* r16 = ssw_align_sse2( + prof_sse2, ref, refLen, + weight_gapO, weight_gapE, + flag, filters, filterd, maskLen); + + init_destroy_sse2(prof_sse2); + return r16; + } + }else { + fprintf(stderr, "Please call the function ssw_init before ssw_align.\n"); + free(r); + return nullptr; + } + r->score1 = best.score; + r->ref_end1 = best.ref; + r->read_end1 = best.read; + r->score2 = 0; + r->ref_end2 = -1; + + if (flag == 0 || (flag == 2 && r->score1 < filters)) { + return r; + } + + // Find the beginning position of the best alignment. + read_reverse = seq_reverse(prof->read, r->read_end1); + __m256i* vP = qP_byte_rev(read_reverse, prof->mat, r->read_end1 + 1,readLen, prof->n, prof->bias); + sw_avx2_byte(ref, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, prof->bias, maskLen, best_reverse); + free(vP); + free(read_reverse); + + r->ref_begin1 = best_reverse.ref; + r->read_begin1 = r->read_end1 - best_reverse.read; + + if ((7&flag) == 0 || ((2&flag) != 0 && r->score1 < filters) || ((4&flag) != 0 && (r->ref_end1 - r->ref_begin1 > filterd || r->read_end1 - r->read_begin1 > filterd))) { + return r; + } + + // Generate cigar. + refLen = r->ref_end1 - r->ref_begin1 + 1; + readLen = r->read_end1 - r->read_begin1 + 1; + band_width = abs(refLen - readLen) + 1; + + path = banded_sw(ref + r->ref_begin1, prof->read + r->read_begin1, refLen, readLen, r->score1, weight_gapO, weight_gapE, band_width, prof->mat, prof->n, r->read_begin1 , prof->readLen); + if (path == nullptr) { + free(r); + r = nullptr; + } + else { + r->cigar = path->seq; + r->cigarLen = path->length; + free(path); + } + + return r; +} + +#endif // #ifdef __AVX2__ diff --git a/thirdparty/sswlib/ssw/ssw_cpp.cpp b/thirdparty/sswlib/ssw/ssw_cpp.cpp deleted file mode 100644 index 4e3df7d..0000000 --- a/thirdparty/sswlib/ssw/ssw_cpp.cpp +++ /dev/null @@ -1,476 +0,0 @@ -#include "ssw_cpp.h" -#include "ssw.h" - -#include - -namespace { - -static const int8_t kBaseTranslation[128] = { - 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, 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, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - // A C G - 4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, - // T - 4, 4, 4, 4, 3, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - // a c g - 4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, - // t - 4, 4, 4, 4, 3, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 -}; - -void BuildSwScoreMatrix(const uint8_t& match_score, - const uint8_t& mismatch_penalty, - int8_t* matrix) { - - // The score matrix looks like - // // A, C, G, T, N - // score_matrix_ = { 2, -2, -2, -2, -2, // A - // -2, 2, -2, -2, -2, // C - // -2, -2, 2, -2, -2, // G - // -2, -2, -2, 2, -2, // T - // -2, -2, -2, -2, -2};// N - - int id = 0; - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - matrix[id] = ((i == j) ? match_score : static_cast(-mismatch_penalty)); - ++id; - } - matrix[id] = static_cast(-mismatch_penalty); // For N - ++id; - } - - for (int i = 0; i < 5; ++i) - matrix[id++] = static_cast(-mismatch_penalty); // For N - -} - -void ConvertAlignment(const s_align& s_al, - const int& query_len, - StripedSmithWaterman::Alignment* al) { - al->sw_score = s_al.score1; - al->sw_score_next_best = s_al.score2; - al->ref_begin = s_al.ref_begin1; - al->ref_end = s_al.ref_end1; - al->query_begin = s_al.read_begin1; - al->query_end = s_al.read_end1; - al->ref_end_next_best = s_al.ref_end2; - - al->cigar.clear(); - al->cigar_string.clear(); - - if (s_al.cigarLen > 0) { - std::ostringstream cigar_string; - if (al->query_begin > 0) { - uint32_t cigar = to_cigar_int(al->query_begin, 'S'); - al->cigar.push_back(cigar); - cigar_string << al->query_begin << 'S'; - } - - for (int i = 0; i < s_al.cigarLen; ++i) { - al->cigar.push_back(s_al.cigar[i]); - cigar_string << cigar_int_to_len(s_al.cigar[i]) << cigar_int_to_op(s_al.cigar[i]); - } - - int end = query_len - al->query_end - 1; - if (end > 0) { - uint32_t cigar = to_cigar_int(end, 'S'); - al->cigar.push_back(cigar); - cigar_string << end << 'S'; - } - - al->cigar_string = cigar_string.str(); - } // end if -} - -// @Function: -// Calculate the length of the previous cigar operator -// and store it in new_cigar and new_cigar_string. -// Clean up in_M (false), in_X (false), length_M (0), and length_X(0). -void CleanPreviousMOperator( - bool* in_M, - bool* in_X, - uint32_t* length_M, - uint32_t* length_X, - std::vector* new_cigar, - std::ostringstream* new_cigar_string) { - if (*in_M) { - uint32_t match = to_cigar_int(*length_M, '='); - new_cigar->push_back(match); - (*new_cigar_string) << *length_M << '='; - } else if (*in_X){ //in_X - uint32_t match = to_cigar_int(*length_X, 'X'); - new_cigar->push_back(match); - (*new_cigar_string) << *length_X << 'X'; - } - - // Clean up - *in_M = false; - *in_X = false; - *length_M = 0; - *length_X = 0; -} - -// @Function: -// 1. Calculate the number of mismatches. -// 2. Modify the cigar string: -// differentiate matches (M) and mismatches(X). -// @Return: -// The number of mismatches. -int CalculateNumberMismatch( - StripedSmithWaterman::Alignment* al, - int8_t const *ref, - int8_t const *query, - const int& query_len) { - - ref += al->ref_begin; - query += al->query_begin; - int mismatch_length = 0; - - std::vector new_cigar; - std::ostringstream new_cigar_string; - - if (al->query_begin > 0) { - uint32_t cigar = to_cigar_int(al->query_begin, 'S'); - new_cigar.push_back(cigar); - new_cigar_string << al->query_begin << 'S'; - } - - bool in_M = false; // the previous is match - bool in_X = false; // the previous is mismatch - uint32_t length_M = 0; - uint32_t length_X = 0; - - for (unsigned int i = 0; i < al->cigar.size(); ++i) { - char op = cigar_int_to_op(al->cigar[i]); - uint32_t length = cigar_int_to_len(al->cigar[i]); - if (op == 'M') { - for (uint32_t j = 0; j < length; ++j) { - if (*ref != *query) { - ++mismatch_length; - if (in_M) { // the previous is match; however the current one is mismatche - uint32_t match = to_cigar_int(length_M, '='); - new_cigar.push_back(match); - new_cigar_string << length_M << '='; - } - length_M = 0; - ++length_X; - in_M = false; - in_X = true; - } else { // *ref == *query - if (in_X) { // the previous is mismatch; however the current one is matche - uint32_t match = to_cigar_int(length_X, 'X'); - new_cigar.push_back(match); - new_cigar_string << length_X << 'X'; - } - ++length_M; - length_X = 0; - in_M = true; - in_X = false; - } // end of if (*ref != *query) - ++ref; - ++query; - } - } else if (op == 'I') { - query += length; - mismatch_length += length; - CleanPreviousMOperator(&in_M, &in_X, &length_M, &length_X, &new_cigar, &new_cigar_string); - new_cigar.push_back(al->cigar[i]); - new_cigar_string << length << 'I'; - } else if (op == 'D') { - ref += length; - mismatch_length += length; - CleanPreviousMOperator(&in_M, &in_X, &length_M, &length_X, &new_cigar, &new_cigar_string); - new_cigar.push_back(al->cigar[i]); - new_cigar_string << length << 'D'; - } - } - - CleanPreviousMOperator(&in_M, &in_X, &length_M, &length_X, &new_cigar, &new_cigar_string); - - int end = query_len - al->query_end - 1; - if (end > 0) { - uint32_t cigar = to_cigar_int(end, 'S'); - new_cigar.push_back(cigar); - new_cigar_string << end << 'S'; - } - - al->cigar_string.clear(); - al->cigar.clear(); - al->cigar_string = new_cigar_string.str(); - al->cigar = new_cigar; - - return mismatch_length; -} - -void SetFlag(const StripedSmithWaterman::Filter& filter, uint8_t* flag) { - if (filter.report_begin_position) *flag |= 0x08; - if (filter.report_cigar) *flag |= 0x0f; -} - -// http://www.cplusplus.com/faq/sequences/arrays/sizeof-array/#cpp -template -inline size_t SizeOfArray( const T(&)[ N ] ) -{ - return N; -} - -} // namespace - - - -namespace StripedSmithWaterman { - -Aligner::Aligner(void) - : score_matrix_(NULL) - , score_matrix_size_(5) - , translation_matrix_(NULL) - , match_score_(2) - , mismatch_penalty_(2) - , gap_opening_penalty_(3) - , gap_extending_penalty_(1) - , translated_reference_(NULL) - , reference_length_(0) -{ - BuildDefaultMatrix(); -} - -Aligner::Aligner( - const uint8_t& match_score, - const uint8_t& mismatch_penalty, - const uint8_t& gap_opening_penalty, - const uint8_t& gap_extending_penalty) - - : score_matrix_(NULL) - , score_matrix_size_(5) - , translation_matrix_(NULL) - , match_score_(match_score) - , mismatch_penalty_(mismatch_penalty) - , gap_opening_penalty_(gap_opening_penalty) - , gap_extending_penalty_(gap_extending_penalty) - , translated_reference_(NULL) - , reference_length_(0) -{ - BuildDefaultMatrix(); -} - -Aligner::Aligner(const int8_t* score_matrix, - const int& score_matrix_size, - const int8_t* translation_matrix, - const int& translation_matrix_size) - - : score_matrix_(NULL) - , score_matrix_size_(score_matrix_size) - , translation_matrix_(NULL) - , match_score_(2) - , mismatch_penalty_(2) - , gap_opening_penalty_(3) - , gap_extending_penalty_(1) - , translated_reference_(NULL) - , reference_length_(0) -{ - score_matrix_ = new int8_t[score_matrix_size_ * score_matrix_size_]; - memcpy(score_matrix_, score_matrix, sizeof(int8_t) * score_matrix_size_ * score_matrix_size_); - translation_matrix_ = new int8_t[translation_matrix_size]; - memcpy(translation_matrix_, translation_matrix, sizeof(int8_t) * translation_matrix_size); -} - - -Aligner::~Aligner(void){ - Clear(); -} - -int Aligner::SetReferenceSequence(const char* seq, const int& length) { - - int len = 0; - if (translation_matrix_) { - // calculate the valid length - //int calculated_ref_length = static_cast(strlen(seq)); - //int valid_length = (calculated_ref_length > length) - // ? length : calculated_ref_length; - int valid_length = length; - // delete the current buffer - CleanReferenceSequence(); - // allocate a new buffer - translated_reference_ = new int8_t[valid_length]; - - len = TranslateBase(seq, valid_length, translated_reference_); - } else { - // nothing - } - - reference_length_ = len; - return len; - - -} - -int Aligner::TranslateBase(const char* bases, const int& length, - int8_t* translated) const { - - const char* ptr = bases; - int len = 0; - for (int i = 0; i < length; ++i) { - translated[i] = translation_matrix_[(int) *ptr]; - ++ptr; - ++len; - } - - return len; -} - - -bool Aligner::Align(const char* query, const Filter& filter, - Alignment* alignment) const -{ - if (!translation_matrix_) return false; - if (reference_length_ == 0) return false; - - int query_len = strlen(query); - if (query_len == 0) return false; - int8_t* translated_query = new int8_t[query_len]; - TranslateBase(query, query_len, translated_query); - - const int8_t score_size = 2; - s_profile* profile = ssw_init(translated_query, query_len, score_matrix_, - score_matrix_size_, score_size); - - uint8_t flag = 0; - SetFlag(filter, &flag); - s_align* s_al = ssw_align(profile, translated_reference_, reference_length_, - static_cast(gap_opening_penalty_), - static_cast(gap_extending_penalty_), - flag, filter.score_filter, filter.distance_filter, query_len); - - alignment->Clear(); - ConvertAlignment(*s_al, query_len, alignment); - alignment->mismatches = CalculateNumberMismatch(&*alignment, translated_reference_, translated_query, query_len); - - - // Free memory - delete [] translated_query; - align_destroy(s_al); - init_destroy(profile); - - return true; -} - - -bool Aligner::Align(const char* query, const char* ref, const int& ref_len, - const Filter& filter, Alignment* alignment) const -{ - if (!translation_matrix_) return false; - - int query_len = strlen(query); - if (query_len == 0) return false; - int8_t* translated_query = new int8_t[query_len]; - TranslateBase(query, query_len, translated_query); - - // calculate the valid length - //int calculated_ref_length = static_cast(strlen(ref)); - //int valid_ref_len = (calculated_ref_length > ref_len) - // ? ref_len : calculated_ref_length; - int valid_ref_len = ref_len; - int8_t* translated_ref = new int8_t[valid_ref_len]; - TranslateBase(ref, valid_ref_len, translated_ref); - - - const int8_t score_size = 2; - s_profile* profile = ssw_init(translated_query, query_len, score_matrix_, - score_matrix_size_, score_size); - - uint8_t flag = 0; - SetFlag(filter, &flag); - s_align* s_al = ssw_align(profile, translated_ref, valid_ref_len, - static_cast(gap_opening_penalty_), - static_cast(gap_extending_penalty_), - flag, filter.score_filter, filter.distance_filter, query_len); - - alignment->Clear(); - ConvertAlignment(*s_al, query_len, alignment); - alignment->mismatches = CalculateNumberMismatch(&*alignment, translated_ref, translated_query, query_len); - - // Free memory - delete [] translated_query; - delete [] translated_ref; - align_destroy(s_al); - init_destroy(profile); - - return true; -} - -void Aligner::Clear(void) { - ClearMatrices(); - CleanReferenceSequence(); -} - -void Aligner::SetAllDefault(void) { - score_matrix_size_ = 5; - match_score_ = 2; - mismatch_penalty_ = 2; - gap_opening_penalty_ = 3; - gap_extending_penalty_ = 1; - reference_length_ = 0; -} - -bool Aligner::ReBuild(void) { - if (translation_matrix_) return false; - - SetAllDefault(); - BuildDefaultMatrix(); - - return true; -} - -bool Aligner::ReBuild( - const uint8_t& match_score, - const uint8_t& mismatch_penalty, - const uint8_t& gap_opening_penalty, - const uint8_t& gap_extending_penalty) { - if (translation_matrix_) return false; - - SetAllDefault(); - - match_score_ = match_score; - mismatch_penalty_ = mismatch_penalty; - gap_opening_penalty_ = gap_opening_penalty; - gap_extending_penalty_ = gap_extending_penalty; - - BuildDefaultMatrix(); - - return true; -} - -bool Aligner::ReBuild( - const int8_t* score_matrix, - const int& score_matrix_size, - const int8_t* translation_matrix, - const int& translation_matrix_size) { - - ClearMatrices(); - score_matrix_ = new int8_t[score_matrix_size_ * score_matrix_size_]; - memcpy(score_matrix_, score_matrix, sizeof(int8_t) * score_matrix_size_ * score_matrix_size_); - translation_matrix_ = new int8_t[translation_matrix_size]; - memcpy(translation_matrix_, translation_matrix, sizeof(int8_t) * translation_matrix_size); - - return true; -} - -void Aligner::BuildDefaultMatrix(void) { - ClearMatrices(); - score_matrix_ = new int8_t[score_matrix_size_ * score_matrix_size_]; - BuildSwScoreMatrix(match_score_, mismatch_penalty_, score_matrix_); - translation_matrix_ = new int8_t[SizeOfArray(kBaseTranslation)]; - memcpy(translation_matrix_, kBaseTranslation, sizeof(int8_t) * SizeOfArray(kBaseTranslation)); -} - -void Aligner::ClearMatrices(void) { - delete [] score_matrix_; - score_matrix_ = NULL; - - delete [] translation_matrix_; - translation_matrix_ = NULL; -} -} // namespace StripedSmithWaterman diff --git a/thirdparty/sswlib/ssw/ssw_cpp.h b/thirdparty/sswlib/ssw/ssw_cpp.h deleted file mode 100644 index cdcf717..0000000 --- a/thirdparty/sswlib/ssw/ssw_cpp.h +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef COMPLETE_STRIPED_SMITH_WATERMAN_CPP_H_ -#define COMPLETE_STRIPED_SMITH_WATERMAN_CPP_H_ - -#include -#include -#include - -namespace StripedSmithWaterman { - -struct Alignment { - uint16_t sw_score; // The best alignment score - uint16_t sw_score_next_best; // The next best alignment score - int32_t ref_begin; // Reference begin position of the best alignment - int32_t ref_end; // Reference end position of the best alignment - int32_t query_begin; // Query begin position of the best alignment - int32_t query_end; // Query end position of the best alignment - int32_t ref_end_next_best; // Reference end position of the next best alignment - int32_t mismatches; // Number of mismatches of the alignment - std::string cigar_string; // Cigar string of the best alignment - std::vector cigar; // Cigar stored in the BAM format - // high 28 bits: length - // low 4 bits: M/I/D/S/X (0/1/2/4/8); - void Clear() { - sw_score = 0; - sw_score_next_best = 0; - ref_begin = 0; - ref_end = 0; - query_begin = 0; - query_end = 0; - ref_end_next_best = 0; - mismatches = 0; - cigar_string.clear(); - cigar.clear(); - }; -}; - -struct Filter { - // NOTE: No matter the filter, those five fields of Alignment will be given anyway. - // sw_score; sw_score_next_best; ref_end; query_end; ref_end_next_best. - // NOTE: Only need score of alignments, please set 'report_begin_position' - // and 'report_cigar' false. - - bool report_begin_position; // Give ref_begin and query_begin. - // If it is not set, ref_begin and query_begin are -1. - bool report_cigar; // Give cigar_string and cigar. - // report_begin_position is automatically TRUE. - - // When *report_cigar* is true and alignment passes these two filters, - // cigar_string and cigar will be given. - uint16_t score_filter; // score >= score_filter - uint16_t distance_filter; // ((ref_end - ref_begin) < distance_filter) && - // ((query_end - read_begin) < distance_filter) - - Filter() - : report_begin_position(true) - , report_cigar(true) - , score_filter(0) - , distance_filter(32767) - {}; - - Filter(const bool& pos, const bool& cigar, const uint16_t& score, const uint16_t& dis) - : report_begin_position(pos) - , report_cigar(cigar) - , score_filter(score) - , distance_filter(dis) - {}; -}; - -class Aligner { - public: - // ========= - // @function Construct an Aligner on default values. - // The function will build the {A.C,G,T,N} aligner. - // If you target for other character aligners, then please - // use the other constructor and pass the corresponding matrix in. - // ========= - Aligner(void); - - // ========= - // @function Construct an Aligner by assigning scores. - // The function will build the {A.C,G,T,N} aligner. - // If you target for other character aligners, then please - // use the other constructor and pass the corresponding matrix in. - // ========= - Aligner(const uint8_t& match_score, - const uint8_t& mismatch_penalty, - const uint8_t& gap_opening_penalty, - const uint8_t& gap_extending_penalty); - - // ========= - // @function Construct an Aligner by the specific matrixs. - // ========= - Aligner(const int8_t* score_matrix, - const int& score_matrix_size, - const int8_t* translation_matrix, - const int& translation_matrix_size); - - ~Aligner(void); - - // ========= - // @function Build the reference sequence and thus make - // Align(const char* query, s_align* alignment) function; - // otherwise the reference should be given when aligning. - // [NOTICE] If there exists a sequence, that one will be deleted - // and replaced. - // @param seq The reference bases; - // [NOTICE] It is not necessary null terminated. - // @param length The length of bases will be be built. - // @return The length of the built bases. - // ========= - int SetReferenceSequence(const char* seq, const int& length); - - void CleanReferenceSequence(void); - - // ========= - // @function Set penalties for opening and extending gaps - // [NOTICE] The defaults are 3 and 1 respectively. - // ========= - void SetGapPenalty(const uint8_t& opening, const uint8_t& extending) { - gap_opening_penalty_ = opening; - gap_extending_penalty_ = extending; - }; - - // ========= - // @function Align the query againt the reference that is set by - // SetReferenceSequence. - // @param query The query sequence. - // @param filter The filter for the alignment. - // @param alignment The container contains the result. - // @return True: succeed; false: fail. - // ========= - bool Align(const char* query, const Filter& filter, Alignment* alignment) const; - - // ========= - // @function Align the query againt the reference. - // [NOTICE] The reference won't replace the reference - // set by SetReferenceSequence. - // @param query The query sequence. - // @param ref The reference sequence. - // [NOTICE] It is not necessary null terminated. - // @param ref_len The length of the reference sequence. - // @param filter The filter for the alignment. - // @param alignment The container contains the result. - // @return True: succeed; false: fail. - // ========= - bool Align(const char* query, const char* ref, const int& ref_len, - const Filter& filter, Alignment* alignment) const; - - // @function Clear up all containers and thus the aligner is disabled. - // To rebuild the aligner please use Build functions. - void Clear(void); - - // ========= - // @function Rebuild the aligner's ability on default values. - // [NOTICE] If the aligner is not cleaned, rebuilding will fail. - // @return True: succeed; false: fail. - // ========= - bool ReBuild(void); - - // ========= - // @function Rebuild the aligner's ability by the specific matrixs. - // [NOTICE] If the aligner is not cleaned, rebuilding will fail. - // @return True: succeed; false: fail. - // ========= - bool ReBuild( - const uint8_t& match_score, - const uint8_t& mismatch_penalty, - const uint8_t& gap_opening_penalty, - const uint8_t& gap_extending_penalty); - - // ========= - // @function Construct an Aligner by the specific matrixs. - // [NOTICE] If the aligner is not cleaned, rebuilding will fail. - // @return True: succeed; false: fail. - // ========= - bool ReBuild( - const int8_t* score_matrix, - const int& score_matrix_size, - const int8_t* translation_matrix, - const int& translation_matrix_size); - - private: - int8_t* score_matrix_; - int score_matrix_size_; - int8_t* translation_matrix_; - - uint8_t match_score_; // default: 2 - uint8_t mismatch_penalty_; // default: 2 - uint8_t gap_opening_penalty_; // default: 3 - uint8_t gap_extending_penalty_; // default: 1 - - int8_t* translated_reference_; - int32_t reference_length_; - - int TranslateBase(const char* bases, const int& length, int8_t* translated) const; - void SetAllDefault(void); - void BuildDefaultMatrix(void); - void ClearMatrices(void); - - Aligner& operator= (const Aligner&); - Aligner (const Aligner&); -}; // class Aligner - - -// ================ -// inline functions -// ================ -inline void Aligner::CleanReferenceSequence(void) { - if (reference_length_ == 0) return; - - // delete the current buffer - if (reference_length_ > 1) delete [] translated_reference_; - else delete translated_reference_; - - reference_length_ = 0; -} -} // namespace StripedSmithWaterman - -#endif // COMPLETE_STRIPED_SMITH_WATERMAN_CPP_H_ diff --git a/thirdparty/sswlib/ssw/ssw_internal.hpp b/thirdparty/sswlib/ssw/ssw_internal.hpp new file mode 100644 index 0000000..9e5d8b0 --- /dev/null +++ b/thirdparty/sswlib/ssw/ssw_internal.hpp @@ -0,0 +1,85 @@ +/** + ** DRAGEN Open Source Software + ** Copyright (c) 2019-2020 Illumina, Inc. + ** All rights reserved. + ** + ** Based on SSW implementation + ** https://github.com/mengyao/Complete-Striped-Smith-Waterman-Library + ** Version 0.1.4 + ** Last revision by Mengyao Zhao on 07/19/16 + ** + ** License: MIT + ** Copyright (c) 2012-2015 Boston College + ** Copyright (c) 2021 Illumina + ** + ** Permission is hereby granted, free of charge, to any person obtaining a copy of this + ** software and associated documentation files (the "Software"), to deal in the Software + ** without restriction, including without limitation the rights to use, copy, modify, + ** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + ** permit persons to whom the Software is furnished to do so, subject to the following + ** conditions: + ** The above copyright notice and this permission notice shall be included in all copies + ** or substantial portions of the Software. + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + ** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + ** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + ** HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + **/ + +// internal shared definitions + +#pragma once + +#include + +#ifdef __GNUC__ +#define LIKELY(x) __builtin_expect((x),1) +#define UNLIKELY(x) __builtin_expect((x),0) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + +#define UNCLIP_BONUS 5 +/* Convert the coordinate in the scoring matrix into the coordinate in one line of the band. */ +#define set_u(u, w, i, j) { int x=(i)-(w); x=x>0?x:0; (u)=(j)-x+1; } + +/* Convert the coordinate in the direction matrix into the coordinate in one line of the band. */ +#define set_d(u, w, i, j, p) { int x=(i)-(w); x=x>0?x:0; x=(j)-x; (u)=x*3+p; } + +/*! @function + @abstract Round an integer to the next closest power-2 integer. + @param x integer to be rounded (in place) + @discussion x will be modified. + */ +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) + +typedef struct { + uint16_t score; + int32_t ref; //0-based position + int32_t read; //alignment ending position on read, 0-based +} alignment_end; + +struct _profile_sse2{ + __m128i* profile_byte; // 0: none + __m128i* profile_word; // 0: none + const int8_t* read; + const int8_t* mat; + int32_t readLen; + int32_t n; + uint8_t bias; +}; + +struct _profile_avx2{ + __m256i* profile_byte; // 0: none + __m256i* profile_word; // 0: none + const int8_t* read; + const int8_t* mat; + int32_t readLen; + int32_t n; + uint8_t bias; +}; + +