From 49fbc9d8564925be952f588243d24498f4ac7b6f Mon Sep 17 00:00:00 2001 From: Sarah Westcott Date: Sun, 7 Feb 2016 16:56:47 -0500 Subject: [PATCH] vsearch weekend updates #169 --- Mothur.xcodeproj/project.pbxproj | 26 +- source/vsearch_src/abundance.cc | 362 +- source/vsearch_src/abundance.h | 181 +- source/vsearch_src/align.cc | 0 source/vsearch_src/align.h | 5 - source/vsearch_src/align_simd.cc | 8 +- source/vsearch_src/align_simd.h | 7 - source/vsearch_src/allpairs.cc | 1385 +++---- source/vsearch_src/allpairs.h | 7 - source/vsearch_src/arch.cc | 233 +- source/vsearch_src/arch.h | 2 - source/vsearch_src/bitmap.cc | 0 source/vsearch_src/bitmap.h | 0 source/vsearch_src/chimera.cc | 3204 +++++++------- source/vsearch_src/chimera.h | 0 source/vsearch_src/cluster.cc | 181 +- source/vsearch_src/cluster.h | 0 source/vsearch_src/cpu.cc | 55 +- source/vsearch_src/cpu.h | 3 + source/vsearch_src/db.cc | 124 +- source/vsearch_src/db.h | 14 +- source/vsearch_src/dbindex.cc | 12 +- source/vsearch_src/dbindex.h | 6 +- source/vsearch_src/derep.cc | 141 +- source/vsearch_src/derep.h | 0 source/vsearch_src/fasta.cc | 222 +- source/vsearch_src/fasta.h | 34 +- source/vsearch_src/fastq.cc | 151 +- source/vsearch_src/fastq.h | 20 + source/vsearch_src/fastqops.cc | 460 +- source/vsearch_src/fastqops.h | 1 + source/vsearch_src/fastxdetect.cc | 0 source/vsearch_src/fastxdetect.h | 0 source/vsearch_src/linmemalign.cc | 0 source/vsearch_src/linmemalign.h | 0 source/vsearch_src/maps.cc | 32 +- source/vsearch_src/maps.h | 3 +- source/vsearch_src/mask.cc | 170 +- source/vsearch_src/mask.h | 9 +- source/vsearch_src/md5.c | 590 +-- source/vsearch_src/md5.h | 0 source/vsearch_src/mergepairs.cc | 812 ++++ source/vsearch_src/mergepairs.h | 61 + source/vsearch_src/minheap.cc | 528 +-- source/vsearch_src/minheap.h | 0 source/vsearch_src/msa.cc | 15 +- source/vsearch_src/msa.h | 2 +- source/vsearch_src/pvalue.h | 4843 ++++++++++++++++++++++ source/vsearch_src/results.cc | 14 +- source/vsearch_src/results.h | 0 source/vsearch_src/search.cc | 1387 +++---- source/vsearch_src/search.h | 0 source/vsearch_src/searchcore.cc | 31 +- source/vsearch_src/searchcore.h | 13 +- source/vsearch_src/searchexact.cc | 717 ++++ source/vsearch_src/searchexact.h | 61 + source/vsearch_src/sha1.c | 0 source/vsearch_src/sha1.h | 0 source/vsearch_src/showalign.cc | 3 +- source/vsearch_src/showalign.h | 0 source/vsearch_src/shuffle.cc | 2 +- source/vsearch_src/shuffle.h | 0 source/vsearch_src/sortbylength.cc | 37 +- source/vsearch_src/sortbylength.h | 0 source/vsearch_src/sortbysize.cc | 37 +- source/vsearch_src/sortbysize.h | 0 source/vsearch_src/subsample.cc | 61 +- source/vsearch_src/subsample.h | 0 source/vsearch_src/unique.cc | 105 +- source/vsearch_src/unique.h | 3 +- source/vsearch_src/userfields.cc | 0 source/vsearch_src/userfields.h | 0 source/vsearch_src/util.cc | 846 ++-- source/vsearch_src/util.h | 17 +- source/vsearch_src/vsearch.cc | 4576 ++++++++++---------- source/vsearch_src/vsearch.h | 717 ++-- source/vsearch_src/vsearchfileparser.cpp | 255 -- source/vsearch_src/vsearchfileparser.h | 44 - source/vsearch_src/xstring.h | 0 79 files changed, 14876 insertions(+), 7959 deletions(-) mode change 100644 => 100755 source/vsearch_src/abundance.cc mode change 100644 => 100755 source/vsearch_src/abundance.h mode change 100644 => 100755 source/vsearch_src/align.cc mode change 100644 => 100755 source/vsearch_src/align.h mode change 100644 => 100755 source/vsearch_src/align_simd.cc mode change 100644 => 100755 source/vsearch_src/align_simd.h mode change 100644 => 100755 source/vsearch_src/allpairs.cc mode change 100644 => 100755 source/vsearch_src/allpairs.h mode change 100644 => 100755 source/vsearch_src/arch.cc mode change 100644 => 100755 source/vsearch_src/arch.h mode change 100644 => 100755 source/vsearch_src/bitmap.cc mode change 100644 => 100755 source/vsearch_src/bitmap.h mode change 100644 => 100755 source/vsearch_src/chimera.cc mode change 100644 => 100755 source/vsearch_src/chimera.h mode change 100644 => 100755 source/vsearch_src/cluster.cc mode change 100644 => 100755 source/vsearch_src/cluster.h mode change 100644 => 100755 source/vsearch_src/cpu.cc mode change 100644 => 100755 source/vsearch_src/cpu.h mode change 100644 => 100755 source/vsearch_src/db.cc mode change 100644 => 100755 source/vsearch_src/db.h mode change 100644 => 100755 source/vsearch_src/dbindex.cc mode change 100644 => 100755 source/vsearch_src/dbindex.h mode change 100644 => 100755 source/vsearch_src/derep.cc mode change 100644 => 100755 source/vsearch_src/derep.h mode change 100644 => 100755 source/vsearch_src/fasta.cc mode change 100644 => 100755 source/vsearch_src/fasta.h mode change 100644 => 100755 source/vsearch_src/fastq.cc mode change 100644 => 100755 source/vsearch_src/fastq.h mode change 100644 => 100755 source/vsearch_src/fastqops.cc mode change 100644 => 100755 source/vsearch_src/fastqops.h mode change 100644 => 100755 source/vsearch_src/fastxdetect.cc mode change 100644 => 100755 source/vsearch_src/fastxdetect.h mode change 100644 => 100755 source/vsearch_src/linmemalign.cc mode change 100644 => 100755 source/vsearch_src/linmemalign.h mode change 100644 => 100755 source/vsearch_src/maps.cc mode change 100644 => 100755 source/vsearch_src/maps.h mode change 100644 => 100755 source/vsearch_src/mask.cc mode change 100644 => 100755 source/vsearch_src/mask.h mode change 100644 => 100755 source/vsearch_src/md5.c mode change 100644 => 100755 source/vsearch_src/md5.h create mode 100755 source/vsearch_src/mergepairs.cc create mode 100755 source/vsearch_src/mergepairs.h mode change 100644 => 100755 source/vsearch_src/minheap.cc mode change 100644 => 100755 source/vsearch_src/minheap.h mode change 100644 => 100755 source/vsearch_src/msa.cc mode change 100644 => 100755 source/vsearch_src/msa.h create mode 100755 source/vsearch_src/pvalue.h mode change 100644 => 100755 source/vsearch_src/results.cc mode change 100644 => 100755 source/vsearch_src/results.h mode change 100644 => 100755 source/vsearch_src/search.cc mode change 100644 => 100755 source/vsearch_src/search.h mode change 100644 => 100755 source/vsearch_src/searchcore.cc mode change 100644 => 100755 source/vsearch_src/searchcore.h create mode 100755 source/vsearch_src/searchexact.cc create mode 100755 source/vsearch_src/searchexact.h mode change 100644 => 100755 source/vsearch_src/sha1.c mode change 100644 => 100755 source/vsearch_src/sha1.h mode change 100644 => 100755 source/vsearch_src/showalign.cc mode change 100644 => 100755 source/vsearch_src/showalign.h mode change 100644 => 100755 source/vsearch_src/shuffle.cc mode change 100644 => 100755 source/vsearch_src/shuffle.h mode change 100644 => 100755 source/vsearch_src/sortbylength.cc mode change 100644 => 100755 source/vsearch_src/sortbylength.h mode change 100644 => 100755 source/vsearch_src/sortbysize.cc mode change 100644 => 100755 source/vsearch_src/sortbysize.h mode change 100644 => 100755 source/vsearch_src/subsample.cc mode change 100644 => 100755 source/vsearch_src/subsample.h mode change 100644 => 100755 source/vsearch_src/unique.cc mode change 100644 => 100755 source/vsearch_src/unique.h mode change 100644 => 100755 source/vsearch_src/userfields.cc mode change 100644 => 100755 source/vsearch_src/userfields.h mode change 100644 => 100755 source/vsearch_src/util.cc mode change 100644 => 100755 source/vsearch_src/util.h mode change 100644 => 100755 source/vsearch_src/vsearch.cc mode change 100644 => 100755 source/vsearch_src/vsearch.h delete mode 100644 source/vsearch_src/vsearchfileparser.cpp delete mode 100644 source/vsearch_src/vsearchfileparser.h mode change 100644 => 100755 source/vsearch_src/xstring.h diff --git a/Mothur.xcodeproj/project.pbxproj b/Mothur.xcodeproj/project.pbxproj index abef6c0b5..e46345765 100755 --- a/Mothur.xcodeproj/project.pbxproj +++ b/Mothur.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 2114A7681C654D7400D3D8D9 /* averagelinkage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2114A7671C654D7400D3D8D9 /* averagelinkage.cpp */; }; 219C1DE01552C4BD004209F9 /* newcommandtemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219C1DDF1552C4BD004209F9 /* newcommandtemplate.cpp */; }; 219C1DE41559BCCF004209F9 /* getcoremicrobiomecommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219C1DE31559BCCD004209F9 /* getcoremicrobiomecommand.cpp */; }; + 21C92AB61C67ACC400597EBB /* mergepairs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 21C92AB11C67ACC400597EBB /* mergepairs.cc */; }; + 21C92AB71C67ACC400597EBB /* searchexact.cc in Sources */ = {isa = PBXBuildFile; fileRef = 21C92AB41C67ACC400597EBB /* searchexact.cc */; }; 481623E21B56A2DB004C60B7 /* pcrseqscommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 481623E11B56A2DB004C60B7 /* pcrseqscommand.cpp */; }; 481FB51C1AC0A63E0076CFF3 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 481FB51B1AC0A63E0076CFF3 /* main.cpp */; }; 481FB5261AC0ADA00076CFF3 /* sequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E9B7DB12D37EC400DA6239 /* sequence.cpp */; }; @@ -864,6 +866,11 @@ 219C1DE11552C508004209F9 /* newcommandtemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = newcommandtemplate.h; path = source/commands/newcommandtemplate.h; sourceTree = ""; }; 219C1DE31559BCCD004209F9 /* getcoremicrobiomecommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = getcoremicrobiomecommand.cpp; path = source/commands/getcoremicrobiomecommand.cpp; sourceTree = ""; }; 219C1DE51559BCF2004209F9 /* getcoremicrobiomecommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = getcoremicrobiomecommand.h; path = source/commands/getcoremicrobiomecommand.h; sourceTree = ""; }; + 21C92AB11C67ACC400597EBB /* mergepairs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mergepairs.cc; path = source/vsearch_src/mergepairs.cc; sourceTree = ""; }; + 21C92AB21C67ACC400597EBB /* mergepairs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mergepairs.h; path = source/vsearch_src/mergepairs.h; sourceTree = ""; }; + 21C92AB31C67ACC400597EBB /* pvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pvalue.h; path = source/vsearch_src/pvalue.h; sourceTree = ""; }; + 21C92AB41C67ACC400597EBB /* searchexact.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = searchexact.cc; path = source/vsearch_src/searchexact.cc; sourceTree = ""; }; + 21C92AB51C67ACC400597EBB /* searchexact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = searchexact.h; path = source/vsearch_src/searchexact.h; sourceTree = ""; }; 481623E11B56A2DB004C60B7 /* pcrseqscommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pcrseqscommand.cpp; path = source/commands/pcrseqscommand.cpp; sourceTree = ""; }; 481623E31B58267D004C60B7 /* INSTALL.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = INSTALL.md; sourceTree = ""; }; 481FB5191AC0A63E0076CFF3 /* TestMothur */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestMothur; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -888,8 +895,8 @@ 487C5A851AB88B93002AF48A /* mimarksattributescommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mimarksattributescommand.cpp; path = source/commands/mimarksattributescommand.cpp; sourceTree = ""; }; 487C5A861AB88B93002AF48A /* mimarksattributescommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mimarksattributescommand.h; path = source/commands/mimarksattributescommand.h; sourceTree = ""; }; 48844B261AA74AF9006EF2B8 /* compare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = compare.h; path = source/datastructures/compare.h; sourceTree = ""; }; - 489B55701BCD7F0100FB7DC8 /* vsearchfileparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vsearchfileparser.cpp; path = source/vsearch_src/vsearchfileparser.cpp; sourceTree = ""; }; - 489B55711BCD7F0100FB7DC8 /* vsearchfileparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vsearchfileparser.h; path = source/vsearch_src/vsearchfileparser.h; sourceTree = ""; }; + 489B55701BCD7F0100FB7DC8 /* vsearchfileparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vsearchfileparser.cpp; path = source/vsearchfileparser.cpp; sourceTree = ""; }; + 489B55711BCD7F0100FB7DC8 /* vsearchfileparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vsearchfileparser.h; path = source/vsearchfileparser.h; sourceTree = ""; }; 48A52F4D1BC428DF00548F6C /* abundance.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = abundance.cc; path = source/vsearch_src/abundance.cc; sourceTree = ""; }; 48A52F4E1BC428DF00548F6C /* abundance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = abundance.h; path = source/vsearch_src/abundance.h; sourceTree = ""; }; 48A52F4F1BC428DF00548F6C /* align_simd.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = align_simd.cc; path = source/vsearch_src/align_simd.cc; sourceTree = ""; }; @@ -1842,6 +1849,8 @@ A7E9B87712D37EC400DA6239 /* validparameter.h */, A7E9B87812D37EC400DA6239 /* venn.cpp */, A7E9B87912D37EC400DA6239 /* venn.h */, + 489B55701BCD7F0100FB7DC8 /* vsearchfileparser.cpp */, + 489B55711BCD7F0100FB7DC8 /* vsearchfileparser.h */, 48A52F4C1BC423E600548F6C /* vsearch */, A7E9B87E12D37EC400DA6239 /* weightedlinkage.cpp */, ); @@ -1949,6 +1958,11 @@ 48A52F821BC428DF00548F6C /* search.h */, 48A52F831BC428DF00548F6C /* searchcore.cc */, 48A52F841BC428DF00548F6C /* searchcore.h */, + 21C92AB11C67ACC400597EBB /* mergepairs.cc */, + 21C92AB21C67ACC400597EBB /* mergepairs.h */, + 21C92AB31C67ACC400597EBB /* pvalue.h */, + 21C92AB41C67ACC400597EBB /* searchexact.cc */, + 21C92AB51C67ACC400597EBB /* searchexact.h */, 48A52F851BC428DF00548F6C /* sha1.c */, 48A52F861BC428DF00548F6C /* sha1.h */, 48A52F871BC428DF00548F6C /* showalign.cc */, @@ -1969,8 +1983,6 @@ 48A52F961BC428DF00548F6C /* util.h */, 48A52F971BC428DF00548F6C /* vsearch.cc */, 48A52F981BC428DF00548F6C /* vsearch.h */, - 489B55701BCD7F0100FB7DC8 /* vsearchfileparser.cpp */, - 489B55711BCD7F0100FB7DC8 /* vsearchfileparser.h */, 48A52F991BC428DF00548F6C /* xstring.h */, ); name = vsearch; @@ -3316,6 +3328,7 @@ A7E9B8DF12D37EC400DA6239 /* hamming.cpp in Sources */, A7E9B8E012D37EC400DA6239 /* hcluster.cpp in Sources */, A7E9B8E112D37EC400DA6239 /* hclustercommand.cpp in Sources */, + 21C92AB71C67ACC400597EBB /* searchexact.cc in Sources */, A7E9B8E212D37EC400DA6239 /* heatmap.cpp in Sources */, A7E9B8E312D37EC400DA6239 /* heatmapcommand.cpp in Sources */, A7E9B8E412D37EC400DA6239 /* heatmapsim.cpp in Sources */, @@ -3375,6 +3388,7 @@ A7E9B91412D37EC400DA6239 /* parsimonycommand.cpp in Sources */, 48A52FB01BC428DF00548F6C /* dbindex.cc in Sources */, A7E9B91512D37EC400DA6239 /* pcoacommand.cpp in Sources */, + 21C92AB61C67ACC400597EBB /* mergepairs.cc in Sources */, 48A52FAE1BC428DF00548F6C /* db.cc in Sources */, A7E9B91712D37EC400DA6239 /* phylodiversitycommand.cpp in Sources */, A7E9B91812D37EC400DA6239 /* phylosummary.cpp in Sources */, @@ -3646,7 +3660,7 @@ ); PRELINK_LIBS = ""; PRODUCT_NAME = mothur; - SDKROOT = macosx10.9; + SDKROOT = iphoneos; SKIP_INSTALL = NO; }; name = Debug; @@ -3674,7 +3688,7 @@ ONLY_ACTIVE_ARCH = YES; PRELINK_LIBS = ""; PRODUCT_NAME = mothur; - SDKROOT = macosx10.9; + SDKROOT = iphoneos; SKIP_INSTALL = NO; "VALID_ARCHS[sdk=*]" = "i386 x86_64"; }; diff --git a/source/vsearch_src/abundance.cc b/source/vsearch_src/abundance.cc old mode 100644 new mode 100755 index 8c96c951c..69a89358b --- a/source/vsearch_src/abundance.cc +++ b/source/vsearch_src/abundance.cc @@ -1,181 +1,181 @@ -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "vsearch.h" - -abundance_t * abundance_init(void) -{ - abundance_t * a = (abundance_t *) xmalloc(sizeof(abundance_t)); - if (regcomp(&a->regex, "(^|;)size=([0-9]+)(;|$)", REG_EXTENDED)) - fatal("Compilation of regular expression for abundance annotation failed"); - return a; -} - -void abundance_exit(abundance_t * a) -{ - regfree(&a->regex); - free(a); -} - -long abundance_get(abundance_t * a, char * header) -{ - /* read size/abundance annotation */ - - long abundance = 1; - regmatch_t pmatch[4]; - - if (!regexec(&a->regex, header, 4, pmatch, 0)) - { - long number = atol(header + pmatch[2].rm_so); - if (number > 0) - abundance = number; - else - fatal("Invalid (zero) abundance annotation in fasta header"); - } - return abundance; -} - -void abundance_fprint_header_with_size(abundance_t * a, - FILE * fp, - char * header, - int header_length, - unsigned long size) -{ - /* remove any previous size annotation */ - /* regexp search for "(^|;)(\d+)(;|$)" */ - /* replace by ';' if not at either end */ - - regmatch_t pmatch[1]; - - if (!regexec(&a->regex, header, 1, pmatch, 0)) - { - int pat_start = pmatch[0].rm_so; - int pat_end = pmatch[0].rm_eo; - - fprintf(fp, - ">%.*s%s%.*s%ssize=%lu;\n", - pat_start, header, - (pat_start > 0 ? ";" : ""), - header_length - pat_end, header + pat_end, - (((pat_end < header_length) && - (header[header_length - 1] != ';')) ? ";" : ""), - size); - } - else - { - fprintf(fp, - ">%s%ssize=%lu;\n", - header, - (((header_length == 0) || - (header[header_length - 1] != ';')) ? ";" : ""), - size); - } -} - -void abundance_fprint_header_strip_size(abundance_t * a, - FILE * fp, - char * header, - int header_length) -{ - regmatch_t pmatch[1]; - - if (!regexec(&a->regex, header, 1, pmatch, 0)) - { - int pat_start = pmatch[0].rm_so; - int pat_end = pmatch[0].rm_eo; - - fprintf(fp, - ">%.*s%s%.*s\n", - pat_start, header, - ((pat_start > 0) && (pat_end < header_length)) ? ";" : "", - header_length - pat_end, header + pat_end); - } - else - fprintf(fp, ">%s\n", header); -} - -char * abundance_strip_size(abundance_t * a, - char * header, - int header_length) -{ - int ret; - char * temp = 0; - regmatch_t pmatch[1]; - - - if (!regexec(&a->regex, header, 1, pmatch, 0)) - { - int pat_start = pmatch[0].rm_so; - int pat_end = pmatch[0].rm_eo; - - ret = asprintf(&temp, - "%.*s%s%.*s", - pat_start, header, - ((pat_start > 0) && (pat_end < header_length)) ? ";" : "", - header_length - pat_end, header + pat_end); - } - else - ret = asprintf(&temp, "%s", header); - - if (ret == -1) - fatal("Out of memory"); - - return temp; -} +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +abundance_t * abundance_init(void) +{ + abundance_t * a = (abundance_t *) xmalloc(sizeof(abundance_t)); + if (regcomp(&a->regex, "(^|;)size=([0-9]+)(;|$)",REG_EXTENDED)) + fatal("Compilation of regular expression for abundance annotation failed"); + return a; +} + +void abundance_exit(abundance_t * a) +{ + regfree(&a->regex); + free(a); +} + +long abundance_get(abundance_t * a, char * header) +{ + /* read size/abundance annotation */ + + long abundance = 1; + regmatch_t pmatch[4]; + + if (!regexec(&a->regex, header, 4, pmatch, 0)) + { + long number = atol(header + pmatch[2].rm_so); + if (number > 0) + abundance = number; + else + fatal("Invalid (zero) abundance annotation in fasta header"); + } + return abundance; +} + +void abundance_fprint_header_with_size(abundance_t * a, + FILE * fp, + char * header, + int header_length, + unsigned long size) +{ + /* remove any previous size annotation */ + /* regexp search for "(^|;)(\d+)(;|$)" */ + /* replace by ';' if not at either end */ + + regmatch_t pmatch[1]; + + if (!regexec(&a->regex, header, 1, pmatch, 0)) + { + int pat_start = pmatch[0].rm_so; + int pat_end = pmatch[0].rm_eo; + + fprintf(fp, + "%.*s%s%.*s%ssize=%lu;", + pat_start, header, + (pat_start > 0 ? ";" : ""), + header_length - pat_end, header + pat_end, + (((pat_end < header_length) && + (header[header_length - 1] != ';')) ? ";" : ""), + size); + } + else + { + fprintf(fp, + "%s%ssize=%lu;", + header, + (((header_length == 0) || + (header[header_length - 1] != ';')) ? ";" : ""), + size); + } +} + +void abundance_fprint_header_strip_size(abundance_t * a, + FILE * fp, + char * header, + int header_length) +{ + regmatch_t pmatch[1]; + + if (!regexec(&a->regex, header, 1, pmatch, 0)) + { + int pat_start = pmatch[0].rm_so; + int pat_end = pmatch[0].rm_eo; + + fprintf(fp, + "%.*s%s%.*s", + pat_start, header, + ((pat_start > 0) && (pat_end < header_length)) ? ";" : "", + header_length - pat_end, header + pat_end); + } + else + fprintf(fp, "%s", header); +} + +char * abundance_strip_size(abundance_t * a, + char * header, + int header_length) +{ + int ret; + char * temp = 0; + regmatch_t pmatch[1]; + + + if (!regexec(&a->regex, header, 1, pmatch, 0)) + { + int pat_start = pmatch[0].rm_so; + int pat_end = pmatch[0].rm_eo; + + ret = sprintf(temp, + "%.*s%s%.*s", + pat_start, header, + ((pat_start > 0) && (pat_end < header_length)) ? ";" : "", + header_length - pat_end, header + pat_end); + } + else + ret = sprintf(temp, "%s", header); + + if (ret == -1) + fatal("Out of memory"); + + return temp; +} diff --git a/source/vsearch_src/abundance.h b/source/vsearch_src/abundance.h old mode 100644 new mode 100755 index 6d36474f7..ad6c1cbc3 --- a/source/vsearch_src/abundance.h +++ b/source/vsearch_src/abundance.h @@ -1,96 +1,85 @@ - - - -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#if defined(_WIN32) -#include -#include -#endif - -typedef struct abundance_s -{ - regex_t regex; -} abundance_t; - -abundance_t * abundance_init(void); - -void abundance_exit(abundance_t * a); - -long abundance_get(abundance_t * a, char * header); - -void abundance_fprint_header_with_size(abundance_t * a, - FILE * fp, - char * header, - int header_length, - unsigned long size); - -void abundance_fprint_header_strip_size(abundance_t * a, - FILE * fp, - char * header, - int header_length); - -char * abundance_strip_size(abundance_t * a, - char * header, - int header_length); - - - +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +typedef struct abundance_s +{ + regex_t regex; +} abundance_t; + +abundance_t * abundance_init(void); + +void abundance_exit(abundance_t * a); + +long abundance_get(abundance_t * a, char * header); + +void abundance_fprint_header_with_size(abundance_t * a, + FILE * fp, + char * header, + int header_length, + unsigned long size); + +void abundance_fprint_header_strip_size(abundance_t * a, + FILE * fp, + char * header, + int header_length); + +char * abundance_strip_size(abundance_t * a, + char * header, + int header_length); diff --git a/source/vsearch_src/align.cc b/source/vsearch_src/align.cc old mode 100644 new mode 100755 diff --git a/source/vsearch_src/align.h b/source/vsearch_src/align.h old mode 100644 new mode 100755 index ce18f332e..23d7ffa1c --- a/source/vsearch_src/align.h +++ b/source/vsearch_src/align.h @@ -1,5 +1,3 @@ - - /* VSEARCH: a versatile open source tool for metagenomics @@ -92,6 +90,3 @@ void nw_align(char * dseq, long queryno, long dbseqno, struct nwinfo_s * nw); - - - diff --git a/source/vsearch_src/align_simd.cc b/source/vsearch_src/align_simd.cc old mode 100644 new mode 100755 index 346c3b830..778e49061 --- a/source/vsearch_src/align_simd.cc +++ b/source/vsearch_src/align_simd.cc @@ -1016,8 +1016,8 @@ void search16(s16info_s * s, R_target_interior); for(unsigned int j=0; j, - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "vsearch.h" - -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - -static pthread_t * pthread; - -/* global constants/data, no need for synchronization */ -static pthread_attr_t attr; - -/* global data protected by mutex */ -static pthread_mutex_t mutex_input; -static pthread_mutex_t mutex_output; - -#else - -create thread - -#endif - -static int qmatches; -static int queries; -static long progress = 0; -static FILE * fp_alnout = 0; -static FILE * fp_samout = 0; -static FILE * fp_userout = 0; -static FILE * fp_blast6out = 0; -static FILE * fp_uc = 0; -static FILE * fp_fastapairs = 0; -static FILE * fp_matched = 0; -static FILE * fp_notmatched = 0; -static int seqcount; /* number of database sequences */ - -inline int allpairs_hit_compare_typed(struct hit * x, struct hit * y) -{ - // high id, then low id - // early target, then late target - - if (x->id > y->id) - return -1; - else - if (x->id < y->id) - return +1; - else - if (x->target < y->target) - return -1; - else - if (x->target > y->target) - return +1; - else - return 0; -} - -int allpairs_hit_compare(const void * a, const void * b) -{ - return allpairs_hit_compare_typed((struct hit *) a, (struct hit *) b); -} - -void allpairs_output_results(int hit_count, - struct hit * hits, - char * query_head, - int qseqlen, - char * qsequence, - char * qsequence_rc) -{ - /* show results */ - long toreport = MIN(opt_maxhits, hit_count); - - if (fp_alnout) - results_show_alnout(fp_alnout, - hits, - toreport, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_samout) - results_show_samout(fp_samout, - hits, - toreport, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (toreport) - { - double top_hit_id = hits[0].id; - - for(int t = 0; t < toreport; t++) - { - struct hit * hp = hits + t; - - if (opt_top_hits_only && (hp->id < top_hit_id)) - break; - - if (fp_fastapairs) - results_show_fastapairs_one(fp_fastapairs, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_uc) - if ((t==0) || opt_uc_allhits) - results_show_uc_one(fp_uc, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_userout) - results_show_userout_one(fp_userout, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_blast6out) - results_show_blast6out_one(fp_blast6out, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - } - } - else if (opt_output_no_hits) - { - if (fp_uc) - results_show_uc_one(fp_uc, - 0, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_userout) - results_show_userout_one(fp_userout, - 0, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_blast6out) - results_show_blast6out_one(fp_blast6out, - 0, - query_head, - qsequence, - qseqlen, - qsequence_rc); - } - - if (hit_count) - { - if (opt_matched) - { - fprintf(fp_matched, - ">%s\n", - query_head); - fprint_fasta_seq_only(fp_matched, - qsequence, - qseqlen, - opt_fasta_width); - } - } - else - { - if (opt_notmatched) - { - fprintf(fp_notmatched, - ">%s\n", - query_head); - fprint_fasta_seq_only(fp_notmatched, - qsequence, - qseqlen, - opt_fasta_width); - } - } -} - -void allpairs_thread_run(long t) -{ - struct searchinfo_s sia; - - struct searchinfo_s * si = & sia; - - si->strand = 0; - si->query_head_alloc = 0; - si->seq_alloc = 0; - si->kmersamplecount = 0; - si->kmers = 0; - si->m = 0; - si->finalized = 0; - - si->hits = (struct hit *) xmalloc(sizeof(struct hit) * seqcount); - - struct nwinfo_s * nw = nw_init(); - - si->s = search16_init(opt_match, - opt_mismatch, - opt_gap_open_query_left, - opt_gap_open_target_left, - opt_gap_open_query_interior, - opt_gap_open_target_interior, - opt_gap_open_query_right, - opt_gap_open_target_right, - opt_gap_extension_query_left, - opt_gap_extension_target_left, - opt_gap_extension_query_interior, - opt_gap_extension_target_interior, - opt_gap_extension_query_right, - opt_gap_extension_target_right); - - - LinearMemoryAligner lma; - - long * scorematrix = lma.scorematrix_create(opt_match, opt_mismatch); - - lma.set_parameters(scorematrix, - opt_gap_open_query_left, - opt_gap_open_target_left, - opt_gap_open_query_interior, - opt_gap_open_target_interior, - opt_gap_open_query_right, - opt_gap_open_target_right, - opt_gap_extension_query_left, - opt_gap_extension_target_left, - opt_gap_extension_query_interior, - opt_gap_extension_target_interior, - opt_gap_extension_query_right, - opt_gap_extension_target_right); - - /* allocate memory for alignment results */ - unsigned int maxhits = seqcount; - unsigned int * pseqnos = - (unsigned int *) xmalloc(sizeof(unsigned int) * maxhits); - CELL * pscores = - (CELL*) xmalloc(sizeof(CELL) * maxhits); - unsigned short * paligned = - (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); - unsigned short * pmatches = - (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); - unsigned short * pmismatches = - (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); - unsigned short * pgaps = - (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); - char** pcigar = (char**) xmalloc(sizeof(char*) * maxhits); - - struct hit * finalhits - = (struct hit *) xmalloc(sizeof(struct hit) * seqcount); - - bool cont = 1; - - while (cont) - { -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_lock(&mutex_input); -#else - todo -#endif - int query_no = queries; - - if (query_no < seqcount) - { - queries++; -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - /* let other threads read input */ - pthread_mutex_unlock(&mutex_input); -#else - todo -#endif - /* init search info */ - si->query_no = query_no; - si->qsize = db_getabundance(query_no); - si->query_head_len = db_getheaderlen(query_no); - si->query_head = db_getheader(query_no); - si->qseqlen = db_getsequencelen(query_no); - si->qsequence = db_getsequence(query_no); - si->rejects = 0; - si->accepts = 0; - si->hit_count = 0; - - for(int target = si->query_no + 1; - target < seqcount; target++) - { - if (opt_acceptall || search_acceptable_unaligned(si, target)) - pseqnos[si->hit_count++] = target; - } - - if (si->hit_count) - { - /* perform alignments */ - - search16_qprep(si->s, si->qsequence, si->qseqlen); - - search16(si->s, - si->hit_count, - pseqnos, - pscores, - paligned, - pmatches, - pmismatches, - pgaps, - pcigar); - - /* convert to hit structure */ - for (int h = 0; h < si->hit_count; h++) - { - struct hit * hit = si->hits + h; - - unsigned int target = pseqnos[h]; - long nwscore = pscores[h]; - - char * nwcigar; - long nwalignmentlength; - long nwmatches; - long nwmismatches; - long nwgaps; - - if (nwscore == SHRT_MAX) - { - /* In case the SIMD aligner cannot align, - perform a new alignment with the - linear memory aligner */ - - char * tseq = db_getsequence(target); - long tseqlen = db_getsequencelen(target); - - if (pcigar[h]) - free(pcigar[h]); - - nwcigar = xstrdup(lma.align(si->qsequence, - tseq, - si->qseqlen, - tseqlen)); - lma.alignstats(nwcigar, - si->qsequence, - tseq, - & nwscore, - & nwalignmentlength, - & nwmatches, - & nwmismatches, - & nwgaps); - } - else - { - nwcigar = pcigar[h]; - nwalignmentlength = paligned[h]; - nwmatches = pmatches[h]; - nwmismatches = pmismatches[h]; - nwgaps = pgaps[h]; - } - - hit->target = target; - hit->strand = 0; - hit->count = 0; - - hit->accepted = 0; - hit->rejected = 0; - hit->aligned = 1; - hit->weak = 0; - - hit->nwscore = nwscore; - hit->nwdiff = nwalignmentlength - nwmatches; - hit->nwgaps = nwgaps; - hit->nwindels = nwalignmentlength - nwmatches - nwmismatches; - hit->nwalignmentlength = nwalignmentlength; - hit->nwid = 100.0 * (nwalignmentlength - hit->nwdiff) / - nwalignmentlength; - hit->nwalignment = nwcigar; - hit->matches = nwalignmentlength - hit->nwdiff; - hit->mismatches = hit->nwdiff - hit->nwindels; - - long dseqlen = db_getsequencelen(target); - hit->shortest = MIN(si->qseqlen, dseqlen); - hit->longest = MAX(si->qseqlen, dseqlen); - - /* trim alignment, compute numbers excluding terminal gaps */ - align_trim(hit); - - /* test accept/reject criteria after alignment */ - if (opt_acceptall || search_acceptable_aligned(si, hit)) - finalhits[si->accepts++] = *hit; - } - - /* sort hits */ - qsort(finalhits, si->accepts, - sizeof(struct hit), allpairs_hit_compare); - } - -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - /* lock mutex for update of global data and output */ - pthread_mutex_lock(&mutex_output); -#else - todo -#endif - /* output results */ - allpairs_output_results(si->accepts, - finalhits, - si->query_head, - si->qseqlen, - si->qsequence, - 0); - - /* update stats */ - if (si->accepts) - qmatches++; - - /* show progress */ - progress += seqcount - query_no - 1; - progress_update(progress); -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_output); - -#else - todo -#endif - - /* free memory for alignment strings */ - for(int i=0; i < si->hit_count; i++) - if (si->hits[i].aligned) - free(si->hits[i].nwalignment); - } - else - { -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - /* let other threads read input */ - pthread_mutex_unlock(&mutex_input); -#else - todo -#endif - cont = 0; - } - } - - free(finalhits); - - free(pcigar); - free(pgaps); - free(pmismatches); - free(pmatches); - free(paligned); - free(pscores); - free(pseqnos); - - search16_exit(si->s); - - nw_exit(nw); - - free(scorematrix); - - free(si->hits); -} - -void * allpairs_thread_worker(void * vp) -{ - long t = (long) vp; - allpairs_thread_run(t); - return 0; -} - -void allpairs_thread_worker_run() -{ - /* initialize threads, start them, join them and return */ - -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - /* init and create worker threads, put them into stand-by mode */ - for(int t=0; t, + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +/* global constants/data, no need for synchronization */ +static int seqcount; /* number of database sequences */ + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + +/* global data protected by mutex */ +static pthread_mutex_t mutex_input; +static pthread_mutex_t mutex_output; +static pthread_attr_t attr; +static pthread_t * pthread; + +#endif + +static int qmatches; +static int queries; +static long progress = 0; +static FILE * fp_alnout = 0; +static FILE * fp_samout = 0; +static FILE * fp_userout = 0; +static FILE * fp_blast6out = 0; +static FILE * fp_uc = 0; +static FILE * fp_fastapairs = 0; +static FILE * fp_matched = 0; +static FILE * fp_notmatched = 0; + +inline int allpairs_hit_compare_typed(struct hit * x, struct hit * y) +{ + // high id, then low id + // early target, then late target + + if (x->id > y->id) + return -1; + else + if (x->id < y->id) + return +1; + else + if (x->target < y->target) + return -1; + else + if (x->target > y->target) + return +1; + else + return 0; +} + +int allpairs_hit_compare(const void * a, const void * b) +{ + return allpairs_hit_compare_typed((struct hit *) a, (struct hit *) b); +} + +void allpairs_output_results(int hit_count, + struct hit * hits, + char * query_head, + int qseqlen, + char * qsequence, + char * qsequence_rc) +{ + /* show results */ + long toreport = MIN(opt_maxhits, hit_count); + + if (fp_alnout) + results_show_alnout(fp_alnout, + hits, + toreport, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_samout) + results_show_samout(fp_samout, + hits, + toreport, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (toreport) + { + double top_hit_id = hits[0].id; + + for(int t = 0; t < toreport; t++) + { + struct hit * hp = hits + t; + + if (opt_top_hits_only && (hp->id < top_hit_id)) + break; + + if (fp_fastapairs) + results_show_fastapairs_one(fp_fastapairs, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_uc) + if ((t==0) || opt_uc_allhits) + results_show_uc_one(fp_uc, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_userout) + results_show_userout_one(fp_userout, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_blast6out) + results_show_blast6out_one(fp_blast6out, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + } + } + else if (opt_output_no_hits) + { + if (fp_uc) + results_show_uc_one(fp_uc, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_userout) + results_show_userout_one(fp_userout, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_blast6out) + results_show_blast6out_one(fp_blast6out, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + } + + if (hit_count) + { + if (opt_matched) + { + fasta_print(fp_matched, + query_head, + qsequence, + qseqlen); + } + } + else + { + if (opt_notmatched) + { + fasta_print(fp_notmatched, + query_head, + qsequence, + qseqlen); + } + } +} + +void allpairs_thread_run(long t) +{ + struct searchinfo_s sia; + + struct searchinfo_s * si = & sia; + + si->strand = 0; + si->query_head_alloc = 0; + si->seq_alloc = 0; + si->kmersamplecount = 0; + si->kmers = 0; + si->m = 0; + si->finalized = 0; + + si->hits = (struct hit *) xmalloc(sizeof(struct hit) * seqcount); + + struct nwinfo_s * nw = nw_init(); + + si->s = search16_init(opt_match, + opt_mismatch, + opt_gap_open_query_left, + opt_gap_open_target_left, + opt_gap_open_query_interior, + opt_gap_open_target_interior, + opt_gap_open_query_right, + opt_gap_open_target_right, + opt_gap_extension_query_left, + opt_gap_extension_target_left, + opt_gap_extension_query_interior, + opt_gap_extension_target_interior, + opt_gap_extension_query_right, + opt_gap_extension_target_right); + + + LinearMemoryAligner lma; + + long * scorematrix = lma.scorematrix_create(opt_match, opt_mismatch); + + lma.set_parameters(scorematrix, + opt_gap_open_query_left, + opt_gap_open_target_left, + opt_gap_open_query_interior, + opt_gap_open_target_interior, + opt_gap_open_query_right, + opt_gap_open_target_right, + opt_gap_extension_query_left, + opt_gap_extension_target_left, + opt_gap_extension_query_interior, + opt_gap_extension_target_interior, + opt_gap_extension_query_right, + opt_gap_extension_target_right); + + /* allocate memory for alignment results */ + unsigned int maxhits = seqcount; + unsigned int * pseqnos = + (unsigned int *) xmalloc(sizeof(unsigned int) * maxhits); + CELL * pscores = + (CELL*) xmalloc(sizeof(CELL) * maxhits); + unsigned short * paligned = + (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); + unsigned short * pmatches = + (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); + unsigned short * pmismatches = + (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); + unsigned short * pgaps = + (unsigned short*) xmalloc(sizeof(unsigned short) * maxhits); + char** pcigar = (char**) xmalloc(sizeof(char*) * maxhits); + + struct hit * finalhits + = (struct hit *) xmalloc(sizeof(struct hit) * seqcount); + + bool cont = 1; + + while (cont) + { +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_lock(&mutex_input); + //#else assume 1 thread +#endif + int query_no = queries; + + if (query_no < seqcount) + { + queries++; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + /* let other threads read input */ + pthread_mutex_unlock(&mutex_input); + //#else assume 1 thread +#endif + /* init search info */ + si->query_no = query_no; + si->qsize = db_getabundance(query_no); + si->query_head_len = db_getheaderlen(query_no); + si->query_head = db_getheader(query_no); + si->qseqlen = db_getsequencelen(query_no); + si->qsequence = db_getsequence(query_no); + si->rejects = 0; + si->accepts = 0; + si->hit_count = 0; + + for(int target = si->query_no + 1; + target < seqcount; target++) + { + if (opt_acceptall || search_acceptable_unaligned(si, target)) + pseqnos[si->hit_count++] = target; + } + + if (si->hit_count) + { + /* perform alignments */ + + search16_qprep(si->s, si->qsequence, si->qseqlen); + + search16(si->s, + si->hit_count, + pseqnos, + pscores, + paligned, + pmatches, + pmismatches, + pgaps, + pcigar); + + /* convert to hit structure */ + for (int h = 0; h < si->hit_count; h++) + { + struct hit * hit = si->hits + h; + + unsigned int target = pseqnos[h]; + long nwscore = pscores[h]; + + char * nwcigar; + long nwalignmentlength; + long nwmatches; + long nwmismatches; + long nwgaps; + + if (nwscore == SHRT_MAX) + { + /* In case the SIMD aligner cannot align, + perform a new alignment with the + linear memory aligner */ + + char * tseq = db_getsequence(target); + long tseqlen = db_getsequencelen(target); + + if (pcigar[h]) + free(pcigar[h]); + + nwcigar = xstrdup(lma.align(si->qsequence, + tseq, + si->qseqlen, + tseqlen)); + lma.alignstats(nwcigar, + si->qsequence, + tseq, + & nwscore, + & nwalignmentlength, + & nwmatches, + & nwmismatches, + & nwgaps); + } + else + { + nwcigar = pcigar[h]; + nwalignmentlength = paligned[h]; + nwmatches = pmatches[h]; + nwmismatches = pmismatches[h]; + nwgaps = pgaps[h]; + } + + hit->target = target; + hit->strand = 0; + hit->count = 0; + + hit->accepted = 0; + hit->rejected = 0; + hit->aligned = 1; + hit->weak = 0; + + hit->nwscore = nwscore; + hit->nwdiff = nwalignmentlength - nwmatches; + hit->nwgaps = nwgaps; + hit->nwindels = nwalignmentlength - nwmatches - nwmismatches; + hit->nwalignmentlength = nwalignmentlength; + hit->nwid = 100.0 * (nwalignmentlength - hit->nwdiff) / + nwalignmentlength; + hit->nwalignment = nwcigar; + hit->matches = nwalignmentlength - hit->nwdiff; + hit->mismatches = hit->nwdiff - hit->nwindels; + + long dseqlen = db_getsequencelen(target); + hit->shortest = MIN(si->qseqlen, dseqlen); + hit->longest = MAX(si->qseqlen, dseqlen); + + /* trim alignment, compute numbers excluding terminal gaps */ + align_trim(hit); + + /* test accept/reject criteria after alignment */ + if (opt_acceptall || search_acceptable_aligned(si, hit)) + finalhits[si->accepts++] = *hit; + } + + /* sort hits */ + qsort(finalhits, si->accepts, + sizeof(struct hit), allpairs_hit_compare); + } + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + /* lock mutex for update of global data and output */ + pthread_mutex_lock(&mutex_output); + //#else assume 1 thread +#endif + /* output results */ + allpairs_output_results(si->accepts, + finalhits, + si->query_head, + si->qseqlen, + si->qsequence, + 0); + + /* update stats */ + if (si->accepts) + qmatches++; + + /* show progress */ + progress += seqcount - query_no - 1; + progress_update(progress); + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_mutex_unlock(&mutex_output); +#endif + /* free memory for alignment strings */ + for(int i=0; i < si->hit_count; i++) + if (si->hits[i].aligned) + free(si->hits[i].nwalignment); + } + else + { +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + /* let other threads read input */ + pthread_mutex_unlock(&mutex_input); + //#else assume 1 thread +#endif + cont = 0; + } + } + + free(finalhits); + + free(pcigar); + free(pgaps); + free(pmismatches); + free(pmatches); + free(paligned); + free(pscores); + free(pseqnos); + + search16_exit(si->s); + + nw_exit(nw); + + free(scorematrix); + + free(si->hits); +} + +void * allpairs_thread_worker(void * vp) +{ + long t = (intptr_t) vp; + allpairs_thread_run(t); + return 0; +} + +void allpairs_thread_worker_run() +{ + /* initialize threads, start them, join them and return */ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + /* init and create worker threads, put them into stand-by mode */ + for(int t=0; t, - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#if defined(_WIN32) -#include -#include -#endif - -#include "vsearch.h" - - -unsigned long arch_get_memused() -{ - struct rusage r_usage; - getrusage(RUSAGE_SELF, & r_usage); - -#if defined (__APPLE__) || (__MACH__) - /* Mac: ru_maxrss gives the size in bytes */ - return r_usage.ru_maxrss; -#elif (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - /* Linux: ru_maxrss gives the size in kilobytes */ - return r_usage.ru_maxrss * 1024; -#else - PROCESS_MEMORY_COUNTERS info; - GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); - return (size_t)info.PeakWorkingSetSize; -#endif -} - -unsigned long arch_get_memtotal() -{ -#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) - - long phys_pages = sysconf(_SC_PHYS_PAGES); - long pagesize = sysconf(_SC_PAGESIZE); - if ((phys_pages == -1) || (pagesize == -1)) - fatal("Cannot determine amount of RAM"); - return pagesize * phys_pages; - -#elif defined(__APPLE__) - - int mib [] = { CTL_HW, HW_MEMSIZE }; - int64_t ram = 0; - size_t length = sizeof(ram); - if(sysctl(mib, 2, &ram, &length, NULL, 0) == -1) - fatal("Cannot determine amount of RAM"); - return ram; - -#else - - struct sysinfo si; - if (sysinfo(&si)) - fatal("Cannot determine amount of RAM"); - return si.totalram * si.mem_unit; - -#endif -} +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +unsigned long arch_get_memused() +{ +#if defined (__APPLE__) || (__MACH__) + /* Mac: ru_maxrss gives the size in bytes */ + struct rusage r_usage; + getrusage(RUSAGE_SELF, & r_usage); + + return r_usage.ru_maxrss; +#elif (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + /* Linux: ru_maxrss gives the size in kilobytes */ + struct rusage r_usage; + getrusage(RUSAGE_SELF, & r_usage); + return r_usage.ru_maxrss * 1024; +#elif defined (_WIN32) + MEMORYSTATUSEX status; + status.dwLength = sizeof(status); + GlobalMemoryStatusEx(&status); + return (size_t)status.ullAvailPhys; +#else + fatal("Cannot determine amount of RAM used"); + return 0; +#endif +} + +unsigned long arch_get_memtotal() +{ +#if defined(__APPLE__) + + int mib [] = { CTL_HW, HW_MEMSIZE }; + int64_t ram = 0; + size_t length = sizeof(ram); + if(sysctl(mib, 2, &ram, &length, NULL, 0) == -1) + fatal("Cannot determine amount of RAM"); + return ram; + +#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) + + long phys_pages = sysconf(_SC_PHYS_PAGES); + long pagesize = sysconf(_SC_PAGESIZE); + if ((phys_pages == -1) || (pagesize == -1)) + fatal("Cannot determine amount of RAM"); + return pagesize * phys_pages; +#elif defined (_WIN32) + MEMORYSTATUSEX status; + status.dwLength = sizeof(status); + GlobalMemoryStatusEx(&status); + return (size_t)status.ullTotalPhys; +#else + + struct sysinfo si; + if (sysinfo(&si)) + fatal("Cannot determine amount of RAM"); + return si.totalram * si.mem_unit; + + +#endif +} diff --git a/source/vsearch_src/arch.h b/source/vsearch_src/arch.h old mode 100644 new mode 100755 index dee7cc97e..235349e10 --- a/source/vsearch_src/arch.h +++ b/source/vsearch_src/arch.h @@ -1,4 +1,3 @@ - /* VSEARCH: a versatile open source tool for metagenomics @@ -61,4 +60,3 @@ unsigned long arch_get_memused(); unsigned long arch_get_memtotal(); - diff --git a/source/vsearch_src/bitmap.cc b/source/vsearch_src/bitmap.cc old mode 100644 new mode 100755 diff --git a/source/vsearch_src/bitmap.h b/source/vsearch_src/bitmap.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/chimera.cc b/source/vsearch_src/chimera.cc old mode 100644 new mode 100755 index f5e16f710..a3adf6c4a --- a/source/vsearch_src/chimera.cc +++ b/source/vsearch_src/chimera.cc @@ -1,1634 +1,1570 @@ -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "vsearch.h" - -/* - This code implements the method described in this paper: - - Robert C. Edgar, Brian J. Haas, Jose C. Clemente, Christopher Quince - and Rob Knight (2011) - UCHIME improves sensitivity and speed of chimera detection - Bioinformatics, 27, 16, 2194-2200 - http://dx.doi.org/10.1093/bioinformatics/btr381 -*/ - - -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - -static pthread_attr_t attr; -static pthread_t * pthread; - -/* mutexes and global data protected by mutex */ -static pthread_mutex_t mutex_input; -static pthread_mutex_t mutex_output; - -#else - - todo - -#endif - -static unsigned int seqno = 0; -static unsigned long progress = 0; -static int chimera_count = 0; -static int nonchimera_count = 0; -static FILE * fp_chimeras = 0; -static FILE * fp_nonchimeras = 0; -static FILE * fp_uchimealns = 0; -static FILE * fp_uchimeout = 0; -static FILE * fp_borderline = 0; -static fasta_handle query_fasta_h; - -/* global constants/data, no need for synchronization */ -const int parts = 4; -const int few = 1; -const int maxcandidates = few * parts; -const int rejects = 64; -const double chimera_id = 0.55; -static int tophits; - -#define ALT -//#define ALT2 - -/* information for each query sequence to be checked */ -struct chimera_info_s -{ - int query_alloc; /* the longest query sequence allocated memory for */ - int head_alloc; /* the longest header allocated memory for */ - - int query_no; - char * query_head; - int query_head_len; - int query_size; - char * query_seq; - int query_len; - - struct searchinfo_s si[parts]; - - unsigned int cand_list[maxcandidates]; - int cand_count; - - struct s16info_s * s; - CELL snwscore[maxcandidates]; - unsigned short snwalignmentlength[maxcandidates]; - unsigned short snwmatches[maxcandidates]; - unsigned short snwmismatches[maxcandidates]; - unsigned short snwgaps[maxcandidates]; - long nwscore[maxcandidates]; - long nwalignmentlength[maxcandidates]; - long nwmatches[maxcandidates]; - long nwmismatches[maxcandidates]; - long nwgaps[maxcandidates]; - char * nwcigar[maxcandidates]; - - int match_size; - int * match; - int * smooth; - int * maxsmooth; - - int best_parents[2]; - - int best_target; - char * best_cigar; - - int * maxi; - char * paln[2]; - char * qaln; - char * diffs; - char * votes; - char * model; - char * ignore; - - struct hit * all_hits; -}; - -static struct chimera_info_s * cia; - -void realloc_arrays(struct chimera_info_s * ci) -{ - int maxhlen = ci->query_head_len; - if (maxhlen > ci->head_alloc) - { - ci->head_alloc = maxhlen; - ci->query_head = (char*) xrealloc(ci->query_head, maxhlen + 1); - } - - /* realloc arrays based on query length */ - - int maxqlen = ci->query_len; - if (maxqlen > ci->query_alloc) - { - ci->query_alloc = maxqlen; - - ci->query_seq = (char*) xrealloc(ci->query_seq, maxqlen + 1); - - for(int i=0; i < parts; i++) - { - int maxpartlen = (maxqlen + parts - 1) / parts; - ci->si[i].qsequence = (char*) xrealloc(ci->si[i].qsequence, - maxpartlen + 1); - } - - ci->maxi = (int *) xrealloc(ci->maxi, (maxqlen + 1) * sizeof(int)); - ci->maxsmooth = (int*) xrealloc(ci->maxsmooth, maxqlen * sizeof(int)); - ci->match = (int*) xrealloc(ci->match, - maxcandidates * maxqlen * sizeof(int)); - ci->smooth = (int*) xrealloc(ci->smooth, - maxcandidates * maxqlen * sizeof(int)); - - int maxalnlen = maxqlen + 2 * db_getlongestsequence(); - ci->paln[0] = (char*) xrealloc(ci->paln[0], maxalnlen+1); - ci->paln[1] = (char*) xrealloc(ci->paln[1], maxalnlen+1); - ci->qaln = (char*) xrealloc(ci->qaln, maxalnlen+1); - ci->diffs = (char*) xrealloc(ci->diffs, maxalnlen+1); - ci->votes = (char*) xrealloc(ci->votes, maxalnlen+1); - ci->model = (char*) xrealloc(ci->model, maxalnlen+1); - ci->ignore = (char*) xrealloc(ci->ignore, maxalnlen+1); - } -} - - -int find_best_parents(struct chimera_info_s * ci) -{ - ci->best_parents[0] = -1; - ci->best_parents[1] = -1; - - /* find the positions with matches for each potential parent */ - - char * qseq = ci->query_seq; - - memset(ci->match, 0, ci->cand_count * ci->query_len * sizeof(int)); - - for(int i=0; i < ci->cand_count; i++) - { - char * tseq = db_getsequence(ci->cand_list[i]); - - int qpos = 0; - int tpos = 0; - - char * p = ci->nwcigar[i]; - char * e = p + strlen(p); - - while (p < e) - { - int run = 1; - int scanlength = 0; - sscanf(p, "%d%n", &run, &scanlength); - p += scanlength; - char op = *p++; - switch (op) - { - case 'M': - for(int k=0; kmatch[i * ci->query_len + qpos] = 1; - qpos++; - tpos++; - } - break; - - case 'I': - tpos += run; - break; - - case 'D': - qpos += run; - break; - } - } - } - - /* Compute smoothed identity score in a window for each candidate, */ - /* and record max smoothed score for each position among candidates. */ - - memset(ci->maxsmooth, 0, ci->query_len * sizeof(int)); - - const int window = 32; - - for(int i = 0; i < ci->cand_count; i++) - { - int sum = 0; - for(int qpos = 0; qpos < ci->query_len; qpos++) - { - int z = i * ci->query_len + qpos; - sum += ci->match[z]; - if (qpos >= window) - sum -= ci->match[z-window]; - if (qpos >= window-1) - { - ci->smooth[z] = sum; - if (ci->smooth[z] > ci->maxsmooth[qpos]) - ci->maxsmooth[qpos] = ci->smooth[z]; - } - } - } - - /* find first parent */ - - int wins[ci->cand_count]; - - memset(wins, 0, ci->cand_count * sizeof(int)); - - for(int qpos = window-1; qpos < ci->query_len; qpos++) - { - if (ci->maxsmooth[qpos] != 0) - for(int i=0; i < ci->cand_count; i++) - { - int z = i * ci->query_len + qpos; - if (ci->smooth[z] == ci->maxsmooth[qpos]) - wins[i]++; - } - } - - int best1_w = -1; - int best1_i = -1; - int best2_w = -1; - int best2_i = -1; - - for(int i=0; i < ci->cand_count; i++) - { - int w = wins[i]; - if (w > best1_w) - { - best1_w = w; - best1_i = i; - } - } - - if (best1_w >= 0) - { - /* find second parent */ - - /* wipe out matches in positions covered by first parent */ - - for(int qpos = window - 1; qpos < ci->query_len; qpos++) - { - int z = best1_i * ci->query_len + qpos; - if (ci->smooth[z] == ci->maxsmooth[qpos]) - { - for(int i = qpos + 1 - window; i <= qpos; i++) - for(int j = 0; j < ci->cand_count; j++) - ci->match[j * ci->query_len + i] = 0; - } - } - - /* - recompute smoothed identity over window, and record max smoothed - score for each position among remaining candidates - */ - - memset(ci->maxsmooth, 0, ci->query_len * sizeof(int)); - - for(int i = 0; i < ci->cand_count; i++) - { - if (i != best1_i) - { - int sum = 0; - for(int qpos = 0; qpos < ci->query_len; qpos++) - { - int z = i * ci->query_len + qpos; - sum += ci->match[z]; - if (qpos >= window) - sum -= ci->match[z-window]; - if (qpos >= window-1) - { - ci->smooth[z] = sum; - if (ci->smooth[z] > ci->maxsmooth[qpos]) - ci->maxsmooth[qpos] = ci->smooth[z]; - } - } - } - } - - /* find second parent */ - - memset(wins, 0, ci->cand_count * sizeof(int)); - - for(int qpos = window-1; qpos < ci->query_len; qpos++) - { - if (ci->maxsmooth[qpos] != 0) - for(int i=0; i < ci->cand_count; i++) - if (i != best1_i) - { - int z = i * ci->query_len + qpos; - if (ci->smooth[z] == ci->maxsmooth[qpos]) - wins[i]++; - } - } - - for(int i=0; i < ci->cand_count; i++) - { - int w = wins[i]; - if (w > best2_w) - { - best2_w = w; - best2_i = i; - } - } - } - - ci->best_parents[0] = best1_i; - ci->best_parents[1] = best2_i; - - return (best1_w >= 0) && (best2_w >= 0); -} - -int eval_parents(struct chimera_info_s * ci) -{ - int status = 1; - - /* create msa */ - - /* find max insertions in front of each position in the query sequence */ - memset(ci->maxi, 0, (ci->query_len + 1) * sizeof(int)); - - for(int j=0; j<2; j++) - { - char * p = ci->nwcigar[ci->best_parents[j]]; - char * e = p + strlen(p); - int pos = 0; - while (p < e) - { - int run = 1; - int scanlength = 0; - sscanf(p, "%d%n", &run, &scanlength); - p += scanlength; - char op = *p++; - switch (op) - { - case 'M': - case 'D': - pos += run; - break; - - case 'I': - if (run > ci->maxi[pos]) - ci->maxi[pos] = run; - break; - } - } - } - - /* find total alignment length */ - int alnlen = 0; - for(int i=0; i < ci->query_len+1; i++) - alnlen += ci->maxi[i]; - alnlen += ci->query_len; - - /* fill in alignment string for query */ - - char * q = ci->qaln; - int qpos = 0; - for (int i=0; i < ci->query_len; i++) - { - for (int j=0; j < ci->maxi[i]; j++) - *q++ = '-'; - *q++ = ci->query_seq[qpos++]; - } - for (int j=0; j < ci->maxi[ci->query_len]; j++) - *q++ = '-'; - *q = 0; - - /* fill in alignment strings for the 2 parents */ - - for(int j=0; j<2; j++) - { - int cand = ci->best_parents[j]; - int target_seqno = ci->cand_list[cand]; - char * target_seq = db_getsequence(target_seqno); - - int inserted = 0; - qpos = 0; - int tpos = 0; - - char * t = ci->paln[j]; - - char * p = ci->nwcigar[cand]; - char * e = p + strlen(p); - while (p < e) - { - int run = 1; - int scanlength = 0; - sscanf(p, "%d%n", &run, &scanlength); - p += scanlength; - char op = *p++; - - if (op == 'I') - { - for(int x=0; x < ci->maxi[qpos]; x++) - { - if (x < run) - *t++ = target_seq[tpos++]; - else - *t++ = '-'; - } - inserted = 1; - } - else - { - for(int x=0; x < run; x++) - { - if (!inserted) - for(int y=0; y < ci->maxi[qpos]; y++) - *t++ = '-'; - - if (op == 'M') - *t++ = target_seq[tpos++]; - else - *t++ = '-'; - - qpos++; - inserted = 0; - } - } - } - - /* add any gaps at the end */ - - if (!inserted) - for(int x=0; x < ci->maxi[qpos]; x++) - *t++ = '-'; - - /* end of sequence string */ - *t = 0; - } - - memset(ci->ignore, 0, alnlen); - - for(int i = 0; i < alnlen; i++) - { - char qsym = chrmap_4bit[(int)(ci->qaln [i])]; - char p1sym = chrmap_4bit[(int)(ci->paln[0][i])]; - char p2sym = chrmap_4bit[(int)(ci->paln[1][i])]; - - /* mark positions to ignore in voting */ - - /* ignore gap positions and those next to the gap */ - if ((!qsym) || (!p1sym) || (!p2sym)) - { - ci->ignore[i] = 1; - if (i>0) - ci->ignore[i-1] = 1; - if (iignore[i+1] = 1; - } - - /* ignore ambigous symbols */ - if ((qsym>4) || (p1sym>4) || (p2sym>4)) - ci->ignore[i] = 1; - - /* lower case parent symbols that differ from query */ - - if (p1sym && (p1sym != qsym)) - ci->paln[0][i] = tolower(ci->paln[0][i]); - - if (p2sym && (p2sym != qsym)) - ci->paln[1][i] = tolower(ci->paln[1][i]); - - /* compute diffs */ - - char diff; - - if (qsym && p1sym && p2sym) - { - if (p1sym == p2sym) - { - if (qsym == p1sym) - diff = ' '; - else - diff = 'N'; - } - else - { - if (qsym == p1sym) - diff = 'A'; - else if (qsym == p2sym) - diff = 'B'; - else - diff = '?'; - } - } - else - diff = ' '; - - ci->diffs[i] = diff; - } - - ci->diffs[alnlen] = 0; - - /* compute score */ - - int sumA = 0; - int sumB = 0; - int sumN = 0; - - for (int i = 0; i < alnlen; i++) - if (!ci->ignore[i]) - { - char diff = ci->diffs[i]; - - if (diff == 'A') - sumA++; - else if (diff == 'B') - sumB++; - else if (diff != ' ') - sumN++; - } - - int left_n = 0; - int left_a = 0; - int left_y = 0; - int right_n = sumA; - int right_a = sumN; - int right_y = sumB; - - double best_h = -1; - int best_i = -1; - int best_reverse = 0; - - int best_left_y = 0; - int best_right_y = 0; - int best_left_n = 0; - int best_right_n = 0; - int best_left_a = 0; - int best_right_a = 0; - - for (int i=0; iignore[i]) - { - char diff = ci->diffs[i]; - if (diff != ' ') - { - if (diff == 'A') - { - left_y++; - right_n--; - } - else if (diff == 'B') - { - left_n++; - right_y--; - } - else - { - left_a++; - right_a--; - } - - double left_h, right_h, h; - - if ((left_y > left_n) && (right_y > right_n)) - { - left_h = left_y / (opt_xn * (left_n + opt_dn) + left_a); - right_h = right_y / (opt_xn * (right_n + opt_dn) + right_a); - h = left_h * right_h; - - if (h > best_h) - { - best_reverse = 0; - best_h = h; - best_i = i; - best_left_n = left_n; - best_left_y = left_y; - best_left_a = left_a; - best_right_n = right_n; - best_right_y = right_y; - best_right_a = right_a; - } - } - else if ((left_n > left_y) && (right_n > right_y)) - { - /* swap left/right and yes/no */ - - left_h = left_n / (opt_xn * (left_y + opt_dn) + left_a); - right_h = right_n / (opt_xn * (right_y + opt_dn) + right_a); - h = left_h * right_h; - - if (h > best_h) - { - best_reverse = 1; - best_h = h; - best_i = i; - best_left_n = left_y; - best_left_y = left_n; - best_left_a = left_a; - best_right_n = right_y; - best_right_y = right_n; - best_right_a = right_a; - } - } - } - } - } - - if (best_h >= 0.0) - { - status = 2; - - /* flip A and B if necessary */ - - if (best_reverse) - for(int i = 0; i < alnlen; i++) - { - char diff = ci->diffs[i]; - if (diff == 'A') - ci->diffs[i] = 'B'; - else if (diff == 'B') - ci->diffs[i] = 'A'; - } - - /* fill in votes and model */ - - for(int i = 0; i < alnlen; i++) - { - char m = i <= best_i ? 'A' : 'B'; - ci->model[i] = m; - - char v = ' '; - if (!ci->ignore[i]) - { - char d = ci->diffs[i]; - - if ((d == 'A') || (d == 'B')) - { - if (d == m) - v = '+'; - else - v = '!'; - } - else if ((d == 'N') || (d == '?')) - { - v = '0'; - } - } - ci->votes[i] = v; - - /* lower case diffs for no votes */ - if (v == '!') - ci->diffs[i] = tolower(ci->diffs[i]); - } - - /* fill in crossover region */ - - for(int i = best_i + 1; i < alnlen; i++) - if ((ci->diffs[i] == ' ') || (ci->diffs[i] == 'A')) - ci->model[i] = 'x'; - else - break; - - ci->votes[alnlen] = 0; - ci->model[alnlen] = 0; - - /* count matches */ - - int index_a = best_reverse ? 1 : 0; - int index_b = best_reverse ? 0 : 1; - - int match_QA = 0; - int match_QB = 0; - int match_AB = 0; - int match_QM = 0; - int cols = 0; - - for(int i = 0; i < alnlen; i++) - { - if (! ci->ignore[i]) - { - cols++; - - char qsym = chrmap_4bit[(int)(ci->qaln[i])]; - char asym = chrmap_4bit[(int)(ci->paln[index_a][i])]; - char bsym = chrmap_4bit[(int)(ci->paln[index_b][i])]; - char msym = i <= best_i ? asym : bsym; - - if (qsym == asym) - match_QA++; - - if (qsym == bsym) - match_QB++; - - if (asym == bsym) - match_AB++; - - if (qsym == msym) - match_QM++; - } - } - - int seqno_a = ci->cand_list[ci->best_parents[index_a]]; - int seqno_b = ci->cand_list[ci->best_parents[index_b]]; - - double QA = 100.0 * match_QA / cols; - double QB = 100.0 * match_QB / cols; - double AB = 100.0 * match_AB / cols; - double QT = MAX(QA, QB); - double QM = 100.0 * match_QM / cols; - double divdiff = QM - QT; - double divfrac = 100.0 * divdiff / QT; - - int sumL = best_left_n + best_left_a + best_left_y; - int sumR = best_right_n + best_right_a + best_right_y; - - if (best_h >= opt_minh) - { - status = 3; - if ((divdiff >= opt_mindiv) && - (sumL >= opt_mindiffs) && - (sumR >= opt_mindiffs)) - status = 4; - } - - /* print alignment */ - -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - pthread_mutex_lock(&mutex_output); -#else - - todo - -#endif - - if (opt_uchimealns && (status == 4)) - { - fprintf(fp_uchimealns, "\n"); - fprintf(fp_uchimealns, "----------------------------------------" - "--------------------------------\n"); - fprintf(fp_uchimealns, "Query (%5d nt) %s\n", - ci->query_len, ci->query_head); - fprintf(fp_uchimealns, "ParentA (%5lu nt) %s\n", - db_getsequencelen(seqno_a), - db_getheader(seqno_a)); - fprintf(fp_uchimealns, "ParentB (%5lu nt) %s\n", - db_getsequencelen(seqno_b), - db_getheader(seqno_b)); - fprintf(fp_uchimealns, "\n"); - - int width = opt_alignwidth > 0 ? opt_alignwidth : alnlen; - qpos = 0; - int p1pos = 0; - int p2pos = 0; - int rest = alnlen; - - for(int i = 0; i < alnlen; i += width) - { - /* count non-gap symbols on current line */ - - int qnt, p1nt, p2nt; - qnt = p1nt = p2nt = 0; - - int w = MIN(rest,width); - - for(int j=0; jqaln[i+j] != '-') - qnt++; - if (ci->paln[0][i+j] != '-') - p1nt++; - if (ci->paln[1][i+j] != '-') - p2nt++; - } - - if (! best_reverse) - { - fprintf(fp_uchimealns, "A %5d %.*s %d\n", - p1pos+1, w, ci->paln[0]+i, p1pos+p1nt); - fprintf(fp_uchimealns, "Q %5d %.*s %d\n", - qpos+1, w, ci->qaln+i, qpos+qnt); - fprintf(fp_uchimealns, "B %5d %.*s %d\n", - p2pos+1, w, ci->paln[1]+i, p2pos+p2nt); - } - else - { - fprintf(fp_uchimealns, "A %5d %.*s %d\n", - p2pos+1, w, ci->paln[1]+i, p2pos+p2nt); - fprintf(fp_uchimealns, "Q %5d %.*s %d\n", - qpos+1, w, ci->qaln+i, qpos+qnt); - fprintf(fp_uchimealns, "B %5d %.*s %d\n", - p1pos+1, w, ci->paln[0]+i, p1pos+p1nt); - } - - fprintf(fp_uchimealns, "Diffs %.*s\n", w, ci->diffs+i); - fprintf(fp_uchimealns, "Votes %.*s\n", w, ci->votes+i); - fprintf(fp_uchimealns, "Model %.*s\n", w, ci->model+i); - fprintf(fp_uchimealns, "\n"); - - qpos += qnt; - p1pos += p1nt; - p2pos += p2nt; - rest -= width; - } - - fprintf(fp_uchimealns, "Ids. QA %.1f%%, QB %.1f%%, AB %.1f%%, " - "QModel %.1f%%, Div. %+.1f%%\n", - QA, QB, AB, QM, divfrac); - - fprintf(fp_uchimealns, "Diffs Left %d: N %d, A %d, Y %d (%.1f%%); " - "Right %d: N %d, A %d, Y %d (%.1f%%), Score %.4f\n", - sumL, best_left_n, best_left_a, best_left_y, - 100.0 * best_left_y / sumL, - sumR, best_right_n, best_right_a, best_right_y, - 100.0 * best_right_y / sumR, - best_h); - } - - if (opt_uchimeout) - { - if (opt_uchimeout5) - { - fprintf(fp_uchimeout, - "%.4f\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t" - "%d\t%d\t%d\t%d\t%d\t%d\t%.1f\t%c\n", - best_h, - ci->query_head, - db_getheader(seqno_a), - db_getheader(seqno_b), - QM, - QA, - QB, - AB, - QT, - best_left_y, - best_left_n, - best_left_a, - best_right_y, - best_right_n, - best_right_a, - divdiff, - status == 4 ? 'Y' : (status == 2 ? 'N' : '?')); - } - else - { - fprintf(fp_uchimeout, - "%.4f\t%s\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t" - "%d\t%d\t%d\t%d\t%d\t%d\t%.1f\t%c\n", - best_h, - ci->query_head, - db_getheader(seqno_a), - db_getheader(seqno_b), - db_getheader(QA >= QB ? seqno_a : seqno_b), - QM, - QA, - QB, - AB, - QT, - best_left_y, - best_left_n, - best_left_a, - best_right_y, - best_right_n, - best_right_a, - divdiff, - status == 4 ? 'Y' : (status == 2 ? 'N' : '?')); - } - } -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_output); -#else - - todo - -#endif - } - - return status; -} - -/* - new chimeric status: - 0: no parents, non-chimeric - 1: score < 0 (no alignment), non-chimeric - 2: score < minh, non-chimeric - 3: score >= minh, suspicious - 4: score >= minh && (divdiff >= opt_mindiv) && ..., chimeric -*/ - -void query_init(struct searchinfo_s * si) -{ - si->qsequence = 0; - si->kmers = 0; - si->hits = (struct hit *) xmalloc(sizeof(struct hit) * tophits); - si->kmers = (count_t *) xmalloc(db_getsequencecount() * - sizeof(count_t) + 32); - si->hit_count = 0; - si->uh = unique_init(); - si->s = search16_init(opt_match, - opt_mismatch, - opt_gap_open_query_left, - opt_gap_open_target_left, - opt_gap_open_query_interior, - opt_gap_open_target_interior, - opt_gap_open_query_right, - opt_gap_open_target_right, - opt_gap_extension_query_left, - opt_gap_extension_target_left, - opt_gap_extension_query_interior, - opt_gap_extension_target_interior, - opt_gap_extension_query_right, - opt_gap_extension_target_right); - si->nw = nw_init(); - si->m = minheap_init(tophits); -} - -void query_exit(struct searchinfo_s * si) -{ - search16_exit(si->s); - unique_exit(si->uh); - minheap_exit(si->m); - nw_exit(si->nw); - - if (si->qsequence) - free(si->qsequence); - if (si->hits) - free(si->hits); - if (si->kmers) - free(si->kmers); -} - -void partition_query(struct chimera_info_s * ci) -{ - int rest = ci->query_len; - char * p = ci->query_seq; - for (int i=0; isi + i; - - si->query_no = ci->query_no; - si->strand = 0; - si->qsize = ci->query_size; - si->query_head_len = ci->query_head_len; - si->query_head = ci->query_head; - si->qseqlen = len; - strncpy(si->qsequence, p, len); - si->qsequence[len] = 0; - - rest -= len; - p += len; - } -} - -void chimera_thread_init(struct chimera_info_s * ci) -{ - ci->query_alloc = 0; - ci->head_alloc = 0; - ci->query_head = 0; - ci->query_seq = 0; - ci->maxi = 0; - ci->maxsmooth = 0; - ci->match = 0; - ci->smooth = 0; - ci->paln[0] = 0; - ci->paln[1] = 0; - ci->qaln = 0; - ci->diffs = 0; - ci->votes = 0; - ci->model = 0; - ci->ignore = 0; - - for(int i = 0; i < parts; i++) - query_init(ci->si + i); - - ci->s = search16_init(opt_match, - opt_mismatch, - opt_gap_open_query_left, - opt_gap_open_target_left, - opt_gap_open_query_interior, - opt_gap_open_target_interior, - opt_gap_open_query_right, - opt_gap_open_target_right, - opt_gap_extension_query_left, - opt_gap_extension_target_left, - opt_gap_extension_query_interior, - opt_gap_extension_target_interior, - opt_gap_extension_query_right, - opt_gap_extension_target_right); -} - -void chimera_thread_exit(struct chimera_info_s * ci) -{ - search16_exit(ci->s); - - for(int i = 0; i < parts; i++) - query_exit(ci->si + i); - - if (ci->maxsmooth) - free(ci->maxsmooth); - if (ci->match) - free(ci->match); - if (ci->smooth) - free(ci->smooth); - if (ci->diffs) - free(ci->diffs); - if (ci->votes) - free(ci->votes); - if (ci->model) - free(ci->model); - if (ci->ignore) - free(ci->ignore); - if (ci->maxi) - free(ci->maxi); - if (ci->qaln) - free(ci->qaln); - if (ci->paln[0]) - free(ci->paln[0]); - if (ci->paln[1]) - free(ci->paln[1]); - - if (ci->query_seq) - free(ci->query_seq); - if (ci->query_head) - free(ci->query_head); -} - -unsigned long chimera_thread_core(struct chimera_info_s * ci) -{ - chimera_thread_init(ci); - - struct hit * allhits_list = (struct hit *) xmalloc(maxcandidates * - sizeof(struct hit)); - - LinearMemoryAligner lma; - - long * scorematrix = lma.scorematrix_create(opt_match, opt_mismatch); - - lma.set_parameters(scorematrix, - opt_gap_open_query_left, - opt_gap_open_target_left, - opt_gap_open_query_interior, - opt_gap_open_target_interior, - opt_gap_open_query_right, - opt_gap_open_target_right, - opt_gap_extension_query_left, - opt_gap_extension_target_left, - opt_gap_extension_query_interior, - opt_gap_extension_target_interior, - opt_gap_extension_query_right, - opt_gap_extension_target_right); - - while(1) - { - /* get next sequence */ -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_lock(&mutex_input); -#else - todo -#endif - - if (opt_uchime_ref) - { - if (fasta_next(query_fasta_h, ! opt_notrunclabels, - chrmap_upcase)) - { - ci->query_head_len = fasta_get_header_length(query_fasta_h); - ci->query_len = fasta_get_sequence_length(query_fasta_h); - ci->query_no = fasta_get_seqno(query_fasta_h); - ci->query_size = fasta_get_abundance(query_fasta_h); - - /* if necessary expand memory for arrays based on query length */ - realloc_arrays(ci); - - /* copy the data locally (query seq, head) */ - strcpy(ci->query_head, fasta_get_header(query_fasta_h)); - strcpy(ci->query_seq, fasta_get_sequence(query_fasta_h)); - } - else - { -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_input); -#else - todo -#endif - - - break; /* end while loop */ - } - } - else - { - if (seqno < db_getsequencecount()) - { - ci->query_no = seqno; - ci->query_head_len = db_getheaderlen(seqno); - ci->query_len = db_getsequencelen(seqno); - ci->query_size = db_getabundance(seqno); - - /* if necessary expand memory for arrays based on query length */ - realloc_arrays(ci); - - strcpy(ci->query_head, db_getheader(seqno)); - strcpy(ci->query_seq, db_getsequence(seqno)); - } - else - { -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_input); -#else - todo -#endif - break; /* end while loop */ - } - } -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_input); - -#else - todo -#endif - - int status = 0; - - /* partition query */ - partition_query(ci); - - /* perform searches and collect candidate parents */ - ci->cand_count = 0; - int allhits_count = 0; - - for (int i=0; isi+i); - search_joinhits(ci->si+i, 0, & hits, & hit_count); - for(int j=0; jcand_count; k++) - if (ci->cand_list[k] == target) - break; - - if (k == ci->cand_count) - ci->cand_list[ci->cand_count++] = target; - - /* deallocate cigar */ - if (allhits_list[i].nwalignment) - free(allhits_list[i].nwalignment); - } - - - /* align full query to each candidate */ - - search16_qprep(ci->s, ci->query_seq, ci->query_len); - - search16(ci->s, - ci->cand_count, - ci->cand_list, - ci->snwscore, - ci->snwalignmentlength, - ci->snwmatches, - ci->snwmismatches, - ci->snwgaps, - ci->nwcigar); - - for(int i=0; i < ci->cand_count; i++) - { - long target = ci->cand_list[i]; - long nwscore = ci->snwscore[i]; - char * nwcigar; - long nwalignmentlength; - long nwmatches; - long nwmismatches; - long nwgaps; - - if (nwscore == SHRT_MAX) - { - /* In case the SIMD aligner cannot align, - perform a new alignment with the - linear memory aligner */ - - char * tseq = db_getsequence(target); - long tseqlen = db_getsequencelen(target); - - if (ci->nwcigar[i]) - free(ci->nwcigar[i]); - - nwcigar = xstrdup(lma.align(ci->query_seq, - tseq, - ci->query_len, - tseqlen)); - lma.alignstats(nwcigar, - ci->query_seq, - tseq, - & nwscore, - & nwalignmentlength, - & nwmatches, - & nwmismatches, - & nwgaps); - - ci->nwcigar[i] = nwcigar; - ci->nwscore[i] = nwscore; - ci->nwalignmentlength[i] = nwalignmentlength; - ci->nwmatches[i] = nwmatches; - ci->nwmismatches[i] = nwmismatches; - ci->nwgaps[i] = nwgaps; - } - else - { - ci->nwscore[i] = ci->snwscore[i]; - ci->nwalignmentlength[i] = ci->snwalignmentlength[i]; - ci->nwmatches[i] = ci->snwmatches[i]; - ci->nwmismatches[i] = ci->snwmismatches[i]; - ci->nwgaps[i] = ci->snwgaps[i]; - } - } - - - /* find the best pair of parents, then compute score for them */ - - if (find_best_parents(ci)) - status = eval_parents(ci); - else - status = 0; - - /* output results */ -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_lock(&mutex_output); -#else - todo -#endif - if (status == 4) - { - chimera_count++; - - if (opt_chimeras) - { - fprint_fasta_hdr_only(fp_chimeras, ci->query_head); - fprint_fasta_seq_only(fp_chimeras, ci->query_seq, - ci->query_len, opt_fasta_width); - } - - -#ifdef ALT2 - if (opt_uchime_denovo) - dbindex_addsequence(seqno); -#endif - } - - if (status == 3) - { - if (opt_borderline) - { - fprint_fasta_hdr_only(fp_borderline, ci->query_head); - fprint_fasta_seq_only(fp_borderline, ci->query_seq, - ci->query_len, opt_fasta_width); - } - } - - if (status < 3) - { - nonchimera_count++; - - /* output no parents, no chimeras */ - if ((status < 2) && opt_uchimeout) - { - if (opt_uchimeout5) - fprintf(fp_uchimeout, - "0.0000\t%s\t*\t*\t*\t*\t*\t*\t*" - "\t0\t0\t0\t0\t0\t0\t*\tN\n", - ci->query_head); - else - fprintf(fp_uchimeout, - "0.0000\t%s\t*\t*\t*\t*\t*\t*\t*\t*" - "\t0\t0\t0\t0\t0\t0\t*\tN\n", - ci->query_head); - } - -#ifndef ALT - /* uchime_denovo: add non-chimeras to db */ - if (opt_uchime_denovo) - dbindex_addsequence(seqno); -#endif - - if (opt_nonchimeras) - { - int size = ci->query_size; - - if (opt_relabel_sha1 || opt_relabel_md5) - { - char * seq = ci->query_seq; - int len = ci->query_len; - - fprintf(fp_nonchimeras, ">"); - - if (opt_relabel_sha1) - fprint_seq_digest_sha1(fp_nonchimeras, seq, len); - else - fprint_seq_digest_md5(fp_nonchimeras, seq, len); - - if (opt_sizeout) - fprintf(fp_nonchimeras, ";size=%d;\n", size); - else - fprintf(fp_nonchimeras, "\n"); - - } - else if (opt_relabel) - { - if (opt_sizeout) - fprintf(fp_nonchimeras, ">%s%d;size=%d;\n", - opt_relabel, nonchimera_count, size); - else - fprintf(fp_nonchimeras, ">%s%d\n", - opt_relabel, nonchimera_count); - } - else - fprintf(fp_nonchimeras, ">%s\n", ci->query_head); - - fprint_fasta_seq_only(fp_nonchimeras, ci->query_seq, - ci->query_len, opt_fasta_width); - } - } - - for (int i=0; i < ci->cand_count; i++) - if (ci->nwcigar[i]) - free(ci->nwcigar[i]); - - if (opt_uchime_ref) - progress = fasta_get_position(query_fasta_h); - else - progress += db_getsequencelen(seqno); - - progress_update(progress); - - seqno++; -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_output); -#else - todo -#endif - } - - if (allhits_list) - free(allhits_list); - - chimera_thread_exit(ci); - - free(scorematrix); - - return 0; -} - -void * chimera_thread_worker(void * vp) -{ - return (void *) chimera_thread_core(cia + (long) vp); -} - -void chimera_threads_run() -{ -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - /* create worker threads */ - for(long t=0; t, + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +/* + This code implements the method described in this paper: + + Robert C. Edgar, Brian J. Haas, Jose C. Clemente, Christopher Quince + and Rob Knight (2011) + UCHIME improves sensitivity and speed of chimera detection + Bioinformatics, 27, 16, 2194-2200 + http://dx.doi.org/10.1093/bioinformatics/btr381 +*/ + +/* global constants/data, no need for synchronization */ +const int parts = 4; +const int few = 4; +const int maxcandidates = few * parts; +const int rejects = 16; +const double chimera_id = 0.55; +static int tophits; +static fasta_handle query_fasta_h; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + +/* mutexes and global data protected by mutex */ +static pthread_attr_t attr; +static pthread_t * pthread; +static pthread_mutex_t mutex_input; +static pthread_mutex_t mutex_output; + +#endif + +static unsigned int seqno = 0; +static unsigned long progress = 0; +static int chimera_count = 0; +static int nonchimera_count = 0; +static FILE * fp_chimeras = 0; +static FILE * fp_nonchimeras = 0; +static FILE * fp_uchimealns = 0; +static FILE * fp_uchimeout = 0; +static FILE * fp_borderline = 0; + +/* information for each query sequence to be checked */ +struct chimera_info_s +{ + int query_alloc; /* the longest query sequence allocated memory for */ + int head_alloc; /* the longest header allocated memory for */ + + int query_no; + char * query_head; + int query_head_len; + int query_size; + char * query_seq; + int query_len; + + struct searchinfo_s si[parts]; + + unsigned int cand_list[maxcandidates]; + int cand_count; + + struct s16info_s * s; + CELL snwscore[maxcandidates]; + unsigned short snwalignmentlength[maxcandidates]; + unsigned short snwmatches[maxcandidates]; + unsigned short snwmismatches[maxcandidates]; + unsigned short snwgaps[maxcandidates]; + long nwscore[maxcandidates]; + long nwalignmentlength[maxcandidates]; + long nwmatches[maxcandidates]; + long nwmismatches[maxcandidates]; + long nwgaps[maxcandidates]; + char * nwcigar[maxcandidates]; + + int match_size; + int * match; + int * smooth; + int * maxsmooth; + + int best_parents[2]; + + int best_target; + char * best_cigar; + + int * maxi; + char * paln[2]; + char * qaln; + char * diffs; + char * votes; + char * model; + char * ignore; + + struct hit * all_hits; +}; + +static struct chimera_info_s * cia; + +void realloc_arrays(struct chimera_info_s * ci) +{ + int maxhlen = ci->query_head_len; + if (maxhlen > ci->head_alloc) + { + ci->head_alloc = maxhlen; + ci->query_head = (char*) xrealloc(ci->query_head, maxhlen + 1); + } + + /* realloc arrays based on query length */ + + int maxqlen = ci->query_len; + if (maxqlen > ci->query_alloc) + { + ci->query_alloc = maxqlen; + + ci->query_seq = (char*) xrealloc(ci->query_seq, maxqlen + 1); + + for(int i=0; i < parts; i++) + { + int maxpartlen = (maxqlen + parts - 1) / parts; + ci->si[i].qsequence = (char*) xrealloc(ci->si[i].qsequence, + maxpartlen + 1); + } + + ci->maxi = (int *) xrealloc(ci->maxi, (maxqlen + 1) * sizeof(int)); + ci->maxsmooth = (int*) xrealloc(ci->maxsmooth, maxqlen * sizeof(int)); + ci->match = (int*) xrealloc(ci->match, + maxcandidates * maxqlen * sizeof(int)); + ci->smooth = (int*) xrealloc(ci->smooth, + maxcandidates * maxqlen * sizeof(int)); + + int maxalnlen = maxqlen + 2 * db_getlongestsequence(); + ci->paln[0] = (char*) xrealloc(ci->paln[0], maxalnlen+1); + ci->paln[1] = (char*) xrealloc(ci->paln[1], maxalnlen+1); + ci->qaln = (char*) xrealloc(ci->qaln, maxalnlen+1); + ci->diffs = (char*) xrealloc(ci->diffs, maxalnlen+1); + ci->votes = (char*) xrealloc(ci->votes, maxalnlen+1); + ci->model = (char*) xrealloc(ci->model, maxalnlen+1); + ci->ignore = (char*) xrealloc(ci->ignore, maxalnlen+1); + } +} + + +int find_best_parents(struct chimera_info_s * ci) +{ + ci->best_parents[0] = -1; + ci->best_parents[1] = -1; + + /* find the positions with matches for each potential parent */ + + char * qseq = ci->query_seq; + + memset(ci->match, 0, ci->cand_count * ci->query_len * sizeof(int)); + + for(int i=0; i < ci->cand_count; i++) + { + char * tseq = db_getsequence(ci->cand_list[i]); + + int qpos = 0; + int tpos = 0; + + char * p = ci->nwcigar[i]; + char * e = p + strlen(p); + + while (p < e) + { + int run = 1; + int scanlength = 0; + sscanf(p, "%d%n", &run, &scanlength); + p += scanlength; + char op = *p++; + switch (op) + { + case 'M': + for(int k=0; kmatch[i * ci->query_len + qpos] = 1; + qpos++; + tpos++; + } + break; + + case 'I': + tpos += run; + break; + + case 'D': + qpos += run; + break; + } + } + } + + /* Compute smoothed identity score in a window for each candidate, */ + /* and record max smoothed score for each position among candidates. */ + + memset(ci->maxsmooth, 0, ci->query_len * sizeof(int)); + + const int window = 32; + + for(int i = 0; i < ci->cand_count; i++) + { + int sum = 0; + for(int qpos = 0; qpos < ci->query_len; qpos++) + { + int z = i * ci->query_len + qpos; + sum += ci->match[z]; + if (qpos >= window) + sum -= ci->match[z-window]; + if (qpos >= window-1) + { + ci->smooth[z] = sum; + if (ci->smooth[z] > ci->maxsmooth[qpos]) + ci->maxsmooth[qpos] = ci->smooth[z]; + } + } + } + + /* find first parent */ + + int wins[ci->cand_count]; + + memset(wins, 0, ci->cand_count * sizeof(int)); + + for(int qpos = window-1; qpos < ci->query_len; qpos++) + { + if (ci->maxsmooth[qpos] != 0) + for(int i=0; i < ci->cand_count; i++) + { + int z = i * ci->query_len + qpos; + if (ci->smooth[z] == ci->maxsmooth[qpos]) + wins[i]++; + } + } + + int best1_w = -1; + int best1_i = -1; + int best2_w = -1; + int best2_i = -1; + + for(int i=0; i < ci->cand_count; i++) + { + int w = wins[i]; + if (w > best1_w) + { + best1_w = w; + best1_i = i; + } + } + + if (best1_w >= 0) + { + /* find second parent */ + + /* wipe out matches in positions covered by first parent */ + + for(int qpos = window - 1; qpos < ci->query_len; qpos++) + { + int z = best1_i * ci->query_len + qpos; + if (ci->smooth[z] == ci->maxsmooth[qpos]) + { + for(int i = qpos + 1 - window; i <= qpos; i++) + for(int j = 0; j < ci->cand_count; j++) + ci->match[j * ci->query_len + i] = 0; + } + } + + /* + recompute smoothed identity over window, and record max smoothed + score for each position among remaining candidates + */ + + memset(ci->maxsmooth, 0, ci->query_len * sizeof(int)); + + for(int i = 0; i < ci->cand_count; i++) + { + if (i != best1_i) + { + int sum = 0; + for(int qpos = 0; qpos < ci->query_len; qpos++) + { + int z = i * ci->query_len + qpos; + sum += ci->match[z]; + if (qpos >= window) + sum -= ci->match[z-window]; + if (qpos >= window-1) + { + ci->smooth[z] = sum; + if (ci->smooth[z] > ci->maxsmooth[qpos]) + ci->maxsmooth[qpos] = ci->smooth[z]; + } + } + } + } + + /* find second parent */ + + memset(wins, 0, ci->cand_count * sizeof(int)); + + for(int qpos = window-1; qpos < ci->query_len; qpos++) + { + if (ci->maxsmooth[qpos] != 0) + for(int i=0; i < ci->cand_count; i++) + if (i != best1_i) + { + int z = i * ci->query_len + qpos; + if (ci->smooth[z] == ci->maxsmooth[qpos]) + wins[i]++; + } + } + + for(int i=0; i < ci->cand_count; i++) + { + int w = wins[i]; + if (w > best2_w) + { + best2_w = w; + best2_i = i; + } + } + } + + ci->best_parents[0] = best1_i; + ci->best_parents[1] = best2_i; + + return (best1_w >= 0) && (best2_w >= 0); +} + +int eval_parents(struct chimera_info_s * ci) +{ + int status = 1; + + /* create msa */ + + /* find max insertions in front of each position in the query sequence */ + memset(ci->maxi, 0, (ci->query_len + 1) * sizeof(int)); + + for(int j=0; j<2; j++) + { + char * p = ci->nwcigar[ci->best_parents[j]]; + char * e = p + strlen(p); + int pos = 0; + while (p < e) + { + int run = 1; + int scanlength = 0; + sscanf(p, "%d%n", &run, &scanlength); + p += scanlength; + char op = *p++; + switch (op) + { + case 'M': + case 'D': + pos += run; + break; + + case 'I': + if (run > ci->maxi[pos]) + ci->maxi[pos] = run; + break; + } + } + } + + /* find total alignment length */ + int alnlen = 0; + for(int i=0; i < ci->query_len+1; i++) + alnlen += ci->maxi[i]; + alnlen += ci->query_len; + + /* fill in alignment string for query */ + + char * q = ci->qaln; + int qpos = 0; + for (int i=0; i < ci->query_len; i++) + { + for (int j=0; j < ci->maxi[i]; j++) + *q++ = '-'; + *q++ = chrmap_upcase[(int)(ci->query_seq[qpos++])]; + } + for (int j=0; j < ci->maxi[ci->query_len]; j++) + *q++ = '-'; + *q = 0; + + /* fill in alignment strings for the 2 parents */ + + for(int j=0; j<2; j++) + { + int cand = ci->best_parents[j]; + int target_seqno = ci->cand_list[cand]; + char * target_seq = db_getsequence(target_seqno); + + int inserted = 0; + qpos = 0; + int tpos = 0; + + char * t = ci->paln[j]; + + char * p = ci->nwcigar[cand]; + char * e = p + strlen(p); + while (p < e) + { + int run = 1; + int scanlength = 0; + sscanf(p, "%d%n", &run, &scanlength); + p += scanlength; + char op = *p++; + + if (op == 'I') + { + for(int x=0; x < ci->maxi[qpos]; x++) + { + if (x < run) + *t++ = chrmap_upcase[(int)(target_seq[tpos++])]; + else + *t++ = '-'; + } + inserted = 1; + } + else + { + for(int x=0; x < run; x++) + { + if (!inserted) + for(int y=0; y < ci->maxi[qpos]; y++) + *t++ = '-'; + + if (op == 'M') + *t++ = chrmap_upcase[(int)(target_seq[tpos++])]; + else + *t++ = '-'; + + qpos++; + inserted = 0; + } + } + } + + /* add any gaps at the end */ + + if (!inserted) + for(int x=0; x < ci->maxi[qpos]; x++) + *t++ = '-'; + + /* end of sequence string */ + *t = 0; + } + + memset(ci->ignore, 0, alnlen); + + for(int i = 0; i < alnlen; i++) + { + char qsym = chrmap_4bit[(int)(ci->qaln [i])]; + char p1sym = chrmap_4bit[(int)(ci->paln[0][i])]; + char p2sym = chrmap_4bit[(int)(ci->paln[1][i])]; + + /* mark positions to ignore in voting */ + + /* ignore gap positions and those next to the gap */ + if ((!qsym) || (!p1sym) || (!p2sym)) + { + ci->ignore[i] = 1; + if (i>0) + ci->ignore[i-1] = 1; + if (iignore[i+1] = 1; + } + + /* ignore ambigous symbols */ + if ((qsym>4) || (p1sym>4) || (p2sym>4)) + ci->ignore[i] = 1; + + /* lower case parent symbols that differ from query */ + + if (p1sym && (p1sym != qsym)) + ci->paln[0][i] = tolower(ci->paln[0][i]); + + if (p2sym && (p2sym != qsym)) + ci->paln[1][i] = tolower(ci->paln[1][i]); + + /* compute diffs */ + + char diff; + + if (qsym && p1sym && p2sym) + { + if (p1sym == p2sym) + { + if (qsym == p1sym) + diff = ' '; + else + diff = 'N'; + } + else + { + if (qsym == p1sym) + diff = 'A'; + else if (qsym == p2sym) + diff = 'B'; + else + diff = '?'; + } + } + else + diff = ' '; + + ci->diffs[i] = diff; + } + + ci->diffs[alnlen] = 0; + + /* compute score */ + + int sumA = 0; + int sumB = 0; + int sumN = 0; + + for (int i = 0; i < alnlen; i++) + if (!ci->ignore[i]) + { + char diff = ci->diffs[i]; + + if (diff == 'A') + sumA++; + else if (diff == 'B') + sumB++; + else if (diff != ' ') + sumN++; + } + + int left_n = 0; + int left_a = 0; + int left_y = 0; + int right_n = sumA; + int right_a = sumN; + int right_y = sumB; + + double best_h = -1; + int best_i = -1; + int best_reverse = 0; + + int best_left_y = 0; + int best_right_y = 0; + int best_left_n = 0; + int best_right_n = 0; + int best_left_a = 0; + int best_right_a = 0; + + for (int i=0; iignore[i]) + { + char diff = ci->diffs[i]; + if (diff != ' ') + { + if (diff == 'A') + { + left_y++; + right_n--; + } + else if (diff == 'B') + { + left_n++; + right_y--; + } + else + { + left_a++; + right_a--; + } + + double left_h, right_h, h; + + if ((left_y > left_n) && (right_y > right_n)) + { + left_h = left_y / (opt_xn * (left_n + opt_dn) + left_a); + right_h = right_y / (opt_xn * (right_n + opt_dn) + right_a); + h = left_h * right_h; + + if (h > best_h) + { + best_reverse = 0; + best_h = h; + best_i = i; + best_left_n = left_n; + best_left_y = left_y; + best_left_a = left_a; + best_right_n = right_n; + best_right_y = right_y; + best_right_a = right_a; + } + } + else if ((left_n > left_y) && (right_n > right_y)) + { + /* swap left/right and yes/no */ + + left_h = left_n / (opt_xn * (left_y + opt_dn) + left_a); + right_h = right_n / (opt_xn * (right_y + opt_dn) + right_a); + h = left_h * right_h; + + if (h > best_h) + { + best_reverse = 1; + best_h = h; + best_i = i; + best_left_n = left_y; + best_left_y = left_n; + best_left_a = left_a; + best_right_n = right_y; + best_right_y = right_n; + best_right_a = right_a; + } + } + } + } + } + + if (best_h >= 0.0) + { + status = 2; + + /* flip A and B if necessary */ + + if (best_reverse) + for(int i = 0; i < alnlen; i++) + { + char diff = ci->diffs[i]; + if (diff == 'A') + ci->diffs[i] = 'B'; + else if (diff == 'B') + ci->diffs[i] = 'A'; + } + + /* fill in votes and model */ + + for(int i = 0; i < alnlen; i++) + { + char m = i <= best_i ? 'A' : 'B'; + ci->model[i] = m; + + char v = ' '; + if (!ci->ignore[i]) + { + char d = ci->diffs[i]; + + if ((d == 'A') || (d == 'B')) + { + if (d == m) + v = '+'; + else + v = '!'; + } + else if ((d == 'N') || (d == '?')) + { + v = '0'; + } + } + ci->votes[i] = v; + + /* lower case diffs for no votes */ + if (v == '!') + ci->diffs[i] = tolower(ci->diffs[i]); + } + + /* fill in crossover region */ + + for(int i = best_i + 1; i < alnlen; i++) + if ((ci->diffs[i] == ' ') || (ci->diffs[i] == 'A')) + ci->model[i] = 'x'; + else + break; + + ci->votes[alnlen] = 0; + ci->model[alnlen] = 0; + + /* count matches */ + + int index_a = best_reverse ? 1 : 0; + int index_b = best_reverse ? 0 : 1; + + int match_QA = 0; + int match_QB = 0; + int match_AB = 0; + int match_QM = 0; + int cols = 0; + + for(int i = 0; i < alnlen; i++) + { + if (! ci->ignore[i]) + { + cols++; + + char qsym = chrmap_4bit[(int)(ci->qaln[i])]; + char asym = chrmap_4bit[(int)(ci->paln[index_a][i])]; + char bsym = chrmap_4bit[(int)(ci->paln[index_b][i])]; + char msym = i <= best_i ? asym : bsym; + + if (qsym == asym) + match_QA++; + + if (qsym == bsym) + match_QB++; + + if (asym == bsym) + match_AB++; + + if (qsym == msym) + match_QM++; + } + } + + int seqno_a = ci->cand_list[ci->best_parents[index_a]]; + int seqno_b = ci->cand_list[ci->best_parents[index_b]]; + + double QA = 100.0 * match_QA / cols; + double QB = 100.0 * match_QB / cols; + double AB = 100.0 * match_AB / cols; + double QT = MAX(QA, QB); + double QM = 100.0 * match_QM / cols; + double divdiff = QM - QT; + double divfrac = 100.0 * divdiff / QT; + + int sumL = best_left_n + best_left_a + best_left_y; + int sumR = best_right_n + best_right_a + best_right_y; + + if (best_h >= opt_minh) + { + status = 3; + if ((divdiff >= opt_mindiv) && + (sumL >= opt_mindiffs) && + (sumR >= opt_mindiffs)) + status = 4; + } + + /* print alignment */ + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_lock(&mutex_output); +#endif + if (opt_uchimealns && (status == 4)) + { + fprintf(fp_uchimealns, "\n"); + fprintf(fp_uchimealns, "----------------------------------------" + "--------------------------------\n"); + fprintf(fp_uchimealns, "Query (%5d nt) %s\n", + ci->query_len, ci->query_head); + fprintf(fp_uchimealns, "ParentA (%5lu nt) %s\n", + db_getsequencelen(seqno_a), + db_getheader(seqno_a)); + fprintf(fp_uchimealns, "ParentB (%5lu nt) %s\n", + db_getsequencelen(seqno_b), + db_getheader(seqno_b)); + fprintf(fp_uchimealns, "\n"); + + int width = opt_alignwidth > 0 ? opt_alignwidth : alnlen; + qpos = 0; + int p1pos = 0; + int p2pos = 0; + int rest = alnlen; + + for(int i = 0; i < alnlen; i += width) + { + /* count non-gap symbols on current line */ + + int qnt, p1nt, p2nt; + qnt = p1nt = p2nt = 0; + + int w = MIN(rest,width); + + for(int j=0; jqaln[i+j] != '-') + qnt++; + if (ci->paln[0][i+j] != '-') + p1nt++; + if (ci->paln[1][i+j] != '-') + p2nt++; + } + + if (! best_reverse) + { + fprintf(fp_uchimealns, "A %5d %.*s %d\n", + p1pos+1, w, ci->paln[0]+i, p1pos+p1nt); + fprintf(fp_uchimealns, "Q %5d %.*s %d\n", + qpos+1, w, ci->qaln+i, qpos+qnt); + fprintf(fp_uchimealns, "B %5d %.*s %d\n", + p2pos+1, w, ci->paln[1]+i, p2pos+p2nt); + } + else + { + fprintf(fp_uchimealns, "A %5d %.*s %d\n", + p2pos+1, w, ci->paln[1]+i, p2pos+p2nt); + fprintf(fp_uchimealns, "Q %5d %.*s %d\n", + qpos+1, w, ci->qaln+i, qpos+qnt); + fprintf(fp_uchimealns, "B %5d %.*s %d\n", + p1pos+1, w, ci->paln[0]+i, p1pos+p1nt); + } + + fprintf(fp_uchimealns, "Diffs %.*s\n", w, ci->diffs+i); + fprintf(fp_uchimealns, "Votes %.*s\n", w, ci->votes+i); + fprintf(fp_uchimealns, "Model %.*s\n", w, ci->model+i); + fprintf(fp_uchimealns, "\n"); + + qpos += qnt; + p1pos += p1nt; + p2pos += p2nt; + rest -= width; + } + + fprintf(fp_uchimealns, "Ids. QA %.1f%%, QB %.1f%%, AB %.1f%%, " + "QModel %.1f%%, Div. %+.1f%%\n", + QA, QB, AB, QM, divfrac); + + fprintf(fp_uchimealns, "Diffs Left %d: N %d, A %d, Y %d (%.1f%%); " + "Right %d: N %d, A %d, Y %d (%.1f%%), Score %.4f\n", + sumL, best_left_n, best_left_a, best_left_y, + 100.0 * best_left_y / sumL, + sumR, best_right_n, best_right_a, best_right_y, + 100.0 * best_right_y / sumR, + best_h); + } + + if (opt_uchimeout) + { + if (opt_uchimeout5) + { + fprintf(fp_uchimeout, + "%.4f\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t" + "%d\t%d\t%d\t%d\t%d\t%d\t%.1f\t%c\n", + best_h, + ci->query_head, + db_getheader(seqno_a), + db_getheader(seqno_b), + QM, + QA, + QB, + AB, + QT, + best_left_y, + best_left_n, + best_left_a, + best_right_y, + best_right_n, + best_right_a, + divdiff, + status == 4 ? 'Y' : (status == 2 ? 'N' : '?')); + } + else + { + fprintf(fp_uchimeout, + "%.4f\t%s\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t" + "%d\t%d\t%d\t%d\t%d\t%d\t%.1f\t%c\n", + best_h, + ci->query_head, + db_getheader(seqno_a), + db_getheader(seqno_b), + db_getheader(QA >= QB ? seqno_a : seqno_b), + QM, + QA, + QB, + AB, + QT, + best_left_y, + best_left_n, + best_left_a, + best_right_y, + best_right_n, + best_right_a, + divdiff, + status == 4 ? 'Y' : (status == 2 ? 'N' : '?')); + } + } +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_output); +#endif + } + + return status; +} + +/* + new chimeric status: + 0: no parents, non-chimeric + 1: score < 0 (no alignment), non-chimeric + 2: score < minh, non-chimeric + 3: score >= minh, suspicious + 4: score >= minh && (divdiff >= opt_mindiv) && ..., chimeric +*/ + +void query_init(struct searchinfo_s * si) +{ + si->qsequence = 0; + si->kmers = 0; + si->hits = (struct hit *) xmalloc(sizeof(struct hit) * tophits); + si->kmers = (count_t *) xmalloc(db_getsequencecount() * + sizeof(count_t) + 32); + si->hit_count = 0; + si->uh = unique_init(); + si->s = search16_init(opt_match, + opt_mismatch, + opt_gap_open_query_left, + opt_gap_open_target_left, + opt_gap_open_query_interior, + opt_gap_open_target_interior, + opt_gap_open_query_right, + opt_gap_open_target_right, + opt_gap_extension_query_left, + opt_gap_extension_target_left, + opt_gap_extension_query_interior, + opt_gap_extension_target_interior, + opt_gap_extension_query_right, + opt_gap_extension_target_right); + si->nw = nw_init(); + si->m = minheap_init(tophits); +} + +void query_exit(struct searchinfo_s * si) +{ + search16_exit(si->s); + unique_exit(si->uh); + minheap_exit(si->m); + nw_exit(si->nw); + + if (si->qsequence) + free(si->qsequence); + if (si->hits) + free(si->hits); + if (si->kmers) + free(si->kmers); +} + +void partition_query(struct chimera_info_s * ci) +{ + int rest = ci->query_len; + char * p = ci->query_seq; + for (int i=0; isi + i; + + si->query_no = ci->query_no; + si->strand = 0; + si->qsize = ci->query_size; + si->query_head_len = ci->query_head_len; + si->query_head = ci->query_head; + si->qseqlen = len; + strncpy(si->qsequence, p, len); + si->qsequence[len] = 0; + + rest -= len; + p += len; + } +} + +void chimera_thread_init(struct chimera_info_s * ci) +{ + ci->query_alloc = 0; + ci->head_alloc = 0; + ci->query_head = 0; + ci->query_seq = 0; + ci->maxi = 0; + ci->maxsmooth = 0; + ci->match = 0; + ci->smooth = 0; + ci->paln[0] = 0; + ci->paln[1] = 0; + ci->qaln = 0; + ci->diffs = 0; + ci->votes = 0; + ci->model = 0; + ci->ignore = 0; + + for(int i = 0; i < parts; i++) + query_init(ci->si + i); + + ci->s = search16_init(opt_match, + opt_mismatch, + opt_gap_open_query_left, + opt_gap_open_target_left, + opt_gap_open_query_interior, + opt_gap_open_target_interior, + opt_gap_open_query_right, + opt_gap_open_target_right, + opt_gap_extension_query_left, + opt_gap_extension_target_left, + opt_gap_extension_query_interior, + opt_gap_extension_target_interior, + opt_gap_extension_query_right, + opt_gap_extension_target_right); +} + +void chimera_thread_exit(struct chimera_info_s * ci) +{ + search16_exit(ci->s); + + for(int i = 0; i < parts; i++) + query_exit(ci->si + i); + + if (ci->maxsmooth) + free(ci->maxsmooth); + if (ci->match) + free(ci->match); + if (ci->smooth) + free(ci->smooth); + if (ci->diffs) + free(ci->diffs); + if (ci->votes) + free(ci->votes); + if (ci->model) + free(ci->model); + if (ci->ignore) + free(ci->ignore); + if (ci->maxi) + free(ci->maxi); + if (ci->qaln) + free(ci->qaln); + if (ci->paln[0]) + free(ci->paln[0]); + if (ci->paln[1]) + free(ci->paln[1]); + + if (ci->query_seq) + free(ci->query_seq); + if (ci->query_head) + free(ci->query_head); +} + +unsigned long chimera_thread_core(struct chimera_info_s * ci) +{ + chimera_thread_init(ci); + + struct hit * allhits_list = (struct hit *) xmalloc(maxcandidates * + sizeof(struct hit)); + + LinearMemoryAligner lma; + + long * scorematrix = lma.scorematrix_create(opt_match, opt_mismatch); + + lma.set_parameters(scorematrix, + opt_gap_open_query_left, + opt_gap_open_target_left, + opt_gap_open_query_interior, + opt_gap_open_target_interior, + opt_gap_open_query_right, + opt_gap_open_target_right, + opt_gap_extension_query_left, + opt_gap_extension_target_left, + opt_gap_extension_query_interior, + opt_gap_extension_target_interior, + opt_gap_extension_query_right, + opt_gap_extension_target_right); + + while(1) + { + /* get next sequence */ + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_lock(&mutex_input); +#endif + + if (opt_uchime_ref) + { + if (fasta_next(query_fasta_h, ! opt_notrunclabels, + chrmap_no_change)) + { + ci->query_head_len = fasta_get_header_length(query_fasta_h); + ci->query_len = fasta_get_sequence_length(query_fasta_h); + ci->query_no = fasta_get_seqno(query_fasta_h); + ci->query_size = fasta_get_abundance(query_fasta_h); + + /* if necessary expand memory for arrays based on query length */ + realloc_arrays(ci); + + /* copy the data locally (query seq, head) */ + strcpy(ci->query_head, fasta_get_header(query_fasta_h)); + strcpy(ci->query_seq, fasta_get_sequence(query_fasta_h)); + } + else + { +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_input); +#endif + break; /* end while loop */ + } + } + else + { + if (seqno < db_getsequencecount()) + { + ci->query_no = seqno; + ci->query_head_len = db_getheaderlen(seqno); + ci->query_len = db_getsequencelen(seqno); + ci->query_size = db_getabundance(seqno); + + /* if necessary expand memory for arrays based on query length */ + realloc_arrays(ci); + + strcpy(ci->query_head, db_getheader(seqno)); + strcpy(ci->query_seq, db_getsequence(seqno)); + } + else + { +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_input); +#endif + break; /* end while loop */ + } + } + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_input); +#endif + + + + int status = 0; + + /* partition query */ + partition_query(ci); + + /* perform searches and collect candidate parents */ + ci->cand_count = 0; + int allhits_count = 0; + + if (ci->query_len >= parts) + for (int i=0; isi+i, opt_qmask); + search_joinhits(ci->si+i, 0, & hits, & hit_count); + for(int j=0; jcand_count; k++) + if (ci->cand_list[k] == target) + break; + + if (k == ci->cand_count) + ci->cand_list[ci->cand_count++] = target; + + /* deallocate cigar */ + if (allhits_list[i].nwalignment) + free(allhits_list[i].nwalignment); + } + + + /* align full query to each candidate */ + + search16_qprep(ci->s, ci->query_seq, ci->query_len); + + search16(ci->s, + ci->cand_count, + ci->cand_list, + ci->snwscore, + ci->snwalignmentlength, + ci->snwmatches, + ci->snwmismatches, + ci->snwgaps, + ci->nwcigar); + + for(int i=0; i < ci->cand_count; i++) + { + long target = ci->cand_list[i]; + long nwscore = ci->snwscore[i]; + char * nwcigar; + long nwalignmentlength; + long nwmatches; + long nwmismatches; + long nwgaps; + + if (nwscore == SHRT_MAX) + { + /* In case the SIMD aligner cannot align, + perform a new alignment with the + linear memory aligner */ + + char * tseq = db_getsequence(target); + long tseqlen = db_getsequencelen(target); + + if (ci->nwcigar[i]) + free(ci->nwcigar[i]); + + nwcigar = xstrdup(lma.align(ci->query_seq, + tseq, + ci->query_len, + tseqlen)); + lma.alignstats(nwcigar, + ci->query_seq, + tseq, + & nwscore, + & nwalignmentlength, + & nwmatches, + & nwmismatches, + & nwgaps); + + ci->nwcigar[i] = nwcigar; + ci->nwscore[i] = nwscore; + ci->nwalignmentlength[i] = nwalignmentlength; + ci->nwmatches[i] = nwmatches; + ci->nwmismatches[i] = nwmismatches; + ci->nwgaps[i] = nwgaps; + } + else + { + ci->nwscore[i] = ci->snwscore[i]; + ci->nwalignmentlength[i] = ci->snwalignmentlength[i]; + ci->nwmatches[i] = ci->snwmatches[i]; + ci->nwmismatches[i] = ci->snwmismatches[i]; + ci->nwgaps[i] = ci->snwgaps[i]; + } + } + + + /* find the best pair of parents, then compute score for them */ + + if (find_best_parents(ci)) + status = eval_parents(ci); + else + status = 0; + + /* output results */ + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_lock(&mutex_output); +#endif + if (status == 4) + { + chimera_count++; + + if (opt_chimeras) + { + fasta_print(fp_chimeras, + ci->query_head, + ci->query_seq, + ci->query_len); + } + } + + if (status == 3) + { + if (opt_borderline) + { + fasta_print(fp_borderline, + ci->query_head, + ci->query_seq, + ci->query_len); + } + } + + if (status < 3) + { + nonchimera_count++; + + /* output no parents, no chimeras */ + if ((status < 2) && opt_uchimeout) + { + if (opt_uchimeout5) + fprintf(fp_uchimeout, + "0.0000\t%s\t*\t*\t*\t*\t*\t*\t*" + "\t0\t0\t0\t0\t0\t0\t*\tN\n", + ci->query_head); + else + fprintf(fp_uchimeout, + "0.0000\t%s\t*\t*\t*\t*\t*\t*\t*\t*" + "\t0\t0\t0\t0\t0\t0\t*\tN\n", + ci->query_head); + } + + /* uchime_denovo: add non-chimeras to db */ + if (opt_uchime_denovo) + dbindex_addsequence(seqno, opt_qmask); + + if (opt_nonchimeras) + { + fasta_print_relabel(fp_nonchimeras, + ci->query_seq, + ci->query_len, + ci->query_head, + ci->query_head_len, + ci->query_size, + nonchimera_count); + } + } + + for (int i=0; i < ci->cand_count; i++) + if (ci->nwcigar[i]) + free(ci->nwcigar[i]); + + if (opt_uchime_ref) + progress = fasta_get_position(query_fasta_h); + else + progress += db_getsequencelen(seqno); + + progress_update(progress); + + seqno++; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_output); +#endif + } + + if (allhits_list) + free(allhits_list); + + chimera_thread_exit(ci); + + free(scorematrix); + + return 0; +} + +void * chimera_thread_worker(void * vp) +{ + return (void *) (chimera_thread_core(cia + (intptr_t) vp)); +} + +void chimera_threads_run() +{ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + /* create worker threads */ + for(long t=0; tqsequence, db_getsequence(seqno)); /* perform search */ - search_onequery(si); + search_onequery(si, opt_qmask); } inline void cluster_worker(long t) @@ -180,6 +176,7 @@ inline void cluster_worker(long t) void * threads_worker(void * vp) { + #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) long t = (long) vp; @@ -199,39 +196,42 @@ void * threads_worker(void * vp) } } pthread_mutex_unlock(&tip->mutex); -#else - todo -#endif - + #endif return 0; } void threads_wakeup(int queries) { + int threads = queries > opt_threads ? opt_threads : queries; + int queries_rest = queries; + int threads_rest = threads; + int query_next = 0; + + /* tell the threads that there is work to do */ + for(int t=0; t < threads; t++) + { + thread_info_t * tip = ti + t; + + tip->query_first = query_next; + tip->query_count = (queries_rest + threads_rest - 1) / threads_rest; + queries_rest -= tip->query_count; + query_next += tip->query_count; + threads_rest--; + #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - int threads = queries > opt_threads ? opt_threads : queries; - int queries_rest = queries; - int threads_rest = threads; - int query_next = 0; - - /* tell the threads that there is work to do */ - for(int t=0; t < threads; t++) - { - thread_info_t * tip = ti + t; + pthread_mutex_lock(&tip->mutex); + tip->work = 1; + pthread_cond_signal(&tip->cond); + pthread_mutex_unlock(&tip->mutex); +#else + ti->work = 1; +#endif + } - tip->query_first = query_next; - tip->query_count = (queries_rest + threads_rest - 1) / threads_rest; - queries_rest -= tip->query_count; - query_next += tip->query_count; - threads_rest--; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - pthread_mutex_lock(&tip->mutex); - tip->work = 1; - pthread_cond_signal(&tip->cond); - pthread_mutex_unlock(&tip->mutex); - } - + /* wait for theads to finish their work */ for(int t=0; t < threads; t++) { @@ -241,20 +241,20 @@ void threads_wakeup(int queries) pthread_cond_wait(&tip->cond, &tip->mutex); pthread_mutex_unlock(&tip->mutex); } -#else - todo #endif } void threads_init() { + /* allocate memory for thread info */ + ti = (thread_info_t *) xmalloc(opt_threads * sizeof(thread_info_t)); + + #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - /* allocate memory for thread info */ - ti = (thread_info_t *) xmalloc(opt_threads * sizeof(thread_info_t)); /* init and create worker threads */ for(int t=0; t < opt_threads; t++) @@ -267,8 +267,11 @@ void threads_init() fatal("Cannot create thread"); } #else - todo + long t = 0; //one thread + ti->work = 0; + cluster_worker(t); #endif + } void threads_exit() @@ -293,11 +296,10 @@ void threads_exit() pthread_cond_destroy(&tip->cond); pthread_mutex_destroy(&tip->mutex); } - free(ti); - pthread_attr_destroy(&attr); -#else - todo + pthread_attr_destroy(&attr); #endif + free(ti); + } void cluster_query_init(struct searchinfo_s * si) @@ -399,11 +401,7 @@ void cluster_core_results_hit(struct hit * best, qsequence, qseqlen, qsequence_rc); if (opt_matched) - { - fprintf(fp_matched, ">%s\n", query_head); - fprint_fasta_seq_only(fp_matched, qsequence, qseqlen, - opt_fasta_width); - } + fasta_print(fp_matched, query_head, qsequence, qseqlen); } void cluster_core_results_nohit(int clusterno, @@ -430,11 +428,7 @@ void cluster_core_results_nohit(int clusterno, } if (opt_notmatched) - { - fprintf(fp_notmatched, ">%s\n", query_head); - fprint_fasta_seq_only(fp_notmatched, qsequence, qseqlen, - opt_fasta_width); - } + fasta_print(fp_notmatched, query_head, qsequence, qseqlen); } int compare_kmersample(const void * a, const void * b) @@ -572,8 +566,7 @@ void cluster_core_parallel() sic->kmersample); /* check if min number of shared kmers is satisfied */ - if ((shared >= MINMATCHSAMPLECOUNT) && - (shared >= si->kmersamplecount / MINMATCHSAMPLEFREQ)) + if (search_enough_kmers(si, shared)) { unsigned int length = sic->qseqlen; @@ -824,7 +817,7 @@ void cluster_core_parallel() clusterinfo[myseqno].strand = 0; /* add current sequence to database */ - dbindex_addsequence(myseqno); + dbindex_addsequence(myseqno, opt_qmask); /* output intermediate results to uc etc */ cluster_core_results_nohit(clusters, @@ -938,7 +931,7 @@ void cluster_core_serial() clusterinfo[seqno].clusterno = clusters; clusterinfo[seqno].cigar = 0; clusterinfo[seqno].strand = 0; - dbindex_addsequence(seqno); + dbindex_addsequence(seqno, opt_qmask); cluster_core_results_nohit(clusters, si_p->query_head, si_p->qseqlen, @@ -1037,7 +1030,7 @@ void cluster(char * dbname, fatal("Unable to open notmatched output file for writing"); } - db_read(dbname, opt_qmask != MASK_SOFT); + db_read(dbname, 0); results_show_samheader(fp_samout, cmdline, dbname); @@ -1055,7 +1048,7 @@ void cluster(char * dbname, else if (opt_cluster_size) db_sortbyabundance(); - dbindex_prepare(1); + dbindex_prepare(1, opt_qmask); /* tophits = the maximum number of hits we need to store */ @@ -1163,43 +1156,13 @@ void cluster(char * dbname, if (opt_centroids) { - unsigned int size = cluster_abundance[clusterno]; - - if (opt_relabel_sha1 || opt_relabel_md5) - { - char * seq = db_getsequence(seqno); - unsigned int len = db_getsequencelen(seqno); - - fprintf(fp_centroids, ">"); - - if (opt_relabel_sha1) - fprint_seq_digest_sha1(fp_centroids, seq, len); - else - fprint_seq_digest_md5(fp_centroids, seq, len); - - if (opt_sizeout) - fprintf(fp_centroids, ";size=%u;\n", size); - else - fprintf(fp_centroids, "\n"); - - db_fprint_fasta_seq_only(fp_centroids, seqno); - } - else if (opt_relabel) - { - if (opt_sizeout) - fprintf(fp_centroids, ">%s%d;size=%u;\n", opt_relabel, i+1, size); - else - fprintf(fp_centroids, ">%s%d\n", opt_relabel, i+1); - - db_fprint_fasta_seq_only(fp_centroids, seqno); - } - else - { - if (opt_sizeout) - db_fprint_fasta_with_size(fp_centroids, seqno, size); - else - db_fprint_fasta(fp_centroids, seqno); - } + fasta_print_relabel(fp_centroids, + db_getsequence(seqno), + db_getsequencelen(seqno), + db_getheader(seqno), + db_getheaderlen(seqno), + cluster_abundance[clusterno], + clusterno+1); } if (opt_uc) @@ -1228,14 +1191,8 @@ void cluster(char * dbname, /* performed for all sequences */ if (opt_clusters) - { - fprintf(fp_clusters, ">%s\n", db_getheader(seqno)); - fprint_fasta_seq_only(fp_clusters, - db_getsequence(seqno), - db_getsequencelen(seqno), - opt_fasta_width); - } - + fasta_print_db(fp_clusters, seqno); + progress_update(i); } @@ -1317,8 +1274,6 @@ void cluster(char * dbname, lastcluster = -1; - abundance_t * abundance_handle = abundance_init(); - for(int i=0; i dataalloc) + size_t needed = datalen + headerlength + 1 + sequencelength + 1; + if (is_fastq) + needed += sequencelength + 1; + while (dataalloc < needed) dataalloc += MEMCHUNK; if (dataalloc > dataalloc_old) datap = (char *) xrealloc(datap, dataalloc); /* store the header */ size_t header_p = datalen; - memcpy(datap + header_p, fasta_get_header(h), headerlength + 1); + memcpy(datap + header_p, + fastx_get_header(h), + headerlength + 1); datalen += headerlength + 1; /* store sequence */ size_t sequence_p = datalen; - memcpy(datap+sequence_p, fasta_get_sequence(h), sequencelength + 1); + memcpy(datap + sequence_p, + fastx_get_sequence(h), + sequencelength + 1); datalen += sequencelength + 1; + size_t quality_p = datalen; + if (is_fastq) + { + /* store quality */ + memcpy(datap+quality_p, + fastx_get_quality(h), + sequencelength + 1); + datalen += sequencelength + 1; + } + /* grow space for index, if necessary */ size_t seqindex_alloc_old = seqindex_alloc; while ((sequences + 1) * sizeof(seqinfo_t) > seqindex_alloc) @@ -154,9 +187,10 @@ void db_read(const char * filename, int upcase) /* update index */ seqinfo_t * seqindex_p = seqindex + sequences; seqindex_p->headerlen = headerlength; - seqindex_p->header_p = header_p; seqindex_p->seqlen = sequencelength; + seqindex_p->header_p = header_p; seqindex_p->seq_p = sequence_p; + seqindex_p->qual_p = quality_p; seqindex_p->size = abundance; /* update statistics */ @@ -169,12 +203,12 @@ void db_read(const char * filename, int upcase) if (headerlength > longestheader) longestheader = headerlength; } - progress_update(fasta_get_position(h)); + progress_update(fastx_get_position(h)); } progress_done(); free(prompt); - fasta_close(h); + fastx_close(h); if (!opt_quiet) { @@ -237,7 +271,6 @@ void db_read(const char * filename, int upcase) } show_rusage(); - } unsigned long db_getsequencecount() @@ -267,65 +300,12 @@ unsigned long db_getshortestsequence() void db_free() { - abundance_exit(db_abundance); if (datap) free(datap); if (seqindex) free(seqindex); } -void db_fprint_fasta_seq_only(FILE * fp, unsigned long seqno) -{ - char * seq = db_getsequence(seqno); - long seqlen = db_getsequencelen(seqno); - fprint_fasta_seq_only(fp, seq, seqlen, opt_fasta_width); -} - -void db_fprint_fasta(FILE * fp, unsigned long seqno) -{ - char * hdr = db_getheader(seqno); - char * seq = db_getsequence(seqno); - long seqlen = db_getsequencelen(seqno); - - fprint_fasta_hdr_only(fp, hdr); - fprint_fasta_seq_only(fp, seq, seqlen, opt_fasta_width); -} - -void db_fprint_fasta_with_size(FILE * fp, unsigned long seqno, unsigned long size) -{ - char * hdr = db_getheader(seqno); - int hdrlen = db_getheaderlen(seqno); - - abundance_fprint_header_with_size(db_abundance, - fp, - hdr, - hdrlen, - size); - - char * seq = db_getsequence(seqno); - long seqlen = db_getsequencelen(seqno); - - fprint_fasta_seq_only(fp, seq, seqlen, opt_fasta_width); -} - -void db_fprint_fasta_strip_size(FILE * fp, unsigned long seqno) -{ - /* write FASTA but remove abundance information, as with --xsize option */ - - char * hdr = db_getheader(seqno); - int hdrlen = db_getheaderlen(seqno); - - abundance_fprint_header_strip_size(db_abundance, - fp, - hdr, - hdrlen); - - char * seq = db_getsequence(seqno); - long seqlen = db_getsequencelen(seqno); - - fprint_fasta_seq_only(fp, seq, seqlen, opt_fasta_width); -} - int compare_bylength(const void * a, const void * b) { seqinfo_t * x = (seqinfo_t *) a; @@ -444,3 +424,5 @@ void db_sortbyabundance() qsort(seqindex, sequences, sizeof(seqinfo_t), compare_byabundance); progress_done(); } + + diff --git a/source/vsearch_src/db.h b/source/vsearch_src/db.h old mode 100644 new mode 100755 index 758af205e..7c7415b41 --- a/source/vsearch_src/db.h +++ b/source/vsearch_src/db.h @@ -62,6 +62,7 @@ struct seqinfo_s { size_t header_p; size_t seq_p; + size_t qual_p; unsigned int headerlen; unsigned int seqlen; unsigned int size; @@ -71,7 +72,6 @@ typedef struct seqinfo_s seqinfo_t; extern char * datap; extern seqinfo_t * seqindex; -extern abundance_t * db_abundance; inline char * db_getheader(unsigned long seqno) { @@ -107,15 +107,6 @@ unsigned long db_getlongestheader(); unsigned long db_getlongestsequence(); unsigned long db_getshortestsequence(); -void db_fprint_fasta(FILE * fp, unsigned long seqno); - -void db_fprint_fasta_seq_only(FILE * fp, unsigned long seqno); - -void db_fprint_fasta_with_size(FILE * fp, unsigned long seqno, unsigned long size); - -void db_fprint_fasta_strip_size(FILE * fp, unsigned long seqno); - - /* Note: the sorting functions below must be called after db_read, but before dbindex_prepare */ @@ -123,3 +114,6 @@ void db_sortbylength(); void db_sortbylength_shortest_first(); void db_sortbyabundance(); + +bool db_is_fastq(); +char * db_getquality(unsigned long seqno); diff --git a/source/vsearch_src/dbindex.cc b/source/vsearch_src/dbindex.cc old mode 100644 new mode 100755 index 636eb2596..0222dedab --- a/source/vsearch_src/dbindex.cc +++ b/source/vsearch_src/dbindex.cc @@ -83,7 +83,7 @@ void fprint_kmer(FILE * f, unsigned int kk, unsigned long kmer) fprintf(f, "%c", sym_nt_2bit[(x >> (2*(kk-i-1))) & 3]); } -void dbindex_addsequence(unsigned int seqno) +void dbindex_addsequence(unsigned int seqno, int seqmask) { #if 0 printf("Adding seqno %d as index element no %d\n", seqno, dbindex_count); @@ -93,7 +93,7 @@ void dbindex_addsequence(unsigned int seqno) unsigned int * uniquelist; unique_count(dbindex_uh, opt_wordlength, db_getsequencelen(seqno), db_getsequence(seqno), - & uniquecount, & uniquelist); + & uniquecount, & uniquelist, seqmask); dbindex_map[dbindex_count] = seqno; for(unsigned int i=0; isize; if ((size >= opt_minuniquesize) && (size <= opt_maxuniquesize)) { - if (opt_output) - { - if (opt_relabel_sha1 || opt_relabel_md5) - { - fprintf(fp_output, ">"); - char * seq = db_getsequence(bp->seqno_first); - unsigned int len = db_getsequencelen(bp->seqno_first); - if (opt_relabel_sha1) - fprint_seq_digest_sha1(fp_output, seq, len); - else - fprint_seq_digest_md5(fp_output, seq, len); - if (opt_sizeout) - fprintf(fp_output, ";size=%u;\n", bp->size); - else - fprintf(fp_output, "\n"); - db_fprint_fasta_seq_only(fp_output, bp->seqno_first); - } - else if (opt_relabel) - { - if (opt_sizeout) - fprintf(fp_output, ">%s%ld;size=%u;\n", opt_relabel, i+1, - bp->size); - else - fprintf(fp_output, ">%s%ld\n", opt_relabel, i+1); - db_fprint_fasta_seq_only(fp_output, bp->seqno_first); - } - else - { - if (opt_sizeout) - db_fprint_fasta_with_size(fp_output, - bp->seqno_first, bp->size); - else - db_fprint_fasta(fp_output, - bp->seqno_first); - } - } selected++; if (selected == opt_topn) break; } - if (opt_output) - progress_update(i); } + + /* write output */ + if (opt_output) { + progress_init("Writing output file", clusters); + + long relabel_count = 0; + for (long i=0; isize; + if ((size >= opt_minuniquesize) && (size <= opt_maxuniquesize)) + { + relabel_count++; + fasta_print_relabel(fp_output, + db_getsequence(bp->seqno_first), + db_getsequencelen(bp->seqno_first), + db_getheader(bp->seqno_first), + db_getheaderlen(bp->seqno_first), + size, + relabel_count); + if (relabel_count == opt_topn) + break; + } + progress_update(i); + } + progress_done(); fclose(fp_output); } @@ -708,63 +695,49 @@ void derep_prefix() show_rusage(); - long selected = 0; + /* count selected */ - if (opt_output) - progress_init("Writing output file", clusters); - + long selected = 0; for (long i=0; isize; if ((size >= opt_minuniquesize) && (size <= opt_maxuniquesize)) { - if (opt_output) - { - if (opt_relabel_sha1 || opt_relabel_md5) - { - fprintf(fp_output, ">"); - char * seq = db_getsequence(bp->seqno_first); - unsigned int len = db_getsequencelen(bp->seqno_first); - if (opt_relabel_sha1) - fprint_seq_digest_sha1(fp_output, seq, len); - else - fprint_seq_digest_md5(fp_output, seq, len); - if (opt_sizeout) - fprintf(fp_output, ";size=%u;\n", bp->size); - else - fprintf(fp_output, "\n"); - db_fprint_fasta_seq_only(fp_output, bp->seqno_first); - } - else if (opt_relabel) - { - if (opt_sizeout) - fprintf(fp_output, ">%s%ld;size=%u;\n", opt_relabel, i+1, - bp->size); - else - fprintf(fp_output, ">%s%ld\n", opt_relabel, i+1); - db_fprint_fasta_seq_only(fp_output, bp->seqno_first); - } - else - { - if (opt_sizeout) - db_fprint_fasta_with_size(fp_output, - bp->seqno_first, bp->size); - else - db_fprint_fasta(fp_output, - bp->seqno_first); - } - } selected++; if (selected == opt_topn) break; } - if (opt_output) - progress_update(i); } + + /* write output */ + if (opt_output) { + progress_init("Writing output file", clusters); + + long relabel_count = 0; + for (long i=0; isize; + if ((size >= opt_minuniquesize) && (size <= opt_maxuniquesize)) + { + relabel_count++; + fasta_print_relabel(fp_output, + db_getsequence(bp->seqno_first), + db_getsequencelen(bp->seqno_first), + db_getheader(bp->seqno_first), + db_getheaderlen(bp->seqno_first), + size, + relabel_count); + if (relabel_count == opt_topn) + break; + } + progress_update(i); + } + progress_done(); fclose(fp_output); } diff --git a/source/vsearch_src/derep.h b/source/vsearch_src/derep.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/fasta.cc b/source/vsearch_src/fasta.cc old mode 100644 new mode 100755 index 579965127..75d37d832 --- a/source/vsearch_src/fasta.cc +++ b/source/vsearch_src/fasta.cc @@ -128,10 +128,11 @@ fasta_handle fasta_open(const char * filename) if (h->format == FORMAT_GZIP) { - /* GZIP: Close ordinary file and open again as gzipped file */ + /* GZIP: Keep original file open, then open as gzipped file as well */ #ifdef HAVE_ZLIB_H - fclose(h->fp); - if (! (h->fp_gz = gzopen(filename, "rb"))) + if (!gz_lib) + fatal("Files compressed with gzip are not supported"); + if (! (h->fp_gz = (*gzdopen_p)(fileno(h->fp), "rb"))) fatal("Unable to open gzip compressed fasta file (%s)", filename); #else fatal("Files compressed with gzip are not supported"); @@ -142,22 +143,25 @@ fasta_handle fasta_open(const char * filename) { /* BZIP2: Keep original file open, then open as bzipped file as well */ #ifdef HAVE_ZLIB_H + if (!bz2_lib) + fatal("Files compressed with bzip2 are not supported"); int bzError; - if (! (h->fp_bz = BZ2_bzReadOpen(& bzError, h->fp, - BZ_VERBOSE_0, BZ_MORE_MEM, NULL, 0))) + if (! (h->fp_bz = (*BZ2_bzReadOpen_p)(& bzError, h->fp, + BZ_VERBOSE_0, BZ_MORE_MEM, + NULL, 0))) fatal("Unable to open bzip2 compressed fasta file (%s)", filename); #else fatal("Files compressed with bzip2 are not supported"); #endif } + + h->stripped_all = 0; for(int i=0; i<256; i++) h->stripped[i] = 0; - h->abundance = abundance_init(); - h->file_position = 0; buffer_init(& h->file_buffer); @@ -165,6 +169,7 @@ fasta_handle fasta_open(const char * filename) buffer_init(& h->sequence_buffer); h->lineno = 1; + h->lineno_start = 1; h->seqno = -1; return h; @@ -205,15 +210,17 @@ void fasta_close(fasta_handle h) case FORMAT_GZIP: #ifdef HAVE_ZLIB_H - gzclose(h->fp_gz); + (*gzclose_p)(h->fp_gz); h->fp_gz = 0; + h->fp = 0; break; #endif case FORMAT_BZIP: #ifdef HAVE_BZLIB_H - BZ2_bzReadClose(&bz_error, h->fp_bz); + (*BZ2_bzReadClose_p)(&bz_error, h->fp_bz); h->fp_bz = 0; + h->fp = 0; break; #endif @@ -221,8 +228,6 @@ void fasta_close(fasta_handle h) fatal("Internal error"); } - abundance_exit(h->abundance); - buffer_free(& h->file_buffer); buffer_free(& h->header_buffer); buffer_free(& h->sequence_buffer); @@ -274,9 +279,10 @@ unsigned long fasta_file_fill_buffer(fasta_handle h) case FORMAT_GZIP: #ifdef HAVE_ZLIB_H - bytes_read = gzread(h->fp_gz, - h->file_buffer.data + h->file_buffer.position, - space); + bytes_read = (*gzread_p)(h->fp_gz, + h->file_buffer.data + + h->file_buffer.position, + space); if (bytes_read < 0) fatal("Error reading gzip compressed fasta file"); break; @@ -284,11 +290,11 @@ unsigned long fasta_file_fill_buffer(fasta_handle h) case FORMAT_BZIP: #ifdef HAVE_BZLIB_H - bytes_read = BZ2_bzRead(& bzError, - h->fp_bz, - h->file_buffer.data - + h->file_buffer.position, - space); + bytes_read = (*BZ2_bzRead_p)(& bzError, + h->fp_bz, + h->file_buffer.data + + h->file_buffer.position, + space); if ((bytes_read < 0) || ! ((bzError == BZ_OK) || (bzError == BZ_STREAM_END) || @@ -313,8 +319,8 @@ void buffer_extend(struct fasta_buffer_s * buffer, char * buf, unsigned long len /* alloc space for len more characters + terminating zero, but round up to nearest block size */ buffer->alloc = - (FASTA_BUFFER_ALLOC * - ((buffer->length + len) / FASTA_BUFFER_ALLOC) + 1); + FASTA_BUFFER_ALLOC * + (((buffer->length + len) / FASTA_BUFFER_ALLOC) + 1); buffer->data = (char*) xrealloc(buffer->data, buffer->alloc); } @@ -329,11 +335,11 @@ void buffer_extend(struct fasta_buffer_s * buffer, char * buf, unsigned long len void fasta_truncate_header(fasta_handle h, bool truncateatspace) { /* Truncate the zero-terminated header string by inserting a new - terminator (zero byte) at the first space (if truncateatspace) - or first linefeed. */ + terminator (zero byte) at the first space/tab character + (if truncateatspace) or first linefeed. */ if (truncateatspace) - h->header_buffer.length = strcspn(h->header_buffer.data, " \n"); + h->header_buffer.length = strcspn(h->header_buffer.data, " \t\n"); else h->header_buffer.length = strcspn(h->header_buffer.data, "\n"); @@ -406,6 +412,8 @@ bool fasta_next(fasta_handle h, bool truncateatspace, char * char_mapping) { + h->lineno_start = h->lineno; + h->header_buffer.length = 0; h->sequence_buffer.length = 0; @@ -490,7 +498,12 @@ bool fasta_next(fasta_handle h, #ifdef HAVE_ZLIB_H if (h->format == FORMAT_GZIP) - h->file_position = gzoffset(h->fp_gz); + { + /* Circumvent the missing gzoffset function in zlib 1.2.3 and earlier */ + int fd = dup(fileno(h->fp)); + h->file_position = lseek(fd, 0, SEEK_CUR); + close(fd); + } else #endif h->file_position = ftell(h->fp); @@ -500,7 +513,7 @@ bool fasta_next(fasta_handle h, long fasta_get_abundance(fasta_handle h) { - return abundance_get(h->abundance, h->header_buffer.data); + return abundance_get(global_abundance, h->header_buffer.data); } unsigned long fasta_get_position(fasta_handle h) @@ -515,7 +528,7 @@ unsigned long fasta_get_size(fasta_handle h) unsigned long fasta_get_lineno(fasta_handle h) { - return h->lineno; + return h->lineno_start; } unsigned long fasta_get_seqno(fasta_handle h) @@ -543,3 +556,158 @@ char * fasta_get_sequence(fasta_handle h) return h->sequence_buffer.data; } + +/* fasta output */ + +void fasta_print_header(FILE * fp, const char * hdr) +{ + fprintf(fp, ">%s\n", hdr); +} + +void fasta_print_sequence(FILE * fp, char * seq, unsigned long len, int width) +{ + /* + The actual length of the sequence may be longer than "len", but only + "len" characters are printed. + + Specify width of lines - zero (or <1) means linearize (all on one line). + */ + + if (width < 1) + fprintf(fp, "%.*s\n", (int)(len), seq); + else + { + long rest = len; + for(unsigned long i=0; i"); + if (opt_relabel || opt_relabel_sha1 || opt_relabel_md5) + { + if (opt_relabel_sha1) + fprint_seq_digest_sha1(fp, seq, len); + else if (opt_relabel_md5) + fprint_seq_digest_md5(fp, seq, len); + else + fprintf(fp, "%s%d", opt_relabel, ordinal); + + if (opt_sizeout) + fprintf(fp, ";size=%u;", abundance); + + if (opt_relabel_keep) + fprintf(fp, " %s", header); + } + else if (opt_sizeout) + { + abundance_fprint_header_with_size(global_abundance, + fp, + header, + header_len, + abundance); + } + else if (opt_xsize) + { + abundance_fprint_header_strip_size(global_abundance, + fp, + header, + header_len); + } + else + { + fprintf(fp, "%s", header); + } + fprintf(fp, "\n"); + + fasta_print_sequence(fp, seq, len, opt_fasta_width); +} + +void fasta_print_db_relabel(FILE * fp, + unsigned long seqno, + int ordinal) +{ + fasta_print_relabel(fp, + db_getsequence(seqno), + db_getsequencelen(seqno), + db_getheader(seqno), + db_getheaderlen(seqno), + db_getabundance(seqno), + ordinal); +} + +void fasta_print_db_sequence(FILE * fp, unsigned long seqno) +{ + char * seq = db_getsequence(seqno); + long seqlen = db_getsequencelen(seqno); + fasta_print_sequence(fp, seq, seqlen, opt_fasta_width); +} + +void fasta_print_db(FILE * fp, unsigned long seqno) +{ + char * hdr = db_getheader(seqno); + char * seq = db_getsequence(seqno); + long seqlen = db_getsequencelen(seqno); + + fasta_print_header(fp, hdr); + fasta_print_sequence(fp, seq, seqlen, opt_fasta_width); +} + +void fasta_print_db_size(FILE * fp, unsigned long seqno, unsigned long size) +{ + char * hdr = db_getheader(seqno); + int hdrlen = db_getheaderlen(seqno); + + fprintf(fp, ">"); + abundance_fprint_header_with_size(global_abundance, + fp, + hdr, + hdrlen, + size); + fprintf(fp, "\n"); + + char * seq = db_getsequence(seqno); + long seqlen = db_getsequencelen(seqno); + + fasta_print_sequence(fp, seq, seqlen, opt_fasta_width); +} + +void fasta_print_db_strip_size(FILE * fp, unsigned long seqno) +{ + /* write FASTA but remove abundance information, as with --xsize option */ + + char * hdr = db_getheader(seqno); + int hdrlen = db_getheaderlen(seqno); + + fprintf(fp, ">"); + abundance_fprint_header_strip_size(global_abundance, + fp, + hdr, + hdrlen); + fprintf(fp, "\n"); + + char * seq = db_getsequence(seqno); + long seqlen = db_getsequencelen(seqno); + + fasta_print_sequence(fp, seq, seqlen, opt_fasta_width); +} + diff --git a/source/vsearch_src/fasta.h b/source/vsearch_src/fasta.h old mode 100644 new mode 100755 index e1f718bdb..df5c4c722 --- a/source/vsearch_src/fasta.h +++ b/source/vsearch_src/fasta.h @@ -78,8 +78,6 @@ struct fasta_s BZFILE * fp_bz; #endif - abundance_t * abundance; - struct fasta_buffer_s file_buffer; struct fasta_buffer_s header_buffer; struct fasta_buffer_s sequence_buffer; @@ -88,6 +86,7 @@ struct fasta_s unsigned long file_position; unsigned long lineno; + unsigned long lineno_start; long seqno; unsigned long stripped_all; @@ -98,6 +97,8 @@ struct fasta_s typedef struct fasta_s * fasta_handle; +/* fasta input */ + fasta_handle fasta_open(const char * filename); void fasta_close(fasta_handle h); bool fasta_next(fasta_handle h, @@ -112,3 +113,32 @@ char * fasta_get_sequence(fasta_handle h); unsigned long fasta_get_header_length(fasta_handle h); unsigned long fasta_get_sequence_length(fasta_handle h); long fasta_get_abundance(fasta_handle h); + +/* fasta output */ + +void fasta_print_header(FILE * fp, const char * hdr); + +void fasta_print_sequence(FILE * fp, char * seq, + unsigned long len, int width); + +void fasta_print(FILE * fp, const char * hdr, + char * seq, unsigned long len); + +void fasta_print_relabel(FILE * fp, + char * seq, + int len, + char * header, + int header_len, + int abundance, + int ordinal); + +void fasta_print_db(FILE * fp, unsigned long seqno); + +void fasta_print_db_sequence(FILE * fp, unsigned long seqno); + +void fasta_print_db_size(FILE * fp, unsigned long seqno, + unsigned long size); + +void fasta_print_db_strip_size(FILE * fp, unsigned long seqno); + +void fasta_print_db_relabel(FILE * fp, unsigned long seqno, int ordinal); diff --git a/source/vsearch_src/fastq.cc b/source/vsearch_src/fastq.cc old mode 100644 new mode 100755 index bd7420d77..f44d59022 --- a/source/vsearch_src/fastq.cc +++ b/source/vsearch_src/fastq.cc @@ -84,7 +84,7 @@ static char map_identity[256]; void fastq_fatal(unsigned long lineno, const char * msg) { char * string; - if (asprintf(& string, + if (sprintf(string, "Invalid line %lu in FASTQ file: %s", lineno, msg) == -1) @@ -136,11 +136,11 @@ void buffer_makespace(struct fastq_buffer_s * buffer, unsigned long x) void buffer_truncate(struct fastq_buffer_s * buffer, bool truncateatspace) { /* Truncate the zero-terminated header string by inserting a new - terminator (zero byte) at the first space (if truncateatspace) - or first linefeed. */ + terminator (zero byte) at the first space/tab character + (if truncateatspace) or first linefeed. */ if (truncateatspace) - buffer->length = strcspn(buffer->data, " \n"); + buffer->length = strcspn(buffer->data, " \t\n"); else buffer->length = strcspn(buffer->data, "\n"); @@ -178,10 +178,11 @@ fastq_handle fastq_open(const char * filename) if (h->format == FORMAT_GZIP) { - /* GZIP: Close ordinary file and open again as gzipped file */ + /* GZIP: Keep original file open, then open as bzipped file as well */ #ifdef HAVE_ZLIB_H - fclose(h->fp); - if (! (h->fp_gz = gzopen(filename, "rb"))) + if (!gz_lib) + fatal("Files compressed with gzip are not supported"); + if (! (h->fp_gz = (*gzdopen_p)(fileno(h->fp), "rb"))) fatal("Unable to open gzip compressed fastq file (%s)", filename); #else fatal("Files compressed with gzip are not supported"); @@ -192,9 +193,12 @@ fastq_handle fastq_open(const char * filename) { /* BZIP2: Keep original file open, then open as bzipped file as well */ #ifdef HAVE_ZLIB_H + if (!bz2_lib) + fatal("Files compressed with bzip2 are not supported"); int bzError; - if (! (h->fp_bz = BZ2_bzReadOpen(& bzError, h->fp, - BZ_VERBOSE_0, BZ_MORE_MEM, NULL, 0))) + if (! (h->fp_bz = (*BZ2_bzReadOpen_p)(& bzError, h->fp, + BZ_VERBOSE_0, BZ_MORE_MEM, + NULL, 0))) fatal("Unable to open bzip2 compressed fastq file (%s)", filename); #else fatal("Files compressed with bzip2 are not supported"); @@ -214,6 +218,7 @@ fastq_handle fastq_open(const char * filename) buffer_init(& h->quality_buffer); h->lineno = 1; + h->lineno_start = 1; h->seqno = -1; for(int i=0; i<256; i++) @@ -257,14 +262,14 @@ void fastq_close(fastq_handle h) case FORMAT_GZIP: #ifdef HAVE_ZLIB_H - gzclose(h->fp_gz); + (*gzclose_p)(h->fp_gz); h->fp_gz = 0; break; #endif case FORMAT_BZIP: #ifdef HAVE_BZLIB_H - BZ2_bzReadClose(&bz_error, h->fp_bz); + (*BZ2_bzReadClose_p)(&bz_error, h->fp_bz); h->fp_bz = 0; break; #endif @@ -285,6 +290,7 @@ void fastq_close(fastq_handle h) h->seqno = -1; free(h); + h=0; } @@ -325,9 +331,10 @@ unsigned long fastq_file_fill_buffer(fastq_handle h) case FORMAT_GZIP: #ifdef HAVE_ZLIB_H - bytes_read = gzread(h->fp_gz, - h->file_buffer.data + h->file_buffer.position, - space); + bytes_read = (*gzread_p)(h->fp_gz, + h->file_buffer.data + + h->file_buffer.position, + space); if (bytes_read < 0) fatal("Error reading gzip compressed fastq file"); break; @@ -335,11 +342,11 @@ unsigned long fastq_file_fill_buffer(fastq_handle h) case FORMAT_BZIP: #ifdef HAVE_BZLIB_H - bytes_read = BZ2_bzRead(& bzError, - h->fp_bz, - h->file_buffer.data - + h->file_buffer.position, - space); + bytes_read = (*BZ2_bzRead_p)(& bzError, + h->fp_bz, + h->file_buffer.data + + h->file_buffer.position, + space); if ((bytes_read < 0) || ! ((bzError == BZ_OK) || (bzError == BZ_STREAM_END) || @@ -449,6 +456,8 @@ bool fastq_next(fastq_handle h, h->quality_buffer.length = 0; h->quality_buffer.data[0] = 0; + h->lineno_start = h->lineno; + unsigned long rest = fastq_file_fill_buffer(h); /* check end of file */ @@ -648,7 +657,12 @@ bool fastq_next(fastq_handle h, #ifdef HAVE_ZLIB_H if (h->format == FORMAT_GZIP) - h->file_position = gzoffset(h->fp_gz); + { + /* Circumvent the missing gzoffset function in zlib 1.2.3 and earlier */ + int fd = dup(fileno(h->fp)); + h->file_position = lseek(fd, 0, SEEK_CUR); + close(fd); + } else #endif h->file_position = ftell(h->fp); @@ -680,7 +694,7 @@ unsigned long fastq_get_size(fastq_handle h) unsigned long fastq_get_lineno(fastq_handle h) { - return h->lineno; + return h->lineno_start; } unsigned long fastq_get_seqno(fastq_handle h) @@ -707,3 +721,98 @@ char * fastq_get_sequence(fastq_handle h) { return h->sequence_buffer.data; } + +void fastq_print_header(FILE * fp, char * header) +{ + fprintf(fp, "@%s\n", header); +} + +void fastq_print_sequence(FILE * fp, char * sequence) +{ + fprintf(fp, "%s\n", sequence); +} + +void fastq_print_quality(FILE * fp, char * quality) +{ + fprintf(fp, "+\n%s\n", quality); +} + +void fastq_print(FILE * fp, char * header, char * sequence, char * quality) +{ + fastq_print_header(fp, header); + fastq_print_sequence(fp, sequence); + fastq_print_quality(fp, quality); +} + +void fastq_print_with_ee(FILE * fp, char * header, + char * sequence, char * quality, double ee) +{ + fprintf(fp, "@%s;ee=%6.4lf\n", header, ee); + fastq_print_sequence(fp, sequence); + fastq_print_quality(fp, quality); +} + +void fastq_print_relabel(FILE * fp, + char * seq, + int len, + char * header, + int header_len, + char * quality, + int abundance, + int ordinal) +{ + fprintf(fp, "@"); + if (opt_relabel || opt_relabel_sha1 || opt_relabel_md5) + { + if (opt_relabel_sha1) + fprint_seq_digest_sha1(fp, seq, len); + else if (opt_relabel_md5) + fprint_seq_digest_md5(fp, seq, len); + else + fprintf(fp, "%s%d", opt_relabel, ordinal); + + if (opt_sizeout) + fprintf(fp, ";size=%u;", abundance); + + if (opt_relabel_keep) + fprintf(fp, " %s", header); + } + else if (opt_sizeout) + { + abundance_fprint_header_with_size(global_abundance, + fp, + header, + header_len, + abundance); + } + else if (opt_xsize) + { + abundance_fprint_header_strip_size(global_abundance, + fp, + header, + header_len); + } + else + { + fprintf(fp, "%s", header); + } + fprintf(fp, "\n"); + fastq_print_sequence(fp, seq); + fastq_print_quality(fp, quality); +} + +long fastq_get_abundance(fastq_handle h) +{ + return abundance_get(global_abundance, h->header_buffer.data); +} + +void fastq_print_db(FILE * fp, unsigned long seqno) +{ + char * hdr = db_getheader(seqno); + char * seq = db_getsequence(seqno); + char * qual = db_getquality(seqno); + + fastq_print_header(fp, hdr); + fastq_print_sequence(fp, seq); + fastq_print_quality(fp, qual); +} diff --git a/source/vsearch_src/fastq.h b/source/vsearch_src/fastq.h old mode 100644 new mode 100755 index 2e7ebc633..0bffae2e8 --- a/source/vsearch_src/fastq.h +++ b/source/vsearch_src/fastq.h @@ -88,12 +88,14 @@ struct fastq_s unsigned long file_position; unsigned long lineno; + unsigned long lineno_start; long seqno; unsigned long stripped_all; unsigned long stripped[256]; int format; + }; typedef struct fastq_s * fastq_handle; @@ -110,6 +112,24 @@ unsigned long fastq_get_seqno(fastq_handle h); char * fastq_get_header(fastq_handle h); char * fastq_get_sequence(fastq_handle h); char * fastq_get_quality(fastq_handle h); +long fastq_get_abundance(fastq_handle h); unsigned long fastq_get_header_length(fastq_handle h); unsigned long fastq_get_sequence_length(fastq_handle h); unsigned long fastq_get_quality_length(fastq_handle h); + +void fastq_print(FILE * fp, char * header, char * sequence, char * quality); + +void fastq_print_with_ee(FILE * fp, char * header, char * sequence, + char * quality, double ee); + +void fastq_print_relabel(FILE * fp, + char * seq, + int len, + char * header, + int header_len, + char * quality, + int abundance, + int ordinal); + + +void fastq_print_db(FILE * fp, unsigned long seqno); diff --git a/source/vsearch_src/fastqops.cc b/source/vsearch_src/fastqops.cc old mode 100644 new mode 100755 index 8e129584d..d9330a808 --- a/source/vsearch_src/fastqops.cc +++ b/source/vsearch_src/fastqops.cc @@ -136,7 +136,7 @@ void fastq_filter() char hex_md5[LEN_HEX_DIG_MD5]; char hex_sha1[LEN_HEX_DIG_SHA1]; - while(fastq_next(h, 0, chrmap_upcase)) + while(fastq_next(h, 0, chrmap_no_change)) { long length = fastq_get_sequence_length(h); char * d = fastq_get_header(h); @@ -195,7 +195,7 @@ void fastq_filter() for (long i = 0; i < length; i++) { int qual = fastq_get_qual(q[i]); - ee += pow(10.0, - qual / 10.0); + ee += exp10(- qual / 10.0); } if ((length >= opt_fastq_minlen) && @@ -205,7 +205,9 @@ void fastq_filter() (ncount <= opt_fastq_maxns)) { /* keep the sequence */ + kept++; + if ((unsigned long)(length) < fastq_get_sequence_length(h)) { truncated++; @@ -213,63 +215,78 @@ void fastq_filter() q[length] = 0; } - if (opt_relabel) - { - (void) snprintf(header, header_alloc, - "%s%ld", opt_relabel, kept); - d = header; - } - else if (opt_relabel_md5) - { - get_hex_seq_digest_md5(hex_md5, p, length); - d = hex_md5; - } - else if (opt_relabel_sha1) - { - get_hex_seq_digest_sha1(hex_sha1, p, length); - d = hex_sha1; - } - if (opt_fastaout) { - fprint_fasta_hdr_only(fp_fastaout, d); - fprint_fasta_seq_only(fp_fastaout, p, length, opt_fasta_width); + fasta_print_relabel(fp_fastaout, + p, length, + d, fastq_get_header_length(h), + 1, kept); } if (opt_fastqout) - fprint_fastq(fp_fastqout, d, p, q, opt_eeout, ee); + { + if (opt_relabel) + { + (void) snprintf(header, header_alloc, + "%s%ld", opt_relabel, kept); + d = header; + } + else if (opt_relabel_md5) + { + get_hex_seq_digest_md5(hex_md5, p, length); + d = hex_md5; + } + else if (opt_relabel_sha1) + { + get_hex_seq_digest_sha1(hex_sha1, p, length); + d = hex_sha1; + } + + if (opt_eeout) + fastq_print_with_ee(fp_fastqout, d, p, q, ee); + else + fastq_print(fp_fastqout, d, p, q); + } } else { + /* discard the sequence */ + discarded++; + p = fastq_get_sequence(h); q = fastq_get_quality(h); - if (opt_relabel) - { - (void) snprintf(header, header_alloc, "%s%ld", opt_relabel, discarded); - d = header; - } - else if (opt_relabel_md5) - { - get_hex_seq_digest_md5(hex_md5, p, length); - d = hex_md5; - } - else if (opt_relabel_sha1) + if (opt_fastaout_discarded) { - get_hex_seq_digest_sha1(hex_sha1, p, length); - d = hex_sha1; + fasta_print_relabel(fp_fastaout_discarded, + p, length, + d, fastq_get_header_length(h), + 1, discarded); } - if (opt_fastaout_discarded) + if (opt_fastqout_discarded) { - fprint_fasta_hdr_only(fp_fastaout_discarded, d); - fprint_fasta_seq_only(fp_fastaout_discarded, - p, - length, - opt_fasta_width); + if (opt_relabel) + { + (void) snprintf(header, header_alloc, "%s%ld", opt_relabel, discarded); + d = header; + } + else if (opt_relabel_md5) + { + get_hex_seq_digest_md5(hex_md5, p, length); + d = hex_md5; + } + else if (opt_relabel_sha1) + { + get_hex_seq_digest_sha1(hex_sha1, p, length); + d = hex_sha1; + } + + if (opt_eeout) + fastq_print_with_ee(fp_fastqout_discarded, d, p, q, ee); + else + fastq_print(fp_fastqout_discarded, d, p, q); } - if (opt_fastqout_discarded) - fprint_fastq(fp_fastqout_discarded, d, p, q, opt_eeout, ee); } progress_update(fastq_get_position(h)); @@ -432,15 +449,18 @@ void fastq_chars() if (fastq_ascii == 64) { if (qmin < 64) - fprintf(stderr, "Guess: Solexa format\n"); + fprintf(stderr, "Guess: Solexa format (phred+64)\n"); else if (qmin < 66) - fprintf(stderr, "Guess: Illumina 1.3+ format\n"); + fprintf(stderr, "Guess: Illumina 1.3+ format (phred+64)\n"); else - fprintf(stderr, "Guess: Illumina 1.5+ format\n"); + fprintf(stderr, "Guess: Illumina 1.5+ format (phred+64)\n"); } else { - fprintf(stderr, "Guess: Sanger / Illumina 1.8+ format\n"); + if (qmax > 73) + fprintf(stderr, "Guess: Illumina 1.8+ format (phred+33)\n"); + else + fprintf(stderr, "Guess: Original Sanger format (phred+33)\n"); } fprintf(stderr, "\n"); @@ -486,7 +506,7 @@ void fastq_chars() double q2p(double q) { - return pow(10.0, - q / 10.0); + return exp10(- q / 10.0); } void fastq_stats() @@ -501,15 +521,22 @@ void fastq_stats() unsigned long symbols = 0; long read_length_alloc = 512; + int * read_length_table = (int*) xmalloc(sizeof(int) * read_length_alloc); memset(read_length_table, 0, sizeof(int) * read_length_alloc); + int * qual_length_table = (int*) xmalloc(sizeof(int) * read_length_alloc * 256); memset(qual_length_table, 0, sizeof(int) * read_length_alloc * 256); + int * ee_length_table = (int *) xmalloc(sizeof(int) * read_length_alloc * 4); memset(ee_length_table, 0, sizeof(int) * read_length_alloc * 4); + int * q_length_table = (int *) xmalloc(sizeof(int) * read_length_alloc * 4); memset(q_length_table, 0, sizeof(int) * read_length_alloc * 4); + double * sumee_length_table = (double *) xmalloc(sizeof(double) * read_length_alloc); + memset(sumee_length_table, 0, sizeof(double) * read_length_alloc); + long len_min = LONG_MAX; long len_max = 0; @@ -535,18 +562,27 @@ void fastq_stats() sizeof(int) * (len+1)); memset(read_length_table + read_length_alloc, 0, sizeof(int) * (len + 1 - read_length_alloc)); + qual_length_table = (int*) xrealloc(qual_length_table, sizeof(int) * (len+1) * 256); memset(qual_length_table + 256 * read_length_alloc, 0, sizeof(int) * (len + 1 - read_length_alloc) * 256); + ee_length_table = (int*) xrealloc(ee_length_table, sizeof(int) * (len+1) * 4); memset(ee_length_table + 4 * read_length_alloc, 0, sizeof(int) * (len + 1 - read_length_alloc) * 4); + q_length_table = (int*) xrealloc(q_length_table, sizeof(int) * (len+1) * 4); memset(q_length_table + 4 * read_length_alloc, 0, sizeof(int) * (len + 1 - read_length_alloc) * 4); + + sumee_length_table = (double *) xrealloc(sumee_length_table, + sizeof(double) * (len+1)); + memset(sumee_length_table + read_length_alloc, 0, + sizeof(double) * (len + 1 - read_length_alloc)); + read_length_alloc = len + 1; } @@ -583,6 +619,8 @@ void fastq_stats() ee += q2p(qual); + sumee_length_table[i] += ee; + for(int z=0; z<4; z++) { if (ee <= ee_limit[z]) @@ -619,7 +657,6 @@ void fastq_stats() long length_accum = 0; long symb_accum = 0; - double p_sum = 0.0; for(long i = 0; i <= len_max; i++) { @@ -636,20 +673,18 @@ void fastq_stats() { int qual = c - opt_fastq_ascii; x += qual_length_table[256*i + c]; - q += qual_length_table[256*i + c] * qual; - - p_sum += qual_length_table[256*i + c] * q2p(qual); e_sum += qual_length_table[256*i + c] * q2p(qual); } avgq_dist[i] = 1.0 * q / x; avgp_dist[i] = e_sum / x; - avgee_dist[i] = 1.0 * p_sum / x; - rate_dist[i] = 1.0 * p_sum / symb_accum; + avgee_dist[i] = sumee_length_table[i] / x; + rate_dist[i] = avgee_dist[i] / (i+1); } if (fp_log) { + fprintf(fp_log, "\n"); fprintf(fp_log, "\n"); fprintf(fp_log, "Read length distribution\n"); fprintf(fp_log, " L N Pct AccPct\n"); @@ -657,12 +692,13 @@ void fastq_stats() for(long i = len_max; i >= len_min; i--) { - fprintf(fp_log, "%2s%5ld %10d %5.1lf%% %5.1lf%%\n", - (i == len_max ? ">=" : " "), - i, - read_length_table[i], - read_length_table[i] * 100.0 / seq_count, - 100.0 * (seq_count - length_dist[i-1]) / seq_count); + if (read_length_table[i] > 0) + fprintf(fp_log, "%2s%5ld %10d %5.1lf%% %5.1lf%%\n", + (i == len_max ? ">=" : " "), + i, + read_length_table[i], + read_length_table[i] * 100.0 / seq_count, + 100.0 * (seq_count - length_dist[i-1]) / seq_count); } fprintf(fp_log, "\n"); @@ -729,14 +765,17 @@ void fastq_stats() read_percentage[z] = 100.0 * read_count[z] / seq_count; } - fprintf(fp_log, - "%5ld %7ld %7ld %7ld %7ld " - "%6.2lf%% %6.2lf%% %6.2lf%% %6.2lf%%\n", - i, - read_count[0], read_count[1], - read_count[2], read_count[3], - read_percentage[0], read_percentage[1], - read_percentage[2], read_percentage[3]); + if (read_count[0] > 0) + { + fprintf(fp_log, + "%5ld %7ld %7ld %7ld %7ld " + "%6.2lf%% %6.2lf%% %6.2lf%% %6.2lf%%\n", + i, + read_count[0], read_count[1], + read_count[2], read_count[3], + read_percentage[0], read_percentage[1], + read_percentage[2], read_percentage[3]); + } } @@ -769,6 +808,7 @@ void fastq_stats() free(qual_length_table); free(ee_length_table); free(q_length_table); + free(sumee_length_table); free(length_dist); free(symb_dist); @@ -784,8 +824,6 @@ void fastq_stats() void fastx_revcomp() { - int filetype = fastx_detect(opt_fastx_revcomp); - unsigned long buffer_alloc = 512; char * seq_buffer = (char*) xmalloc(buffer_alloc); char * qual_buffer = (char*) xmalloc(buffer_alloc); @@ -795,176 +833,182 @@ void fastx_revcomp() unsigned long suffix_length = opt_label_suffix ? strlen(opt_label_suffix) : 0; - if (filetype == 1) + fastx_handle h = fastx_open(opt_fastx_revcomp); + + if (!h) + fatal("Unrecognized file type (not proper FASTA or FASTQ format)"); + + if (opt_fastqout && ! h->is_fastq) + fatal("Cannot write FASTQ output with a FASTA input file, lacking quality scores"); + + unsigned long filesize = fastx_get_size(h); + + FILE * fp_fastaout = 0; + FILE * fp_fastqout = 0; + + if (opt_fastaout) { - /* fasta */ - fasta_handle h = fasta_open(opt_fastx_revcomp); - unsigned long filesize = fasta_get_size(h); + fp_fastaout = fopen(opt_fastaout, "w"); + if (!fp_fastaout) + fatal("Unable to open fasta output file for writing"); + } + + if (opt_fastqout) + { + fp_fastqout = fopen(opt_fastqout, "w"); + if (!fp_fastqout) + fatal("Unable to open fastq output file for writing"); + } + + if (h->is_fastq) + progress_init("Reading fastq file", filesize); + else + progress_init("Reading fasta file", filesize); + + while(fastx_next(h, 0, chrmap_no_change)) + { + /* header */ - FILE * fp_fastaout = 0; - FILE * fp_fastqout = 0; + unsigned long hlen = fastx_get_header_length(h); - if (opt_fastaout) + if (hlen + suffix_length + 1 > header_alloc) { - fp_fastaout = fopen(opt_fastaout, "w"); - if (!fp_fastaout) - fatal("Unable to open fasta output file for writing"); + header_alloc = hlen + suffix_length + 1; + header = (char*) xrealloc(header, header_alloc); } - if (opt_fastqout) - { - fp_fastqout = fopen(opt_fastqout, "w"); - if (!fp_fastqout) - fatal("Unable to open fastq output file for writing"); + char * d = fastx_get_header(h); - fprintf(stderr, "WARNING: Writing FASTQ output without base quality information; using max value\n"); - } + if (opt_label_suffix) + snprintf(header, header_alloc, "%s%s", d, opt_label_suffix); + else + snprintf(header, header_alloc, "%s", d); - progress_init("Reading fasta file", filesize); - - while(fasta_next(h, 0, chrmap_no_change)) - { - unsigned long length = fasta_get_sequence_length(h); - unsigned long hlen = fasta_get_header_length(h); - char * d = fasta_get_header(h); - char * p = fasta_get_sequence(h); - if (hlen + suffix_length + 1 > header_alloc) - header_alloc = hlen + suffix_length + 1; - header = (char*) xrealloc(header, header_alloc); + /* sequence */ - if (length + 1 > buffer_alloc) - buffer_alloc = length + 1; + unsigned long length = fastx_get_sequence_length(h); + + if (length + 1 > buffer_alloc) + { + buffer_alloc = length + 1; seq_buffer = (char *) xrealloc(seq_buffer, buffer_alloc); qual_buffer = (char *) xrealloc(qual_buffer, buffer_alloc); - - if (opt_label_suffix) - snprintf(header, header_alloc, "%s%s", d, opt_label_suffix); - else - snprintf(header, header_alloc, "%s", d); + } - reverse_complement(seq_buffer, p, length); - - /* set quality values to max */ + char * p = fastx_get_sequence(h); + reverse_complement(seq_buffer, p, length); + + + /* quality values */ + + char * q = fastx_get_quality(h); + + if (fastx_is_fastq(h)) + { + /* reverse quality values */ for(unsigned long i=0; i header_alloc) - header_alloc = hlen + suffix_length + 1; - header = (char*) xrealloc(header, header_alloc); + char * header = fastq_get_header(h); - if (length + 1 > buffer_alloc) - buffer_alloc = length + 1; - seq_buffer = (char *) xrealloc(seq_buffer, buffer_alloc); - qual_buffer = (char *) xrealloc(qual_buffer, buffer_alloc); - - if (opt_label_suffix) - snprintf(header, header_alloc, "%s%s", d, opt_label_suffix); - else - snprintf(header, header_alloc, "%s", d); + /* sequence */ - reverse_complement(seq_buffer, p, length); - - /* reverse quality values */ - for(unsigned long i=0; i opt_fastq_qmax) + { + fprintf(stderr, + "\nFASTQ quality score (%d) above maximum (%ld) in entry no %lu starting on line %lu\n", + q, + opt_fastq_qmax, + fastq_get_seqno(h) + 1, + fastq_get_lineno(h)); + fatal("FASTQ quality score too high"); + } + if (q < opt_fastq_qminout) + q = opt_fastq_qminout; + if (q > opt_fastq_qmaxout) + q = opt_fastq_qmaxout; + q += opt_fastq_asciiout; + if (q < 33) + q = 33; + if (q > 126) + q = 126; + quality[i] = q; } - progress_done(); - - if (opt_fastaout) - fclose(fp_fastaout); - - if (opt_fastqout) - fclose(fp_fastqout); + quality[length] = 0; - fastq_close(h); + fastq_print(fp_fastqout, header, sequence, quality); + + progress_update(fastq_get_position(h)); } - else - fatal("Unable to determine file type."); - free(header); - free(seq_buffer); - free(qual_buffer); + progress_done(); + + fclose(fp_fastqout); + fastq_close(h); } diff --git a/source/vsearch_src/fastqops.h b/source/vsearch_src/fastqops.h old mode 100644 new mode 100755 index 90bd3303d..525155f8e --- a/source/vsearch_src/fastqops.h +++ b/source/vsearch_src/fastqops.h @@ -62,3 +62,4 @@ void fastq_chars(); void fastq_filter(); void fastq_stats(); void fastx_revcomp(); +void fastq_convert(); diff --git a/source/vsearch_src/fastxdetect.cc b/source/vsearch_src/fastxdetect.cc old mode 100644 new mode 100755 diff --git a/source/vsearch_src/fastxdetect.h b/source/vsearch_src/fastxdetect.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/linmemalign.cc b/source/vsearch_src/linmemalign.cc old mode 100644 new mode 100755 diff --git a/source/vsearch_src/linmemalign.h b/source/vsearch_src/linmemalign.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/maps.cc b/source/vsearch_src/maps.cc old mode 100644 new mode 100755 index a955bb41c..043212c15 --- a/source/vsearch_src/maps.cc +++ b/source/vsearch_src/maps.cc @@ -244,7 +244,7 @@ unsigned int chrmap_4bit[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -unsigned int chrmap_masked[256] = +unsigned int chrmap_mask_lower[256] = { /* @@ -274,6 +274,36 @@ unsigned int chrmap_masked[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; +unsigned int chrmap_mask_ambig[256] = + { + /* + + Should character be masked and not used for search ? + Mask everything but A, C, G, T and U. + Lower case letters are NOT masked. + + @ A B C D E F G H I J K L M N O + P Q R S T U V W X Y Z [ \ ] ^ _ + */ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + char chrmap_complement[256] = { diff --git a/source/vsearch_src/maps.h b/source/vsearch_src/maps.h old mode 100644 new mode 100755 index b2309527a..fd518316f --- a/source/vsearch_src/maps.h +++ b/source/vsearch_src/maps.h @@ -66,7 +66,8 @@ extern unsigned int char_fq_action_seq[256]; extern unsigned int char_fq_action_qual[256]; extern unsigned int chrmap_2bit[256]; extern unsigned int chrmap_4bit[256]; -extern unsigned int chrmap_masked[256]; +extern unsigned int chrmap_mask_ambig[256]; +extern unsigned int chrmap_mask_lower[256]; extern char chrmap_complement[256]; extern char chrmap_normalize[256]; extern char chrmap_upcase[256]; diff --git a/source/vsearch_src/mask.cc b/source/vsearch_src/mask.cc old mode 100644 new mode 100755 index 2f319ddf5..9fa5e79b6 --- a/source/vsearch_src/mask.cc +++ b/source/vsearch_src/mask.cc @@ -124,8 +124,16 @@ void dust(char * m, int len) int a, b; /* make a local copy of the original sequence */ - char * s = (char*) alloca(len); - memcpy(s, m, len); + char * s = (char*) alloca(len+1); + strcpy(s, m); + + if (! opt_hardmask) + { + /* convert sequence to upper case unless hardmask in effect */ + for(int i=0; i < len; i++) + m[i] = toupper(m[i]); + m[len] = 0; + } for (int i=0; i < len; i += dust_window2) { @@ -149,11 +157,10 @@ void dust(char * m, int len) #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - static pthread_t * pthread; - static pthread_attr_t attr; - static pthread_mutex_t myMutex; -#else - todo +static pthread_t * pthread; +static pthread_attr_t attr; +static pthread_mutex_t myMutex; + #endif static int nextseq = 0; @@ -161,43 +168,33 @@ static int seqcount = 0; void * dust_all_worker(void * vp) { - while(1) - { #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - pthread_mutex_lock(&myMutex); -#else - todo -#endif + while(1) + { + pthread_mutex_lock(&mutex); int seqno = nextseq; if (seqno < seqcount) { nextseq++; progress_update(seqno); -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&myMutex); -#else - todo -#endif + pthread_mutex_unlock(&mutex); dust(db_getsequence(seqno), db_getsequencelen(seqno)); } else { -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&myMutex); -#else - todo -#endif + pthread_mutex_unlock(&mutex); break; } } +#endif return 0; } void dust_all() { + nextseq = 0; + seqcount = db_getsequencecount(); progress_init("Masking", seqcount); #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) @@ -217,11 +214,16 @@ void dust_all() free(pthread); pthread_attr_destroy(&attr); - #else - todo + while(1){ + int seqno = nextseq; + if (seqno < seqcount){ + nextseq++; + progress_update(seqno); + dust(db_getsequence(seqno), db_getsequencelen(seqno)); + }else{ break; } + } #endif - progress_done(); } @@ -246,21 +248,21 @@ void maskfasta() if (!fp_output) fatal("Unable to open mask output file for writing"); - db_read(opt_maskfasta, opt_qmask != MASK_SOFT); + db_read(opt_maskfasta, 0); show_rusage(); seqcount = db_getsequencecount(); if (opt_qmask == MASK_DUST) dust_all(); - else if (opt_hardmask) + else if ((opt_qmask == MASK_SOFT) && (opt_hardmask)) hardmask_all(); show_rusage(); progress_init("Writing output", seqcount); for(int i=0; i opt_max_unmasked_pct) + discarded_more++; + else + { + kept++; + + if (opt_fastaout) + fasta_print_db(fp_fastaout, i); + + if (opt_fastqout) + fastq_print_db(fp_fastqout, i); + } + + progress_update(i); + } + progress_done(); + + if (!opt_quiet) + { + if (opt_min_unmasked_pct > 0.0) + fprintf(stderr, "%d sequences with less than %.1lf%% unmasked residues discarded\n", discarded_less, opt_min_unmasked_pct); + if (opt_max_unmasked_pct < 100.0) + fprintf(stderr, "%d sequences with more than %.1lf%% unmasked residues discarded\n", discarded_more, opt_max_unmasked_pct); + fprintf(stderr, "%d sequences kept\n", kept); + } + + if (opt_log) + { + if (opt_min_unmasked_pct > 0.0) + fprintf(fp_log, "%d sequences with less than %.1lf%% unmasked residues discarded\n", discarded_less, opt_min_unmasked_pct); + if (opt_max_unmasked_pct < 100.0) + fprintf(fp_log, "%d sequences with more than %.1lf%% unmasked residues discarded\n", discarded_more, opt_max_unmasked_pct); + fprintf(fp_log, "%d sequences kept\n", kept); + } + + show_rusage(); + db_free(); + + if (fp_fastaout) + fclose(fp_fastaout); + if (fp_fastqout) + fclose(fp_fastqout); +} diff --git a/source/vsearch_src/mask.h b/source/vsearch_src/mask.h old mode 100644 new mode 100755 index 9db8c9686..474bfa69f --- a/source/vsearch_src/mask.h +++ b/source/vsearch_src/mask.h @@ -1,6 +1,3 @@ - -extern "C" { - /* VSEARCH: a versatile open source tool for metagenomics @@ -67,11 +64,9 @@ extern "C" { #define MASK_SOFT 2 void maskfasta(); +void fastx_mask(); + void dust(char * m, int len); void hardmask(char * m, int len); void dust_all(); void hardmask_all(); - -} - - diff --git a/source/vsearch_src/md5.c b/source/vsearch_src/md5.c old mode 100644 new mode 100755 index 7d43a603a..4bcd0cd9c --- a/source/vsearch_src/md5.c +++ b/source/vsearch_src/md5.c @@ -1,295 +1,295 @@ -/* - * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. - * MD5 Message-Digest Algorithm (RFC 1321). - * - * Homepage: - * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - * - * Author: - * Alexander Peslyak, better known as Solar Designer - * - * This software was written by Alexander Peslyak in 2001. No copyright is - * claimed, and the software is hereby placed in the public domain. - * In case this attempt to disclaim copyright and place the software in the - * public domain is deemed null and void, then the software is - * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * (This is a heavily cut-down "BSD license".) - * - * This differs from Colin Plumb's older public domain implementation in that - * no exactly 32-bit integer data type is required (any 32-bit or wider - * unsigned integer data type will do), there's no compile-time endianness - * configuration, and the function prototypes match OpenSSL's. No code from - * Colin Plumb's implementation has been reused; this comment merely compares - * the properties of the two independent implementations. - * - * The primary goals of this implementation are portability and ease of use. - * It is meant to be fast, but not as fast as possible. Some known - * optimizations are not included to reduce source code size and avoid - * compile-time configuration. - */ - -#ifndef HAVE_OPENSSL - -#include - -#include "md5.h" - -/* - * The basic MD5 functions. - * - * F and G are optimized compared to their RFC 1321 definitions for - * architectures that lack an AND-NOT instruction, just like in Colin Plumb's - * implementation. - */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) - -/* - * The MD5 transformation for all four rounds. - */ -#define STEP(f, a, b, c, d, x, t, s) \ - (a) += f((b), (c), (d)) + (x) + (t); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ - (a) += (b); - -/* - * SET reads 4 input bytes in little-endian byte order and stores them - * in a properly aligned word in host byte order. - * - * The check for little-endian architectures that tolerate unaligned - * memory accesses is just an optimization. Nothing will break if it - * doesn't work. - */ -#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) -#define SET(n) \ - (*(MD5_u32plus *)&ptr[(n) * 4]) -#define GET(n) \ - SET(n) -#else -#define SET(n) \ - (ctx->block[(n)] = \ - (MD5_u32plus)ptr[(n) * 4] | \ - ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) -#define GET(n) \ - (ctx->block[(n)]) -#endif - -/* - * This processes one or more 64-byte data blocks, but does NOT update - * the bit counters. There are no alignment requirements. - */ -static void *body(MD5_CTX *ctx, void *data, unsigned long size) -{ - unsigned char *ptr; - MD5_u32plus a, b, c, d; - MD5_u32plus saved_a, saved_b, saved_c, saved_d; - - ptr = data; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - do { - saved_a = a; - saved_b = b; - saved_c = c; - saved_d = d; - -/* Round 1 */ - STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) - STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) - STEP(F, c, d, a, b, SET(2), 0x242070db, 17) - STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) - STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) - STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) - STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) - STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) - STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) - STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) - STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) - STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) - STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) - STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) - STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) - STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) - -/* Round 2 */ - STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) - STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) - STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) - STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) - STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) - STEP(G, d, a, b, c, GET(10), 0x02441453, 9) - STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) - STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) - STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) - STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) - STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) - STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) - STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) - STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) - STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) - STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) - -/* Round 3 */ - STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) - STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) - STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) - STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) - STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) - STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) - STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) - STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) - STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) - STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) - STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) - STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) - STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) - STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) - STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) - STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) - -/* Round 4 */ - STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) - STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) - STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) - STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) - STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) - STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) - STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) - STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) - STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) - STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) - STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) - STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) - STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) - STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) - STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) - STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) - - a += saved_a; - b += saved_b; - c += saved_c; - d += saved_d; - - ptr += 64; - } while (size -= 64); - - ctx->a = a; - ctx->b = b; - ctx->c = c; - ctx->d = d; - - return ptr; -} - -void MD5_Init(MD5_CTX *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - - ctx->lo = 0; - ctx->hi = 0; -} - -void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size) -{ - MD5_u32plus saved_lo; - unsigned long used, free; - - saved_lo = ctx->lo; - if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) - ctx->hi++; - ctx->hi += size >> 29; - - used = saved_lo & 0x3f; - - if (used) { - free = 64 - used; - - if (size < free) { - memcpy(&ctx->buffer[used], data, size); - return; - } - - memcpy(&ctx->buffer[used], data, free); - data = (unsigned char *)data + free; - size -= free; - body(ctx, ctx->buffer, 64); - } - - if (size >= 64) { - data = body(ctx, data, size & ~(unsigned long)0x3f); - size &= 0x3f; - } - - memcpy(ctx->buffer, data, size); -} - -void MD5_Final(unsigned char *result, MD5_CTX *ctx) -{ - unsigned long used, free; - - used = ctx->lo & 0x3f; - - ctx->buffer[used++] = 0x80; - - free = 64 - used; - - if (free < 8) { - memset(&ctx->buffer[used], 0, free); - body(ctx, ctx->buffer, 64); - used = 0; - free = 64; - } - - memset(&ctx->buffer[used], 0, free - 8); - - ctx->lo <<= 3; - ctx->buffer[56] = ctx->lo; - ctx->buffer[57] = ctx->lo >> 8; - ctx->buffer[58] = ctx->lo >> 16; - ctx->buffer[59] = ctx->lo >> 24; - ctx->buffer[60] = ctx->hi; - ctx->buffer[61] = ctx->hi >> 8; - ctx->buffer[62] = ctx->hi >> 16; - ctx->buffer[63] = ctx->hi >> 24; - - body(ctx, ctx->buffer, 64); - - result[0] = ctx->a; - result[1] = ctx->a >> 8; - result[2] = ctx->a >> 16; - result[3] = ctx->a >> 24; - result[4] = ctx->b; - result[5] = ctx->b >> 8; - result[6] = ctx->b >> 16; - result[7] = ctx->b >> 24; - result[8] = ctx->c; - result[9] = ctx->c >> 8; - result[10] = ctx->c >> 16; - result[11] = ctx->c >> 24; - result[12] = ctx->d; - result[13] = ctx->d >> 8; - result[14] = ctx->d >> 16; - result[15] = ctx->d >> 24; - - memset(ctx, 0, sizeof(*ctx)); -} - -#endif +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#ifndef HAVE_OPENSSL + +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static void *body(MD5_CTX *ctx, void *data, unsigned long size) +{ + unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (unsigned char*) data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, free; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + free = 64 - used; + + if (size < free) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, free); + data = (unsigned char *)data + free; + size -= free; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, free; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + memset(&ctx->buffer[used], 0, free); + body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx->buffer[used], 0, free - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif diff --git a/source/vsearch_src/md5.h b/source/vsearch_src/md5.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/mergepairs.cc b/source/vsearch_src/mergepairs.cc new file mode 100755 index 000000000..edba2de20 --- /dev/null +++ b/source/vsearch_src/mergepairs.cc @@ -0,0 +1,812 @@ +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" +#include "pvalue.h" + +/* Use default PEAR scoring method and statistics */ +const int score_method = 2; +const double pvalue_level = 0.01; +const double alpha = 1.0; +const double beta = -1.0; + +/* + TODO: + - Parallelize with pthreads + - Check matching labels of forward and reverse reads (/1 and /2) +*/ + +/* static variables, needs lock */ + +static FILE * fp_fastqout = 0; +static FILE * fp_fastaout = 0; +static FILE * fp_fastqout_notmerged_fwd = 0; +static FILE * fp_fastqout_notmerged_rev = 0; +static FILE * fp_fastaout_notmerged_fwd = 0; +static FILE * fp_fastaout_notmerged_rev = 0; +static FILE * fp_eetabbedout = 0; + +static long merged = 0; +static long notmerged = 0; +static long total = 0; + +FILE * fileopenw(char * filename) +{ + FILE * fp = 0; + fp = fopen(filename, "w"); + if (!fp) + fatal("Unable to open file for writing (%s)", filename); + return fp; +} + +int get_qual(char q) +{ + int qual = q - opt_fastq_ascii; + char msg[200]; + + if (qual < opt_fastq_qmin) + { + snprintf(msg, 200, "FASTQ quality value (%d) below qmin (%ld)", + qual, opt_fastq_qmin); + fatal(msg); + } + else if (qual > opt_fastq_qmax) + { + snprintf(msg, 200, "FASTQ quality value (%d) above qmax (%ld)", + qual, opt_fastq_qmax); + fatal(msg); + } + return qual; +} + +static char merge_qual_same[128][128]; +static char merge_qual_diff[128][128]; +static double match_oes[128][128]; +static double match_score[128][128]; +static double mism_oes[128][128]; +static double mism_score[128][128]; +static double q2p[128]; +static double ambig_score; +static double ambig_oes; + +double q_to_p(double q) +{ + int x = q - opt_fastq_ascii; + if (x < 2) + return 0.75; + else + return exp10(-x/10.0); +} + +void precompute_qual() +{ + /* Precompute tables of scores etc */ + + ambig_oes = alpha * 0.25 + beta * 0.75; + + switch (score_method) + { + case 1: + ambig_score = alpha * 0.25 + beta * 0.75; + break; + case 2: + ambig_score = beta * 0.75; + break; + case 3: + ambig_score = beta; + break; + } + + for (int x = 33; x < 126; x++) + { + double px = q_to_p(x); + q2p[x] = px; + + for (int y = 33; y < 126; y++) + { + double py = q_to_p(y); + + double p, q, oes, score; + + /* Quality score equations from Edgar & Flyvbjerg (2015) */ + + /* Match */ + p = px * py / 3.0 / (1.0 - px - py + 4.0 * px * py / 3.0); + q = opt_fastq_ascii + MIN(round(-10.0*log10(p)), opt_fastq_qmaxout); + merge_qual_same[x][y] = q; + + /* Mismatch, x is highest quality */ + p = px * (1.0 - py / 3.0) / (px + py - 4.0 * px * py / 3.0); + q = opt_fastq_ascii + MIN(round(-10.0*log10(p)), opt_fastq_qmaxout); + merge_qual_diff[x][y] = q; + + /* Score weights from PEAR */ + + /* Match */ + + /* probability that they really are similar, + given that they look similar and have + error probabilites of px and py, resp. */ + + p = 1.0 - px - py + px * py * 4.0 / 3.0; + + oes = alpha * p + beta * (1.0 - p); + + switch (score_method) + { + case 1: + score = alpha * p + beta * (1.0 - p); + break; + case 2: + score = alpha * p; + break; + case 3: + score = alpha; + break; + } + + match_oes[x][y] = oes; + match_score[x][y] = score; + + /* Mismatch */ + + /* Probability that they really are different, + given that they look different and have + error probabilities of px and py, resp. */ + + p = 1.0 - px / 3.0 - py / 3.0 + px * py * 4.0 / 9.0; + + oes = (beta - alpha) * p + alpha; + + switch (score_method) + { + case 1: + score = alpha * (1.0 - p) + beta * p; + break; + case 2: + score = beta * p; + break; + case 3: + score = beta; + break; + } + + mism_oes[x][y] = oes; + mism_score[x][y] = score; + } + } +} + +void merge_sym(char * sym, char * qual, + char fwd_sym, char rev_sym, + char fwd_qual, char rev_qual) +{ + if (rev_sym == 'N') + { + * sym = fwd_sym; + * qual = fwd_qual; + } + else if (fwd_sym == 'N') + { + * sym = rev_sym; + * qual = rev_qual; + } + else if (fwd_sym == rev_sym) + { + /* agreement */ + * sym = fwd_sym; + * qual = merge_qual_same[(unsigned)fwd_qual][(unsigned)rev_qual]; + } + else + { + /* disagreement */ + if (fwd_qual > rev_qual) + { + * sym = fwd_sym; + * qual = merge_qual_diff[(unsigned)fwd_qual][(unsigned)rev_qual]; + } + else + { + * sym = rev_sym; + * qual = merge_qual_diff[(unsigned)rev_qual][(unsigned)fwd_qual]; + } + } +} + +static char * merged_sequence = 0; +static char * merged_quality = 0; +static char * merged_header = 0; + +static size_t merged_sequence_alloc = 0; +static size_t merged_header_alloc = 0; + +void keep(char * fwd_header, char * rev_header, + char * fwd_sequence, char * rev_sequence, + char * fwd_quality, char * rev_quality, + long fwd_trunc, long rev_trunc, + long offset) +{ + /* The offset is the distance between the (truncated) 3' ends of the two + sequences */ + + long rev_3prime_overhang = offset > fwd_trunc ? offset - fwd_trunc : 0; + long fwd_5prime_overhang = fwd_trunc > offset ? fwd_trunc - offset : 0; + long mergelen = fwd_trunc + rev_trunc - offset; + + if (opt_label_suffix) + { + size_t need = strlen(fwd_header) + strlen(opt_label_suffix) + 1; + if (need > merged_header_alloc) + { + merged_header_alloc = need; + merged_header = (char*)xrealloc(merged_header, merged_header_alloc); + } + } + + if ((size_t)(mergelen + 1) > merged_sequence_alloc) + { + merged_sequence_alloc = mergelen + 1; + merged_sequence = (char*)xrealloc(merged_sequence,merged_sequence_alloc); + merged_quality = (char*)xrealloc(merged_quality,merged_sequence_alloc); + } + + char * merged_sequence = (char *) xmalloc(mergelen + 1); + char * merged_quality = (char *) xmalloc(mergelen + 1); + + double ee = 0.0; + + long fwd_pos = 0; + long rev_pos = rev_trunc - 1 + fwd_5prime_overhang - rev_3prime_overhang; + + long fwd_errors = 0; + long rev_errors = 0; + + for(long i = 0; i < mergelen; i++) + { + bool has_fwd = 0; + if ((fwd_pos >= 0) && (fwd_pos < fwd_trunc)) + has_fwd = 1; + + bool has_rev = 0; + if ((rev_pos >= 0) && (rev_pos < rev_trunc)) + has_rev = 1; + + char sym; + char qual; + + if (has_fwd && has_rev) + { + char fwd_sym = fwd_sequence[fwd_pos]; + char rev_sym = chrmap_complement[(int)(rev_sequence[rev_pos])]; + char fwd_qual = fwd_quality[fwd_pos]; + char rev_qual = rev_quality[rev_pos]; + + merge_sym(& sym, + & qual, + fwd_qual < 2 ? 'N' : fwd_sym, + rev_qual < 2 ? 'N' : rev_sym, + fwd_qual, + rev_qual); + + if (sym != fwd_sym) + fwd_errors++; + if (sym != rev_sym) + rev_errors++; + } + else if (has_fwd) + { + sym = fwd_sequence[fwd_pos]; + qual = fwd_quality[fwd_pos]; + } + else + { + sym = chrmap_complement[(int)(rev_sequence[rev_pos])]; + qual = rev_quality[rev_pos]; + } + + merged_sequence[i] = sym; + merged_quality[i] = qual; + + ee += q2p[(unsigned)qual]; + + fwd_pos++; + rev_pos--; + } + + merged_sequence[mergelen] = 0; + merged_quality[mergelen] = 0; + + if (ee <= opt_fastq_maxee) + { + merged++; + + if (opt_label_suffix) + (void) sprintf(merged_header, "%s%s", fwd_header, opt_label_suffix); + + if (opt_fastqout) + { + if (opt_fastq_eeout) + fastq_print_with_ee(fp_fastqout, + opt_label_suffix ? merged_header : fwd_header, + merged_sequence, + merged_quality, + ee); + else + fastq_print(fp_fastqout, + opt_label_suffix ? merged_header : fwd_header, + merged_sequence, + merged_quality); + } + + if (opt_fastaout) + fasta_print(fp_fastaout, + opt_label_suffix ? merged_header : fwd_header, + merged_sequence, + mergelen); + + if (opt_eetabbedout) + { + double ee_fwd = 0.0; + for(int i=0; i rev_trunc ? i - rev_trunc : 0; + long rev_3prime_overhang = i > fwd_trunc ? i - fwd_trunc : 0; + long overlap = i - fwd_3prime_overhang - rev_3prime_overhang; + long diffs = 0; + long fwd_pos_start = fwd_trunc - fwd_3prime_overhang - 1; + long rev_pos_start = rev_trunc - rev_3prime_overhang - overlap; + + double score = overlap_score(fwd_sequence, rev_sequence, + fwd_quality, rev_quality, + fwd_pos_start, rev_pos_start, + overlap, + & diffs); + + if ((diffs <= opt_fastq_maxdiffs) && (score > best_score)) + { + best_score = score; + best_i = i; + } + } + + /* compute oes for best alignment */ + + if (best_score > 0.0) + { + long i = best_i; + long fwd_3prime_overhang = i > rev_trunc ? i - rev_trunc : 0; + long rev_3prime_overhang = i > fwd_trunc ? i - fwd_trunc : 0; + long overlap = i - fwd_3prime_overhang - rev_3prime_overhang; + long fwd_pos_start = fwd_trunc - fwd_3prime_overhang - 1; + long rev_pos_start = rev_trunc - rev_3prime_overhang - overlap; + + best_oes = overlap_oes(fwd_sequence, rev_sequence, + fwd_quality, rev_quality, + fwd_pos_start, rev_pos_start, + overlap); + } + + /* Statistical test as in PEAR */ + + const int basefreqpct = (int) (0.25 * 100.0); + + int overlapregion = opt_fastq_minovlen; + if (overlapregion > 99) + overlapregion = 99; + if (overlapregion < 1) + overlapregion = 1; + + double cutoff; + + if (pvalue_level == 1.0) + { + cutoff = DBL_MIN; + } + else if (pvalue_level == 0.01) + { + cutoff = precomp2_01[overlapregion][basefreqpct]; + } + else if (pvalue_level == 0.05) + { + cutoff = precomp2_05[overlapregion][basefreqpct]; + } + else if (pvalue_level == 0.001) + { + cutoff = precomp2_001[overlapregion][basefreqpct]; + } + else + { + cutoff = precomp2_0001[overlapregion][basefreqpct]; + } + + if (best_oes <= cutoff) + best_i = 0; + + return best_i; +} + +void fastq_mergepairs() +{ + /* open input files */ + + fastq_handle fastq_fwd = fastq_open(opt_fastq_mergepairs); + fastq_handle fastq_rev = fastq_open(opt_reverse); + + /* open output files */ + + if (opt_fastqout) + fp_fastqout = fileopenw(opt_fastqout); + if (opt_fastaout) + fp_fastaout = fileopenw(opt_fastaout); + if (opt_fastqout_notmerged_fwd) + fp_fastqout_notmerged_fwd = fileopenw(opt_fastqout_notmerged_fwd); + if (opt_fastqout_notmerged_rev) + fp_fastqout_notmerged_rev = fileopenw(opt_fastqout_notmerged_rev); + if (opt_fastaout_notmerged_fwd) + fp_fastaout_notmerged_fwd = fileopenw(opt_fastaout_notmerged_fwd); + if (opt_fastaout_notmerged_rev) + fp_fastaout_notmerged_rev = fileopenw(opt_fastaout_notmerged_rev); + if (opt_eetabbedout) + fp_eetabbedout = fileopenw(opt_eetabbedout); + + /* precompute merged quality values */ + + precompute_qual(); + + /* init progress */ + + unsigned long filesize = fastq_get_size(fastq_fwd); + progress_init("Merging reads", filesize); + + /* start loop */ + + while(fastq_next(fastq_fwd, 1, chrmap_upcase)) + { + if (! fastq_next(fastq_rev, 1, chrmap_upcase)) + fatal("More forward reads than reverse reads"); + + /* TODO: Check that labels match: label/1 and label/2 */ + + total++; + + long fwd_length = fastq_get_sequence_length(fastq_fwd); + long rev_length = fastq_get_sequence_length(fastq_rev); + + char * fwd_header = fastq_get_header(fastq_fwd); + char * rev_header = fastq_get_header(fastq_rev); + + char * fwd_sequence = fastq_get_sequence(fastq_fwd); + char * rev_sequence = fastq_get_sequence(fastq_rev); + + char * fwd_quality = fastq_get_quality(fastq_fwd); + char * rev_quality = fastq_get_quality(fastq_rev); + + long fwd_trunc = fwd_length; + long rev_trunc = rev_length; + + bool skip = 0; + + /* check length */ + + if ((fwd_length < opt_fastq_minlen) || + (rev_length < opt_fastq_minlen)) + skip = 1; + + /* truncate sequences by quality */ + + if (!skip) + { + for (long i = 0; i < fwd_length; i++) + if (get_qual(fwd_quality[i]) <= opt_fastq_truncqual) + { + fwd_trunc = i; + break; + } + if (fwd_trunc < opt_fastq_minlen) + skip = 1; + } + + if (!skip) + { + for (long i = 0; i < rev_length; i++) + if (get_qual(rev_quality[i]) <= opt_fastq_truncqual) + { + rev_trunc = i; + break; + } + if (rev_trunc < opt_fastq_minlen) + skip = 1; + } + + /* count n's */ + + /* replace quality of N's by zero */ + + if (!skip) + { + long fwd_ncount = 0; + for (long i = 0; i < fwd_trunc; i++) + if (fwd_sequence[i] == 'N') + { + fwd_quality[i] = opt_fastq_ascii; + fwd_ncount++; + } + if (fwd_ncount > opt_fastq_maxns) + skip = 1; + } + + if (!skip) + { + long rev_ncount = 0; + for (long i = 0; i < rev_trunc; i++) + if (rev_sequence[i] == 'N') + { + rev_quality[i] = opt_fastq_ascii; + rev_ncount++; + } + if (rev_ncount > opt_fastq_maxns) + skip = 1; + } + + long offset = 0; + + if (!skip) + { + offset = merge(fwd_sequence, rev_sequence, + fwd_quality, rev_quality, + fwd_trunc, rev_trunc); + } + + if (offset) + { + keep(fwd_header, rev_header, + fwd_sequence, rev_sequence, + fwd_quality, rev_quality, + fwd_trunc, rev_trunc, + offset); + } + else + discard(fwd_header, rev_header, + fwd_sequence, rev_sequence, + fwd_quality, rev_quality, + fwd_length, rev_length); + + progress_update(fastq_get_position(fastq_fwd)); + } + + progress_done(); + + if (fastq_next(fastq_rev, 1, chrmap_upcase)) + fatal("More reverse reads than forward reads"); + + fprintf(stderr, + "%lu read pairs total\n", + total); + + fprintf(stderr, + "%lu pairs merged (%.1lf%%) and %lu pairs not merged (%.1lf%%).\n", + merged, + 100.0 * merged / total, + notmerged, + 100.0 * notmerged / total); + + if (opt_eetabbedout) + fclose(fp_eetabbedout); + if (opt_fastaout_notmerged_rev) + fclose(fp_fastaout_notmerged_rev); + if (opt_fastaout_notmerged_fwd) + fclose(fp_fastaout_notmerged_fwd); + if (opt_fastqout_notmerged_rev) + fclose(fp_fastqout_notmerged_rev); + if (opt_fastqout_notmerged_fwd) + fclose(fp_fastqout_notmerged_fwd); + if (opt_fastaout) + fclose(fp_fastaout); + if (opt_fastqout) + fclose(fp_fastqout); + + fastq_close(fastq_rev); + fastq_rev = 0; + fastq_close(fastq_fwd); + fastq_fwd = 0; + + if (merged_sequence) + free(merged_sequence); + if (merged_quality) + free(merged_quality); + if (merged_header) + free(merged_header); +} diff --git a/source/vsearch_src/mergepairs.h b/source/vsearch_src/mergepairs.h new file mode 100755 index 000000000..ee0cf3a05 --- /dev/null +++ b/source/vsearch_src/mergepairs.h @@ -0,0 +1,61 @@ +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +void fastq_mergepairs(); diff --git a/source/vsearch_src/minheap.cc b/source/vsearch_src/minheap.cc old mode 100644 new mode 100755 index 545eca124..7885c3e9e --- a/source/vsearch_src/minheap.cc +++ b/source/vsearch_src/minheap.cc @@ -1,261 +1,267 @@ -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "vsearch.h" - -/* implement a priority queue with a min heap binary array structure */ -/* elements with the lowest count should be at the top (root) */ - -int -elem_smaller(elem_t * a, elem_t * b) -{ - /* return 1 if a is smaller than b, 0 if equal or greater */ - if (a->count < b->count) - return 1; - else if (a->count > b->count) - return 0; - else if (a->length > b->length) - return 1; - else if (a->length < b->length) - return 0; - else if (a->seqno > b->seqno) - return 1; - else - return 0; -} - -int minheap_compare(const void * a, const void * b) -{ - elem_t * x = (elem_t*) a; - elem_t * y = (elem_t*) b; - - if (elem_smaller(x, y)) - return -1; - else - return +1; -} - -minheap_t * -minheap_init(int size) -{ - minheap_t * m = (minheap_t *) xmalloc(sizeof(minheap_t)); - m->alloc = size; - m->array = (elem_t *) xmalloc(size * sizeof(elem_t)); - m->count = 0; - return m; -} - -void -minheap_exit(minheap_t * m) -{ - free(m->array); - free(m); -} - -static int swaps = 0; - -void -minheap_replaceroot(minheap_t * m, elem_t tmp) -{ - /* remove the element at the root, then swap children up - to the root and insert tmp at suitable place */ - - /* start with root */ - int p = 0; - int c = 2*p+1; - - /* while at least one child */ - while (c < m->count) - { - /* if two children: swap with the one with smallest value */ - if ((c + 1 < m->count) && (elem_smaller(m->array + c + 1, m->array + c))) - c++; - - /* swap parent and child if child has lower value */ - if (elem_smaller(m->array + c, &tmp)) - { - m->array[p] = m->array[c]; - swaps++; - } - else - break; - - /* step down */ - p = c; - c = 2*p+1; - } - - m->array[p] = tmp; -} - - -void -minheap_add(minheap_t * m, elem_t * n) -{ - if (m->count < m->alloc) - { - /* space for another item at end; swap upwards */ - - int i = m->count++; - int p = (i-1)/2; - while ((i>0) && elem_smaller(n, m->array+p)) - { - m->array[i] = m->array[p]; - i = p; - p = (i-1)/2; - swaps++; - } - m->array[i] = *n; - } - else if (elem_smaller(m->array, n)) - { - /* replace the root if new element is larger than root */ - minheap_replaceroot(m, *n); - } -} - -#if 0 -inline int -minheap_isempty(minheap_t * m) -{ - return !m->count; -} - -inline void -minheap_empty(minheap_t * m) -{ - m->count = 0; -} -#endif - -elem_t -minheap_pop(minheap_t * m) -{ - /* return top element and restore order */ - static elem_t zero = {0,0,0}; - - if (m->count) - { - elem_t top = m->array[0]; - m->count--; - if (m->count) - { - elem_t tmp = m->array[m->count]; - minheap_replaceroot(m, tmp); - } - return top; - } - else - return zero; -} - -void -minheap_sort(minheap_t * m) -{ - qsort(m->array, m->count, sizeof(elem_t), minheap_compare); -} - -void -minheap_dump(minheap_t * m) -{ - for(int i=0; i < m->count; i++) - printf("%s%u", i>0 ? " " : "", m->array[i].count); - printf("\n"); -} - -elem_t -minheap_poplast(minheap_t * m) -{ - /* return top element and restore order */ - static elem_t zero = {0,0,0}; - - if (m->count) - return m->array[--m->count]; - else - return zero; -} - - -void -minheap_test() -{ - minheap_t * m = minheap_init(10000000); - - int samples = 10000000; - swaps = 0; - - for(int i=samples; i>=0; i--) - { - elem_t x = {(unsigned int)(random()),0,1}; - minheap_add(m, & x); - } - - minheap_sort(m); - - while(! minheap_isempty(m)) - { - elem_t x = minheap_poplast(m); - printf("%u\n", x.count); - } - - printf("Swaps: %d\n\n", swaps); - - minheap_exit(m); -} +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +/* implement a priority queue with a min heap binary array structure */ +/* elements with the lowest count should be at the top (root) */ + +int +elem_smaller(elem_t * a, elem_t * b) +{ + /* return 1 if a is smaller than b, 0 if equal or greater */ + if (a->count < b->count) + return 1; + else if (a->count > b->count) + return 0; + else if (a->length > b->length) + return 1; + else if (a->length < b->length) + return 0; + else if (a->seqno > b->seqno) + return 1; + else + return 0; +} + +int minheap_compare(const void * a, const void * b) +{ + elem_t * x = (elem_t*) a; + elem_t * y = (elem_t*) b; + + if (elem_smaller(x, y)) + return -1; + else + return +1; +} + +minheap_t * +minheap_init(int size) +{ + minheap_t * m = (minheap_t *) xmalloc(sizeof(minheap_t)); + m->alloc = size; + m->array = (elem_t *) xmalloc(size * sizeof(elem_t)); + m->count = 0; + return m; +} + +void +minheap_exit(minheap_t * m) +{ + free(m->array); + free(m); +} + +static int swaps = 0; + +void +minheap_replaceroot(minheap_t * m, elem_t tmp) +{ + /* remove the element at the root, then swap children up + to the root and insert tmp at suitable place */ + + /* start with root */ + int p = 0; + int c = 2*p+1; + + /* while at least one child */ + while (c < m->count) + { + /* if two children: swap with the one with smallest value */ + if ((c + 1 < m->count) && (elem_smaller(m->array + c + 1, m->array + c))) + c++; + + /* swap parent and child if child has lower value */ + if (elem_smaller(m->array + c, &tmp)) + { + m->array[p] = m->array[c]; + swaps++; + } + else + break; + + /* step down */ + p = c; + c = 2*p+1; + } + + m->array[p] = tmp; +} + + +void +minheap_add(minheap_t * m, elem_t * n) +{ + if (m->count < m->alloc) + { + /* space for another item at end; swap upwards */ + + int i = m->count++; + int p = (i-1)/2; + while ((i>0) && elem_smaller(n, m->array+p)) + { + m->array[i] = m->array[p]; + i = p; + p = (i-1)/2; + swaps++; + } + m->array[i] = *n; + } + else if (elem_smaller(m->array, n)) + { + /* replace the root if new element is larger than root */ + minheap_replaceroot(m, *n); + } +} + +#if 0 +inline int +minheap_isempty(minheap_t * m) +{ + return !m->count; +} + +inline void +minheap_empty(minheap_t * m) +{ + m->count = 0; +} +#endif + +elem_t +minheap_pop(minheap_t * m) +{ + /* return top element and restore order */ + static elem_t zero = {0,0,0}; + + if (m->count) + { + elem_t top = m->array[0]; + m->count--; + if (m->count) + { + elem_t tmp = m->array[m->count]; + minheap_replaceroot(m, tmp); + } + return top; + } + else + return zero; +} + +void +minheap_sort(minheap_t * m) +{ + qsort(m->array, m->count, sizeof(elem_t), minheap_compare); +} + +void +minheap_dump(minheap_t * m) +{ + for(int i=0; i < m->count; i++) + printf("%s%u", i>0 ? " " : "", m->array[i].count); + printf("\n"); +} + +elem_t +minheap_poplast(minheap_t * m) +{ + /* return top element and restore order */ + static elem_t zero = {0,0,0}; + + if (m->count) + return m->array[--m->count]; + else + return zero; +} + + +void +minheap_test() +{ + minheap_t * m = minheap_init(10000000); + + int samples = 10000000; + swaps = 0; + + for(int i=samples; i>=0; i--) + { + elem_t x; x.seqno = 0; x.length = 1; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + x.count = (unsigned int) (random()); +#else + x.count = (unsigned int) (rand()); +#endif + //= {(unsigned int)(random()),0,1}; + minheap_add(m, & x); + } + + minheap_sort(m); + + while(! minheap_isempty(m)) + { + elem_t x = minheap_poplast(m); + printf("%u\n", x.count); + } + + printf("Swaps: %d\n\n", swaps); + + minheap_exit(m); +} diff --git a/source/vsearch_src/minheap.h b/source/vsearch_src/minheap.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/msa.cc b/source/vsearch_src/msa.cc old mode 100644 new mode 100755 index e9a2b3a6d..71aad6243 --- a/source/vsearch_src/msa.cc +++ b/source/vsearch_src/msa.cc @@ -143,7 +143,7 @@ void msa_add(char c) void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, int cluster, int target_count, struct msa_target_s * target_list, - long totalabundance, abundance_t * abundance_handle) + long totalabundance) { int centroid_seqno = target_list[0].seqno; int centroid_len = db_getsequencelen(centroid_seqno); @@ -289,7 +289,7 @@ void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, { fprintf(fp_msaout, ">%s%s\n", j ? "" : "*", db_getheader(target_seqno)); - fprint_fasta_seq_only(fp_msaout, aln, alnlen, opt_fasta_width); + fasta_print_sequence(fp_msaout, aln, alnlen, opt_fasta_width); } } @@ -345,10 +345,7 @@ void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, cons[conslen] = 0; if (fp_msaout) - { - fprint_fasta_hdr_only(fp_msaout, "consensus"); - fprint_fasta_seq_only(fp_msaout, aln, alnlen, opt_fasta_width); - } + fasta_print(fp_msaout, "consensus", aln, alnlen); if (fp_consout) { @@ -356,7 +353,7 @@ void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, { /* must remove old size info first */ char * header_wo_size - = abundance_strip_size(abundance_handle, + = abundance_strip_size(global_abundance, db_getheader(centroid_seqno), db_getheaderlen(centroid_seqno)); fprintf(fp_consout, @@ -377,7 +374,7 @@ void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, fprintf(fp_consout, "\n"); - fprint_fasta_seq_only(fp_consout, cons, conslen, opt_fasta_width); + fasta_print_sequence(fp_consout, cons, conslen, opt_fasta_width); } if (fp_profile) @@ -386,7 +383,7 @@ void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, if (opt_sizeout) { char * header_wo_size - = abundance_strip_size(abundance_handle, + = abundance_strip_size(global_abundance, db_getheader(centroid_seqno), db_getheaderlen(centroid_seqno)); fprintf(fp_profile, diff --git a/source/vsearch_src/msa.h b/source/vsearch_src/msa.h old mode 100644 new mode 100755 index 6249d69c2..be8377abc --- a/source/vsearch_src/msa.h +++ b/source/vsearch_src/msa.h @@ -68,4 +68,4 @@ struct msa_target_s void msa(FILE * fp_msaout, FILE * fp_consout, FILE * fp_profile, int cluster, int target_count, struct msa_target_s * target_list, - long totalabundance, abundance_t * abundance_handle); + long totalabundance); diff --git a/source/vsearch_src/pvalue.h b/source/vsearch_src/pvalue.h new file mode 100755 index 000000000..d9d59e513 --- /dev/null +++ b/source/vsearch_src/pvalue.h @@ -0,0 +1,4843 @@ +/* + Precomputed statistics for significance testing of merged sequence pairs + + These values were obtained from PEAR: + + https://github.com/xflouris/PEAR + + http://www.exelixis-lab.org/web/software/pear + + Copyright Jiajie Zhang, Kassian Kobert, Tomas Flouri & Alexandros Stamatakis + + Zhang J, Kobert K, Flouri T & Stamatakis A (2014) + PEAR: a fast and accurate Illumina Paired-End reAd mergeR + Bioinformatics, 30(5):614-20. + doi: 10.1093/bioinformatics/btt593 + + Included in vsearch with permission. +*/ + +/* + Value range from 0 to 99, precomp_05 is the table for p-value < 0.5, + precomp_05[i][j] is the proportion of match of the best + overlap, given i minimal allowed overlap, and random match q = + j/100, that will reach a p-value at least 0.05. Which means if the + user specify p = 0.05, then we observed a f, given min_0 = i and q = + j/100 if f >= precomp_05[i][j], this assembly will be kept. +*/ + +double precomp2_05[100][100] = + { + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0 + }, + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 4.0, 4.0, 4.0, 5.0, 5.0, + 6.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 3.0, 4.0, 4.0, 5.0, 5.0, + 5.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 3.0, 4.0, 4.0, 4.0, 5.0, + 5.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 3.0, 3.0, 4.0, 4.0, 5.0, + 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 3.0, 3.0, 4.0, 4.0, 5.0, + 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 3.0, 3.0, 4.0, 4.0, 5.0, + 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 2.0, 3.0, 4.0, 4.0, 5.0, + 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 2.0, 3.0, 3.0, 4.0, 4.0, + 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 2.0, 3.0, 3.0, 4.0, 4.0, + 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 2.0, 2.0, 3.0, 4.0, 4.0, + 5.0, 5.0, 6.0, 7.0, 8.0, 9.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 2.0, 2.0, 3.0, 3.0, 4.0, + 5.0, 5.0, 6.0, 7.0, 8.0, 8.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 1.0, 2.0, 3.0, 3.0, 4.0, + 5.0, 5.0, 6.0, 7.0, 8.0, 8.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 1.0, 2.0, 2.0, 3.0, 4.0, + 4.0, 5.0, 6.0, 7.0, 8.0, 8.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 1.0, 2.0, 2.0, 3.0, 4.0, + 4.0, 5.0, 6.0, 7.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 1.0, 1.0, 2.0, 3.0, 3.0, + 4.0, 5.0, 6.0, 7.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 0.0, 1.0, 2.0, 3.0, 3.0, + 4.0, 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 0.0, 1.0, 2.0, 2.0, 3.0, + 4.0, 5.0, 6.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 0.0, 1.0, 1.0, 2.0, 3.0, + 4.0, 5.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 0.0, 0.0, 1.0, 2.0, 3.0, + 4.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -1.0, 0.0, 1.0, 2.0, 3.0, + 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -1.0, 0.0, 1.0, 2.0, 2.0, + 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -1.0, 0.0, 1.0, 1.0, 2.0, + 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -2.0, -1.0, 0.0, 1.0, 2.0, + 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -2.0, -1.0, 0.0, 1.0, 2.0, + 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -2.0, -1.0, 0.0, 1.0, 2.0, + 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -2.0, -1.0, 0.0, 1.0, 1.0, + 2.0, 3.0, 4.0, 5.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -3.0, -2.0, -1.0, 0.0, 1.0, + 2.0, 3.0, 4.0, 5.0, 6.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -3.0, -2.0, -1.0, 0.0, 1.0, + 2.0, 3.0, 4.0, 5.0, 6.0, 8.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -3.0, -2.0, -1.0, 0.0, 1.0, + 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 12.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -3.0, -3.0, -1.0, 0.0, 1.0, + 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -4.0, -3.0, -2.0, -1.0, 0.0, + 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -4.0, -3.0, -2.0, -1.0, 0.0, + 1.0, 2.0, 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -4.0, -3.0, -2.0, -1.0, 0.0, + 1.0, 2.0, 3.0, 5.0, 6.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -5.0, -4.0, -3.0, -1.0, 0.0, + 1.0, 2.0, 3.0, 5.0, 6.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -5.0, -4.0, -3.0, -2.0, 0.0, + 1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -5.0, -4.0, -3.0, -2.0, -1.0, + 1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -6.0, -4.0, -3.0, -2.0, -1.0, + 0.0, 2.0, 3.0, 4.0, 5.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -6.0, -5.0, -4.0, -2.0, -1.0, + 0.0, 1.0, 3.0, 4.0, 5.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -6.0, -5.0, -4.0, -3.0, -1.0, + 0.0, 1.0, 2.0, 4.0, 5.0, 7.0, 8.0, 10.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -7.0, -5.0, -4.0, -3.0, -2.0, + 0.0, 1.0, 2.0, 4.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -7.0, -6.0, -4.0, -3.0, -2.0, + 0.0, 1.0, 2.0, 4.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -7.0, -6.0, -5.0, -3.0, -2.0, + -1.0, 1.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -8.0, -6.0, -5.0, -4.0, -2.0, + -1.0, 0.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -8.0, -7.0, -5.0, -4.0, -3.0, + -1.0, 0.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -8.0, -7.0, -6.0, -4.0, -3.0, + -1.0, 0.0, 2.0, 3.0, 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -9.0, -7.0, -6.0, -4.0, -3.0, + -2.0, 0.0, 1.0, 3.0, 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -9.0, -8.0, -6.0, -5.0, -3.0, + -2.0, 0.0, 1.0, 3.0, 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -9.0, -8.0, -6.0, -5.0, -3.0, + -2.0, -1.0, 1.0, 2.0, 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -10.0, -8.0, -7.0, -5.0, -4.0, + -2.0, -1.0, 1.0, 2.0, 4.0, 5.0, 7.0, 9.0, 11.0, 13.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -10.0, -8.0, -7.0, -5.0, -4.0, + -2.0, -1.0, 1.0, 2.0, 4.0, 5.0, 7.0, 9.0, 11.0, 12.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -10.0, -9.0, -7.0, -6.0, -4.0, + -3.0, -1.0, 0.0, 2.0, 4.0, 5.0, 7.0, 9.0, 10.0, 12.0, + 15.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -11.0, -9.0, -7.0, -6.0, -4.0, + -3.0, -1.0, 0.0, 2.0, 3.0, 5.0, 7.0, 9.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -11.0, -9.0, -8.0, -6.0, -5.0, + -3.0, -2.0, 0.0, 2.0, 3.0, 5.0, 7.0, 9.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -11.0, -10.0, -8.0, -7.0, -5.0, + -3.0, -2.0, 0.0, 2.0, 3.0, 5.0, 7.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -12.0, -10.0, -8.0, -7.0, -5.0, + -4.0, -2.0, 0.0, 1.0, 3.0, 5.0, 7.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -12.0, -10.0, -9.0, -7.0, -5.0, + -4.0, -2.0, -1.0, 1.0, 3.0, 5.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -12.0, -11.0, -9.0, -7.0, -6.0, + -4.0, -2.0, -1.0, 1.0, 3.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -13.0, -11.0, -9.0, -8.0, -6.0, + -4.0, -3.0, -1.0, 1.0, 3.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -13.0, -11.0, -10.0, -8.0, -6.0, + -4.0, -3.0, -1.0, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -13.0, -12.0, -10.0, -8.0, -6.0, + -5.0, -3.0, -1.0, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -14.0, -12.0, -10.0, -8.0, -7.0, + -5.0, -3.0, -1.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -14.0, -12.0, -11.0, -9.0, -7.0, + -5.0, -3.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 17.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -14.0, -13.0, -11.0, -9.0, -7.0, + -5.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -15.0, -13.0, -11.0, -9.0, -7.0, + -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -15.0, -13.0, -11.0, -10.0, -8.0, + -6.0, -4.0, -2.0, 0.0, 2.0, 3.0, 5.0, 7.0, 10.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -15.0, -14.0, -12.0, -10.0, -8.0, + -6.0, -4.0, -2.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -16.0, -14.0, -12.0, -10.0, -8.0, + -6.0, -4.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -16.0, -14.0, -12.0, -10.0, -9.0, + -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -16.0, -15.0, -13.0, -11.0, -9.0, + -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 12.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -17.0, -15.0, -13.0, -11.0, -9.0, + -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -17.0, -15.0, -13.0, -11.0, -9.0, + -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -18.0, -16.0, -14.0, -12.0, -10.0, + -8.0, -6.0, -4.0, -2.0, 0.0, 3.0, 5.0, 7.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 25.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -18.0, -16.0, -14.0, -12.0, -10.0, + -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 5.0, 7.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 24.0, 28.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -18.0, -16.0, -14.0, -12.0, -10.0, + -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 7.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -19.0, -17.0, -15.0, -12.0, -10.0, + -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -19.0, -17.0, -15.0, -13.0, -11.0, + -9.0, -7.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 9.0, 11.0, + 14.0, 16.0, 19.0, 22.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -19.0, -17.0, -15.0, -13.0, -11.0, + -9.0, -7.0, -5.0, -3.0, 0.0, 2.0, 4.0, 6.0, 9.0, 11.0, + 13.0, 16.0, 19.0, 22.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -20.0, -18.0, -15.0, -13.0, -11.0, + -9.0, -7.0, -5.0, -3.0, -1.0, 2.0, 4.0, 6.0, 9.0, 11.0, + 13.0, 16.0, 19.0, 22.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -20.0, -18.0, -16.0, -14.0, -12.0, + -9.0, -7.0, -5.0, -3.0, -1.0, 2.0, 4.0, 6.0, 8.0, 11.0, + 13.0, 16.0, 19.0, 22.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -21.0, -18.0, -16.0, -14.0, -12.0, + -10.0, -7.0, -5.0, -3.0, -1.0, 1.0, 4.0, 6.0, 8.0, 11.0, + 13.0, 16.0, 19.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -21.0, -19.0, -16.0, -14.0, -12.0, + -10.0, -8.0, -6.0, -3.0, -1.0, 1.0, 4.0, 6.0, 8.0, 11.0, + 13.0, 16.0, 19.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -21.0, -19.0, -17.0, -15.0, -12.0, + -10.0, -8.0, -6.0, -3.0, -1.0, 1.0, 3.0, 6.0, 8.0, 11.0, + 13.0, 16.0, 19.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -22.0, -19.0, -17.0, -15.0, -13.0, + -10.0, -8.0, -6.0, -4.0, -1.0, 1.0, 3.0, 6.0, 8.0, 11.0, + 13.0, 16.0, 19.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -22.0, -20.0, -17.0, -15.0, -13.0, + -11.0, -8.0, -6.0, -4.0, -2.0, 1.0, 3.0, 6.0, 8.0, 11.0, + 13.0, 16.0, 19.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -22.0, -20.0, -18.0, -15.0, -13.0, + -11.0, -9.0, -6.0, -4.0, -2.0, 1.0, 3.0, 5.0, 8.0, 10.0, + 13.0, 16.0, 19.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -23.0, -20.0, -18.0, -16.0, -13.0, + -11.0, -9.0, -7.0, -4.0, -2.0, 0.0, 3.0, 5.0, 8.0, 10.0, + 13.0, 16.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -23.0, -21.0, -18.0, -16.0, -14.0, + -11.0, -9.0, -7.0, -4.0, -2.0, 0.0, 3.0, 5.0, 8.0, 10.0, + 13.0, 16.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -23.0, -21.0, -19.0, -16.0, -14.0, + -12.0, -9.0, -7.0, -5.0, -2.0, 0.0, 3.0, 5.0, 8.0, 10.0, + 13.0, 16.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -24.0, -21.0, -19.0, -17.0, -14.0, + -12.0, -10.0, -7.0, -5.0, -2.0, 0.0, 2.0, 5.0, 8.0, 10.0, + 13.0, 16.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -24.0, -22.0, -19.0, -17.0, -15.0, + -12.0, -10.0, -7.0, -5.0, -3.0, 0.0, 2.0, 5.0, 7.0, 10.0, + 13.0, 16.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -24.0, -22.0, -20.0, -17.0, -15.0, + -12.0, -10.0, -8.0, -5.0, -3.0, 0.0, 2.0, 5.0, 7.0, 10.0, + 13.0, 15.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + }, + { + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, -25.0, -22.0, -20.0, -18.0, -15.0, + -13.0, -10.0, -8.0, -5.0, -3.0, 0.0, 2.0, 5.0, 7.0, 10.0, + 13.0, 15.0, 18.0, 21.0, 24.0, 27.0, 31.0, 34.0, 37.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, + 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0 + } + }; + +double precomp2_01[100][100] = + { + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0 + }, + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 6.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 5.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 5.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 5.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 5.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 5.0, 5.0, 6.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 4.0, 5.0, 5.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 4.0, 5.0, 5.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 4.0, 5.0, 5.0, 6.0, 7.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 4.0, 4.0, 5.0, 6.0, 6.0, + 7.0, 8.0, 9.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 4.0, 4.0, 5.0, 6.0, 6.0, + 7.0, 8.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 4.0, 4.0, 5.0, 6.0, 6.0, + 7.0, 8.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 3.0, 4.0, 5.0, 5.0, 6.0, + 7.0, 8.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 3.0, 4.0, 4.0, 5.0, 6.0, + 7.0, 8.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 3.0, 4.0, 4.0, 5.0, 6.0, + 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 3.0, 3.0, 4.0, 5.0, 6.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 2.0, 3.0, 4.0, 5.0, 6.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 2.0, 3.0, 4.0, 5.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 2.0, 3.0, 4.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 2.0, 3.0, 3.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 1.0, 2.0, 3.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 1.0, 2.0, 3.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 1.0, 2.0, 3.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 1.0, 2.0, 3.0, 4.0, 5.0, + 6.0, 6.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 1.0, 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 9.0, 10.0, 11.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 0.0, 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, 10.0, 11.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 0.0, 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 0.0, 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -1.0, 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -1.0, 0.0, 1.0, 2.0, 4.0, + 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -1.0, 0.0, 1.0, 2.0, 3.0, + 4.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -1.0, 0.0, 1.0, 2.0, 3.0, + 4.0, 5.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -2.0, -1.0, 1.0, 2.0, 3.0, + 4.0, 5.0, 7.0, 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -2.0, -1.0, 0.0, 2.0, 3.0, + 4.0, 5.0, 6.0, 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -2.0, -1.0, 0.0, 1.0, 3.0, + 4.0, 5.0, 6.0, 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -2.0, -1.0, 0.0, 1.0, 2.0, + 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -3.0, -1.0, 0.0, 1.0, 2.0, + 3.0, 5.0, 6.0, 7.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -3.0, -2.0, 0.0, 1.0, 2.0, + 3.0, 5.0, 6.0, 7.0, 9.0, 10.0, 12.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -3.0, -2.0, -1.0, 1.0, 2.0, + 3.0, 4.0, 6.0, 7.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -4.0, -2.0, -1.0, 0.0, 2.0, + 3.0, 4.0, 6.0, 7.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -4.0, -3.0, -1.0, 0.0, 1.0, + 3.0, 4.0, 5.0, 7.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -4.0, -3.0, -2.0, 0.0, 1.0, + 3.0, 4.0, 5.0, 7.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -5.0, -3.0, -2.0, 0.0, 1.0, + 2.0, 4.0, 5.0, 7.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -5.0, -3.0, -2.0, -1.0, 1.0, + 2.0, 4.0, 5.0, 6.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -5.0, -4.0, -2.0, -1.0, 1.0, + 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -5.0, -4.0, -3.0, -1.0, 0.0, + 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -6.0, -4.0, -3.0, -1.0, 0.0, + 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -6.0, -5.0, -3.0, -2.0, 0.0, + 1.0, 3.0, 4.0, 6.0, 8.0, 9.0, 11.0, 13.0, 15.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -6.0, -5.0, -3.0, -2.0, 0.0, + 1.0, 3.0, 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, 14.0, 17.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -7.0, -5.0, -4.0, -2.0, 0.0, + 1.0, 3.0, 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -7.0, -5.0, -4.0, -2.0, -1.0, + 1.0, 2.0, 4.0, 6.0, 7.0, 9.0, 11.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -7.0, -6.0, -4.0, -3.0, -1.0, + 1.0, 2.0, 4.0, 5.0, 7.0, 9.0, 11.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -8.0, -6.0, -4.0, -3.0, -1.0, + 0.0, 2.0, 4.0, 5.0, 7.0, 9.0, 11.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -8.0, -6.0, -5.0, -3.0, -1.0, + 0.0, 2.0, 4.0, 5.0, 7.0, 9.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -8.0, -7.0, -5.0, -3.0, -2.0, + 0.0, 2.0, 3.0, 5.0, 7.0, 9.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -9.0, -7.0, -5.0, -4.0, -2.0, + 0.0, 2.0, 3.0, 5.0, 7.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -9.0, -7.0, -5.0, -4.0, -2.0, + 0.0, 1.0, 3.0, 5.0, 7.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -9.0, -8.0, -6.0, -4.0, -2.0, + -1.0, 1.0, 3.0, 5.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -9.0, -8.0, -6.0, -4.0, -3.0, + -1.0, 1.0, 3.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -10.0, -8.0, -6.0, -5.0, -3.0, + -1.0, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 19.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -10.0, -8.0, -7.0, -5.0, -3.0, + -1.0, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -10.0, -9.0, -7.0, -5.0, -3.0, + -1.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -11.0, -9.0, -7.0, -5.0, -3.0, + -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -11.0, -9.0, -7.0, -6.0, -4.0, + -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -11.0, -10.0, -8.0, -6.0, -4.0, + -2.0, 0.0, 2.0, 4.0, 5.0, 7.0, 9.0, 12.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -12.0, -10.0, -8.0, -6.0, -4.0, + -2.0, 0.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -12.0, -10.0, -8.0, -6.0, -4.0, + -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -12.0, -10.0, -9.0, -7.0, -5.0, + -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 14.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -13.0, -11.0, -9.0, -7.0, -5.0, + -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -13.0, -11.0, -9.0, -7.0, -5.0, + -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -13.0, -11.0, -9.0, -7.0, -5.0, + -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -14.0, -12.0, -10.0, -8.0, -6.0, + -4.0, -2.0, 0.0, 2.0, 5.0, 7.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -14.0, -12.0, -10.0, -8.0, -6.0, + -4.0, -2.0, 0.0, 2.0, 4.0, 7.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -14.0, -12.0, -10.0, -8.0, -6.0, + -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -15.0, -13.0, -11.0, -9.0, -6.0, + -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 9.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -15.0, -13.0, -11.0, -9.0, -7.0, + -5.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 11.0, 13.0, 16.0, + 18.0, 21.0, 24.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -15.0, -13.0, -11.0, -9.0, -7.0, + -5.0, -3.0, -1.0, 2.0, 4.0, 6.0, 8.0, 11.0, 13.0, 15.0, + 18.0, 21.0, 24.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -16.0, -14.0, -12.0, -9.0, -7.0, + -5.0, -3.0, -1.0, 1.0, 4.0, 6.0, 8.0, 11.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -16.0, -14.0, -12.0, -10.0, -7.0, + -5.0, -3.0, -1.0, 1.0, 4.0, 6.0, 8.0, 10.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -16.0, -14.0, -12.0, -10.0, -8.0, + -6.0, -3.0, -1.0, 1.0, 3.0, 6.0, 8.0, 10.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -17.0, -15.0, -12.0, -10.0, -8.0, + -6.0, -3.0, -1.0, 1.0, 3.0, 6.0, 8.0, 10.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -17.0, -15.0, -13.0, -10.0, -8.0, + -6.0, -4.0, -1.0, 1.0, 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -18.0, -15.0, -13.0, -11.0, -9.0, + -6.0, -4.0, -2.0, 1.0, 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -18.0, -16.0, -13.0, -11.0, -9.0, + -6.0, -4.0, -2.0, 0.0, 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, + 18.0, 21.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -18.0, -16.0, -14.0, -11.0, -9.0, + -7.0, -4.0, -2.0, 0.0, 3.0, 5.0, 7.0, 10.0, 12.0, 15.0, + 18.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -19.0, -16.0, -14.0, -12.0, -9.0, + -7.0, -5.0, -2.0, 0.0, 2.0, 5.0, 7.0, 10.0, 12.0, 15.0, + 18.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -19.0, -17.0, -14.0, -12.0, -9.0, + -7.0, -5.0, -2.0, 0.0, 2.0, 5.0, 7.0, 10.0, 12.0, 15.0, + 18.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -19.0, -17.0, -15.0, -12.0, -10.0, + -7.0, -5.0, -3.0, 0.0, 2.0, 5.0, 7.0, 10.0, 12.0, 15.0, + 18.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -20.0, -17.0, -15.0, -12.0, -10.0, + -8.0, -5.0, -3.0, 0.0, 2.0, 5.0, 7.0, 10.0, 12.0, 15.0, + 18.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -20.0, -18.0, -15.0, -13.0, -10.0, + -8.0, -5.0, -3.0, -1.0, 2.0, 4.0, 7.0, 9.0, 12.0, 15.0, + 18.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + }, + { + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, -20.0, -18.0, -15.0, -13.0, -11.0, + -8.0, -6.0, -3.0, -1.0, 2.0, 4.0, 7.0, 9.0, 12.0, 15.0, + 17.0, 20.0, 23.0, 26.0, 29.0, 33.0, 36.0, 39.0, 43.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, + 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0, 46.0 + } + }; + +double precomp2_001[100][100] = + { + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0 + }, + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 10.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 8.0, 8.0, 9.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 7.0, 8.0, 9.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 7.0, 8.0, 9.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 7.0, 7.0, 8.0, 9.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 6.0, 7.0, 8.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 6.0, 7.0, 8.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 6.0, 7.0, 8.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 6.0, 7.0, 7.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 6.0, 7.0, 7.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 6.0, 6.0, 7.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 5.0, 6.0, 7.0, 8.0, 9.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 5.0, 6.0, 7.0, 8.0, 9.0, + 10.0, 11.0, 11.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 5.0, 6.0, 7.0, 8.0, 9.0, + 10.0, 10.0, 11.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 5.0, 6.0, 7.0, 8.0, 9.0, + 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 5.0, 6.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 5.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 3.0, 4.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 3.0, 4.0, 5.0, 6.0, 7.0, + 9.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 3.0, 4.0, 5.0, 6.0, 7.0, + 8.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 3.0, 4.0, 5.0, 6.0, 7.0, + 8.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 2.0, 4.0, 5.0, 6.0, 7.0, + 8.0, 9.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 2.0, 3.0, 5.0, 6.0, 7.0, + 8.0, 9.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 2.0, 3.0, 4.0, 6.0, 7.0, + 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 2.0, 3.0, 4.0, 5.0, 7.0, + 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 2.0, 3.0, 4.0, 5.0, 6.0, + 8.0, 9.0, 10.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 1.0, 3.0, 4.0, 5.0, 6.0, + 8.0, 9.0, 10.0, 12.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 1.0, 2.0, 4.0, 5.0, 6.0, + 7.0, 9.0, 10.0, 12.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 1.0, 2.0, 3.0, 5.0, 6.0, + 7.0, 9.0, 10.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 1.0, 2.0, 3.0, 4.0, 6.0, + 7.0, 9.0, 10.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 0.0, 2.0, 3.0, 4.0, 6.0, + 7.0, 8.0, 10.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 0.0, 1.0, 3.0, 4.0, 6.0, + 7.0, 8.0, 10.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 0.0, 1.0, 3.0, 4.0, 5.0, + 7.0, 8.0, 10.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 0.0, 1.0, 2.0, 4.0, 5.0, + 7.0, 8.0, 9.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -1.0, 1.0, 2.0, 4.0, 5.0, + 6.0, 8.0, 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -1.0, 0.0, 2.0, 3.0, 5.0, + 6.0, 8.0, 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -1.0, 0.0, 2.0, 3.0, 5.0, + 6.0, 8.0, 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -2.0, 0.0, 1.0, 3.0, 4.0, + 6.0, 7.0, 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -2.0, 0.0, 1.0, 3.0, 4.0, + 6.0, 7.0, 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -2.0, -1.0, 1.0, 2.0, 4.0, + 6.0, 7.0, 9.0, 10.0, 12.0, 14.0, 16.0, 17.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -2.0, -1.0, 1.0, 2.0, 4.0, + 5.0, 7.0, 9.0, 10.0, 12.0, 14.0, 16.0, 17.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -3.0, -1.0, 0.0, 2.0, 4.0, + 5.0, 7.0, 9.0, 10.0, 12.0, 14.0, 15.0, 17.0, 20.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -3.0, -1.0, 0.0, 2.0, 3.0, + 5.0, 7.0, 8.0, 10.0, 12.0, 14.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -3.0, -2.0, 0.0, 2.0, 3.0, + 5.0, 7.0, 8.0, 10.0, 12.0, 14.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -4.0, -2.0, 0.0, 1.0, 3.0, + 5.0, 6.0, 8.0, 10.0, 12.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -4.0, -2.0, 0.0, 1.0, 3.0, + 5.0, 6.0, 8.0, 10.0, 12.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -4.0, -2.0, -1.0, 1.0, 3.0, + 4.0, 6.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -4.0, -3.0, -1.0, 1.0, 2.0, + 4.0, 6.0, 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -5.0, -3.0, -1.0, 1.0, 2.0, + 4.0, 6.0, 8.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -5.0, -3.0, -1.0, 0.0, 2.0, + 4.0, 6.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -5.0, -3.0, -2.0, 0.0, 2.0, + 4.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -6.0, -4.0, -2.0, 0.0, 2.0, + 4.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -6.0, -4.0, -2.0, 0.0, 1.0, + 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -6.0, -4.0, -2.0, -1.0, 1.0, + 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -7.0, -5.0, -3.0, -1.0, 1.0, + 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -7.0, -5.0, -3.0, -1.0, 1.0, + 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -7.0, -5.0, -3.0, -1.0, 1.0, + 3.0, 5.0, 6.0, 8.0, 10.0, 13.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -7.0, -5.0, -4.0, -2.0, 0.0, + 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 15.0, 17.0, 19.0, 22.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -8.0, -6.0, -4.0, -2.0, 0.0, + 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -8.0, -6.0, -4.0, -2.0, 0.0, + 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -8.0, -6.0, -4.0, -2.0, 0.0, + 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -9.0, -7.0, -4.0, -2.0, 0.0, + 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -9.0, -7.0, -5.0, -3.0, -1.0, + 1.0, 3.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -9.0, -7.0, -5.0, -3.0, -1.0, + 1.0, 3.0, 5.0, 8.0, 10.0, 12.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -10.0, -7.0, -5.0, -3.0, -1.0, + 1.0, 3.0, 5.0, 7.0, 10.0, 12.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -10.0, -8.0, -6.0, -3.0, -1.0, + 1.0, 3.0, 5.0, 7.0, 9.0, 12.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -10.0, -8.0, -6.0, -4.0, -2.0, + 1.0, 3.0, 5.0, 7.0, 9.0, 12.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -10.0, -8.0, -6.0, -4.0, -2.0, + 0.0, 3.0, 5.0, 7.0, 9.0, 11.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -11.0, -9.0, -6.0, -4.0, -2.0, + 0.0, 2.0, 5.0, 7.0, 9.0, 11.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -11.0, -9.0, -7.0, -4.0, -2.0, + 0.0, 2.0, 4.0, 7.0, 9.0, 11.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -11.0, -9.0, -7.0, -5.0, -2.0, + 0.0, 2.0, 4.0, 7.0, 9.0, 11.0, 14.0, 16.0, 19.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -12.0, -10.0, -7.0, -5.0, -3.0, + 0.0, 2.0, 4.0, 6.0, 9.0, 11.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -12.0, -10.0, -7.0, -5.0, -3.0, + -1.0, 2.0, 4.0, 6.0, 9.0, 11.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -12.0, -10.0, -8.0, -5.0, -3.0, + -1.0, 1.0, 4.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -13.0, -10.0, -8.0, -6.0, -3.0, + -1.0, 1.0, 4.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -13.0, -11.0, -8.0, -6.0, -4.0, + -1.0, 1.0, 3.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -13.0, -11.0, -9.0, -6.0, -4.0, + -1.0, 1.0, 3.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -14.0, -11.0, -9.0, -6.0, -4.0, + -2.0, 1.0, 3.0, 6.0, 8.0, 10.0, 13.0, 16.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -14.0, -12.0, -9.0, -7.0, -4.0, + -2.0, 1.0, 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -14.0, -12.0, -9.0, -7.0, -5.0, + -2.0, 0.0, 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + }, + { + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, -15.0, -12.0, -10.0, -7.0, -5.0, + -2.0, 0.0, 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, 18.0, 21.0, + 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 46.0, 50.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, + 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0, 53.0 + } + }; + +double precomp2_0001[100][100] = + { + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0 + }, + { + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, + 99.0, 99.0, 99.0, 99.0, 99.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 10.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 11.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 10.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 9.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 8.0, 9.0, 9.0, 10.0, 11.0, + 12.0, 14.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 6.0, 7.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 6.0, 7.0, 8.0, 10.0, 11.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 6.0, 7.0, 8.0, 9.0, 11.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 6.0, 7.0, 8.0, 9.0, 10.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 6.0, 7.0, 8.0, 9.0, 10.0, + 12.0, 13.0, 14.0, 16.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 5.0, 7.0, 8.0, 9.0, 10.0, + 11.0, 13.0, 14.0, 15.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 5.0, 6.0, 8.0, 9.0, 10.0, + 11.0, 13.0, 14.0, 15.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 5.0, 6.0, 7.0, 9.0, 10.0, + 11.0, 13.0, 14.0, 15.0, 17.0, 19.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 5.0, 6.0, 7.0, 9.0, 10.0, + 11.0, 13.0, 14.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 5.0, 6.0, 7.0, 8.0, 10.0, + 11.0, 12.0, 14.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 4.0, 6.0, 7.0, 8.0, 10.0, + 11.0, 12.0, 14.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 4.0, 5.0, 7.0, 8.0, 9.0, + 11.0, 12.0, 14.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 4.0, 5.0, 7.0, 8.0, 9.0, + 11.0, 12.0, 14.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 4.0, 5.0, 6.0, 8.0, 9.0, + 11.0, 12.0, 14.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 3.0, 5.0, 6.0, 8.0, 9.0, + 10.0, 12.0, 13.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 3.0, 5.0, 6.0, 7.0, 9.0, + 10.0, 12.0, 13.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 3.0, 4.0, 6.0, 7.0, 9.0, + 10.0, 12.0, 13.0, 15.0, 17.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 3.0, 4.0, 6.0, 7.0, 9.0, + 10.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 2.0, 4.0, 5.0, 7.0, 8.0, + 10.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 2.0, 4.0, 5.0, 7.0, 8.0, + 10.0, 11.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 2.0, 3.0, 5.0, 7.0, 8.0, + 10.0, 11.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 2.0, 3.0, 5.0, 6.0, 8.0, + 10.0, 11.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 1.0, 3.0, 5.0, 6.0, 8.0, + 9.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 1.0, 3.0, 4.0, 6.0, 8.0, + 9.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 1.0, 2.0, 4.0, 6.0, 8.0, + 9.0, 11.0, 13.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 1.0, 2.0, 4.0, 6.0, 7.0, + 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 0.0, 2.0, 4.0, 5.0, 7.0, + 9.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 0.0, 2.0, 4.0, 5.0, 7.0, + 9.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 0.0, 2.0, 3.0, 5.0, 7.0, + 9.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 0.0, 1.0, 3.0, 5.0, 7.0, + 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -1.0, 1.0, 3.0, 5.0, 6.0, + 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -1.0, 1.0, 3.0, 5.0, 6.0, + 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -1.0, 1.0, 2.0, 4.0, 6.0, + 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -1.0, 0.0, 2.0, 4.0, 6.0, + 8.0, 10.0, 12.0, 13.0, 15.0, 17.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -2.0, 0.0, 2.0, 4.0, 6.0, + 8.0, 10.0, 11.0, 13.0, 15.0, 17.0, 20.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -2.0, 0.0, 2.0, 4.0, 6.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -2.0, 0.0, 2.0, 3.0, 5.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 30.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -3.0, -1.0, 1.0, 3.0, 5.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -3.0, -1.0, 1.0, 3.0, 5.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -3.0, -1.0, 1.0, 3.0, 5.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -3.0, -1.0, 1.0, 3.0, 5.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -4.0, -2.0, 0.0, 2.0, 4.0, + 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -4.0, -2.0, 0.0, 2.0, 4.0, + 6.0, 8.0, 10.0, 13.0, 15.0, 17.0, 19.0, 22.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -4.0, -2.0, 0.0, 2.0, 4.0, + 6.0, 8.0, 10.0, 12.0, 15.0, 17.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -5.0, -2.0, 0.0, 2.0, 4.0, + 6.0, 8.0, 10.0, 12.0, 15.0, 17.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -5.0, -3.0, -1.0, 2.0, 4.0, + 6.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -5.0, -3.0, -1.0, 1.0, 3.0, + 6.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -5.0, -3.0, -1.0, 1.0, 3.0, + 5.0, 8.0, 10.0, 12.0, 14.0, 17.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -6.0, -4.0, -1.0, 1.0, 3.0, + 5.0, 7.0, 10.0, 12.0, 14.0, 16.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -6.0, -4.0, -2.0, 1.0, 3.0, + 5.0, 7.0, 10.0, 12.0, 14.0, 16.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -6.0, -4.0, -2.0, 0.0, 3.0, + 5.0, 7.0, 9.0, 12.0, 14.0, 16.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -7.0, -4.0, -2.0, 0.0, 2.0, + 5.0, 7.0, 9.0, 12.0, 14.0, 16.0, 19.0, 21.0, 24.0, 27.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -7.0, -5.0, -2.0, 0.0, 2.0, + 5.0, 7.0, 9.0, 11.0, 14.0, 16.0, 19.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -7.0, -5.0, -3.0, 0.0, 2.0, + 4.0, 7.0, 9.0, 11.0, 14.0, 16.0, 19.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -8.0, -5.0, -3.0, 0.0, 2.0, + 4.0, 6.0, 9.0, 11.0, 14.0, 16.0, 18.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -8.0, -5.0, -3.0, -1.0, 2.0, + 4.0, 6.0, 9.0, 11.0, 13.0, 16.0, 18.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -8.0, -6.0, -3.0, -1.0, 1.0, + 4.0, 6.0, 9.0, 11.0, 13.0, 16.0, 18.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -8.0, -6.0, -4.0, -1.0, 1.0, + 4.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -9.0, -6.0, -4.0, -1.0, 1.0, + 3.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -9.0, -7.0, -4.0, -2.0, 1.0, + 3.0, 6.0, 8.0, 11.0, 13.0, 16.0, 18.0, 21.0, 24.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -9.0, -7.0, -4.0, -2.0, 1.0, + 3.0, 6.0, 8.0, 10.0, 13.0, 15.0, 18.0, 21.0, 23.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + }, + { + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, -10.0, -7.0, -5.0, -2.0, 0.0, + 3.0, 5.0, 8.0, 10.0, 13.0, 15.0, 18.0, 21.0, 23.0, 26.0, + 29.0, 32.0, 36.0, 39.0, 42.0, 46.0, 49.0, 53.0, 56.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, + 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0 + } + }; diff --git a/source/vsearch_src/results.cc b/source/vsearch_src/results.cc old mode 100644 new mode 100755 index 7409a0bc8..4a0a63099 --- a/source/vsearch_src/results.cc +++ b/source/vsearch_src/results.cc @@ -75,18 +75,20 @@ void results_show_fastapairs_one(FILE * fp, hp->nwalignment, hp->nwalignmentlength, 0); - fprint_fasta_hdr_only(fp, query_head); - fprint_fasta_seq_only(fp, qrow + hp->trim_q_left + hp->trim_t_left, - hp->internal_alignmentlength, 0); + fasta_print_header(fp, query_head); + fasta_print_sequence(fp, + qrow + hp->trim_q_left + hp->trim_t_left, + hp->internal_alignmentlength, 0); free(qrow); char * trow = align_getrow(db_getsequence(hp->target), hp->nwalignment, hp->nwalignmentlength, 1); - fprint_fasta_hdr_only(fp, db_getheader(hp->target)); - fprint_fasta_seq_only(fp, trow + hp->trim_q_left + hp->trim_t_left, - hp->internal_alignmentlength, 0); + fasta_print_header(fp, db_getheader(hp->target)); + fasta_print_sequence(fp, + trow + hp->trim_q_left + hp->trim_t_left, + hp->internal_alignmentlength, 0); free(trow); fprintf(fp, "\n"); diff --git a/source/vsearch_src/results.h b/source/vsearch_src/results.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/search.cc b/source/vsearch_src/search.cc old mode 100644 new mode 100755 index cb92e02c6..ec2408528 --- a/source/vsearch_src/search.cc +++ b/source/vsearch_src/search.cc @@ -1,709 +1,678 @@ -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "vsearch.h" - -static struct searchinfo_s * si_plus; -static struct searchinfo_s * si_minus; - - -/* global constants/data, no need for synchronization */ -static int tophits; /* the maximum number of hits to keep */ -static int seqcount; /* number of database sequences */ -static fasta_handle query_fasta_h; - -/* global data protected by mutex */ -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - static pthread_attr_t attr; - static pthread_t * pthread; - static pthread_mutex_t mutex_input; - static pthread_mutex_t mutex_output; -#else - todo -#endif -static int qmatches; -static int queries; -static int * dbmatched; -static FILE * fp_samout = 0; -static FILE * fp_alnout = 0; -static FILE * fp_userout = 0; -static FILE * fp_blast6out = 0; -static FILE * fp_uc = 0; -static FILE * fp_fastapairs = 0; -static FILE * fp_matched = 0; -static FILE * fp_notmatched = 0; -static FILE * fp_dbmatched = 0; -static FILE * fp_dbnotmatched = 0; - -void search_output_results(int hit_count, - struct hit * hits, - char * query_head, - int qseqlen, - char * qsequence, - char * qsequence_rc) -{ -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_lock(&mutex_output); -#else - todo -#endif - /* show results */ - long toreport = MIN(opt_maxhits, hit_count); - - if (fp_alnout) - results_show_alnout(fp_alnout, - hits, - toreport, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_samout) - results_show_samout(fp_samout, - hits, - toreport, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (toreport) - { - double top_hit_id = hits[0].id; - - for(int t = 0; t < toreport; t++) - { - struct hit * hp = hits + t; - - if (opt_top_hits_only && (hp->id < top_hit_id)) - break; - - if (fp_fastapairs) - results_show_fastapairs_one(fp_fastapairs, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_uc) - if ((t==0) || opt_uc_allhits) - results_show_uc_one(fp_uc, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_userout) - results_show_userout_one(fp_userout, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_blast6out) - results_show_blast6out_one(fp_blast6out, - hp, - query_head, - qsequence, - qseqlen, - qsequence_rc); - } - } - else if (opt_output_no_hits) - { - if (fp_uc) - results_show_uc_one(fp_uc, - 0, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_userout) - results_show_userout_one(fp_userout, - 0, - query_head, - qsequence, - qseqlen, - qsequence_rc); - - if (fp_blast6out) - results_show_blast6out_one(fp_blast6out, - 0, - query_head, - qsequence, - qseqlen, - qsequence_rc); - } - - if (hit_count) - { - if (opt_matched) - { - fprintf(fp_matched, - ">%s\n", - query_head); - fprint_fasta_seq_only(fp_matched, - qsequence, - qseqlen, - opt_fasta_width); - } - } - else - { - if (opt_notmatched) - { - fprintf(fp_notmatched, - ">%s\n", - query_head); - fprint_fasta_seq_only(fp_notmatched, - qsequence, - qseqlen, - opt_fasta_width); - } - } - - /* update matching db sequences */ - for (int i=0; i < hit_count; i++) - if (hits[i].accepted) - dbmatched[hits[i].target]++; -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_output); -#else - todo -#endif -} - -int search_query(long t) -{ - for (int s = 0; s < opt_strand; s++) - { - struct searchinfo_s * si = s ? si_minus+t : si_plus+t; - - /* mask query */ - if (opt_qmask == MASK_DUST) - { - dust(si->qsequence, si->qseqlen); - } - else if ((opt_qmask == MASK_SOFT) && (opt_hardmask)) - { - hardmask(si->qsequence, si->qseqlen); - } - - /* perform search */ - search_onequery(si); - } - - struct hit * hits; - int hit_count; - - search_joinhits(si_plus + t, - opt_strand > 1 ? si_minus + t : 0, - & hits, - & hit_count); - - search_output_results(hit_count, - hits, - si_plus[t].query_head, - si_plus[t].qseqlen, - si_plus[t].qsequence, - opt_strand > 1 ? si_minus[t].qsequence : 0); - - /* free memory for alignment strings */ - for(int i=0; iquery_head_len = query_head_len; - si->qseqlen = qseqlen; - si->query_no = query_no; - si->qsize = qsize; - si->strand = s; - - /* allocate more memory for header and sequence, if necessary */ - - if (si->query_head_len + 1 > si->query_head_alloc) - { - si->query_head_alloc = si->query_head_len + 2001; - si->query_head = (char*) - xrealloc(si->query_head, (size_t)(si->query_head_alloc)); - } - - if (si->qseqlen + 1 > si->seq_alloc) - { - si->seq_alloc = si->qseqlen + 2001; - si->qsequence = (char*) - xrealloc(si->qsequence, (size_t)(si->seq_alloc)); - } - } - - /* plus strand: copy header and sequence */ - strcpy(si_plus[t].query_head, qhead); - strcpy(si_plus[t].qsequence, qseq); - - /* get progress as amount of input file read */ - unsigned long progress = fasta_get_position(query_fasta_h); -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - /* let other threads read input */ - pthread_mutex_unlock(&mutex_input); -#else - todo -#endif - - /* minus strand: copy header and reverse complementary sequence */ - if (opt_strand > 1) - { - strcpy(si_minus[t].query_head, si_plus[t].query_head); - reverse_complement(si_minus[t].qsequence, - si_plus[t].qsequence, - si_plus[t].qseqlen); - } - - int match = search_query(t); -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - /* lock mutex for update of global data and output */ - pthread_mutex_lock(&mutex_output); -#else - todo -#endif - - /* update stats */ - queries++; - - if (match) - qmatches++; - - /* show progress */ - progress_update(progress); -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_output); -#else - todo -#endif - - } - else - { -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_unlock(&mutex_input); -#else - todo -#endif - - break; - } - } -} - -void search_thread_init(struct searchinfo_s * si) -{ - /* thread specific initialiation */ - si->uh = unique_init(); - si->kmers = (count_t *) xmalloc(seqcount * sizeof(count_t) + 32); - si->m = minheap_init(tophits); - si->hits = (struct hit *) xmalloc - (sizeof(struct hit) * (tophits) * opt_strand); - si->qsize = 1; - si->query_head_alloc = 0; - si->query_head = 0; - si->seq_alloc = 0; - si->qsequence = 0; -#ifdef COMPARENONVECTORIZED - si->nw = nw_init(); -#else - si->nw = 0; -#endif - si->s = search16_init(opt_match, - opt_mismatch, - opt_gap_open_query_left, - opt_gap_open_target_left, - opt_gap_open_query_interior, - opt_gap_open_target_interior, - opt_gap_open_query_right, - opt_gap_open_target_right, - opt_gap_extension_query_left, - opt_gap_extension_target_left, - opt_gap_extension_query_interior, - opt_gap_extension_target_interior, - opt_gap_extension_query_right, - opt_gap_extension_target_right); -} - -void search_thread_exit(struct searchinfo_s * si) -{ - /* thread specific clean up */ - search16_exit(si->s); -#ifdef COMPARENONVECTORIZED - nw_exit(si->nw); -#endif - unique_exit(si->uh); - free(si->hits); - minheap_exit(si->m); - free(si->kmers); - if (si->query_head) - free(si->query_head); - if (si->qsequence) - free(si->qsequence); -} - - - -void * search_thread_worker(void * vp) -{ - long t = (long) vp; - search_thread_run(t); - return 0; -} - -void search_thread_worker_run() -{ - /* initialize threads, start them, join them and return */ -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - /* init and create worker threads, put them into stand-by mode */ - for(int t=0; t seqcount)) - opt_maxrejects = seqcount; - - if ((opt_maxaccepts == 0) || (opt_maxaccepts > seqcount)) - opt_maxaccepts = seqcount; - - tophits = opt_maxrejects + opt_maxaccepts + MAXDELAYED; - - if (tophits > seqcount) - tophits = seqcount; -} - -void search_done() -{ - /* clean up, global */ - dbindex_free(); - db_free(); - if (opt_matched) - fclose(fp_matched); - if (opt_notmatched) - fclose(fp_notmatched); - if (opt_fastapairs) - fclose(fp_fastapairs); - if (fp_uc) - fclose(fp_uc); - if (fp_blast6out) - fclose(fp_blast6out); - if (fp_userout) - fclose(fp_userout); - if (fp_alnout) - fclose(fp_alnout); - if (fp_samout) - fclose(fp_samout); - show_rusage(); -} - -void usearch_global(char * cmdline, char * progheader) -{ - search_prep(cmdline, progheader); - - if (opt_dbmatched) - { - fp_dbmatched = fopen(opt_dbmatched, "w"); - if (! fp_dbmatched) - fatal("Unable to open dbmatched output file for writing"); - } - - if (opt_dbnotmatched) - { - fp_dbnotmatched = fopen(opt_dbnotmatched, "w"); - if (! fp_dbnotmatched) - fatal("Unable to open dbnotmatched output file for writing"); - } - - dbmatched = (int*) xmalloc(seqcount * sizeof(int*)); - memset(dbmatched, 0, seqcount * sizeof(int*)); - - /* prepare reading of queries */ - qmatches = 0; - queries = 0; - query_fasta_h = fasta_open(opt_usearch_global); - - /* allocate memory for thread info */ - si_plus = (struct searchinfo_s *) xmalloc(opt_threads * - sizeof(struct searchinfo_s)); - if (opt_strand > 1) - si_minus = (struct searchinfo_s *) xmalloc(opt_threads * - sizeof(struct searchinfo_s)); - else - si_minus = 0; -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread = (pthread_t *) xmalloc(opt_threads * sizeof(pthread_t)); - - /* init mutexes for input and output */ - pthread_mutex_init(&mutex_input, NULL); - pthread_mutex_init(&mutex_output, NULL); -#else - todo -#endif - progress_init("Searching", fasta_get_size(query_fasta_h)); - search_thread_worker_run(); - progress_done(); -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - pthread_mutex_destroy(&mutex_output); - pthread_mutex_destroy(&mutex_input); - - free(pthread); -#else - todo -#endif - free(si_plus); - if (si_minus) - free(si_minus); - - fasta_close(query_fasta_h); - - if (!opt_quiet) - fprintf(stderr, "Matching query sequences: %d of %d (%.2f%%)\n", - qmatches, queries, 100.0 * qmatches / queries); - - if (opt_log) - fprintf(fp_log, "Matching query sequences: %d of %d (%.2f%%)\n", - qmatches, queries, 100.0 * qmatches / queries); - - if (opt_dbmatched || opt_dbnotmatched) - { - for(long i=0; i, + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +static struct searchinfo_s * si_plus; +static struct searchinfo_s * si_minus; + + +/* global constants/data, no need for synchronization */ +static int tophits; /* the maximum number of hits to keep */ +static int seqcount; /* number of database sequences */ +static fasta_handle query_fasta_h; + +/* global data protected by mutex */ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) +static pthread_mutex_t mutex_input; +static pthread_mutex_t mutex_output; +static pthread_t * pthread; +static pthread_attr_t attr; +#endif + +static int qmatches; +static int queries; +static int * dbmatched; +static FILE * fp_samout = 0; +static FILE * fp_alnout = 0; +static FILE * fp_userout = 0; +static FILE * fp_blast6out = 0; +static FILE * fp_uc = 0; +static FILE * fp_fastapairs = 0; +static FILE * fp_matched = 0; +static FILE * fp_notmatched = 0; +static FILE * fp_dbmatched = 0; +static FILE * fp_dbnotmatched = 0; + +void search_output_results(int hit_count, + struct hit * hits, + char * query_head, + int qseqlen, + char * qsequence, + char * qsequence_rc) +{ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_lock(&mutex_output); +#endif + /* show results */ + long toreport = MIN(opt_maxhits, hit_count); + + if (fp_alnout) + results_show_alnout(fp_alnout, + hits, + toreport, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_samout) + results_show_samout(fp_samout, + hits, + toreport, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (toreport) + { + double top_hit_id = hits[0].id; + + for(int t = 0; t < toreport; t++) + { + struct hit * hp = hits + t; + + if (opt_top_hits_only && (hp->id < top_hit_id)) + break; + + if (fp_fastapairs) + results_show_fastapairs_one(fp_fastapairs, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_uc) + if ((t==0) || opt_uc_allhits) + results_show_uc_one(fp_uc, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_userout) + results_show_userout_one(fp_userout, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_blast6out) + results_show_blast6out_one(fp_blast6out, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + } + } + else if (opt_output_no_hits) + { + if (fp_uc) + results_show_uc_one(fp_uc, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_userout) + results_show_userout_one(fp_userout, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_blast6out) + results_show_blast6out_one(fp_blast6out, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + } + + if (hit_count) + { + if (opt_matched) + fasta_print(fp_matched, + query_head, + qsequence, + qseqlen); + } + else + { + if (opt_notmatched) + fasta_print(fp_notmatched, + query_head, + qsequence, + qseqlen); + } + + /* update matching db sequences */ + for (int i=0; i < hit_count; i++) + if (hits[i].accepted) + dbmatched[hits[i].target]++; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_output); +#endif +} + +int search_query(long t) +{ + for (int s = 0; s < opt_strand; s++) + { + struct searchinfo_s * si = s ? si_minus+t : si_plus+t; + + /* mask query */ + if (opt_qmask == MASK_DUST) + { + dust(si->qsequence, si->qseqlen); + } + else if ((opt_qmask == MASK_SOFT) && (opt_hardmask)) + { + hardmask(si->qsequence, si->qseqlen); + } + + /* perform search */ + search_onequery(si, opt_qmask); + } + + struct hit * hits; + int hit_count; + + search_joinhits(si_plus + t, + opt_strand > 1 ? si_minus + t : 0, + & hits, + & hit_count); + + search_output_results(hit_count, + hits, + si_plus[t].query_head, + si_plus[t].qseqlen, + si_plus[t].qsequence, + opt_strand > 1 ? si_minus[t].qsequence : 0); + + /* free memory for alignment strings */ + for(int i=0; iquery_head_len = query_head_len; + si->qseqlen = qseqlen; + si->query_no = query_no; + si->qsize = qsize; + si->strand = s; + + /* allocate more memory for header and sequence, if necessary */ + + if (si->query_head_len + 1 > si->query_head_alloc) + { + si->query_head_alloc = si->query_head_len + 2001; + si->query_head = (char*) + xrealloc(si->query_head, (size_t)(si->query_head_alloc)); + } + + if (si->qseqlen + 1 > si->seq_alloc) + { + si->seq_alloc = si->qseqlen + 2001; + si->qsequence = (char*) + xrealloc(si->qsequence, (size_t)(si->seq_alloc)); + } + } + + /* plus strand: copy header and sequence */ + strcpy(si_plus[t].query_head, qhead); + strcpy(si_plus[t].qsequence, qseq); + + /* get progress as amount of input file read */ + unsigned long progress = fasta_get_position(query_fasta_h); + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + /* let other threads read input */ + pthread_mutex_unlock(&mutex_input); +#endif + /* minus strand: copy header and reverse complementary sequence */ + if (opt_strand > 1) + { + strcpy(si_minus[t].query_head, si_plus[t].query_head); + reverse_complement(si_minus[t].qsequence, + si_plus[t].qsequence, + si_plus[t].qseqlen); + } + + int match = search_query(t); + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + /* lock mutex for update of global data and output */ + pthread_mutex_lock(&mutex_output); +#endif + /* update stats */ + queries++; + + if (match) + qmatches++; + + /* show progress */ + progress_update(progress); +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_output); +#endif + } + else + { +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_unlock(&mutex_input); +#endif + break; + } + } +} + +void search_thread_init(struct searchinfo_s * si) +{ + /* thread specific initialiation */ + si->uh = unique_init(); + si->kmers = (count_t *) xmalloc(seqcount * sizeof(count_t) + 32); + si->m = minheap_init(tophits); + si->hits = (struct hit *) xmalloc + (sizeof(struct hit) * (tophits) * opt_strand); + si->qsize = 1; + si->query_head_alloc = 0; + si->query_head = 0; + si->seq_alloc = 0; + si->qsequence = 0; +#ifdef COMPARENONVECTORIZED + si->nw = nw_init(); +#else + si->nw = 0; +#endif + si->s = search16_init(opt_match, + opt_mismatch, + opt_gap_open_query_left, + opt_gap_open_target_left, + opt_gap_open_query_interior, + opt_gap_open_target_interior, + opt_gap_open_query_right, + opt_gap_open_target_right, + opt_gap_extension_query_left, + opt_gap_extension_target_left, + opt_gap_extension_query_interior, + opt_gap_extension_target_interior, + opt_gap_extension_query_right, + opt_gap_extension_target_right); +} + +void search_thread_exit(struct searchinfo_s * si) +{ + /* thread specific clean up */ + search16_exit(si->s); +#ifdef COMPARENONVECTORIZED + nw_exit(si->nw); +#endif + unique_exit(si->uh); + free(si->hits); + minheap_exit(si->m); + free(si->kmers); + if (si->query_head) + free(si->query_head); + if (si->qsequence) + free(si->qsequence); +} + + + +void * search_thread_worker(void * vp) +{ + long t = (intptr_t) vp; + search_thread_run(t); + return 0; +} + +void search_thread_worker_run() +{ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + /* initialize threads, start them, join them and return */ + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + /* init and create worker threads, put them into stand-by mode */ + for(int t=0; t seqcount)) + opt_maxrejects = seqcount; + + if ((opt_maxaccepts == 0) || (opt_maxaccepts > seqcount)) + opt_maxaccepts = seqcount; + + tophits = opt_maxrejects + opt_maxaccepts + MAXDELAYED; + + if (tophits > seqcount) + tophits = seqcount; +} + +void search_done() +{ + /* clean up, global */ + dbindex_free(); + db_free(); + if (opt_matched) + fclose(fp_matched); + if (opt_notmatched) + fclose(fp_notmatched); + if (opt_fastapairs) + fclose(fp_fastapairs); + if (fp_uc) + fclose(fp_uc); + if (fp_blast6out) + fclose(fp_blast6out); + if (fp_userout) + fclose(fp_userout); + if (fp_alnout) + fclose(fp_alnout); + if (fp_samout) + fclose(fp_samout); + show_rusage(); +} + +void usearch_global(char * cmdline, char * progheader) +{ + search_prep(cmdline, progheader); + + if (opt_dbmatched) + { + fp_dbmatched = fopen(opt_dbmatched, "w"); + if (! fp_dbmatched) + fatal("Unable to open dbmatched output file for writing"); + } + + if (opt_dbnotmatched) + { + fp_dbnotmatched = fopen(opt_dbnotmatched, "w"); + if (! fp_dbnotmatched) + fatal("Unable to open dbnotmatched output file for writing"); + } + + dbmatched = (int*) xmalloc(seqcount * sizeof(int*)); + memset(dbmatched, 0, seqcount * sizeof(int*)); + + /* prepare reading of queries */ + qmatches = 0; + queries = 0; + query_fasta_h = fasta_open(opt_usearch_global); + + /* allocate memory for thread info */ + si_plus = (struct searchinfo_s *) xmalloc(opt_threads * + sizeof(struct searchinfo_s)); + if (opt_strand > 1) + si_minus = (struct searchinfo_s *) xmalloc(opt_threads * + sizeof(struct searchinfo_s)); + else + si_minus = 0; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread = (pthread_t *) xmalloc(opt_threads * sizeof(pthread_t)); + + /* init mutexes for input and output */ + pthread_mutex_init(&mutex_input, NULL); + pthread_mutex_init(&mutex_output, NULL); +#endif + + progress_init("Searching", fasta_get_size(query_fasta_h)); + search_thread_worker_run(); + progress_done(); + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + pthread_mutex_destroy(&mutex_output); + pthread_mutex_destroy(&mutex_input); + free(pthread); +#endif + + free(si_plus); + if (si_minus) + free(si_minus); + + fasta_close(query_fasta_h); + + if (!opt_quiet) + fprintf(stderr, "Matching query sequences: %d of %d (%.2f%%)\n", + qmatches, queries, 100.0 * qmatches / queries); + + if (opt_log) + fprintf(fp_log, "Matching query sequences: %d of %d (%.2f%%)\n", + qmatches, queries, 100.0 * qmatches / queries); + + if (opt_dbmatched || opt_dbnotmatched) + { + for(long i=0; i= opt_minwordmatches) || (count >= si->kmersamplecount); +} + inline void topscore_insert(int i, struct searchinfo_s * si) { count_t count = si->kmers[i]; /* ignore sequences with very few kmer matches */ - if (count < MINMATCHSAMPLECOUNT) - return; - - if (count < si->kmersamplecount / MINMATCHSAMPLEFREQ) + if (!search_enough_kmers(si, count)) return; unsigned int seqno = dbindex_getmapping(i); @@ -209,12 +212,16 @@ void search_topscores(struct searchinfo_s * si) if (bitmap) { - if (ssse3_present) - increment_counters_from_bitmap_ssse3(si->kmers, - bitmap, indexed_count); - else - increment_counters_from_bitmap_sse2(si->kmers, - bitmap, indexed_count); + if (ssse3_present) { + #ifdef __SSE2__ +#else + increment_counters_from_bitmap_ssse3(si->kmers, bitmap, indexed_count); +#endif + }else{ + #ifdef __SSE2__ + increment_counters_from_bitmap_sse2(si->kmers, bitmap, indexed_count); + #endif + } } else { @@ -592,7 +599,7 @@ void align_delayed(struct searchinfo_s * si) si->finalized = si->hit_count; } -void search_onequery(struct searchinfo_s * si) +void search_onequery(struct searchinfo_s * si, int seqmask) { si->hit_count = 0; @@ -619,7 +626,7 @@ void search_onequery(struct searchinfo_s * si) /* extract unique kmer samples from query*/ unique_count(si->uh, opt_wordlength, si->qseqlen, si->qsequence, - & si->kmersamplecount, & si->kmersample); + & si->kmersamplecount, & si->kmersample, seqmask); /* find database sequences with the most kmer hits */ search_topscores(si); diff --git a/source/vsearch_src/searchcore.h b/source/vsearch_src/searchcore.h old mode 100644 new mode 100755 index 9bb407f6e..a8e086374 --- a/source/vsearch_src/searchcore.h +++ b/source/vsearch_src/searchcore.h @@ -63,11 +63,9 @@ /* the number of alignments that can be delayed */ #define MAXDELAYED 8 -/* minimum number of kmer matches */ -#define MINMATCHSAMPLECOUNT 6 - -/* minimum kmer match frequency */ -#define MINMATCHSAMPLEFREQ 16 +/* Default minimum number of word matches for word lengths 7-15 */ +const int minwordmatches_defaults[] = + { -1, -1, -1, -1, -1, -1, -1, 14, 12, 11, 10, 9, 8, 7, 5, 3 }; struct hit { @@ -144,7 +142,7 @@ struct searchinfo_s int finalized; }; -void search_onequery(struct searchinfo_s * si); +void search_onequery(struct searchinfo_s * si, int seqmask); struct hit * search_findbest2_byid(struct searchinfo_s * si_p, struct searchinfo_s * si_m); @@ -163,3 +161,6 @@ void search_joinhits(struct searchinfo_s * si_p, struct searchinfo_s * si_m, struct hit * * hits, int * hit_count); + +bool search_enough_kmers(struct searchinfo_s * si, + unsigned int count); diff --git a/source/vsearch_src/searchexact.cc b/source/vsearch_src/searchexact.cc new file mode 100755 index 000000000..3ade09d6f --- /dev/null +++ b/source/vsearch_src/searchexact.cc @@ -0,0 +1,717 @@ +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +static struct searchinfo_s * si_plus; +static struct searchinfo_s * si_minus; + + +/* global constants/data, no need for synchronization */ +static int tophits; /* the maximum number of hits to keep */ +static int seqcount; /* number of database sequences */ +static fasta_handle query_fasta_h; + +/* global data protected by mutex */ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) +static pthread_mutex_t mutex_input; +static pthread_mutex_t mutex_output; +static pthread_t * pthread; +static pthread_attr_t attr; +#endif + +static int qmatches; +static int queries; +static int * dbmatched; +static FILE * fp_samout = 0; +static FILE * fp_alnout = 0; +static FILE * fp_userout = 0; +static FILE * fp_blast6out = 0; +static FILE * fp_uc = 0; +static FILE * fp_fastapairs = 0; +static FILE * fp_matched = 0; +static FILE * fp_notmatched = 0; +static FILE * fp_dbmatched = 0; +static FILE * fp_dbnotmatched = 0; + +void add_hit(struct searchinfo_s * si, unsigned long seqno) +{ + if (search_acceptable_unaligned(si, seqno)) + { + struct hit * hp = si->hits + si->hit_count; + si->hit_count++; + + hp->target = seqno; + hp->strand = si->strand; + + hp->count = 0; + + hp->nwscore = si->qseqlen * opt_match; + hp->nwdiff = 0; + hp->nwgaps = 0; + hp->nwindels = 0; + hp->nwalignmentlength = si->qseqlen; + hp->nwid = 100.0; + hp->matches = si->qseqlen; + hp->mismatches = 0; + + int ret = sprintf(hp->nwalignment, "%dM", si->qseqlen); + if ((ret == -1) || (!hp->nwalignment)) + fatal("Out of memory"); + + hp->internal_alignmentlength = si->qseqlen; + hp->internal_gaps = 0; + hp->internal_indels = 0; + hp->trim_q_left = 0; + hp->trim_q_right = 0; + hp->trim_t_left = 0; + hp->trim_t_right = 0; + hp->trim_aln_left = 0; + hp->trim_aln_right = 0; + + hp->id = 100.0; + hp->id0 = 100.0; + hp->id1 = 100.0; + hp->id2 = 100.0; + hp->id3 = 100.0; + hp->id4 = 100.0; + + hp->shortest = si->qseqlen; + hp->longest = si->qseqlen; + + hp->aligned = 1; + + hp->accepted = 0; + hp->rejected = 0; + hp->weak = 0; + (void) search_acceptable_aligned(si, hp); + } +} + +void search_exact_onequery(struct searchinfo_s * si) +{ + dbhash_search_info_s info; + + char * seq = si->qsequence; + unsigned long seqlen = si->qseqlen; + char * normalized = (char*) xmalloc(seqlen+1); + string_normalize(normalized, seq, seqlen); + + si->hit_count = 0; + + long ret = dbhash_search_first(normalized, seqlen, & info); + while (ret >= 0) + { + add_hit(si, ret); + ret = dbhash_search_next(&info); + } + free(normalized); +} + +void search_exact_output_results(int hit_count, + struct hit * hits, + char * query_head, + int qseqlen, + char * qsequence, + char * qsequence_rc) +{ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_mutex_lock(&mutex_output); +#endif + /* show results */ + long toreport = MIN(opt_maxhits, hit_count); + + if (fp_alnout) + results_show_alnout(fp_alnout, + hits, + toreport, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_samout) + results_show_samout(fp_samout, + hits, + toreport, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (toreport) + { + double top_hit_id = hits[0].id; + + for(int t = 0; t < toreport; t++) + { + struct hit * hp = hits + t; + + if (opt_top_hits_only && (hp->id < top_hit_id)) + break; + + if (fp_fastapairs) + results_show_fastapairs_one(fp_fastapairs, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_uc) + if ((t==0) || opt_uc_allhits) + results_show_uc_one(fp_uc, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_userout) + results_show_userout_one(fp_userout, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_blast6out) + results_show_blast6out_one(fp_blast6out, + hp, + query_head, + qsequence, + qseqlen, + qsequence_rc); + } + } + else if (opt_output_no_hits) + { + if (fp_uc) + results_show_uc_one(fp_uc, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_userout) + results_show_userout_one(fp_userout, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + + if (fp_blast6out) + results_show_blast6out_one(fp_blast6out, + 0, + query_head, + qsequence, + qseqlen, + qsequence_rc); + } + + if (hit_count) + { + if (opt_matched) + fasta_print(fp_matched, + query_head, + qsequence, + qseqlen); + } + else + { + if (opt_notmatched) + fasta_print(fp_notmatched, + query_head, + qsequence, + qseqlen); + } + + /* update matching db sequences */ + for (int i=0; i < hit_count; i++) + if (hits[i].accepted) + dbmatched[hits[i].target]++; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_mutex_unlock(&mutex_output); +#endif +} + +int search_exact_query(long t) +{ + for (int s = 0; s < opt_strand; s++) + { + struct searchinfo_s * si = s ? si_minus+t : si_plus+t; + + /* mask query */ + if (opt_qmask == MASK_DUST) + { + dust(si->qsequence, si->qseqlen); + } + else if ((opt_qmask == MASK_SOFT) && (opt_hardmask)) + { + hardmask(si->qsequence, si->qseqlen); + } + + /* perform search */ + search_exact_onequery(si); + } + + struct hit * hits; + int hit_count; + + search_joinhits(si_plus + t, + opt_strand > 1 ? si_minus + t : 0, + & hits, + & hit_count); + + search_exact_output_results(hit_count, + hits, + si_plus[t].query_head, + si_plus[t].qseqlen, + si_plus[t].qsequence, + opt_strand > 1 ? si_minus[t].qsequence : 0); + + /* free memory for alignment strings */ + for(int i=0; iquery_head_len = query_head_len; + si->qseqlen = qseqlen; + si->query_no = query_no; + si->qsize = qsize; + si->strand = s; + + /* allocate more memory for header and sequence, if necessary */ + + if (si->query_head_len + 1 > si->query_head_alloc) + { + si->query_head_alloc = si->query_head_len + 2001; + si->query_head = (char*) + xrealloc(si->query_head, (size_t)(si->query_head_alloc)); + } + + if (si->qseqlen + 1 > si->seq_alloc) + { + si->seq_alloc = si->qseqlen + 2001; + si->qsequence = (char*) + xrealloc(si->qsequence, (size_t)(si->seq_alloc)); + } + } + + /* plus strand: copy header and sequence */ + strcpy(si_plus[t].query_head, qhead); + strcpy(si_plus[t].qsequence, qseq); + + /* get progress as amount of input file read */ + unsigned long progress = fasta_get_position(query_fasta_h); +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + /* let other threads read input */ + pthread_mutex_unlock(&mutex_input); +#endif + /* minus strand: copy header and reverse complementary sequence */ + if (opt_strand > 1) + { + strcpy(si_minus[t].query_head, si_plus[t].query_head); + reverse_complement(si_minus[t].qsequence, + si_plus[t].qsequence, + si_plus[t].qseqlen); + } + + int match = search_exact_query(t); +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + /* lock mutex for update of global data and output */ + pthread_mutex_lock(&mutex_output); +#endif + /* update stats */ + queries++; + + if (match) + qmatches++; + + /* show progress */ + progress_update(progress); +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_mutex_unlock(&mutex_output); +#endif + } + else + { +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_mutex_unlock(&mutex_input); +#endif + break; + } + } +} + +void search_exact_thread_init(struct searchinfo_s * si) +{ + /* thread specific initialiation */ + si->uh = 0; + si->kmers = 0; + si->m = 0; + si->hits = (struct hit *) xmalloc + (sizeof(struct hit) * (tophits) * opt_strand); + si->qsize = 1; + si->query_head_alloc = 0; + si->query_head = 0; + si->seq_alloc = 0; + si->qsequence = 0; + si->nw = 0; + si->s = 0; +} + +void search_exact_thread_exit(struct searchinfo_s * si) +{ + /* thread specific clean up */ + free(si->hits); + if (si->query_head) + free(si->query_head); + if (si->qsequence) + free(si->qsequence); +} + +void * search_exact_thread_worker(void * vp) +{ + long t = (intptr_t) vp; + search_exact_thread_run(t); + return 0; +} + +void search_exact_thread_worker_run() +{ +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + /* initialize threads, start them, join them and return */ + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + /* init and create worker threads, put them into stand-by mode */ + for(int t=0; t 1) + si_minus = (struct searchinfo_s *) xmalloc(opt_threads * + sizeof(struct searchinfo_s)); + else + si_minus = 0; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread = (pthread_t *) xmalloc(opt_threads * sizeof(pthread_t)); + + /* init mutexes for input and output */ + pthread_mutex_init(&mutex_input, NULL); + pthread_mutex_init(&mutex_output, NULL); +#endif + progress_init("Searching", fasta_get_size(query_fasta_h)); + search_exact_thread_worker_run(); + progress_done(); +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + pthread_mutex_destroy(&mutex_output); + pthread_mutex_destroy(&mutex_input); + + free(pthread); +#endif + + free(si_plus); + if (si_minus) + free(si_minus); + + fasta_close(query_fasta_h); + + if (!opt_quiet) + fprintf(stderr, "Matching query sequences: %d of %d (%.2f%%)\n", + qmatches, queries, 100.0 * qmatches / queries); + + if (opt_log) + fprintf(fp_log, "Matching query sequences: %d of %d (%.2f%%)\n", + qmatches, queries, 100.0 * qmatches / queries); + + if (opt_dbmatched || opt_dbnotmatched) + { + for(long i=0; i, + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +void search_exact(char * cmdline, char * progheader); diff --git a/source/vsearch_src/sha1.c b/source/vsearch_src/sha1.c old mode 100644 new mode 100755 diff --git a/source/vsearch_src/sha1.h b/source/vsearch_src/sha1.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/showalign.cc b/source/vsearch_src/showalign.cc old mode 100644 new mode 100755 index f2b5c231d..2e9779234 --- a/source/vsearch_src/showalign.cc +++ b/source/vsearch_src/showalign.cc @@ -2,7 +2,7 @@ VSEARCH: a versatile open source tool for metagenomics - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + Copyright (C) 2014-2016, Torbjorn Rognes, Frederic Mahe and Tomas Flouri All rights reserved. Contact: Torbjorn Rognes , @@ -267,6 +267,7 @@ char * align_getrow(char * seq, char * cigar, int alen, int origin) { strncpy(r, s, len); r += len; + s += len; } else { diff --git a/source/vsearch_src/showalign.h b/source/vsearch_src/showalign.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/shuffle.cc b/source/vsearch_src/shuffle.cc old mode 100644 new mode 100755 index 505f62d0a..37ade2ce4 --- a/source/vsearch_src/shuffle.cc +++ b/source/vsearch_src/shuffle.cc @@ -100,7 +100,7 @@ void shuffle() progress_init("Writing output", passed); for(int i=0; i"); - - if (opt_relabel_sha1) - fprint_seq_digest_sha1(fp_output, seq, len); - else - fprint_seq_digest_md5(fp_output, seq, len); - - if (opt_sizeout) - fprintf(fp_output, ";size=%u;\n", size); - else - fprintf(fp_output, "\n"); - - db_fprint_fasta_seq_only(fp_output, seqno); - } - else if (opt_relabel) - { - if (opt_sizeout) - fprintf(fp_output, ">%s%d;size=%u;\n", opt_relabel, i+1, size); - else - fprintf(fp_output, ">%s%d\n", opt_relabel, i+1); - - db_fprint_fasta_seq_only(fp_output, seqno); - } - else - { - db_fprint_fasta(fp_output, seqno); - } - + fasta_print_db_relabel(fp_output, sortinfo[i].seqno, i+1); progress_update(i); } progress_done(); diff --git a/source/vsearch_src/sortbylength.h b/source/vsearch_src/sortbylength.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/sortbysize.cc b/source/vsearch_src/sortbysize.cc old mode 100644 new mode 100755 index 35579984d..279db2d43 --- a/source/vsearch_src/sortbysize.cc +++ b/source/vsearch_src/sortbysize.cc @@ -156,42 +156,7 @@ void sortbysize() progress_init("Writing output", passed); for(int i=0; i"); - - if (opt_relabel_sha1) - fprint_seq_digest_sha1(fp_output, seq, len); - else - fprint_seq_digest_md5(fp_output, seq, len); - - if (opt_sizeout) - fprintf(fp_output, ";size=%u;\n", size); - else - fprintf(fp_output, "\n"); - - db_fprint_fasta_seq_only(fp_output, seqno); - } - else if (opt_relabel) - { - if (opt_sizeout) - fprintf(fp_output, ">%s%d;size=%u;\n", opt_relabel, i+1, size); - else - fprintf(fp_output, ">%s%d\n", opt_relabel, i+1); - - db_fprint_fasta_seq_only(fp_output, seqno); - } - else - { - db_fprint_fasta(fp_output, seqno); - } - + fasta_print_db_relabel(fp_output, sortinfo[i].seqno, i+1); progress_update(i); } progress_done(); diff --git a/source/vsearch_src/sortbysize.h b/source/vsearch_src/sortbysize.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/subsample.cc b/source/vsearch_src/subsample.cc old mode 100644 new mode 100755 index 61423ecac..cb15f781c --- a/source/vsearch_src/subsample.cc +++ b/source/vsearch_src/subsample.cc @@ -62,13 +62,29 @@ void subsample() { - FILE * fp_output = fopen(opt_fastaout, "w"); - if (!fp_output) - fatal("Unable to open subsampling output file for writing"); + FILE * fp_fastaout = 0; + FILE * fp_fastqout = 0; + + if (opt_fastaout) + { + fp_fastaout = fopen(opt_fastaout, "w"); + if (!fp_fastaout) + fatal("Unable to open fasta output file for writing"); + } + + if (opt_fastqout) + { + fp_fastqout = fopen(opt_fastqout, "w"); + if (!fp_fastqout) + fatal("Unable to open fastq output file for writing"); + } db_read(opt_fastx_subsample, 0); show_rusage(); + if (fp_fastqout && ! db_is_fastq()) + fatal("Cannot write FASTQ output with a FASTA input file, lacking quality scores"); + int dbsequencecount = db_getsequencecount(); unsigned long mass_total = 0; @@ -132,20 +148,32 @@ void subsample() } progress_done(); - int sampled = 0; + int samples = 0; progress_init("Writing output", dbsequencecount); for(int i=0; i0) { - if (opt_sizeout) - db_fprint_fasta_with_size(fp_output, i, abundance[i]); - else if (opt_xsize) - db_fprint_fasta_strip_size(fp_output, i); - else - db_fprint_fasta(fp_output, i); - - sampled++; + samples++; + + if (opt_fastaout) + fasta_print_relabel(fp_fastaout, + db_getsequence(i), + db_getsequencelen(i), + db_getheader(i), + db_getheaderlen(i), + abundance[i], + samples); + + if (opt_fastqout) + fastq_print_relabel(fp_fastqout, + db_getsequence(i), + db_getsequencelen(i), + db_getheader(i), + db_getheaderlen(i), + db_getquality(i), + abundance[i], + samples); } progress_update(i); } @@ -153,8 +181,13 @@ void subsample() free(abundance); - fprintf(stderr, "Subsampled %lu reads from %d amplicons\n", n, sampled); + fprintf(stderr, "Subsampled %lu reads from %d amplicons\n", n, samples); db_free(); - fclose(fp_output); + + if (opt_fastaout) + fclose(fp_fastaout); + + if (opt_fastqout) + fclose(fp_fastqout); } diff --git a/source/vsearch_src/subsample.h b/source/vsearch_src/subsample.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/unique.cc b/source/vsearch_src/unique.cc old mode 100644 new mode 100755 index 4c1d899ac..76fd45f0b --- a/source/vsearch_src/unique.cc +++ b/source/vsearch_src/unique.cc @@ -60,14 +60,12 @@ #include "vsearch.h" -/* Find the unique kmers or words in a given sequence. Currently the - definintion of "unique kmers" are the kmers that appear exactly once; - kmers that appear twice or more often are ignored. - Maybe the definition should be all kmers that appear in the input - sequence, but that each of those kmers shoudl appear only - once in the resulting list. - Experiments indicate that the current (first) definition gives - both the highest sensitivity and precision. */ +/* + Find the unique kmers or words in a given sequence. + Unique is now defined as all different words occuring at least once. + Earlier it was defined as those words occuring exactly once, but + that caused a problem when searching for sequences with many repeats. +*/ #define HASH CityHash64 @@ -136,7 +134,8 @@ void unique_count_bitmap(struct uhandle_s * uh, int seqlen, char * seq, unsigned int * listlen, - unsigned int * * list) + unsigned int * * list, + int seqmask) { /* if necessary, reallocate list of unique kmers */ @@ -154,12 +153,12 @@ void unique_count_bitmap(struct uhandle_s * uh, if (uh->bitmap_size < size) { - uh->bitmap = (unsigned long *) xrealloc(uh->bitmap, size >> 2UL); + uh->bitmap = (unsigned long *) xrealloc(uh->bitmap, size >> 3UL); uh->bitmap_size = size; } - memset(uh->bitmap, 0, size >> 2UL); - + memset(uh->bitmap, 0, size >> 3UL); + unsigned long bad = 0; unsigned long kmer = 0; unsigned long mask = size - 1UL; @@ -168,55 +167,44 @@ void unique_count_bitmap(struct uhandle_s * uh, char * e2 = s + seqlen; if (e2 < e1) e1 = e2; + + unsigned int * maskmap = (seqmask != MASK_NONE) ? + chrmap_mask_lower : chrmap_mask_ambig; while (s < e1) { bad <<= 2UL; - bad |= chrmap_masked[(int)(*s)]; + bad |= maskmap[(int)(*s)]; kmer <<= 2UL; kmer |= chrmap_2bit[(int)(*s++)]; } - - int candidates = 0; + + int unique = 0; while (s < e2) { bad <<= 2UL; - bad |= chrmap_masked[(int)(*s)]; + bad |= maskmap[(int)(*s)]; bad &= mask; kmer <<= 2UL; kmer |= chrmap_2bit[(int)(*s++)]; kmer &= mask; - + if (!bad) { unsigned long x = kmer >> 6UL; unsigned long y = 1UL << (kmer & 63UL); - - unsigned long uniq = uh->bitmap[2*x]; - unsigned long seen = uh->bitmap[2*x+1]; - - uh->bitmap[2*x] = (uniq & ~y) | (y & ~seen); - uh->bitmap[2*x+1] = seen | y; - - uh->list[candidates++] = kmer; + if (!(uh->bitmap[x] & y)) + { + /* not seen before */ + uh->list[unique++] = kmer; + uh->bitmap[x] |= y; + } } } - - int unique = 0; - for (int i = 0; i < candidates; i++) - { - kmer = uh->list[i]; - unsigned long x = kmer >> 6UL; - unsigned long y = 1UL << (kmer & 63UL); - - if (uh->bitmap[2*x] & y) - uh->list[unique++] = uh->list[i]; - } - *listlen = unique; *list = uh->list; } @@ -226,10 +214,9 @@ void unique_count_hash(struct uhandle_s * uh, int seqlen, char * seq, unsigned int * listlen, - unsigned int * * list) + unsigned int * * list, + int seqmask) { - unsigned long unique; - /* if necessary, reallocate hash table and list of unique kmers */ if (uh->alloc < 2*seqlen) @@ -261,25 +248,30 @@ void unique_count_hash(struct uhandle_s * uh, if (e2 < e1) e1 = e2; + unsigned int * maskmap = (seqmask != MASK_NONE) ? + chrmap_mask_lower : chrmap_mask_ambig; + while (s < e1) { bad <<= 2UL; - bad |= chrmap_masked[(int)(*s)]; + bad |= maskmap[(int)(*s)]; kmer <<= 2; kmer |= chrmap_2bit[(int)(*s++)]; } - + + unsigned long unique = 0; + while (s < e2) { bad <<= 2UL; - bad |= chrmap_masked[(int)(*s)]; + bad |= maskmap[(int)(*s)]; bad &= mask; kmer <<= 2; kmer |= chrmap_2bit[(int)(*s++)]; kmer &= mask; - + if (!bad) { /* find free appropriate bucket in hash */ @@ -287,16 +279,16 @@ void unique_count_hash(struct uhandle_s * uh, while((uh->hash[j].count) && (uh->hash[j].kmer != kmer)) j = (j + 1) & uh->hash_mask; - uh->hash[j].kmer = kmer; - uh->hash[j].count++; + if (!(uh->hash[j].count)) + { + /* not seen before */ + uh->list[unique++] = kmer; + uh->hash[j].kmer = kmer; + uh->hash[j].count = 1; + } } } - unique = 0; - for(int i=0; isize; i++) - if (uh->hash[i].count == 1) - uh->list[unique++] = uh->hash[i].kmer; - *listlen = unique; *list = uh->list; } @@ -306,12 +298,13 @@ void unique_count(struct uhandle_s * uh, int seqlen, char * seq, unsigned int * listlen, - unsigned int * * list) + unsigned int * * list, + int seqmask) { if (k<10) - unique_count_bitmap(uh, k, seqlen, seq, listlen, list); + unique_count_bitmap(uh, k, seqlen, seq, listlen, list, seqmask); else - unique_count_hash(uh, k, seqlen, seq, listlen, list); + unique_count_hash(uh, k, seqlen, seq, listlen, list, seqmask); } int unique_count_shared(struct uhandle_s * uh, @@ -330,7 +323,7 @@ int unique_count_shared(struct uhandle_s * uh, unsigned int kmer = list[i]; unsigned long x = kmer >> 6UL; unsigned long y = 1UL << (kmer & 63UL); - if (uh->bitmap[2*x] & y) + if (uh->bitmap[x] & y) count++; } } @@ -342,7 +335,7 @@ int unique_count_shared(struct uhandle_s * uh, unsigned long j = HASH((char*)&kmer, (k+3)/4) & uh->hash_mask; while((uh->hash[j].count) && (uh->hash[j].kmer != kmer)) j = (j + 1) & uh->hash_mask; - if (uh->hash[j].count == 1) + if (uh->hash[j].count) count++; } } diff --git a/source/vsearch_src/unique.h b/source/vsearch_src/unique.h old mode 100644 new mode 100755 index 557fc2f69..f9c8cebe9 --- a/source/vsearch_src/unique.h +++ b/source/vsearch_src/unique.h @@ -70,7 +70,8 @@ void unique_count(struct uhandle_s * uh, int seqlen, char * seq, unsigned int * listlen, - unsigned int * * list); + unsigned int * * list, + int seqmask); int unique_count_shared(struct uhandle_s * uh, int k, diff --git a/source/vsearch_src/userfields.cc b/source/vsearch_src/userfields.cc old mode 100644 new mode 100755 diff --git a/source/vsearch_src/userfields.h b/source/vsearch_src/userfields.h old mode 100644 new mode 100755 diff --git a/source/vsearch_src/util.cc b/source/vsearch_src/util.cc old mode 100644 new mode 100755 index f09fc4117..00e1f9c1e --- a/source/vsearch_src/util.cc +++ b/source/vsearch_src/util.cc @@ -1,412 +1,434 @@ -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "vsearch.h" - -static const char * progress_prompt; -static unsigned long progress_next; -static unsigned long progress_size; -static unsigned long progress_chunk; -static const unsigned long progress_granularity = 200; - -void progress_init(const char * prompt, unsigned long size) -{ - if (! opt_quiet) - { - progress_prompt = prompt; - progress_size = size; - progress_chunk = size < progress_granularity ? - 1 : size / progress_granularity; - progress_next = 0; - fprintf(stderr, "%s %.0f%%", prompt, 0.0); - } -} - -void progress_update(unsigned long progress) -{ - if (! opt_quiet) - if (progress >= progress_next) - { - fprintf(stderr, " \r%s %.0f%%", progress_prompt, - 100.0 * progress / progress_size); - progress_next = progress + progress_chunk; - } -} - -void progress_done() -{ - if (! opt_quiet) - fprintf(stderr, " \r%s %.0f%%\n", progress_prompt, 100.0); -} - -long gcd(long a, long b) -{ - if (b == 0) - { - return a; - } - else - { - return gcd(b, a % b); - } -} - -void __attribute__((noreturn)) fatal(const char * msg) -{ - fprintf(stderr, "\n\n"); - fprintf(stderr, "fatal error: %s\n", msg); - - if (opt_log) - { - fprintf(fp_log, "\n\n"); - fprintf(fp_log, "fatal error: %s\n", msg); - } - - exit(EXIT_FAILURE); -} - -void __attribute__((noreturn)) fatal(const char * format, const char * message) -{ - fprintf(stderr, "\n\n"); - fprintf(stderr, format, message); - fprintf(stderr, "\n"); - - if (opt_log) - { - fprintf(fp_log, "\n\n"); - fprintf(fp_log, format, message); - fprintf(fp_log, "\n"); - } - - exit(EXIT_FAILURE); -} - -void * xmalloc(size_t size) -{ - const size_t alignment = 16; - void * t = 0; - if (posix_memalign(& t, alignment, size)) - fatal("Unable to allocate enough memory."); - if (!t) - fatal("Unable to allocate enough memory."); - return t; -} - -void * xrealloc(void *ptr, size_t size) -{ - if (size == 0) - size = 1; - void * t = realloc(ptr, size); - if (!t) - fatal("Unable to allocate enough memory."); - return t; -} - -char * xstrdup(const char *s) -{ - size_t len = strlen(s); - char * p = (char*) xmalloc(len+1); - return strcpy(p, s); -} - - -char * xstrchrnul(char *s, int c) -{ - char * r = strchr(s, c); - - if (r) - return r; - else - return (char *)s + strlen(s); -} - -unsigned long hash_cityhash64(char * s, unsigned long n) -{ - return CityHash64((const char*)s, n); -} - -long getusec(void) -{ - struct timeval tv; - if(gettimeofday(&tv,0) != 0) return 0; - return tv.tv_sec * 1000000 + tv.tv_usec; -} - -void show_rusage() -{ -#if 0 - struct rusage r_usage; - getrusage(RUSAGE_SELF, & r_usage); - - fprintf(stderr, "Time: %.3fs (user)", r_usage.ru_utime.tv_sec * 1.0 + (double) r_usage.ru_utime.tv_usec * 1.0e-6); - fprintf(stderr, " %.3fs (sys)", r_usage.ru_stime.tv_sec * 1.0 + r_usage.ru_stime.tv_usec * 1.0e-6); - - fprintf(stderr, " Memory: %luMB\n", arch_get_memused() / 1024 / 1024); - - if (opt_log) - { - fprintf(fp_log, "Time: %.3fs (user)", r_usage.ru_utime.tv_sec * 1.0 + (double) r_usage.ru_utime.tv_usec * 1.0e-6); - fprintf(fp_log, " %.3fs (sys)", r_usage.ru_stime.tv_sec * 1.0 + r_usage.ru_stime.tv_usec * 1.0e-6); - - fprintf(fp_log, " Memory: %luMB\n", arch_get_memused() / 1024 / 1024); - } -#endif -} - -void fprint_fasta_hdr_only(FILE * fp, const char * hdr) -{ - fprintf(fp, ">%s\n", hdr); -} - -void fprint_fasta_seq_only(FILE * fp, char * seq, unsigned long len, int width) -{ - /* - The actual length of the sequence may be longer than "len", but only - "len" characters are printed. - - Specify width of lines - zero (or <1) means linearize (all on one line). - */ - - if (width < 1) - fprintf(fp, "%.*s\n", (int)(len), seq); - else - { - long rest = len; - for(unsigned long i=0; i 0 - The random() function returns a random number in the range - 0 to 2147483647 (=2^31-1=RAND_MAX), inclusive. - We should avoid some of the upper generated numbers to - avoid modulo bias. - */ - - long random_max = RAND_MAX; - long limit = random_max - (random_max + 1) % n; - long r = random(); - while (r > limit) - r = random(); - return r % n; -} - -unsigned long random_ulong(unsigned long n) -{ - /* - Generate a random integer in the range 0 to n-1, inclusive, - n must be > 0 - */ - - unsigned long random_max = ULONG_MAX; - unsigned long limit = random_max - (random_max - n + 1) % n; - unsigned long r = ((random() << 48) ^ (random() << 32) ^ - (random() << 16) ^ (random())); - while (r > limit) - r = ((random() << 48) ^ (random() << 32) ^ - (random() << 16) ^ (random())); - return r % n; -} - -void string_normalize(char * normalized, char * s, unsigned int len) -{ - /* convert string to upper case and replace U by T */ - char * p = s; - char * q = normalized; - for(unsigned int i=0; i> 4]; - hex[2*i+1] = hexdigits[digest[i] & 15]; - } - hex[2*LEN_DIG_SHA1] = 0; -} - -void get_hex_seq_digest_md5(char * hex, char * seq, int seqlen) -{ - /* Save hexadecimal representation of the MD5 hash of the sequence. - The string array digest must be large enough (LEN_HEX_DIG_MD5). - First normalize string by uppercasing it and replacing U's with T's. */ - - char * normalized = (char*) xmalloc(seqlen+1); - string_normalize(normalized, seq, seqlen); - - unsigned char digest[LEN_DIG_MD5]; - - MD5(normalized, (size_t) seqlen, digest); - - free(normalized); - - for(int i=0; i> 4]; - hex[2*i+1] = hexdigits[digest[i] & 15]; - } - hex[2*LEN_DIG_MD5] = 0; -} - - -void fprint_seq_digest_sha1(FILE * fp, char * seq, int seqlen) -{ - char digest[LEN_HEX_DIG_SHA1]; - get_hex_seq_digest_sha1(digest, seq, seqlen); - fprintf(fp, "%s", digest); -} - -void fprint_seq_digest_md5(FILE * fp, char * seq, int seqlen) -{ - char digest[LEN_HEX_DIG_MD5]; - get_hex_seq_digest_md5(digest, seq, seqlen); - fprintf(fp, "%s", digest); -} +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +static const char * progress_prompt; +static unsigned long progress_next; +static unsigned long progress_size; +static unsigned long progress_chunk; +static const unsigned long progress_granularity = 200; + +void progress_init(const char * prompt, unsigned long size) +{ + if (! opt_quiet) + { + progress_prompt = prompt; + progress_size = size; + progress_chunk = size < progress_granularity ? + 1 : size / progress_granularity; + progress_next = 0; + fprintf(stderr, "%s %.0f%%", prompt, 0.0); + } +} + +void progress_update(unsigned long progress) +{ + if (! opt_quiet) + if (progress >= progress_next) + { + if (progress_size > 0) + fprintf(stderr, " \r%s %.0f%%", progress_prompt, + 100.0 * progress / progress_size); + else + fprintf(stderr, " \r%s ?%%", progress_prompt); + progress_next = progress + progress_chunk; + } +} + +void progress_done() +{ + if (! opt_quiet) + fprintf(stderr, " \r%s %.0f%%\n", progress_prompt, 100.0); +} + +long gcd(long a, long b) +{ + if (b == 0) + { + return a; + } + else + { + return gcd(b, a % b); + } +} + +void __attribute__((noreturn)) fatal(const char * msg) +{ + fprintf(stderr, "\n\n"); + fprintf(stderr, "Fatal error: %s\n", msg); + + if (opt_log) + { + fprintf(fp_log, "\n\n"); + fprintf(fp_log, "Fatal error: %s\n", msg); + } + + exit(EXIT_FAILURE); +} + +void __attribute__((noreturn)) fatal(const char * format, + const char * message) +{ + fprintf(stderr, "\n\n"); + fprintf(stderr, format, message); + fprintf(stderr, "\n"); + + if (opt_log) + { + fprintf(fp_log, "\n\n"); + fprintf(fp_log, format, message); + fprintf(fp_log, "\n"); + } + + exit(EXIT_FAILURE); +} + +void * xmalloc(size_t size) +{ + const size_t alignment = 16; + void * t = 0; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + if (posix_memalign(& t, alignment, size)) + fatal("Unable to allocate enough memory."); +#else + t = _aligned_malloc(size, alignment); +#endif + + if (!t) + fatal("Unable to allocate enough memory."); + return t; +} + +void * xrealloc(void *ptr, size_t size) +{ + if (size == 0) + size = 1; + void * t = realloc(ptr, size); + if (!t) + fatal("Unable to allocate enough memory."); + return t; +} + +char * xstrdup(const char *s) +{ + size_t len = strlen(s); + char * p = (char*) xmalloc(len+1); + return strcpy(p, s); +} + + +char * xstrchrnul(char *s, int c) +{ + char * r = strchr(s, c); + + if (r) + return r; + else + return (char *)s + strlen(s); +} + +unsigned long hash_cityhash64(char * s, unsigned long n) +{ + return CityHash64((const char*)s, n); +} + +long getusec(void) +{ + struct timeval tv; + +#if defined (_WIN32) + static const unsigned __int64 epoch = (uint64_t)(116444736000000000); + FILETIME file_time; + SYSTEMTIME system_time; + ULARGE_INTEGER ularge; + + GetSystemTime(&system_time); + if ((SystemTimeToFileTime(&system_time, &file_time)) == 0) { return 0; } //failed + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tv.tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L); + tv.tv_usec = (long) (system_time.wMilliseconds * 1000); + return tv.tv_sec; + + + +#else + if(gettimeofday(&tv,0) != 0) return 0; + return tv.tv_sec * 1000000 + tv.tv_usec; +#endif +} + +void show_rusage() +{ +#if 0 + struct rusage r_usage; + getrusage(RUSAGE_SELF, & r_usage); + + fprintf(stderr, "Time: %.3fs (user)", r_usage.ru_utime.tv_sec * 1.0 + (double) r_usage.ru_utime.tv_usec * 1.0e-6); + fprintf(stderr, " %.3fs (sys)", r_usage.ru_stime.tv_sec * 1.0 + r_usage.ru_stime.tv_usec * 1.0e-6); + + fprintf(stderr, " Memory: %luMB\n", arch_get_memused() / 1024 / 1024); + + if (opt_log) + { + fprintf(fp_log, "Time: %.3fs (user)", r_usage.ru_utime.tv_sec * 1.0 + (double) r_usage.ru_utime.tv_usec * 1.0e-6); + fprintf(fp_log, " %.3fs (sys)", r_usage.ru_stime.tv_sec * 1.0 + r_usage.ru_stime.tv_usec * 1.0e-6); + + fprintf(fp_log, " Memory: %luMB\n", arch_get_memused() / 1024 / 1024); + } +#endif +} + +void reverse_complement(char * rc, char * seq, long len) +{ + /* Write the reverse complementary sequence to rc. + The memory for rc must be long enough for the rc of the sequence + (identical to the length of seq + 1. */ + + for(long i=0; i 0 + The random() function returns a random number in the range + 0 to 2147483647 (=2^31-1=RAND_MAX), inclusive. + We should avoid some of the upper generated numbers to + avoid modulo bias. + */ + + long random_max = RAND_MAX; + long limit = random_max - (random_max + 1) % n; + long r = 1; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + r = random(); + while (r > limit) { r = random(); } +#else + r = rand(); + while (r > limit) { r = rand(); } +#endif + return r % n; +} + +unsigned long random_ulong(unsigned long n) +{ + /* + Generate a random integer in the range 0 to n-1, inclusive, + n must be > 0 + */ + + + unsigned long random_max = ULONG_MAX; + unsigned long limit = random_max - (random_max - n + 1) % n; + unsigned long r_long = 1; + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + + unsigned long r = ((random() << 48) ^ (random() << 32) ^ + (random() << 16) ^ (random())); + while (r > limit) + r = ((random() << 48) ^ (random() << 32) ^ + (random() << 16) ^ (random())); + + r_long = r; +#else + + long long r = ((rand() << 48) ^ (rand() << 32) ^ + (rand() << 16) ^ (rand())); + while (r > limit) + r = ((rand() << 48) ^ (rand() << 32) ^ + (rand() << 16) ^ (rand())); + + + r_long = (unsigned long) r; + +#endif + + return r_long % n; +} + +void string_normalize(char * normalized, char * s, unsigned int len) +{ + /* convert string to upper case and replace U by T */ + char * p = s; + char * q = normalized; + for(unsigned int i=0; i> 4]; + hex[2*i+1] = hexdigits[digest[i] & 15]; + } + hex[2*LEN_DIG_SHA1] = 0; +} + +void get_hex_seq_digest_md5(char * hex, char * seq, int seqlen) +{ + /* Save hexadecimal representation of the MD5 hash of the sequence. + The string array digest must be large enough (LEN_HEX_DIG_MD5). + First normalize string by uppercasing it and replacing U's with T's. */ + + char * normalized = (char*) xmalloc(seqlen+1); + string_normalize(normalized, seq, seqlen); + + unsigned char digest[LEN_DIG_MD5]; + + MD5(normalized, (size_t) seqlen, digest); + + free(normalized); + + for(int i=0; i> 4]; + hex[2*i+1] = hexdigits[digest[i] & 15]; + } + hex[2*LEN_DIG_MD5] = 0; +} + + +void fprint_seq_digest_sha1(FILE * fp, char * seq, int seqlen) +{ + char digest[LEN_HEX_DIG_SHA1]; + get_hex_seq_digest_sha1(digest, seq, seqlen); + fprintf(fp, "%s", digest); +} + +void fprint_seq_digest_md5(FILE * fp, char * seq, int seqlen) +{ + char digest[LEN_HEX_DIG_MD5]; + get_hex_seq_digest_md5(digest, seq, seqlen); + fprintf(fp, "%s", digest); +} + + diff --git a/source/vsearch_src/util.h b/source/vsearch_src/util.h old mode 100644 new mode 100755 index 1dcc1e5da..012d335e0 --- a/source/vsearch_src/util.h +++ b/source/vsearch_src/util.h @@ -1,5 +1,3 @@ - - /* VSEARCH: a versatile open source tool for metagenomics @@ -68,6 +66,10 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif +#ifndef exp10 +#define exp10(x) (pow(10.0,(x))) +#endif + #define MD5_DIGEST_LENGTH 16 #define SHA_DIGEST_LENGTH SHA1_DIGEST_SIZE @@ -77,7 +79,6 @@ #define LEN_HEX_DIG_MD5 (2*LEN_DIG_MD5+1) #define LEN_HEX_DIG_SHA1 (2*LEN_DIG_SHA1+1) - long gcd(long a, long b); void fatal(const char * msg); void fatal(const char * format, const char * message); @@ -88,12 +89,6 @@ char * xstrchrnul(char *s, int c); unsigned long hash_cityhash64(char * s, unsigned long n); long getusec(void); void show_rusage(); -void fprint_fasta_hdr_only(FILE * fp, const char * hdr); -void fprint_fasta_seq_only(FILE * fp, char * seq, unsigned long len, int width); -void reverse_complement(char * rc, char * seq, long len); - -void fprint_fastq(FILE * fp, char * header, char * sequence, char * quality, - bool add_ee, double ee); void progress_init(const char * prompt, unsigned long size); void progress_update(unsigned long progress); @@ -105,6 +100,8 @@ unsigned long random_ulong(unsigned long n); void string_normalize(char * normalized, char * s, unsigned int len); +void reverse_complement(char * rc, char * seq, long len); + void fprint_hex(FILE * fp, unsigned char * data, int len); void get_hex_seq_digest_sha1(char * hex, char * seq, int seqlen); @@ -112,5 +109,3 @@ void get_hex_seq_digest_md5(char * hex, char * seq, int seqlen); void fprint_seq_digest_sha1(FILE * fp, char * seq, int seqlen); void fprint_seq_digest_md5(FILE * fp, char * seq, int seqlen); - - diff --git a/source/vsearch_src/vsearch.cc b/source/vsearch_src/vsearch.cc old mode 100644 new mode 100755 index d1e3352f7..d9b942652 --- a/source/vsearch_src/vsearch.cc +++ b/source/vsearch_src/vsearch.cc @@ -1,2094 +1,2482 @@ -/* - - VSEARCH: a versatile open source tool for metagenomics - - Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri - All rights reserved. - - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ - - - -#include "vsearch.h" - - -/* options */ - -extern int opterr; - -bool opt_clusterout_id; -bool opt_clusterout_sort; -bool opt_eeout; -bool opt_quiet; -bool opt_relabel_md5; -bool opt_relabel_sha1; -bool opt_samheader; -bool opt_sizeorder; -bool opt_xsize; -char * opt_allpairs_global; -char * opt_alnout; -char * opt_blast6out; -char * opt_borderline; -char * opt_centroids; -char * opt_chimeras; -char * opt_cluster_fast; -char * opt_cluster_size; -char * opt_cluster_smallmem; -char * opt_clusters; -char * opt_consout; -char * opt_db; -char * opt_dbmatched; -char * opt_dbnotmatched; -char * opt_derep_fulllength; -char * opt_derep_prefix; -char * opt_fastaout; -char * opt_fastaout_discarded; -char * opt_fastapairs; -char * opt_fastq_chars; -char * opt_fastq_filter; -char * opt_fastq_stats; -char * opt_fastqout; -char * opt_fastqout_discarded; -char * opt_fastx_revcomp; -char * opt_fastx_subsample; -char * opt_label_suffix; -char * opt_log; -char * opt_maskfasta; -char * opt_matched; -char * opt_msaout; -char * opt_nonchimeras; -char * opt_notmatched; -char * opt_output; -char * opt_pattern; -char * opt_profile; -char * opt_relabel; -char * opt_samout; -char * opt_shuffle; -char * opt_sortbylength; -char * opt_sortbysize; -char * opt_uc; -char * opt_uchime_denovo; -char * opt_uchime_ref; -char * opt_uchimealns; -char * opt_uchimeout; -char * opt_usearch_global; -char * opt_userout; -double opt_abskew; -double opt_dn; -double opt_fastq_maxee; -double opt_fastq_maxee_rate; -double opt_id; -double opt_maxid; -double opt_maxqt; -double opt_maxsizeratio; -double opt_maxsl; -double opt_mid; -double opt_mindiv; -double opt_minh; -double opt_minqt; -double opt_minsizeratio; -double opt_minsl; -double opt_query_cov; -double opt_sample_pct; -double opt_target_cov; -double opt_weak_id; -double opt_xn; -int opt_acceptall; -int opt_alignwidth; -int opt_cons_truncate; -int opt_gap_extension_query_interior; -int opt_gap_extension_query_left; -int opt_gap_extension_query_right; -int opt_gap_extension_target_interior; -int opt_gap_extension_target_left; -int opt_gap_extension_target_right; -int opt_gap_open_query_interior; -int opt_gap_open_query_left; -int opt_gap_open_query_right; -int opt_gap_open_target_interior; -int opt_gap_open_target_left; -int opt_gap_open_target_right; -int opt_help; -int opt_mindiffs; -int opt_slots; -int opt_uchimeout5; -int opt_usersort; -int opt_version; -long opt_dbmask; -long opt_fasta_width; -long opt_fastq_ascii; -long opt_fastq_maxns; -long opt_fastq_minlen; -long opt_fastq_qmax; -long opt_fastq_qmaxout; -long opt_fastq_qmin; -long opt_fastq_stripleft; -long opt_fastq_tail; -long opt_fastq_trunclen; -long opt_fastq_truncqual; -long opt_fulldp; -long opt_hardmask; -long opt_iddef; -long opt_idprefix; -long opt_idsuffix; -long opt_leftjust; -long opt_match; -long opt_maxaccepts; -long opt_maxdiffs; -long opt_maxgaps; -long opt_maxhits; -long opt_maxqsize; -long opt_maxrejects; -long opt_maxseqlength; -long opt_maxsize; -long opt_maxsubs; -long opt_maxuniquesize; -long opt_mincols; -long opt_minseqlength; -long opt_minsize; -long opt_mintsize; -long opt_minuniquesize; -long opt_mismatch; -long opt_notrunclabels; -long opt_output_no_hits; -long opt_qmask; -long opt_randseed; -long opt_rightjust; -long opt_rowlen; -long opt_sample_size; -long opt_self; -long opt_selfid; -long opt_sizein; -long opt_sizeout; -long opt_strand; -long opt_threads; -long opt_top_hits_only; -long opt_topn; -long opt_uc_allhits; -long opt_wordlength; - -/* Other variables */ - -/* cpu features available */ - -long mmx_present = 0; -long sse_present = 0; -long sse2_present = 0; -long sse3_present = 0; -long ssse3_present = 0; -long sse41_present = 0; -long sse42_present = 0; -long popcnt_present = 0; -long avx_present = 0; -long avx2_present = 0; - -static char * progname; -static char progheader[80]; -static char * cmdline; -static time_t time_start; -static time_t time_finish; - -FILE * fp_log = 0; - -#define cpuid(f1, f2, a, b, c, d) \ - __asm__ __volatile__ ("cpuid" \ - : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ - : "a" (f1), "c" (f2)); - -void cpu_features_detect() -{ - unsigned int a, b, c, d; - - cpuid(0, 0, a, b, c, d); - unsigned int maxlevel = a & 0xff; - - if (maxlevel >= 1) - { - cpuid(1, 0, a, b, c, d); - mmx_present = (d >> 23) & 1; - sse_present = (d >> 25) & 1; - sse2_present = (d >> 26) & 1; - sse3_present = (c >> 0) & 1; - ssse3_present = (c >> 9) & 1; - sse41_present = (c >> 19) & 1; - sse42_present = (c >> 20) & 1; - popcnt_present = (c >> 23) & 1; - avx_present = (c >> 28) & 1; - - if (maxlevel >= 7) - { - cpuid(7, 0, a, b, c, d); - avx2_present = (b >> 5) & 1; - } - } -} - -void cpu_features_show() -{ - fprintf(stderr, "CPU features:"); - if (mmx_present) - fprintf(stderr, " mmx"); - if (sse_present) - fprintf(stderr, " sse"); - if (sse2_present) - fprintf(stderr, " sse2"); - if (sse3_present) - fprintf(stderr, " sse3"); - if (ssse3_present) - fprintf(stderr, " ssse3"); - if (sse41_present) - fprintf(stderr, " sse4.1"); - if (sse42_present) - fprintf(stderr, " sse4.2"); - if (popcnt_present) - fprintf(stderr, " popcnt"); - if (avx_present) - fprintf(stderr, " avx"); - if (avx2_present) - fprintf(stderr, " avx2"); - fprintf(stderr, "\n"); -} - - -void args_get_gap_penalty_string(char * arg, int is_open) -{ - /* See http://www.drive5.com/usearch/manual/aln_params.html - - --gapopen *E/10I/1E/2L/3RQ/4RT/1IQ - --gapext *E/10I/1E/2L/3RQ/4RT/1IQ - - integer or * - followed by I, E, L, R, Q or T characters - separated by / - * means infinitely high (disallow) - E=end - I=interior - L=left - R=right - Q=query - T=target - - E cannot be combined with L or R - - We do not support floating point values. Therefore, - all default score and penalties are multiplied by 2. - - */ - - char *p = arg; - - while (*p) - { - int skip = 0; - int pen = 0; - - if (sscanf(p, "%d%n", &pen, &skip) == 1) - { - p += skip; - } - else if (*p == '*') - { - pen = 10000; - p++; - } - else - fatal("Invalid gap penalty argument (%s)", p); - - char * q = p; - - int set_E = 0; - int set_I = 0; - int set_L = 0; - int set_R = 0; - int set_Q = 0; - int set_T = 0; - - while((*p) && (*p != '/')) - { - switch(*p) - { - case 'E': - set_E = 1; - break; - case 'I': - set_I = 1; - break; - case 'L': - set_L = 1; - break; - case 'R': - set_R = 1; - break; - case 'Q': - set_Q = 1; - break; - case 'T': - set_T = 1; - break; - default: - fatal("Invalid char '%.1s' in gap penalty string", p); - break; - } - p++; - } - - if (*p == '/') - p++; - - if (set_E && (set_L || set_R)) - fatal("Invalid gap penalty string (E and L or R) '%s'", q); - - if (set_E) - { - set_L = 1; - set_R = 1; - } - - /* if neither L, I, R nor E is specified, it applies to all */ - - if ((!set_L) && (!set_I) && (!set_R)) - { - set_L = 1; - set_I = 1; - set_R = 1; - } - - /* if neither Q nor T is specified, it applies to both */ - - if ((!set_Q) && (!set_T)) - { - set_Q = 1; - set_T = 1; - } - - if (is_open) - { - if (set_Q) - { - if (set_L) - opt_gap_open_query_left = pen; - if (set_I) - opt_gap_open_query_interior = pen; - if (set_R) - opt_gap_open_query_right = pen; - } - if (set_T) - { - if (set_L) - opt_gap_open_target_left = pen; - if (set_I) - opt_gap_open_target_interior = pen; - if (set_R) - opt_gap_open_target_right = pen; - } - } - else - { - if (set_Q) - { - if (set_L) - opt_gap_extension_query_left = pen; - if (set_I) - opt_gap_extension_query_interior = pen; - if (set_R) - opt_gap_extension_query_right = pen; - } - if (set_T) - { - if (set_L) - opt_gap_extension_target_left = pen; - if (set_I) - opt_gap_extension_target_interior = pen; - if (set_R) - opt_gap_extension_target_right = pen; - } - } - } -} - - -long args_getlong(char * arg) -{ - int len = 0; - long temp = 0; - int ret = sscanf(arg, "%ld%n", &temp, &len); - if ((ret == 0) || (((unsigned int)(len)) < strlen(arg))) - fatal("Illegal option argument"); - return temp; -} - -double args_getdouble(char * arg) -{ - int len = 0; - double temp = 0; - int ret = sscanf(arg, "%lf%n", &temp, &len); - if ((ret == 0) || (((unsigned int)(len)) < strlen(arg))) - fatal("Illegal option argument"); - return temp; -} - -void args_init(int argc, char *argv[]) -{ - /* Set defaults */ - progname = argv[0]; - - opt_abskew = 2.0; - opt_acceptall = 0; - opt_alignwidth = 80; - opt_allpairs_global = 0; - opt_alnout = 0; - opt_borderline = 0; - opt_centroids = 0; - opt_chimeras = 0; - opt_cluster_fast = 0; - opt_cluster_size = 0; - opt_cluster_smallmem = 0; - opt_clusterout_id = 0; - opt_clusterout_sort = 0; - opt_clusters = 0; - opt_cons_truncate = 0; - opt_consout = 0; - opt_db = 0; - opt_dbmask = MASK_DUST; - opt_dbmatched = 0; - opt_dbnotmatched = 0; - opt_derep_fulllength = 0; - opt_derep_prefix = 0; - opt_dn = 1.4; - opt_eeout = 0; - opt_fasta_width = 80; - opt_fastaout = 0; - opt_fastaout_discarded = 0; - opt_fastapairs = 0; - opt_fastq_ascii = 33; - opt_fastq_chars = 0; - opt_fastq_maxee = DBL_MAX; - opt_fastq_maxee_rate = DBL_MAX; - opt_fastq_maxns = LONG_MAX; - opt_fastq_minlen = 1; - opt_fastq_qmax = 41; - opt_fastq_qmaxout = 41; - opt_fastq_qmin = 0; - opt_fastq_stats = 0; - opt_fastq_stripleft = 0; - opt_fastq_tail = 4; - opt_fastq_trunclen = 0; - opt_fastq_truncqual = LONG_MIN; - opt_fastqout = 0; - opt_fastqout_discarded = 0; - opt_fastx_revcomp = 0; - opt_fastx_subsample = 0; - opt_fulldp = 0; - opt_gap_extension_query_interior=2; - opt_gap_extension_query_left=1; - opt_gap_extension_query_right=1; - opt_gap_extension_target_interior=2; - opt_gap_extension_target_left=1; - opt_gap_extension_target_right=1; - opt_gap_open_query_interior=20; - opt_gap_open_query_left=2; - opt_gap_open_query_right=2; - opt_gap_open_target_interior=20; - opt_gap_open_target_left=2; - opt_gap_open_target_right=2; - opt_hardmask = 0; - opt_help = 0; - opt_id = -1.0; - opt_iddef = 2; - opt_idprefix = 0; - opt_idsuffix = 0; - opt_label_suffix = 0; - opt_leftjust = 0; - opt_log = 0; - opt_match = 2; - opt_matched = 0; - opt_maxaccepts = 1; - opt_maxdiffs = INT_MAX; - opt_maxgaps = INT_MAX; - opt_maxhits = LONG_MAX; - opt_maxid = 1.0; - opt_maxqsize = INT_MAX; - opt_maxqt = DBL_MAX; - opt_maxrejects = -1; - opt_maxseqlength = 50000; - opt_maxsize = LONG_MAX; - opt_maxsizeratio = DBL_MAX; - opt_maxsl = DBL_MAX; - opt_maxsubs = INT_MAX; - opt_maxuniquesize = LONG_MAX; - opt_mid = 0.0; - opt_mincols = 0; - opt_mindiffs = 3; - opt_mindiv = 0.8; - opt_minh = 0.28; - opt_minqt = 0.0; - opt_minseqlength = 0; - opt_minsize = 0; - opt_minsizeratio = 0.0; - opt_minsl = 0.0; - opt_mintsize = 0; - opt_minuniquesize = 0; - opt_mismatch = -4; - opt_msaout = 0; - opt_nonchimeras = 0; - opt_notmatched = 0; - opt_notrunclabels = 0; - opt_output = 0; - opt_output_no_hits = 0; - opt_pattern = 0; - opt_profile = 0; - opt_qmask = MASK_DUST; - opt_query_cov = 0.0; - opt_quiet = false; - opt_randseed = 0; - opt_relabel = 0; - opt_relabel_md5 = 0; - opt_relabel_sha1 = 0; - opt_rightjust = 0; - opt_rowlen = 64; - opt_samheader = 0; - opt_samout = 0; - opt_sample_pct = 0; - opt_sample_size = 0; - opt_self = 0; - opt_selfid = 0; - opt_shuffle = 0; - opt_sizein = 0; - opt_sizeorder = 0; - opt_sizeout = 0; - opt_slots = 0; - opt_sortbylength = 0; - opt_sortbysize = 0; - opt_strand = 1; - opt_target_cov = 0.0; - opt_threads = 0; - opt_top_hits_only = 0; - opt_topn = LONG_MAX; - opt_uc_allhits = 0; - opt_uchime_denovo = 0; - opt_uchime_ref = 0; - opt_uchimealns = 0; - opt_uchimeout = 0; - opt_uchimeout5 = 0; - opt_usearch_global = 0; - opt_userout = 0; - opt_usersort = 0; - opt_version = 0; - opt_weak_id = 10.0; - opt_wordlength = 8; - opt_xn = 8.0; - opt_xsize = 0; - - opterr = 1; - - //changed to NULL to use getopt_long.h class - this avoids pulling mothur's - struct option long_options[] = - - { - {"help", no_argument, NULL, 0 }, - {"version", no_argument, NULL, 0 }, - {"alnout", required_argument, NULL, 0 }, - {"usearch_global", required_argument, NULL, 0 }, - {"db", required_argument, NULL, 0 }, - {"id", required_argument, NULL, 0 }, - {"maxaccepts", required_argument, NULL, 0 }, - {"maxrejects", required_argument, NULL, 0 }, - {"wordlength", required_argument, NULL, 0 }, - {"match", required_argument, NULL, 0 }, - {"mismatch", required_argument, NULL, 0 }, - {"fulldp", no_argument, NULL, 0 }, - {"strand", required_argument, NULL, 0 }, - {"threads", required_argument, NULL, 0 }, - {"gapopen", required_argument, NULL, 0 }, - {"gapext", required_argument, NULL, 0 }, - {"rowlen", required_argument, NULL, 0 }, - {"userfields", required_argument, NULL, 0 }, - {"userout", required_argument, NULL, 0 }, - {"self", no_argument, NULL, 0 }, - {"blast6out", required_argument, NULL, 0 }, - {"uc", required_argument, NULL, 0 }, - {"weak_id", required_argument, NULL, 0 }, - {"uc_allhits", no_argument, NULL, 0 }, - {"notrunclabels", no_argument, NULL, 0 }, - {"sortbysize", required_argument, NULL, 0 }, - {"output", required_argument, NULL, 0 }, - {"minsize", required_argument, NULL, 0 }, - {"maxsize", required_argument, NULL, 0 }, - {"relabel", required_argument, NULL, 0 }, - {"sizeout", no_argument, NULL, 0 }, - {"derep_fulllength", required_argument, NULL, 0 }, - {"minseqlength", required_argument, NULL, 0 }, - {"minuniquesize", required_argument, NULL, 0 }, - {"topn", required_argument, NULL, 0 }, - {"maxseqlength", required_argument, NULL, 0 }, - {"sizein", no_argument, NULL, 0 }, - {"sortbylength", required_argument, NULL, 0 }, - {"matched", required_argument, NULL, 0 }, - {"notmatched", required_argument, NULL, 0 }, - {"dbmatched", required_argument, NULL, 0 }, - {"dbnotmatched", required_argument, NULL, 0 }, - {"fastapairs", required_argument, NULL, 0 }, - {"output_no_hits", no_argument, NULL, 0 }, - {"maxhits", required_argument, NULL, 0 }, - {"top_hits_only", no_argument, NULL, 0 }, - {"fasta_width", required_argument, NULL, 0 }, - {"query_cov", required_argument, NULL, 0 }, - {"target_cov", required_argument, NULL, 0 }, - {"idprefix", required_argument, NULL, 0 }, - {"idsuffix", required_argument, NULL, 0 }, - {"minqt", required_argument, NULL, 0 }, - {"maxqt", required_argument, NULL, 0 }, - {"minsl", required_argument, NULL, 0 }, - {"maxsl", required_argument, NULL, 0 }, - {"leftjust", no_argument, NULL, 0 }, - {"rightjust", no_argument, NULL, 0 }, - {"selfid", no_argument, NULL, 0 }, - {"maxid", required_argument, NULL, 0 }, - {"minsizeratio", required_argument, NULL, 0 }, - {"maxsizeratio", required_argument, NULL, 0 }, - {"maxdiffs", required_argument, NULL, 0 }, - {"maxsubs", required_argument, NULL, 0 }, - {"maxgaps", required_argument, NULL, 0 }, - {"mincols", required_argument, NULL, 0 }, - {"maxqsize", required_argument, NULL, 0 }, - {"mintsize", required_argument, NULL, 0 }, - {"mid", required_argument, NULL, 0 }, - {"shuffle", required_argument, NULL, 0 }, - {"randseed", required_argument, NULL, 0 }, - {"maskfasta", required_argument, NULL, 0 }, - {"hardmask", no_argument, NULL, 0 }, - {"qmask", required_argument, NULL, 0 }, - {"dbmask", required_argument, NULL, 0 }, - {"cluster_smallmem", required_argument, NULL, 0 }, - {"cluster_fast", required_argument, NULL, 0 }, - {"centroids", required_argument, NULL, 0 }, - {"clusters", required_argument, NULL, 0 }, - {"consout", required_argument, NULL, 0 }, - {"cons_truncate", no_argument, NULL, 0 }, - {"msaout", required_argument, NULL, 0 }, - {"usersort", no_argument, NULL, 0 }, - {"xn", required_argument, NULL, 0 }, - {"iddef", required_argument, NULL, 0 }, - {"slots", required_argument, NULL, 0 }, - {"pattern", required_argument, NULL, 0 }, - {"maxuniquesize", required_argument, NULL, 0 }, - {"abskew", required_argument, NULL, 0 }, - {"chimeras", required_argument, NULL, 0 }, - {"dn", required_argument, NULL, 0 }, - {"mindiffs", required_argument, NULL, 0 }, - {"mindiv", required_argument, NULL, 0 }, - {"minh", required_argument, NULL, 0 }, - {"nonchimeras", required_argument, NULL, 0 }, - {"uchime_denovo", required_argument, NULL, 0 }, - {"uchime_ref", required_argument, NULL, 0 }, - {"uchimealns", required_argument, NULL, 0 }, - {"uchimeout", required_argument, NULL, 0 }, - {"uchimeout5", no_argument, NULL, 0 }, - {"alignwidth", required_argument, NULL, 0 }, - {"allpairs_global", required_argument, NULL, 0 }, - {"acceptall", no_argument, NULL, 0 }, - {"cluster_size", required_argument, NULL, 0 }, - {"samout", required_argument, NULL, 0 }, - {"log", required_argument, NULL, 0 }, - {"quiet", no_argument, NULL, 0 }, - {"fastx_subsample", required_argument, NULL, 0 }, - {"sample_pct", required_argument, NULL, 0 }, - {"fastq_chars", required_argument, NULL, 0 }, - {"profile", required_argument, NULL, 0 }, - {"sample_size", required_argument, NULL, 0 }, - {"fastaout", required_argument, NULL, 0 }, - {"xsize", no_argument, NULL, 0 }, - {"clusterout_id", no_argument, NULL, 0 }, - {"clusterout_sort", no_argument, NULL, 0 }, - {"borderline", required_argument, NULL, 0 }, - {"relabel_sha1", no_argument, NULL, 0 }, - {"relabel_md5", no_argument, NULL, 0 }, - {"derep_prefix", required_argument, NULL, 0 }, - {"fastq_filter", required_argument, NULL, 0 }, - {"fastqout", required_argument, NULL, 0 }, - {"fastaout_discarded", required_argument, NULL, 0 }, - {"fastqout_discarded", required_argument, NULL, 0 }, - {"fastq_truncqual", required_argument, NULL, 0 }, - {"fastq_maxee", required_argument, NULL, 0 }, - {"fastq_trunclen", required_argument, NULL, 0 }, - {"fastq_minlen", required_argument, NULL, 0 }, - {"fastq_stripleft", required_argument, NULL, 0 }, - {"fastq_maxee_rate", required_argument, NULL, 0 }, - {"fastq_maxns", required_argument, NULL, 0 }, - {"eeout", no_argument, NULL, 0 }, - {"fastq_ascii", required_argument, NULL, 0 }, - {"fastq_qmin", required_argument, NULL, 0 }, - {"fastq_qmax", required_argument, NULL, 0 }, - {"fastq_qmaxout", required_argument, NULL, 0 }, - {"fastq_stats", required_argument, NULL, 0 }, - {"fastq_tail", required_argument, NULL, 0 }, - {"fastx_revcomp", required_argument, NULL, 0 }, - {"label_suffix", required_argument, NULL, 0 }, - {"h", no_argument, NULL, 0 }, - {"samheader", no_argument, NULL, 0 }, - {"sizeorder", no_argument, NULL, 0 }, - { 0, 0, 0, 0 } - }; - - int option_count = sizeof(long_options) / sizeof(struct option); - bool options_selected[option_count]; - - memset(options_selected, 0, sizeof(options_selected)); - - int option_index = 0; - int c; - - while ((c = getopt_long(argc, argv, "", long_options, - &option_index)) == 0) - { - - if (option_index < option_count) - options_selected[option_index] = 1; - - switch(option_index) - { - - case 0: - opt_help = 1; - break; - case 1: - opt_version = 1; - break; - - case 2: - opt_alnout = optarg; - break; - - case 3: - opt_usearch_global = optarg; - break; - - case 4: - opt_db = optarg; - break; - - case 5: - opt_id = args_getdouble(optarg); - break; - - case 6: - opt_maxaccepts = args_getlong(optarg); - break; - - case 7: - opt_maxrejects = args_getlong(optarg); - break; - - case 8: - opt_wordlength = args_getlong(optarg); - break; - - case 9: - opt_match = args_getlong(optarg); - break; - - case 10: - opt_mismatch = args_getlong(optarg); - break; - - case 11: - opt_fulldp = 1; - break; - - case 12: - if (strcasecmp(optarg, "plus") == 0) - opt_strand = 1; - else if (strcasecmp(optarg, "both") == 0) - opt_strand = 2; - else - opt_strand = 0; - break; - - case 13: - opt_threads = args_getlong(optarg); - break; - - case 14: - args_get_gap_penalty_string(optarg, 1); - break; - - case 15: - args_get_gap_penalty_string(optarg, 0); - break; - - case 16: - opt_rowlen = args_getlong(optarg); - break; - - case 17: - if (!parse_userfields_arg(optarg)) - fatal("Unrecognized userfield argument"); - break; - - case 18: - opt_userout = optarg; - break; - - case 19: - opt_self = 1; - break; - - case 20: - opt_blast6out = optarg; - break; - - case 21: - opt_uc = optarg; - break; - - case 22: - opt_weak_id = args_getdouble(optarg); - break; - - case 23: - opt_uc_allhits = 1; - break; - - case 24: - opt_notrunclabels = 1; - break; - - case 25: - opt_sortbysize = optarg; - break; - - case 26: - opt_output = optarg; - break; - - case 27: - opt_minsize = args_getlong(optarg); - break; - - case 28: - opt_maxsize = args_getlong(optarg); - break; - - case 29: - opt_relabel = optarg; - break; - - case 30: - opt_sizeout = 1; - break; - - case 31: - opt_derep_fulllength = optarg; - break; - - case 32: - opt_minseqlength = args_getlong(optarg); - break; - - case 33: - opt_minuniquesize = args_getlong(optarg); - break; - - case 34: - opt_topn = args_getlong(optarg); - break; - - case 35: - opt_maxseqlength = args_getlong(optarg); - break; - - case 36: - opt_sizein = 1; - break; - - case 37: - opt_sortbylength = optarg; - break; - - case 38: - opt_matched = optarg; - break; - - case 39: - opt_notmatched = optarg; - break; - - case 40: - opt_dbmatched = optarg; - break; - - case 41: - opt_dbnotmatched = optarg; - break; - - case 42: - opt_fastapairs = optarg; - break; - - case 43: - opt_output_no_hits = 1; - break; - - case 44: - opt_maxhits = args_getlong(optarg); - break; - - case 45: - opt_top_hits_only = 1; - break; - - case 46: - opt_fasta_width = args_getlong(optarg); - break; - - case 47: - opt_query_cov = args_getdouble(optarg); - break; - - case 48: - opt_target_cov = args_getdouble(optarg); - break; - - case 49: - opt_idprefix = args_getlong(optarg); - break; - - case 50: - opt_idsuffix = args_getlong(optarg); - break; - - case 51: - opt_minqt = args_getdouble(optarg); - break; - - case 52: - opt_maxqt = args_getdouble(optarg); - break; - - case 53: - opt_minsl = args_getdouble(optarg); - break; - - case 54: - opt_maxsl = args_getdouble(optarg); - break; - - case 55: - opt_leftjust = 1; - break; - - case 56: - opt_rightjust = 1; - break; - - case 57: - opt_selfid = 1; - break; - - case 58: - opt_maxid = args_getdouble(optarg); - break; - - case 59: - opt_minsizeratio = args_getdouble(optarg); - break; - - case 60: - opt_maxsizeratio = args_getdouble(optarg); - break; - - case 61: - opt_maxdiffs = args_getlong(optarg); - break; - - case 62: - opt_maxsubs = args_getlong(optarg); - break; - - case 63: - opt_maxgaps = args_getlong(optarg); - break; - - case 64: - opt_mincols = args_getlong(optarg); - break; - - case 65: - opt_maxqsize = args_getlong(optarg); - break; - - case 66: - opt_mintsize = args_getlong(optarg); - break; - - case 67: - opt_mid = args_getdouble(optarg); - break; - - case 68: - opt_shuffle = optarg; - break; - - case 69: - opt_randseed = args_getlong(optarg); - break; - - case 70: - opt_maskfasta = optarg; - break; - - case 71: - opt_hardmask = 1; - break; - - case 72: - if (strcasecmp(optarg, "none") == 0) - opt_qmask = MASK_NONE; - else if (strcasecmp(optarg, "dust") == 0) - opt_qmask = MASK_DUST; - else if (strcasecmp(optarg, "soft") == 0) - opt_qmask = MASK_SOFT; - else - opt_qmask = MASK_ERROR; - break; - - case 73: - if (strcasecmp(optarg, "none") == 0) - opt_dbmask = MASK_NONE; - else if (strcasecmp(optarg, "dust") == 0) - opt_dbmask = MASK_DUST; - else if (strcasecmp(optarg, "soft") == 0) - opt_dbmask = MASK_SOFT; - else - opt_dbmask = MASK_ERROR; - break; - - case 74: - opt_cluster_smallmem = optarg; - break; - - case 75: - opt_cluster_fast = optarg; - break; - - case 76: - opt_centroids = optarg; - break; - - case 77: - opt_clusters = optarg; - break; - - case 78: - opt_consout = optarg; - break; - - case 79: - fprintf(stderr, "WARNING: Option --cons_truncate is ignored\n"); - opt_cons_truncate = 1; - break; - - case 80: - opt_msaout = optarg; - break; - - case 81: - opt_usersort = 1; - break; - - case 82: - opt_xn = args_getdouble(optarg); - break; - - case 83: - opt_iddef = args_getlong(optarg); - break; - - case 84: - fprintf(stderr, "WARNING: Option --slots is ignored\n"); - opt_slots = args_getlong(optarg); - break; - - case 85: - fprintf(stderr, "WARNING: Option --pattern is ignored\n"); - opt_pattern = optarg; - break; - - case 86: - opt_maxuniquesize = args_getlong(optarg); - break; - - case 87: - opt_abskew = args_getdouble(optarg); - break; - - case 88: - opt_chimeras = optarg; - break; - - case 89: - opt_dn = args_getdouble(optarg); - break; - - case 90: - opt_mindiffs = args_getlong(optarg); - break; - - case 91: - opt_mindiv = args_getdouble(optarg); - break; - - case 92: - opt_minh = args_getdouble(optarg); - break; - - case 93: - opt_nonchimeras = optarg; - break; - - case 94: - opt_uchime_denovo = optarg; - break; - - case 95: - opt_uchime_ref = optarg; - break; - - case 96: - opt_uchimealns = optarg; - break; - - case 97: - opt_uchimeout = optarg; - break; - - case 98: - opt_uchimeout5 = 1; - break; - - case 99: - opt_alignwidth = args_getlong(optarg); - break; - - case 100: - opt_allpairs_global = optarg; - break; - - case 101: - opt_acceptall = 1; - break; - - case 102: - opt_cluster_size = optarg; - break; - - case 103: - opt_samout = optarg; - break; - - case 104: - opt_log = optarg; - break; - - case 105: - opt_quiet = true; - break; - - case 106: - opt_fastx_subsample = optarg; - break; - - case 107: - opt_sample_pct = args_getdouble(optarg); - break; - - case 108: - opt_fastq_chars = optarg; - break; - - case 109: - opt_profile = optarg; - break; - - case 110: - opt_sample_size = args_getlong(optarg); - break; - - case 111: - opt_fastaout = optarg; - break; - - case 112: - opt_xsize = 1; - break; - - case 113: - opt_clusterout_id = 1; - break; - - case 114: - opt_clusterout_sort = 1; - break; - - case 115: - opt_borderline = optarg; - break; - - case 116: - opt_relabel_sha1 = 1; - break; - - case 117: - opt_relabel_md5 = 1; - break; - - case 118: - opt_derep_prefix = optarg; - break; - - case 119: - opt_fastq_filter = optarg; - break; - - case 120: - opt_fastqout = optarg; - break; - - case 121: - opt_fastaout_discarded = optarg; - break; - - case 122: - opt_fastqout_discarded = optarg; - break; - - case 123: - opt_fastq_truncqual = args_getlong(optarg); - break; - - case 124: - opt_fastq_maxee = args_getdouble(optarg); - break; - - case 125: - opt_fastq_trunclen = args_getlong(optarg); - break; - - case 126: - opt_fastq_minlen = args_getlong(optarg); - break; - - case 127: - opt_fastq_stripleft = args_getlong(optarg); - break; - - case 128: - opt_fastq_maxee_rate = args_getdouble(optarg); - break; - - case 129: - opt_fastq_maxns = args_getlong(optarg); - break; - - case 130: - opt_eeout = 1; - break; - - case 131: - opt_fastq_ascii = args_getlong(optarg); - break; - - case 132: - opt_fastq_qmin = args_getlong(optarg); - break; - - case 133: - opt_fastq_qmax = args_getlong(optarg); - break; - - case 134: - opt_fastq_qmaxout = args_getlong(optarg); - break; - - case 135: - opt_fastq_stats = optarg; - break; - - case 136: - opt_fastq_tail = args_getlong(optarg); - break; - - case 137: - opt_fastx_revcomp = optarg; - break; - - case 138: - opt_label_suffix = optarg; - break; - - case 139: - opt_help = 1; - break; - - case 140: - opt_samheader = 1; - break; - - case 141: - opt_sizeorder = 1; - break; - - default: - fatal("Internal error in option parsing"); - } - } - - /* Terminate if ambiguous or illegal options have been detected */ - if (c != -1) - exit(EXIT_FAILURE); - - /* Terminate after reporting any extra non-option arguments */ - if (optind < argc) - fatal("Unrecognized string on command line (%s)", argv[optind]); - - int commands = 0; - - if (opt_fastq_chars) - commands++; - if (opt_fastq_filter) - commands++; - if (opt_fastq_stats) - commands++; - if (opt_usearch_global) - commands++; - if (opt_sortbysize) - commands++; - if (opt_sortbylength) - commands++; - if (opt_derep_fulllength) - commands++; - if (opt_derep_prefix) - commands++; - if (opt_help) - commands++; - if (opt_version) - commands++; - if (opt_shuffle) - commands++; - if (opt_fastx_subsample) - commands++; - if (opt_maskfasta) - commands++; - if (opt_cluster_smallmem) - commands++; - if (opt_cluster_fast) - commands++; - if (opt_cluster_size) - commands++; - if (opt_uchime_denovo) - commands++; - if (opt_uchime_ref) - commands++; - if (opt_allpairs_global) - commands++; - if (opt_fastx_revcomp) - commands++; - - if (commands > 1) - fatal("More than one command specified"); - - if (opt_weak_id > opt_id) - opt_weak_id = opt_id; - - if (opt_maxrejects == -1) - { - if (opt_cluster_fast) - opt_maxrejects = 8; - else - opt_maxrejects = 32; - } - - if (opt_minseqlength < 0) - fatal("The argument to --minseqlength must be positive"); - - if (opt_maxaccepts < 0) - fatal("The argument to --maxaccepts must not be negative"); - - if (opt_maxrejects < 0) - fatal("The argument to --maxrejects must not be negative"); - - if ((opt_threads < 0) || (opt_threads > 1024)) - fatal("The argument to --threads must be in the range 0 (default) to 1024"); - - if ((opt_wordlength < 3) || (opt_wordlength > 15)) - fatal("The argument to --wordlength must be in the range 3 to 15"); - - if ((opt_iddef < 0) || (opt_iddef > 4)) - fatal("The argument to --iddef must in the range 0 to 4"); - - if (opt_match <= 0) - fatal("The argument to --match must be positive"); - - if (opt_mismatch >= 0) - fatal("The argument to --mismatch must be negative"); - - if (opt_alignwidth < 0) - fatal("The argument to --alignwidth must not be negative"); - - if (opt_rowlen < 0) - fatal("The argument to --rowlen must not be negative"); - - if (opt_strand < 1) - fatal("The argument to --strand must be plus or both"); - - if (opt_qmask == MASK_ERROR) - fatal("The argument to --qmask must be none, dust or soft"); - - if (opt_dbmask == MASK_ERROR) - fatal("The argument to --dbmask must be none, dust or soft"); - - if ((opt_sample_pct < 0.0) || (opt_sample_pct > 100.0)) - fatal("The argument to --sample_pct must be in the range 0.0 to 100.0"); - - if (opt_sample_size < 0) - fatal("The argument to --sample_size must not be negative"); - - if (opt_relabel_sha1 && opt_relabel_md5) - fatal("Specify either --relabel_sha1 or --relabel_md5, not both"); - - if (opt_fastq_tail < 1) - fatal("The argument to --fastq_tail must be positive"); - - - /* TODO: check valid range of gap penalties */ - - /* adapt/adjust parameters */ - -#if 1 - - /* - Adjust gap open penalty according to convention. - - The specified gap open penalties include the penalty for - a single nucleotide gap: - - gap penalty = gap open penalty + (gap length - 1) * gap extension penalty - - The rest of the code assumes the first nucleotide gap penalty is not - included in the gap opening penalty. - */ - - opt_gap_open_query_left -= opt_gap_extension_query_left; - opt_gap_open_target_left -= opt_gap_extension_target_left; - opt_gap_open_query_interior -= opt_gap_extension_query_interior; - opt_gap_open_target_interior -= opt_gap_extension_target_interior; - opt_gap_open_query_right -= opt_gap_extension_query_right; - opt_gap_open_target_right -= opt_gap_extension_target_right; - -#endif - - if (opt_threads == 0) - opt_threads = sysconf(_SC_NPROCESSORS_ONLN); - - /* set default opt_minseqlength depending on command */ - - if (opt_minseqlength == 0) - { - if (opt_cluster_smallmem || opt_cluster_fast || opt_cluster_size || - opt_usearch_global || opt_derep_fulllength || opt_derep_prefix ) - opt_minseqlength = 32; - else - opt_minseqlength = 1; - } -} - - -void cmd_help() -{ - /* 0 1 2 3 4 5 6 7 */ - /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ - - if (! opt_quiet) - { - fprintf(stdout, - "Usage: %s [OPTIONS]\n", progname); - - fprintf(stdout, - "\n" - "General options\n" - " --fasta_width INT width of FASTA seq lines, 0 for no wrap (80)\n" - " --help | --h display help information\n" - " --log FILENAME write messages, timing and memory info to file\n" - " --maxseqlength INT maximum sequence length (50000)\n" - " --minseqlength INT min seq length (clust/derep/search: 32, other:1)\n" - " --notrunclabels do not truncate labels at first space\n" - " --quiet output just warnings and fatal errors to stderr\n" - " --threads INT number of threads to use, zero for all cores (0)\n" - " --version display version information\n" - "\n" - "Chimera detection\n" - " --uchime_denovo FILENAME detect chimeras de novo\n" - " --uchime_ref FILENAME detect chimeras using a reference database\n" - "Options\n" - " --abskew REAL min abundance ratio of parent vs chimera (2.0)\n" - " --alignwidth INT width of alignment in uchimealn output (80)\n" - " --borderline FILENAME output borderline chimeric sequences to file\n" - " --chimeras FILENAME output chimeric sequences to file\n" - " --db FILENAME reference database for --uchime_ref\n" - " --dn REAL 'no' vote pseudo-count (1.4)\n" - " --mindiffs INT minimum number of differences in segment (3)\n" - " --mindiv REAL minimum divergence from closest parent (0.8)\n" - " --minh REAL minimum score (0.28)\n" - " --nonchimeras FILENAME output non-chimeric sequences to file\n" - " --relabel STRING relabel nonchimeras with this prefix string\n" - " --relabel_md5 relabel with md5 digest of normalized sequence\n" - " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" - " --self exclude identical labels for --uchime_ref\n" - " --selfid exclude identical sequences for --uchime_ref\n" - " --sizeout include abundance information when relabelling\n" - " --uchimealns FILENAME output chimera alignments to file\n" - " --uchimeout FILENAME output to chimera info to tab-separated file\n" - " --uchimeout5 make output compatible with uchime version 5\n" - " --xn REAL 'no' vote weight (8.0)\n" - "\n" - "Clustering\n" - " --cluster_fast FILENAME cluster sequences after sorting by length\n" - " --cluster_size FILENAME cluster sequences after sorting by abundance\n" - " --cluster_smallmem FILENAME cluster already sorted sequences (see -usersort)\n" - "Options (most searching options also apply)\n" - " --centroids FILENAME output centroid sequences to FASTA file\n" - " --clusterout_id add cluster id info to consout and profile files\n" - " --clusterout_sort order msaout, consout, profile by decr abundance\n" - " --clusters STRING output each cluster to a separate FASTA file\n" - " --consout FILENAME output cluster consensus sequences to FASTA file\n" - " --cons_truncate do not ignore terminal gaps in MSA for consensus\n" - " --id REAL reject if identity lower\n" - " --iddef INT id definition, 0-4=CD-HIT,all,int,MBL,BLAST (2)\n" - " --msaout FILENAME output multiple seq. alignments to FASTA file\n" - " --profile FILENAME output sequence profile of each cluster to file\n" - " --qmask none|dust|soft mask seqs with dust, soft or no method (dust)\n" - " --relabel STRING relabel centroids with this prefix string\n" - " --relabel_md5 relabel with md5 digest of normalized sequence\n" - " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" - " --sizein propagate abundance annotation from input\n" - " --sizeorder Sort accepted centroids by abundance (AGC)\n" - " --sizeout write cluster abundances to centroid file\n" - " --strand plus|both cluster using plus or both strands (plus)\n" - " --uc FILENAME filename for UCLUST-like output\n" - " --usersort indicate sequences not presorted by length\n" - "\n" - "Dereplication\n" - " --derep_fulllength FILENAME dereplicate sequences in the given FASTA file\n" - " --derep_prefix FILENAME dereplicate sequences in file based on prefixes\n" - "Options\n" - " --maxuniquesize INT maximum abundance for output from dereplication\n" - " --minuniquesize INT minimum abundance for output from dereplication\n" - " --output FILENAME output FASTA file\n" - " --relabel STRING relabel with this prefix string after derep.\n" - " --relabel_md5 relabel with md5 digest of normalized sequence\n" - " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" - " --sizein propagate abundance annotation from input\n" - " --sizeout write abundance annotation to output\n" - " --strand plus|both dereplicate plus or both strands (plus)\n" - " --topn INT output just the n most abundant sequences\n" - " --uc FILENAME filename for UCLUST-like output\n" - "\n" - "FASTA/FASTQ file processing\n" - " --fastq_chars FILENAME Analyse FASTQ file for version and quality range\n" - " --fastq_filter FILENAME Filter FASTQ file, output to FASTQ or FASTA file\n" - " --fastq_stats FILENAME Report FASTQ file statistics\n" - " --fastx_revcomp FILENAME Reverse-complement seqs in FASTA or FASTQ file\n" - "Options\n" - " --eeout Include expected errors in FASTQ filter output\n" - " --fastaout FILENAME FASTA filename for passed seqs from FASTQ filter\n" - " --fastaout_discarded FNAME FASTA filename for discarded by FASTQ filter\n" - " --fastq_ascii INT ASCII char no for FASTQ quality base value (33)\n" - " --fastq_maxee REAL Maximum expected error value for FASTQ filter\n" - " --fastq_maxee_rate REAL Maximum expected error rate for FASTQ filter\n" - " --fastq_maxns INT Maximum number of N's for FASTQ filter\n" - " --fastq_minlen INT Minimum length for FASTQ filter\n" - " --fastq_qmax INT Maximum base quality value for FASTQ input (41)\n" - " --fastq_qmaxout INT Maximum base quality value for FASTQ output\n" - " --fastq_qmin INT Minimum base quality value for FASTQ input (0)\n" - " --fastq_stripleft INT Bases on the left to delete for FASTQ filter\n" - " --fastq_tail INT Length of tails of same quality score to count\n" - " --fastq_trunclen INT Read length for FASTQ filter truncation\n" - " --fastq_truncqual INT Base quality value for FASTQ filter truncation\n" - " --fastqout FILENAME FASTQ filename for passed seqs from FASTQ filter\n" - " --fastqout_discarded FNAME FASTQ filename for discarded by FASTQ filter\n" - " --label_suffix STRING Label to add to output for --fastx_revcomp\n" - "\n" - "Masking\n" - " --maskfasta FILENAME mask sequences in the given FASTA file\n" - "Options\n" - " --hardmask mask by replacing with N instead of lower case\n" - " --output FILENAME output to specified FASTA file\n" - " --qmask none|dust|soft mask seqs with dust, soft or no method (dust)\n" - "\n" - "Pairwise alignment\n" - " --allpairs_global FILENAME perform global alignment of all sequence pairs\n" - "Options (most searching options also apply)\n" - " --alnout FILENAME filename for human-readable alignment output\n" - " --acceptall output all pairwise alignments\n" - "\n" - "Searching\n" - " --usearch_global FILENAME filename of queries for global alignment search\n" - "Options\n" - " --alnout FILENAME filename for human-readable alignment output\n" - " --blast6out FILENAME filename for blast-like tab-separated output\n" - " --db FILENAME filename for FASTA formatted database for search\n" - " --dbmask none|dust|soft mask db with dust, soft or no method (dust)\n" - " --dbmatched FILENAME FASTA file for matching database sequences\n" - " --dbnotmatched FILENAME FASTA file for non-matching database sequences\n" - " --fastapairs FILENAME FASTA file with pairs of query and target\n" - " --fulldp full dynamic programming alignment (always on)\n" - " --gapext STRING penalties for gap extension (2I/1E)\n" - " --gapopen STRING penalties for gap opening (20I/2E)\n" - " --hardmask mask by replacing with N instead of lower case\n" - " --id REAL reject if identity lower\n" - " --iddef INT id definition, 0-4=CD-HIT,all,int,MBL,BLAST (2)\n" - " --idprefix INT reject if first n nucleotides do not match\n" - " --idsuffix INT reject if last n nucleotides do not match\n" - " --leftjust reject if terminal gaps at alignment left end\n" - " --match INT score for match (2)\n" - " --matched FILENAME FASTA file for matching query sequences\n" - " --maxaccepts INT number of hits to accept and show per strand (1)\n" - " --maxdiffs INT reject if more substitutions or indels\n" - " --maxgaps INT reject if more indels\n" - " --maxhits INT maximum number of hits to show (unlimited)\n" - " --maxid REAL reject if identity higher\n" - " --maxqsize INT reject if query abundance larger\n" - " --maxqt REAL reject if query/target length ratio higher\n" - " --maxrejects INT number of non-matching hits to consider (32)\n" - " --maxsizeratio REAL reject if query/target abundance ratio higher\n" - " --maxsl REAL reject if shorter/longer length ratio higher\n" - " --maxsubs INT reject if more substitutions\n" - " --mid REAL reject if percent identity lower, ignoring gaps\n" - " --mincols INT reject if alignment length shorter\n" - " --minqt REAL reject if query/target length ratio lower\n" - " --minsizeratio REAL reject if query/target abundance ratio lower\n" - " --minsl REAL reject if shorter/longer length ratio lower\n" - " --mintsize INT reject if target abundance lower\n" - " --mismatch INT score for mismatch (-4)\n" - " --notmatched FILENAME FASTA file for non-matching query sequences\n" - " --output_no_hits output non-matching queries to output files\n" - " --pattern STRING option is ignored\n" - " --qmask none|dust|soft mask query with dust, soft or no method (dust)\n" - " --query_cov REAL reject if fraction of query seq. aligned lower\n" - " --rightjust reject if terminal gaps at alignment right end\n" - " --rowlen INT width of alignment lines in alnout output (64)\n" - " --samheader include a header in the SAM output file\n" - " --samout FILENAME filename for SAM format output\n" - " --self reject if labels identical\n" - " --selfid reject if sequences identical\n" - " --sizeout write abundance annotation to dbmatched file\n" - " --slots INT option is ignored\n" - " --strand plus|both search plus or both strands (plus)\n" - " --target_cov REAL reject if fraction of target seq. aligned lower\n" - " --top_hits_only output only hits with identity equal to the best\n" - " --uc FILENAME filename for UCLUST-like output\n" - " --uc_allhits show all, not just top hit with uc output\n" - " --userfields STRING fields to output in userout file\n" - " --userout FILENAME filename for user-defined tab-separated output\n" - " --weak_id REAL include aligned hits with >= id; continue search\n" - " --wordlength INT length of words for database index 3-15 (8)\n" - "\n" - "Shuffling\n" - " --shuffle FILENAME shuffle order of sequences in FASTA file randomly\n" - "Options\n" - " --output FILENAME output to specified FASTA file\n" - " --randseed INT seed for PRNG, zero to use random data source (0)\n" - " --topn INT output just first n sequences\n" - "\n" - "Sorting\n" - " --sortbylength FILENAME sort sequences by length in given FASTA file\n" - " --sortbysize FILENAME abundance sort sequences in given FASTA file\n" - "Options\n" - " --maxsize INT maximum abundance for sortbysize\n" - " --minsize INT minimum abundance for sortbysize\n" - " --output FILENAME output FASTA file\n" - " --relabel STRING relabel with this prefix string after sorting\n" - " --relabel_md5 relabel with md5 digest of normalized sequence\n" - " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" - " --sizeout include abundance information when relabelling\n" - " --topn INT output just top n seqs after sorting\n" - "\n" - "Subsampling\n" - " --fastx_subsample FILENAME subsample sequences from given FASTA file\n" - "Options\n" - " --fastaout FILENAME output FASTA file for subsamples\n" - " --randseed INT seed for PRNG, zero to use random data source (0)\n" - " --sample_pct REAL sampling percentage between 0.0 and 100.0\n" - " --sample_size INT sampling size\n" - " --sizein consider abundance info from input, do not ignore\n" - " --sizeout update abundance information in output\n" - " --xsize strip abundance information in output\n" - ); - } -} - -void cmd_allpairs_global() -{ - /* check options */ - - if ((!opt_alnout) && (!opt_userout) && - (!opt_uc) && (!opt_blast6out) && - (!opt_matched) && (!opt_notmatched) && - (!opt_samout)) - fatal("No output files specified"); - - if (! (opt_acceptall || ((opt_id >= 0.0) && (opt_id <= 1.0)))) - fatal("Specify either --acceptall or --id with an identity from 0.0 to 1.0"); - - allpairs_global(cmdline, progheader); -} - -void cmd_usearch_global() -{ - /* check options */ - - if ((!opt_alnout) && (!opt_userout) && - (!opt_uc) && (!opt_blast6out) && - (!opt_matched) && (!opt_notmatched) && - (!opt_dbmatched) && (!opt_dbnotmatched) && - (!opt_samout)) - fatal("No output files specified"); - - if (!opt_db) - fatal("Database filename not specified with --db"); - - if ((opt_id < 0.0) || (opt_id > 1.0)) - fatal("Identity between 0.0 and 1.0 must be specified with --id"); - - usearch_global(cmdline, progheader); -} - -void cmd_sortbysize() -{ - if (!opt_output) - fatal("FASTA output file for sortbysize must be specified with --output"); - - sortbysize(); -} - -void cmd_sortbylength() -{ - if (!opt_output) - fatal("FASTA output file for sortbylength must be specified with --output"); - - sortbylength(); -} - -void cmd_derep() -{ - if ((!opt_output) && (!opt_uc)) - fatal("Output file for derepl_fulllength must be specified with --output or --uc"); - - if (opt_derep_fulllength) - derep_fulllength(); - else - { - if (opt_strand > 1) - fatal("Option '--strand both' not supported with --derep_prefix"); - else - derep_prefix(); - } -} - -void cmd_shuffle() -{ - if (!opt_output) - fatal("Output file for shuffling must be specified with --output"); - - shuffle(); -} - -void cmd_subsample() -{ - if (!opt_fastaout) - fatal("Output file for subsampling must be specified with --fastaout"); - - if ((opt_sample_pct > 0) && (opt_sample_size > 0)) - fatal("Specify either --sample_pct or --sample_size, not both"); - - subsample(); -} - -void cmd_maskfasta() -{ - if (!opt_output) - fatal("Output file for masking must be specified with --output"); - - maskfasta(); -} - -void cmd_none() -{ - if (! opt_quiet) - fprintf(stderr, - "For help, please enter: %s --help\n" - "\n" - "For further details, please see the manual by entering: man vsearch\n" - "\n" - "Some basic command examples:\n" - "\n" - "vsearch --allpairs_global FILENAME --id 0.5 --alnout FILENAME\n" - "vsearch --cluster_fast FILENAME --id 0.97 --centroids FILENAME\n" - "vsearch --cluster_size FILENAME --id 0.97 --centroids FILENAME\n" - "vsearch --cluster_smallmem FILENAME --usersort --id 0.97 --centroids FILENAME\n" - "vsearch --derep_fulllength FILENAME --output FILENAME\n" - "vsearch --maskfasta FILENAME --output FILENAME\n" - "vsearch --shuffle FILENAME --output FILENAME\n" - "vsearch --sortbylength FILENAME --output FILENAME\n" - "vsearch --sortbysize FILENAME --output FILENAME\n" - "vsearch --uchime_denovo FILENAME --nonchimeras FILENAME\n" - "vsearch --uchime_ref FILENAME --db FILENAME --nonchimeras FILENAME\n" - "vsearch --usearch_global FILENAME --db FILENAME --id 0.97 --alnout FILENAME\n" - "\n", - progname); -} - -void cmd_fastx_revcomp() -{ - if ((!opt_fastaout) && (!opt_fastqout)) - fatal("No output files specified"); - - fastx_revcomp(); -} - -void cmd_cluster() -{ - if ((!opt_alnout) && (!opt_userout) && - (!opt_uc) && (!opt_blast6out) && - (!opt_matched) && (!opt_notmatched) && - (!opt_centroids) && (!opt_clusters) && - (!opt_consout) && (!opt_msaout) && - (!opt_samout) && (!opt_profile)) - fatal("No output files specified"); - - if ((opt_id < 0.0) || (opt_id > 1.0)) - fatal("Identity between 0.0 and 1.0 must be specified with --id"); - - if (opt_cluster_fast) - cluster_fast(cmdline, progheader); - else if (opt_cluster_smallmem) - cluster_smallmem(cmdline, progheader); - else if (opt_cluster_size) - cluster_size(cmdline, progheader); -} - -void cmd_uchime() -{ - if ((!opt_chimeras) && (!opt_nonchimeras) && - (!opt_uchimeout) && (!opt_uchimealns)) - fatal("No output files specified"); - - if (opt_uchime_ref && ! opt_db) - fatal("Database filename not specified with --db"); - - if (opt_xn <= 1.0) - fatal("Argument to --xn must be > 1"); - - if (opt_dn <= 0.0) - fatal("Argument to --dn must be > 0"); - - if (opt_mindiffs <= 0) - fatal("Argument to --mindiffs must be > 0"); - - if (opt_mindiv <= 0.0) - fatal("Argument to --mindiv must be > 0"); - - if (opt_minh <= 0.0) - fatal("Argument to --minh must be > 0"); - - if (opt_abskew <= 1.0) - fatal("Argument to --abskew must be > 1"); - - chimera(); -} - -void cmd_fastq_filter() -{ - if ((!opt_fastqout) && (!opt_fastaout) && - (!opt_fastqout_discarded) && (!opt_fastaout_discarded)) - fatal("No output files specified"); - fastq_filter(); -} - -void fillheader() -{ - snprintf(progheader, 80, - "%s v%s_%s, %.1fGB RAM, %ld cores", - PROG_NAME, PROG_VERSION, PROG_ARCH, - arch_get_memtotal() / 1024.0 / 1024.0 / 1024.0, - sysconf(_SC_NPROCESSORS_ONLN)); -} - -void getentirecommandline(int argc, char *argv[]) -{ - int len = 0; - for (int i=0; i, + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "vsearch.h" + +/* options */ + +bool opt_fastq_allowmergestagger; +bool opt_fastq_nostagger; +bool opt_fastq_eeout; +bool opt_clusterout_id; +bool opt_clusterout_sort; +bool opt_eeout; +bool opt_quiet; +bool opt_relabel_keep; +bool opt_relabel_md5; +bool opt_relabel_sha1; +bool opt_samheader; +bool opt_sizeorder; +bool opt_xsize; +char * opt_eetabbedout; +char * opt_fastaout_notmerged_fwd; +char * opt_fastaout_notmerged_rev; +char * opt_fastq_mergepairs; +char * opt_fastqout_notmerged_fwd; +char * opt_fastqout_notmerged_rev; +char * opt_allpairs_global; +char * opt_alnout; +char * opt_blast6out; +char * opt_borderline; +char * opt_centroids; +char * opt_chimeras; +char * opt_cluster_fast; +char * opt_cluster_size; +char * opt_cluster_smallmem; +char * opt_clusters; +char * opt_consout; +char * opt_db; +char * opt_dbmatched; +char * opt_dbnotmatched; +char * opt_derep_fulllength; +char * opt_derep_prefix; +char * opt_fastaout; +char * opt_fastaout_discarded; +char * opt_fastapairs; +char * opt_fastq_chars; +char * opt_fastq_convert; +char * opt_fastq_filter; +char * opt_fastq_stats; +char * opt_fastqout; +char * opt_fastqout_discarded; +char * opt_fastx_mask; +char * opt_fastx_revcomp; +char * opt_fastx_subsample; +char * opt_label_suffix; +char * opt_log; +char * opt_maskfasta; +char * opt_matched; +char * opt_msaout; +char * opt_nonchimeras; +char * opt_notmatched; +char * opt_output; +char * opt_pattern; +char * opt_profile; +char * opt_relabel; +char * opt_samout; +char * opt_search_exact; +char * opt_shuffle; +char * opt_sortbylength; +char * opt_sortbysize; +char * opt_uc; +char * opt_uchime_denovo; +char * opt_uchime_ref; +char * opt_uchimealns; +char * opt_uchimeout; +char * opt_usearch_global; +char * opt_userout; +char * opt_reverse; +double opt_abskew; +double opt_dn; +double opt_fastq_maxee; +double opt_fastq_maxee_rate; +double opt_id; +double opt_max_unmasked_pct; +double opt_maxid; +double opt_maxqt; +double opt_maxsizeratio; +double opt_maxsl; +double opt_mid; +double opt_min_unmasked_pct; +double opt_mindiv; +double opt_minh; +double opt_minqt; +double opt_minsizeratio; +double opt_minsl; +double opt_query_cov; +double opt_sample_pct; +double opt_target_cov; +double opt_weak_id; +double opt_xn; +int opt_acceptall; +int opt_alignwidth; +int opt_cons_truncate; +int opt_gap_extension_query_interior; +int opt_gap_extension_query_left; +int opt_gap_extension_query_right; +int opt_gap_extension_target_interior; +int opt_gap_extension_target_left; +int opt_gap_extension_target_right; +int opt_gap_open_query_interior; +int opt_gap_open_query_left; +int opt_gap_open_query_right; +int opt_gap_open_target_interior; +int opt_gap_open_target_left; +int opt_gap_open_target_right; +int opt_help; +int opt_mindiffs; +int opt_slots; +int opt_uchimeout5; +int opt_usersort; +int opt_version; +long opt_fastq_maxdiffs; +long opt_fastq_maxmergelen; +long opt_fastq_minmergelen; +long opt_fastq_minovlen; +long opt_dbmask; +long opt_fasta_width; +long opt_fastq_ascii; +long opt_fastq_asciiout; +long opt_fastq_maxns; +long opt_fastq_minlen; +long opt_fastq_qmax; +long opt_fastq_qmaxout; +long opt_fastq_qmin; +long opt_fastq_qminout; +long opt_fastq_stripleft; +long opt_fastq_tail; +long opt_fastq_trunclen; +long opt_fastq_truncqual; +long opt_fulldp; +long opt_hardmask; +long opt_iddef; +long opt_idprefix; +long opt_idsuffix; +long opt_leftjust; +long opt_match; +long opt_maxaccepts; +long opt_maxdiffs; +long opt_maxgaps; +long opt_maxhits; +long opt_maxqsize; +long opt_maxrejects; +long opt_maxseqlength; +long opt_maxsize; +long opt_maxsubs; +long opt_maxuniquesize; +long opt_mincols; +long opt_minseqlength; +long opt_minsize; +long opt_mintsize; +long opt_minuniquesize; +long opt_minwordmatches; +long opt_mismatch; +long opt_notrunclabels; +long opt_output_no_hits; +long opt_qmask; +long opt_randseed; +long opt_rightjust; +long opt_rowlen; +long opt_sample_size; +long opt_self; +long opt_selfid; +long opt_sizein; +long opt_sizeout; +long opt_strand; +long opt_threads; +long opt_top_hits_only; +long opt_topn; +long opt_uc_allhits; +long opt_wordlength; + +/* Other variables */ + +/* cpu features available */ + +long mmx_present = 0; +long sse_present = 0; +long sse2_present = 0; +long sse3_present = 0; +long ssse3_present = 0; +long sse41_present = 0; +long sse42_present = 0; +long popcnt_present = 0; +long avx_present = 0; +long avx2_present = 0; + +static char * progname; +static char progheader[80]; +static char * cmdline; +static time_t time_start; +static time_t time_finish; + +FILE * fp_log = 0; + +abundance_t * global_abundance; + +#define cpuid(f1, f2, a, b, c, d) \ + __asm__ __volatile__ ("cpuid" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "a" (f1), "c" (f2)); + +void cpu_features_detect() +{ + unsigned int a, b, c, d; + + cpuid(0, 0, a, b, c, d); + unsigned int maxlevel = a & 0xff; + + if (maxlevel >= 1) + { + cpuid(1, 0, a, b, c, d); + mmx_present = (d >> 23) & 1; + sse_present = (d >> 25) & 1; + sse2_present = (d >> 26) & 1; + sse3_present = (c >> 0) & 1; + ssse3_present = (c >> 9) & 1; + sse41_present = (c >> 19) & 1; + sse42_present = (c >> 20) & 1; + popcnt_present = (c >> 23) & 1; + avx_present = (c >> 28) & 1; + + if (maxlevel >= 7) + { + cpuid(7, 0, a, b, c, d); + avx2_present = (b >> 5) & 1; + } + } +} + +void cpu_features_show() +{ + fprintf(stderr, "CPU features:"); + if (mmx_present) + fprintf(stderr, " mmx"); + if (sse_present) + fprintf(stderr, " sse"); + if (sse2_present) + fprintf(stderr, " sse2"); + if (sse3_present) + fprintf(stderr, " sse3"); + if (ssse3_present) + fprintf(stderr, " ssse3"); + if (sse41_present) + fprintf(stderr, " sse4.1"); + if (sse42_present) + fprintf(stderr, " sse4.2"); + if (popcnt_present) + fprintf(stderr, " popcnt"); + if (avx_present) + fprintf(stderr, " avx"); + if (avx2_present) + fprintf(stderr, " avx2"); + fprintf(stderr, "\n"); +} + + +void args_get_gap_penalty_string(char * arg, int is_open) +{ + /* See http://www.drive5.com/usearch/manual/aln_params.html + + --gapopen *E/10I/1E/2L/3RQ/4RT/1IQ + --gapext *E/10I/1E/2L/3RQ/4RT/1IQ + + integer or * + followed by I, E, L, R, Q or T characters + separated by / + * means infinitely high (disallow) + E=end + I=interior + L=left + R=right + Q=query + T=target + + E cannot be combined with L or R + + We do not support floating point values. Therefore, + all default score and penalties are multiplied by 2. + + */ + + char *p = arg; + + while (*p) + { + int skip = 0; + int pen = 0; + + if (sscanf(p, "%d%n", &pen, &skip) == 1) + { + p += skip; + } + else if (*p == '*') + { + pen = 1000; + p++; + } + else + fatal("Invalid gap penalty argument (%s)", p); + + char * q = p; + + int set_E = 0; + int set_I = 0; + int set_L = 0; + int set_R = 0; + int set_Q = 0; + int set_T = 0; + + while((*p) && (*p != '/')) + { + switch(*p) + { + case 'E': + set_E = 1; + break; + case 'I': + set_I = 1; + break; + case 'L': + set_L = 1; + break; + case 'R': + set_R = 1; + break; + case 'Q': + set_Q = 1; + break; + case 'T': + set_T = 1; + break; + default: + fatal("Invalid char '%.1s' in gap penalty string", p); + break; + } + p++; + } + + if (*p == '/') + p++; + + if (set_E && (set_L || set_R)) + fatal("Invalid gap penalty string (E and L or R) '%s'", q); + + if (set_E) + { + set_L = 1; + set_R = 1; + } + + /* if neither L, I, R nor E is specified, it applies to all */ + + if ((!set_L) && (!set_I) && (!set_R)) + { + set_L = 1; + set_I = 1; + set_R = 1; + } + + /* if neither Q nor T is specified, it applies to both */ + + if ((!set_Q) && (!set_T)) + { + set_Q = 1; + set_T = 1; + } + + if (is_open) + { + if (set_Q) + { + if (set_L) + opt_gap_open_query_left = pen; + if (set_I) + opt_gap_open_query_interior = pen; + if (set_R) + opt_gap_open_query_right = pen; + } + if (set_T) + { + if (set_L) + opt_gap_open_target_left = pen; + if (set_I) + opt_gap_open_target_interior = pen; + if (set_R) + opt_gap_open_target_right = pen; + } + } + else + { + if (set_Q) + { + if (set_L) + opt_gap_extension_query_left = pen; + if (set_I) + opt_gap_extension_query_interior = pen; + if (set_R) + opt_gap_extension_query_right = pen; + } + if (set_T) + { + if (set_L) + opt_gap_extension_target_left = pen; + if (set_I) + opt_gap_extension_target_interior = pen; + if (set_R) + opt_gap_extension_target_right = pen; + } + } + } +} + + +long args_getlong(char * arg) +{ + int len = 0; + long temp = 0; + int ret = sscanf(arg, "%ld%n", &temp, &len); + if ((ret == 0) || (((unsigned int)(len)) < strlen(arg))) + fatal("Illegal option argument"); + return temp; +} + +double args_getdouble(char * arg) +{ + int len = 0; + double temp = 0; + int ret = sscanf(arg, "%lf%n", &temp, &len); + if ((ret == 0) || (((unsigned int)(len)) < strlen(arg))) + fatal("Illegal option argument"); + return temp; +} + +void args_init(int argc, char **argv) +{ + /* Set defaults */ + + progname = argv[0]; + + opt_abskew = 2.0; + opt_acceptall = 0; + opt_alignwidth = 80; + opt_allpairs_global = 0; + opt_alnout = 0; + opt_blast6out = 0; + opt_borderline = 0; + opt_centroids = 0; + opt_chimeras = 0; + opt_cluster_fast = 0; + opt_cluster_size = 0; + opt_cluster_smallmem = 0; + opt_clusterout_id = 0; + opt_clusterout_sort = 0; + opt_clusters = 0; + opt_cons_truncate = 0; + opt_consout = 0; + opt_db = 0; + opt_dbmask = MASK_DUST; + opt_dbmatched = 0; + opt_dbnotmatched = 0; + opt_derep_fulllength = 0; + opt_derep_prefix = 0; + opt_dn = 1.4; + opt_eeout = 0; + opt_eetabbedout = 0; + opt_fastaout_notmerged_fwd = 0; + opt_fastaout_notmerged_rev = 0; + opt_fasta_width = 80; + opt_fastaout = 0; + opt_fastaout_discarded = 0; + opt_fastapairs = 0; + opt_fastq_allowmergestagger = 0; + opt_fastq_ascii = 33; + opt_fastq_asciiout = 33; + opt_fastq_chars = 0; + opt_fastq_convert = 0; + opt_fastq_eeout = 0; + opt_fastq_filter = 0; + opt_fastq_maxdiffs = 1000000; + opt_fastq_maxee = DBL_MAX; + opt_fastq_maxee_rate = DBL_MAX; + opt_fastq_maxmergelen = 1000000; + opt_fastq_maxns = LONG_MAX; + opt_fastq_mergepairs = 0; + opt_fastq_minlen = 1; + opt_fastq_minmergelen = 0; + opt_fastq_minovlen = 16; + opt_fastq_nostagger = 1; + opt_fastqout_notmerged_fwd = 0; + opt_fastqout_notmerged_rev = 0; + opt_fastq_qmax = 41; + opt_fastq_qmaxout = 41; + opt_fastq_qmin = 0; + opt_fastq_qminout = 0; + opt_fastq_stats = 0; + opt_fastq_stripleft = 0; + opt_fastq_tail = 4; + opt_fastq_trunclen = 0; + opt_fastq_truncqual = LONG_MIN; + opt_fastqout = 0; + opt_fastqout_discarded = 0; + opt_fastx_mask = 0; + opt_fastx_revcomp = 0; + opt_fastx_subsample = 0; + opt_fulldp = 0; + opt_gap_extension_query_interior=2; + opt_gap_extension_query_left=1; + opt_gap_extension_query_right=1; + opt_gap_extension_target_interior=2; + opt_gap_extension_target_left=1; + opt_gap_extension_target_right=1; + opt_gap_open_query_interior=20; + opt_gap_open_query_left=2; + opt_gap_open_query_right=2; + opt_gap_open_target_interior=20; + opt_gap_open_target_left=2; + opt_gap_open_target_right=2; + opt_hardmask = 0; + opt_help = 0; + opt_id = -1.0; + opt_iddef = 2; + opt_idprefix = 0; + opt_idsuffix = 0; + opt_label_suffix = 0; + opt_leftjust = 0; + opt_log = 0; + opt_maskfasta = 0; + opt_match = 2; + opt_matched = 0; + opt_max_unmasked_pct = 100.0; + opt_maxaccepts = 1; + opt_maxdiffs = INT_MAX; + opt_maxgaps = INT_MAX; + opt_maxhits = LONG_MAX; + opt_maxid = 1.0; + opt_maxqsize = INT_MAX; + opt_maxqt = DBL_MAX; + opt_maxrejects = -1; + opt_maxseqlength = 50000; + opt_maxsize = LONG_MAX; + opt_maxsizeratio = DBL_MAX; + opt_maxsl = DBL_MAX; + opt_maxsubs = INT_MAX; + opt_maxuniquesize = LONG_MAX; + opt_mid = 0.0; + opt_min_unmasked_pct = 0.0; + opt_mincols = 0; + opt_mindiffs = 3; + opt_mindiv = 0.8; + opt_minh = 0.28; + opt_minqt = 0.0; + opt_minseqlength = 0; + opt_minsize = 0; + opt_minsizeratio = 0.0; + opt_minsl = 0.0; + opt_mintsize = 0; + opt_minuniquesize = 0; + opt_minwordmatches = 0; + opt_mismatch = -4; + opt_msaout = 0; + opt_nonchimeras = 0; + opt_notmatched = 0; + opt_notrunclabels = 0; + opt_output = 0; + opt_output_no_hits = 0; + opt_pattern = 0; + opt_profile = 0; + opt_qmask = MASK_DUST; + opt_query_cov = 0.0; + opt_quiet = false; + opt_randseed = 0; + opt_relabel = 0; + opt_relabel_keep = 0; + opt_relabel_md5 = 0; + opt_relabel_sha1 = 0; + opt_reverse = 0; + opt_rightjust = 0; + opt_rowlen = 64; + opt_samheader = 0; + opt_samout = 0; + opt_sample_pct = 0; + opt_sample_size = 0; + opt_search_exact = 0; + opt_self = 0; + opt_selfid = 0; + opt_shuffle = 0; + opt_sizein = 0; + opt_sizeorder = 0; + opt_sizeout = 0; + opt_slots = 0; + opt_sortbylength = 0; + opt_sortbysize = 0; + opt_strand = 1; + opt_target_cov = 0.0; + opt_threads = 0; + opt_top_hits_only = 0; + opt_topn = LONG_MAX; + opt_uc = 0; + opt_uc_allhits = 0; + opt_uchime_denovo = 0; + opt_uchime_ref = 0; + opt_uchimealns = 0; + opt_uchimeout = 0; + opt_uchimeout5 = 0; + opt_usearch_global = 0; + opt_userout = 0; + opt_usersort = 0; + opt_version = 0; + opt_weak_id = 10.0; + opt_wordlength = 8; + opt_xn = 8.0; + opt_xsize = 0; + + opterr = 1; + + static struct option long_options[] = + + { + {"help", no_argument, 0, 0 }, + {"version", no_argument, 0, 0 }, + {"alnout", required_argument, 0, 0 }, + {"usearch_global", required_argument, 0, 0 }, + {"db", required_argument, 0, 0 }, + {"id", required_argument, 0, 0 }, + {"maxaccepts", required_argument, 0, 0 }, + {"maxrejects", required_argument, 0, 0 }, + {"wordlength", required_argument, 0, 0 }, + {"match", required_argument, 0, 0 }, + {"mismatch", required_argument, 0, 0 }, + {"fulldp", no_argument, 0, 0 }, + {"strand", required_argument, 0, 0 }, + {"threads", required_argument, 0, 0 }, + {"gapopen", required_argument, 0, 0 }, + {"gapext", required_argument, 0, 0 }, + {"rowlen", required_argument, 0, 0 }, + {"userfields", required_argument, 0, 0 }, + {"userout", required_argument, 0, 0 }, + {"self", no_argument, 0, 0 }, + {"blast6out", required_argument, 0, 0 }, + {"uc", required_argument, 0, 0 }, + {"weak_id", required_argument, 0, 0 }, + {"uc_allhits", no_argument, 0, 0 }, + {"notrunclabels", no_argument, 0, 0 }, + {"sortbysize", required_argument, 0, 0 }, + {"output", required_argument, 0, 0 }, + {"minsize", required_argument, 0, 0 }, + {"maxsize", required_argument, 0, 0 }, + {"relabel", required_argument, 0, 0 }, + {"sizeout", no_argument, 0, 0 }, + {"derep_fulllength", required_argument, 0, 0 }, + {"minseqlength", required_argument, 0, 0 }, + {"minuniquesize", required_argument, 0, 0 }, + {"topn", required_argument, 0, 0 }, + {"maxseqlength", required_argument, 0, 0 }, + {"sizein", no_argument, 0, 0 }, + {"sortbylength", required_argument, 0, 0 }, + {"matched", required_argument, 0, 0 }, + {"notmatched", required_argument, 0, 0 }, + {"dbmatched", required_argument, 0, 0 }, + {"dbnotmatched", required_argument, 0, 0 }, + {"fastapairs", required_argument, 0, 0 }, + {"output_no_hits", no_argument, 0, 0 }, + {"maxhits", required_argument, 0, 0 }, + {"top_hits_only", no_argument, 0, 0 }, + {"fasta_width", required_argument, 0, 0 }, + {"query_cov", required_argument, 0, 0 }, + {"target_cov", required_argument, 0, 0 }, + {"idprefix", required_argument, 0, 0 }, + {"idsuffix", required_argument, 0, 0 }, + {"minqt", required_argument, 0, 0 }, + {"maxqt", required_argument, 0, 0 }, + {"minsl", required_argument, 0, 0 }, + {"maxsl", required_argument, 0, 0 }, + {"leftjust", no_argument, 0, 0 }, + {"rightjust", no_argument, 0, 0 }, + {"selfid", no_argument, 0, 0 }, + {"maxid", required_argument, 0, 0 }, + {"minsizeratio", required_argument, 0, 0 }, + {"maxsizeratio", required_argument, 0, 0 }, + {"maxdiffs", required_argument, 0, 0 }, + {"maxsubs", required_argument, 0, 0 }, + {"maxgaps", required_argument, 0, 0 }, + {"mincols", required_argument, 0, 0 }, + {"maxqsize", required_argument, 0, 0 }, + {"mintsize", required_argument, 0, 0 }, + {"mid", required_argument, 0, 0 }, + {"shuffle", required_argument, 0, 0 }, + {"randseed", required_argument, 0, 0 }, + {"maskfasta", required_argument, 0, 0 }, + {"hardmask", no_argument, 0, 0 }, + {"qmask", required_argument, 0, 0 }, + {"dbmask", required_argument, 0, 0 }, + {"cluster_smallmem", required_argument, 0, 0 }, + {"cluster_fast", required_argument, 0, 0 }, + {"centroids", required_argument, 0, 0 }, + {"clusters", required_argument, 0, 0 }, + {"consout", required_argument, 0, 0 }, + {"cons_truncate", no_argument, 0, 0 }, + {"msaout", required_argument, 0, 0 }, + {"usersort", no_argument, 0, 0 }, + {"xn", required_argument, 0, 0 }, + {"iddef", required_argument, 0, 0 }, + {"slots", required_argument, 0, 0 }, + {"pattern", required_argument, 0, 0 }, + {"maxuniquesize", required_argument, 0, 0 }, + {"abskew", required_argument, 0, 0 }, + {"chimeras", required_argument, 0, 0 }, + {"dn", required_argument, 0, 0 }, + {"mindiffs", required_argument, 0, 0 }, + {"mindiv", required_argument, 0, 0 }, + {"minh", required_argument, 0, 0 }, + {"nonchimeras", required_argument, 0, 0 }, + {"uchime_denovo", required_argument, 0, 0 }, + {"uchime_ref", required_argument, 0, 0 }, + {"uchimealns", required_argument, 0, 0 }, + {"uchimeout", required_argument, 0, 0 }, + {"uchimeout5", no_argument, 0, 0 }, + {"alignwidth", required_argument, 0, 0 }, + {"allpairs_global", required_argument, 0, 0 }, + {"acceptall", no_argument, 0, 0 }, + {"cluster_size", required_argument, 0, 0 }, + {"samout", required_argument, 0, 0 }, + {"log", required_argument, 0, 0 }, + {"quiet", no_argument, 0, 0 }, + {"fastx_subsample", required_argument, 0, 0 }, + {"sample_pct", required_argument, 0, 0 }, + {"fastq_chars", required_argument, 0, 0 }, + {"profile", required_argument, 0, 0 }, + {"sample_size", required_argument, 0, 0 }, + {"fastaout", required_argument, 0, 0 }, + {"xsize", no_argument, 0, 0 }, + {"clusterout_id", no_argument, 0, 0 }, + {"clusterout_sort", no_argument, 0, 0 }, + {"borderline", required_argument, 0, 0 }, + {"relabel_sha1", no_argument, 0, 0 }, + {"relabel_md5", no_argument, 0, 0 }, + {"derep_prefix", required_argument, 0, 0 }, + {"fastq_filter", required_argument, 0, 0 }, + {"fastqout", required_argument, 0, 0 }, + {"fastaout_discarded", required_argument, 0, 0 }, + {"fastqout_discarded", required_argument, 0, 0 }, + {"fastq_truncqual", required_argument, 0, 0 }, + {"fastq_maxee", required_argument, 0, 0 }, + {"fastq_trunclen", required_argument, 0, 0 }, + {"fastq_minlen", required_argument, 0, 0 }, + {"fastq_stripleft", required_argument, 0, 0 }, + {"fastq_maxee_rate", required_argument, 0, 0 }, + {"fastq_maxns", required_argument, 0, 0 }, + {"eeout", no_argument, 0, 0 }, + {"fastq_ascii", required_argument, 0, 0 }, + {"fastq_qmin", required_argument, 0, 0 }, + {"fastq_qmax", required_argument, 0, 0 }, + {"fastq_qmaxout", required_argument, 0, 0 }, + {"fastq_stats", required_argument, 0, 0 }, + {"fastq_tail", required_argument, 0, 0 }, + {"fastx_revcomp", required_argument, 0, 0 }, + {"label_suffix", required_argument, 0, 0 }, + {"h", no_argument, 0, 0 }, + {"samheader", no_argument, 0, 0 }, + {"sizeorder", no_argument, 0, 0 }, + {"minwordmatches", required_argument, 0, 0 }, + {"v", no_argument, 0, 0 }, + {"relabel_keep", no_argument, 0, 0 }, + {"search_exact", required_argument, 0, 0 }, + {"fastx_mask", required_argument, 0, 0 }, + {"min_unmasked_pct", required_argument, 0, 0 }, + {"max_unmasked_pct", required_argument, 0, 0 }, + {"fastq_convert", required_argument, 0, 0 }, + {"fastq_asciiout", required_argument, 0, 0 }, + {"fastq_qminout", required_argument, 0, 0 }, + {"fastq_mergepairs", required_argument, 0, 0 }, + {"fastq_eeout", no_argument, 0, 0 }, + {"fastqout_notmerged_fwd",required_argument, 0, 0 }, + {"fastqout_notmerged_rev",required_argument, 0, 0 }, + {"fastq_minovlen", required_argument, 0, 0 }, + {"fastq_minmergelen", required_argument, 0, 0 }, + {"fastq_maxmergelen", required_argument, 0, 0 }, + {"fastq_nostagger", no_argument, 0, 0 }, + {"fastq_allowmergestagger", no_argument, 0, 0 }, + {"fastq_maxdiffs", required_argument, 0, 0 }, + {"fastaout_notmerged_fwd",required_argument, 0, 0 }, + {"fastaout_notmerged_rev",required_argument, 0, 0 }, + {"reverse", required_argument, 0, 0 }, + {"eetabbedout", required_argument, 0, 0 }, + { 0, 0, 0, 0 } + }; + + int option_count = sizeof(long_options) / sizeof(struct option); + bool options_selected[option_count]; + + memset(options_selected, 0, sizeof(options_selected)); + + int option_index = 0; + int c; + + while ((c = getopt_long_only(argc, argv, "", long_options, + &option_index)) == 0) + { + if (option_index < option_count) + options_selected[option_index] = 1; + + switch(option_index) + { + case 0: + opt_help = 1; + break; + + case 1: + opt_version = 1; + break; + + case 2: + opt_alnout = optarg; + break; + + case 3: + opt_usearch_global = optarg; + break; + + case 4: + opt_db = optarg; + break; + + case 5: + opt_id = args_getdouble(optarg); + break; + + case 6: + opt_maxaccepts = args_getlong(optarg); + break; + + case 7: + opt_maxrejects = args_getlong(optarg); + break; + + case 8: + opt_wordlength = args_getlong(optarg); + break; + + case 9: + opt_match = args_getlong(optarg); + break; + + case 10: + opt_mismatch = args_getlong(optarg); + break; + + case 11: + opt_fulldp = 1; + break; + + case 12: + if (strcasecmp(optarg, "plus") == 0) + opt_strand = 1; + else if (strcasecmp(optarg, "both") == 0) + opt_strand = 2; + else + opt_strand = 0; + break; + + case 13: + opt_threads = (long) args_getdouble(optarg); + break; + + case 14: + args_get_gap_penalty_string(optarg, 1); + break; + + case 15: + args_get_gap_penalty_string(optarg, 0); + break; + + case 16: + opt_rowlen = args_getlong(optarg); + break; + + case 17: + if (!parse_userfields_arg(optarg)) + fatal("Unrecognized userfield argument"); + break; + + case 18: + opt_userout = optarg; + break; + + case 19: + opt_self = 1; + break; + + case 20: + opt_blast6out = optarg; + break; + + case 21: + opt_uc = optarg; + break; + + case 22: + opt_weak_id = args_getdouble(optarg); + break; + + case 23: + opt_uc_allhits = 1; + break; + + case 24: + opt_notrunclabels = 1; + break; + + case 25: + opt_sortbysize = optarg; + break; + + case 26: + opt_output = optarg; + break; + + case 27: + opt_minsize = args_getlong(optarg); + break; + + case 28: + opt_maxsize = args_getlong(optarg); + break; + + case 29: + opt_relabel = optarg; + break; + + case 30: + opt_sizeout = 1; + break; + + case 31: + opt_derep_fulllength = optarg; + break; + + case 32: + opt_minseqlength = args_getlong(optarg); + break; + + case 33: + opt_minuniquesize = args_getlong(optarg); + break; + + case 34: + opt_topn = args_getlong(optarg); + break; + + case 35: + opt_maxseqlength = args_getlong(optarg); + break; + + case 36: + opt_sizein = 1; + break; + + case 37: + opt_sortbylength = optarg; + break; + + case 38: + opt_matched = optarg; + break; + + case 39: + opt_notmatched = optarg; + break; + + case 40: + opt_dbmatched = optarg; + break; + + case 41: + opt_dbnotmatched = optarg; + break; + + case 42: + opt_fastapairs = optarg; + break; + + case 43: + opt_output_no_hits = 1; + break; + + case 44: + opt_maxhits = args_getlong(optarg); + break; + + case 45: + opt_top_hits_only = 1; + break; + + case 46: + opt_fasta_width = args_getlong(optarg); + break; + + case 47: + opt_query_cov = args_getdouble(optarg); + break; + + case 48: + opt_target_cov = args_getdouble(optarg); + break; + + case 49: + opt_idprefix = args_getlong(optarg); + break; + + case 50: + opt_idsuffix = args_getlong(optarg); + break; + + case 51: + opt_minqt = args_getdouble(optarg); + break; + + case 52: + opt_maxqt = args_getdouble(optarg); + break; + + case 53: + opt_minsl = args_getdouble(optarg); + break; + + case 54: + opt_maxsl = args_getdouble(optarg); + break; + + case 55: + opt_leftjust = 1; + break; + + case 56: + opt_rightjust = 1; + break; + + case 57: + opt_selfid = 1; + break; + + case 58: + opt_maxid = args_getdouble(optarg); + break; + + case 59: + opt_minsizeratio = args_getdouble(optarg); + break; + + case 60: + opt_maxsizeratio = args_getdouble(optarg); + break; + + case 61: + opt_maxdiffs = args_getlong(optarg); + break; + + case 62: + opt_maxsubs = args_getlong(optarg); + break; + + case 63: + opt_maxgaps = args_getlong(optarg); + break; + + case 64: + opt_mincols = args_getlong(optarg); + break; + + case 65: + opt_maxqsize = args_getlong(optarg); + break; + + case 66: + opt_mintsize = args_getlong(optarg); + break; + + case 67: + opt_mid = args_getdouble(optarg); + break; + + case 68: + opt_shuffle = optarg; + break; + + case 69: + opt_randseed = args_getlong(optarg); + break; + + case 70: + opt_maskfasta = optarg; + break; + + case 71: + opt_hardmask = 1; + break; + + case 72: + if (strcasecmp(optarg, "none") == 0) + opt_qmask = MASK_NONE; + else if (strcasecmp(optarg, "dust") == 0) + opt_qmask = MASK_DUST; + else if (strcasecmp(optarg, "soft") == 0) + opt_qmask = MASK_SOFT; + else + opt_qmask = MASK_ERROR; + break; + + case 73: + if (strcasecmp(optarg, "none") == 0) + opt_dbmask = MASK_NONE; + else if (strcasecmp(optarg, "dust") == 0) + opt_dbmask = MASK_DUST; + else if (strcasecmp(optarg, "soft") == 0) + opt_dbmask = MASK_SOFT; + else + opt_dbmask = MASK_ERROR; + break; + + case 74: + opt_cluster_smallmem = optarg; + break; + + case 75: + opt_cluster_fast = optarg; + break; + + case 76: + opt_centroids = optarg; + break; + + case 77: + opt_clusters = optarg; + break; + + case 78: + opt_consout = optarg; + break; + + case 79: + fprintf(stderr, "WARNING: Option --cons_truncate is ignored\n"); + opt_cons_truncate = 1; + break; + + case 80: + opt_msaout = optarg; + break; + + case 81: + opt_usersort = 1; + break; + + case 82: + opt_xn = args_getdouble(optarg); + break; + + case 83: + opt_iddef = args_getlong(optarg); + break; + + case 84: + fprintf(stderr, "WARNING: Option --slots is ignored\n"); + opt_slots = args_getlong(optarg); + break; + + case 85: + fprintf(stderr, "WARNING: Option --pattern is ignored\n"); + opt_pattern = optarg; + break; + + case 86: + opt_maxuniquesize = args_getlong(optarg); + break; + + case 87: + opt_abskew = args_getdouble(optarg); + break; + + case 88: + opt_chimeras = optarg; + break; + + case 89: + opt_dn = args_getdouble(optarg); + break; + + case 90: + opt_mindiffs = args_getlong(optarg); + break; + + case 91: + opt_mindiv = args_getdouble(optarg); + break; + + case 92: + opt_minh = args_getdouble(optarg); + break; + + case 93: + opt_nonchimeras = optarg; + break; + + case 94: + opt_uchime_denovo = optarg; + break; + + case 95: + opt_uchime_ref = optarg; + break; + + case 96: + opt_uchimealns = optarg; + break; + + case 97: + opt_uchimeout = optarg; + break; + + case 98: + opt_uchimeout5 = 1; + break; + + case 99: + opt_alignwidth = args_getlong(optarg); + break; + + case 100: + opt_allpairs_global = optarg; + break; + + case 101: + opt_acceptall = 1; + break; + + case 102: + opt_cluster_size = optarg; + break; + + case 103: + opt_samout = optarg; + break; + + case 104: + opt_log = optarg; + break; + + case 105: + opt_quiet = true; + break; + + case 106: + opt_fastx_subsample = optarg; + break; + + case 107: + opt_sample_pct = args_getdouble(optarg); + break; + + case 108: + opt_fastq_chars = optarg; + break; + + case 109: + opt_profile = optarg; + break; + + case 110: + opt_sample_size = args_getlong(optarg); + break; + + case 111: + opt_fastaout = optarg; + break; + + case 112: + opt_xsize = 1; + break; + + case 113: + opt_clusterout_id = 1; + break; + + case 114: + opt_clusterout_sort = 1; + break; + + case 115: + opt_borderline = optarg; + break; + + case 116: + opt_relabel_sha1 = 1; + break; + + case 117: + opt_relabel_md5 = 1; + break; + + case 118: + opt_derep_prefix = optarg; + break; + + case 119: + opt_fastq_filter = optarg; + break; + + case 120: + opt_fastqout = optarg; + break; + + case 121: + opt_fastaout_discarded = optarg; + break; + + case 122: + opt_fastqout_discarded = optarg; + break; + + case 123: + opt_fastq_truncqual = args_getlong(optarg); + break; + + case 124: + opt_fastq_maxee = args_getdouble(optarg); + break; + + case 125: + opt_fastq_trunclen = args_getlong(optarg); + break; + + case 126: + opt_fastq_minlen = args_getlong(optarg); + break; + + case 127: + opt_fastq_stripleft = args_getlong(optarg); + break; + + case 128: + opt_fastq_maxee_rate = args_getdouble(optarg); + break; + + case 129: + opt_fastq_maxns = args_getlong(optarg); + break; + + case 130: + opt_eeout = 1; + break; + + case 131: + opt_fastq_ascii = args_getlong(optarg); + break; + + case 132: + opt_fastq_qmin = args_getlong(optarg); + break; + + case 133: + opt_fastq_qmax = args_getlong(optarg); + break; + + case 134: + opt_fastq_qmaxout = args_getlong(optarg); + break; + + case 135: + opt_fastq_stats = optarg; + break; + + case 136: + opt_fastq_tail = args_getlong(optarg); + break; + + case 137: + opt_fastx_revcomp = optarg; + break; + + case 138: + opt_label_suffix = optarg; + break; + + case 139: + opt_help = 1; + break; + + case 140: + opt_samheader = 1; + break; + + case 141: + opt_sizeorder = 1; + break; + + case 142: + opt_minwordmatches = args_getlong(optarg); + break; + + case 143: + opt_version = 1; + break; + + case 144: + opt_relabel_keep = 1; + break; + + case 145: + opt_search_exact = optarg; + break; + + case 146: + opt_fastx_mask = optarg; + break; + + case 147: + opt_min_unmasked_pct = args_getdouble(optarg); + break; + + case 148: + opt_max_unmasked_pct = args_getdouble(optarg); + break; + + case 149: + opt_fastq_convert = optarg; + break; + + case 150: + opt_fastq_asciiout = args_getlong(optarg); + break; + + case 151: + opt_fastq_qminout = args_getlong(optarg); + break; + + case 152: + opt_fastq_mergepairs = optarg; + break; + + case 153: + opt_fastq_eeout = 1; + break; + + case 154: + opt_fastqout_notmerged_fwd = optarg; + break; + + case 155: + opt_fastqout_notmerged_rev = optarg; + break; + + case 156: + opt_fastq_minovlen = args_getlong(optarg); + break; + + case 157: + opt_fastq_minmergelen = args_getlong(optarg); + break; + + case 158: + opt_fastq_maxmergelen = args_getlong(optarg); + break; + + case 159: + opt_fastq_nostagger = optarg; + break; + + case 160: + opt_fastq_allowmergestagger = 1; + break; + + case 161: + opt_fastq_maxdiffs = args_getlong(optarg); + break; + + case 162: + opt_fastaout_notmerged_fwd = optarg; + break; + + case 163: + opt_fastaout_notmerged_rev = optarg; + break; + + case 164: + opt_reverse = optarg; + break; + + case 165: + opt_eetabbedout = optarg; + break; + + default: + fatal("Internal error in option parsing"); + } + } + + /* Terminate if ambiguous or illegal options have been detected */ + if (c != -1) + exit(EXIT_FAILURE); + + /* Terminate after reporting any extra non-option arguments */ + if (optind < argc) + fatal("Unrecognized string on command line (%s)", argv[optind]); + + int commands = 0; + + if (opt_fastq_chars) + commands++; + if (opt_fastq_filter) + commands++; + if (opt_fastq_stats) + commands++; + if (opt_usearch_global) + commands++; + if (opt_sortbysize) + commands++; + if (opt_sortbylength) + commands++; + if (opt_derep_fulllength) + commands++; + if (opt_derep_prefix) + commands++; + if (opt_help) + commands++; + if (opt_version) + commands++; + if (opt_shuffle) + commands++; + if (opt_fastx_subsample) + commands++; + if (opt_maskfasta) + commands++; + if (opt_cluster_smallmem) + commands++; + if (opt_cluster_fast) + commands++; + if (opt_cluster_size) + commands++; + if (opt_uchime_denovo) + commands++; + if (opt_uchime_ref) + commands++; + if (opt_allpairs_global) + commands++; + if (opt_fastx_revcomp) + commands++; + if (opt_search_exact) + commands++; + if (opt_fastx_mask) + commands++; + if (opt_fastq_convert) + commands++; + if (opt_fastq_mergepairs) + commands++; + + if (commands > 1) + fatal("More than one command specified"); + + if (opt_weak_id > opt_id) + opt_weak_id = opt_id; + + if (opt_maxrejects == -1) + { + if (opt_cluster_fast) + opt_maxrejects = 8; + else + opt_maxrejects = 32; + } + + if (opt_minseqlength < 0) + fatal("The argument to --minseqlength must be positive"); + + if (opt_maxaccepts < 0) + fatal("The argument to --maxaccepts must not be negative"); + + if (opt_maxrejects < 0) + fatal("The argument to --maxrejects must not be negative"); + + if ((opt_threads < 0) || (opt_threads > 1024)) + fatal("The argument to --threads must be in the range 0 (default) to 1024"); + + if ((opt_wordlength < 7) || (opt_wordlength > 15)) + fatal("The argument to --wordlength must be in the range 7 to 15"); + + if ((opt_iddef < 0) || (opt_iddef > 4)) + fatal("The argument to --iddef must in the range 0 to 4"); + + if (opt_match <= 0) + fatal("The argument to --match must be positive"); + + if (opt_mismatch >= 0) + fatal("The argument to --mismatch must be negative"); + + if (opt_alignwidth < 0) + fatal("The argument to --alignwidth must not be negative"); + + if (opt_rowlen < 0) + fatal("The argument to --rowlen must not be negative"); + + if (opt_strand < 1) + fatal("The argument to --strand must be plus or both"); + + if (opt_qmask == MASK_ERROR) + fatal("The argument to --qmask must be none, dust or soft"); + + if (opt_dbmask == MASK_ERROR) + fatal("The argument to --dbmask must be none, dust or soft"); + + if ((opt_sample_pct < 0.0) || (opt_sample_pct > 100.0)) + fatal("The argument to --sample_pct must be in the range 0.0 to 100.0"); + + if (opt_sample_size < 0) + fatal("The argument to --sample_size must not be negative"); + + if (opt_relabel_sha1 && opt_relabel_md5) + fatal("Specify either --relabel_sha1 or --relabel_md5, not both"); + + if (opt_fastq_tail < 1) + fatal("The argument to --fastq_tail must be positive"); + + if (opt_minwordmatches < 0) + fatal("The argument to --minwordmatches must not be negative"); + + if ((opt_min_unmasked_pct < 0.0) && (opt_min_unmasked_pct > 100.0)) + fatal("The argument to --min_unmasked_pct must be between 0.0 and 100.0"); + + if ((opt_max_unmasked_pct < 0.0) && (opt_max_unmasked_pct > 100.0)) + fatal("The argument to --max_unmasked_pct must be between 0.0 and 100.0"); + + if (opt_min_unmasked_pct > opt_max_unmasked_pct) + fatal("The argument to --min_unmasked_pct cannot be larger than to --max_unmasked_pct"); + + if (opt_fastq_qmin > opt_fastq_qmax) + fatal("The argument to --fastq_qmin cannot be larger than to --fastq_qmax"); + + if (opt_fastq_qminout > opt_fastq_qmaxout) + fatal("The argument to --fastq_qminout cannot be larger than to --fastq_qmaxout"); + + /* TODO: check valid range of gap penalties */ + + /* adapt/adjust parameters */ + +#if 1 + + /* + Adjust gap open penalty according to convention. + + The specified gap open penalties include the penalty for + a single nucleotide gap: + + gap penalty = gap open penalty + (gap length - 1) * gap extension penalty + + The rest of the code assumes the first nucleotide gap penalty is not + included in the gap opening penalty. + */ + + opt_gap_open_query_left -= opt_gap_extension_query_left; + opt_gap_open_target_left -= opt_gap_extension_target_left; + opt_gap_open_query_interior -= opt_gap_extension_query_interior; + opt_gap_open_target_interior -= opt_gap_extension_target_interior; + opt_gap_open_query_right -= opt_gap_extension_query_right; + opt_gap_open_target_right -= opt_gap_extension_target_right; + +#endif + + if (opt_minwordmatches == 0) + opt_minwordmatches = minwordmatches_defaults[opt_wordlength]; + + if (opt_threads == 0) { + int numProcessors = 1; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + numProcessors = sysconf(_SC_NPROCESSORS_ONLN) +#else + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + numProcessors = sysinfo.dwNumberOfProcessors; +#endif + + opt_threads = numProcessors; + } + /* set default opt_minseqlength depending on command */ + + if (opt_minseqlength == 0) + { + if (opt_cluster_smallmem || opt_cluster_fast || opt_cluster_size || + opt_usearch_global || opt_derep_fulllength || opt_derep_prefix ) + opt_minseqlength = 32; + else + opt_minseqlength = 1; + } +} + + +void cmd_help() +{ + /* 0 1 2 3 4 5 6 7 */ + /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ + + if (! opt_quiet) + { + fprintf(stdout, + "Usage: %s [OPTIONS]\n", progname); + + fprintf(stdout, + "\n" + "General options\n" + " --fasta_width INT width of FASTA seq lines, 0 for no wrap (80)\n" + " --help | --h display help information\n" + " --log FILENAME write messages, timing and memory info to file\n" + " --maxseqlength INT maximum sequence length (50000)\n" + " --minseqlength INT min seq length (clust/derep/search: 32, other:1)\n" + " --notrunclabels do not truncate labels at first space\n" + " --quiet output just warnings and fatal errors to stderr\n" + " --threads INT number of threads to use, zero for all cores (0)\n" + " --version display version information\n" + "\n" + "Chimera detection\n" + " --uchime_denovo FILENAME detect chimeras de novo\n" + " --uchime_ref FILENAME detect chimeras using a reference database\n" + "Options\n" + " --abskew REAL min abundance ratio of parent vs chimera (2.0)\n" + " --alignwidth INT width of alignment in uchimealn output (80)\n" + " --borderline FILENAME output borderline chimeric sequences to file\n" + " --chimeras FILENAME output chimeric sequences to file\n" + " --db FILENAME reference database for --uchime_ref\n" + " --dn REAL 'no' vote pseudo-count (1.4)\n" + " --mindiffs INT minimum number of differences in segment (3)\n" + " --mindiv REAL minimum divergence from closest parent (0.8)\n" + " --minh REAL minimum score (0.28)\n" + " --nonchimeras FILENAME output non-chimeric sequences to file\n" + " --relabel STRING relabel nonchimeras with this prefix string\n" + " --relabel_keep keep the old label after the new when relabelling\n" + " --relabel_md5 relabel with md5 digest of normalized sequence\n" + " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" + " --self exclude identical labels for --uchime_ref\n" + " --selfid exclude identical sequences for --uchime_ref\n" + " --sizeout include abundance information when relabelling\n" + " --uchimealns FILENAME output chimera alignments to file\n" + " --uchimeout FILENAME output to chimera info to tab-separated file\n" + " --uchimeout5 make output compatible with uchime version 5\n" + " --xn REAL 'no' vote weight (8.0)\n" + " --xsize strip abundance information in output\n" + "\n" + "Clustering\n" + " --cluster_fast FILENAME cluster sequences after sorting by length\n" + " --cluster_size FILENAME cluster sequences after sorting by abundance\n" + " --cluster_smallmem FILENAME cluster already sorted sequences (see -usersort)\n" + "Options (most searching options also apply)\n" + " --centroids FILENAME output centroid sequences to FASTA file\n" + " --clusterout_id add cluster id info to consout and profile files\n" + " --clusterout_sort order msaout, consout, profile by decr abundance\n" + " --clusters STRING output each cluster to a separate FASTA file\n" + " --consout FILENAME output cluster consensus sequences to FASTA file\n" + " --cons_truncate do not ignore terminal gaps in MSA for consensus\n" + " --id REAL reject if identity lower\n" + " --iddef INT id definition, 0-4=CD-HIT,all,int,MBL,BLAST (2)\n" + " --msaout FILENAME output multiple seq. alignments to FASTA file\n" + " --profile FILENAME output sequence profile of each cluster to file\n" + " --qmask none|dust|soft mask seqs with dust, soft or no method (dust)\n" + " --relabel STRING relabel centroids with this prefix string\n" + " --relabel_keep keep the old label after the new when relabelling\n" + " --relabel_md5 relabel with md5 digest of normalized sequence\n" + " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" + " --sizein propagate abundance annotation from input\n" + " --sizeorder sort accepted centroids by abundance (AGC)\n" + " --sizeout write cluster abundances to centroid file\n" + " --strand plus|both cluster using plus or both strands (plus)\n" + " --uc FILENAME specify filename for UCLUST-like output\n" + " --usersort indicate sequences not pre-sorted by length\n" + " --xsize strip abundance information in output\n" + "\n" + "Dereplication\n" + " --derep_fulllength FILENAME dereplicate sequences in the given FASTA file\n" + " --derep_prefix FILENAME dereplicate sequences in file based on prefixes\n" + "Options\n" + " --maxuniquesize INT maximum abundance for output from dereplication\n" + " --minuniquesize INT minimum abundance for output from dereplication\n" + " --output FILENAME output FASTA file\n" + " --relabel STRING relabel with this prefix string after derep.\n" + " --relabel_keep keep the old label after the new when relabelling\n" + " --relabel_md5 relabel with md5 digest of normalized sequence\n" + " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" + " --sizein propagate abundance annotation from input\n" + " --sizeout write abundance annotation to output\n" + " --strand plus|both dereplicate plus or both strands (plus)\n" + " --topn INT output just the n most abundant sequences\n" + " --uc FILENAME filename for UCLUST-like output\n" + " --xsize strip abundance information in output\n" + "\n" + "FASTQ filtering\n" + " --fastq_filter FILENAME filter FASTQ file, output to FASTQ or FASTA file\n" + "Options\n" + " --eeout include expected errors in FASTQ filter output\n" + " --fastaout FILENAME FASTA output filename for passed sequences\n" + " --fastaout_discarded FNAME FASTA filename for discarded sequences\n" + " --fastqout FILENAME FASTQ output filename for passed sequences\n" + " --fastqout_discarded FNAME FASTQ filename for discarded sequences\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_maxee REAL maximum expected error value for FASTQ filter\n" + " --fastq_maxee_rate REAL maximum expected error rate for FASTQ filter\n" + " --fastq_maxns INT maximum number of N's for FASTQ filter\n" + " --fastq_minlen INT minimum length for FASTQ filter\n" + " --fastq_stripleft INT bases on the left to delete for FASTQ filter\n" + " --fastq_trunclen INT read length for FASTQ filter truncation\n" + " --fastq_truncqual INT base quality value for FASTQ filter truncation\n" + " --relabel STRING relabel filtered sequences with given prefix\n" + " --relabel_keep keep the old label after the new when relabelling\n" + " --relabel_md5 relabel filtered sequences with md5 digest\n" + " --relabel_sha1 relabel filtered sequences with sha1 digest\n" + " --sizeout include abundance information when relabelling\n" + " --xsize strip abundance information in output\n" + "\n" + "FASTQ format conversion\n" + " --fastq_convert FILENAME convert between FASTQ file formats\n" + "Options\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_asciiout INT FASTQ output quality score ASCII base char (33)\n" + " --fastq_qmax INT maximum base quality value for FASTQ input (41)\n" + " --fastq_qmaxout INT maximum base quality value for FASTQ output (41)\n" + " --fastq_qmin INT minimum base quality value for FASTQ input (0)\n" + " --fastq_qminout INT minimum base quality value for FASTQ output (0)\n" + "\n" + "FASTQ format detection and quality analysis\n" + " --fastq_chars FILENAME analyse FASTQ file for version and quality range\n" + "Options\n" + " --fastq_tail INT min length of tails to count for fastq_chars (4)\n" + "\n" + "FASTQ paired-end reads merging\n" + " --fastq_mergepairs FILENAME merge paired-end reads into one sequence\n" + "Options:\n" + " --eetabbedout FILENAME output error statistics to specified file\n" + " --fastaout FILENAME FASTA output filename for merged sequences\n" + " --fastaout_notmerged_fwd FN FASTA filename for non-merged forward sequences\n" + " --fastaout_notmerged_rev FN FASTA filename for non-merged reverse sequences\n" + " --fastq_allowmergestagger Allow merging of staggered reads\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_eeout include expected errors in FASTQ output\n" + " --fastq_maxdiffs maximum number of different bases in overlap\n" + " --fastq_maxee REAL maximum expected error value for merged sequence\n" + " --fastq_maxmergelen maximum length of entire merged sequence\n" + " --fastq_maxns INT maximum number of N's\n" + " --fastq_minlen INT minimum input read length after truncation (1)\n" + " --fastq_minmergelen minimum length of entire merged sequence\n" + " --fastq_minovlen minimum length of overlap between reads\n" + " --fastq_nostagger disallow merging of staggered reads (default)\n" + " --fastq_qmax INT maximum base quality value for FASTQ input (41)\n" + " --fastq_qmaxout INT maximum base quality value for FASTQ output (41)\n" + " --fastq_qmin INT minimum base quality value for FASTQ input (0)\n" + " --fastq_qminout INT minimum base quality value for FASTQ output (0)\n" + " --fastq_truncqual INT base quality value for truncation\n" + " --fastqout FILENAME FASTQ output filename for merged sequences\n" + " --fastqout_notmerged_fwd F FASTQ filename for non-merged forward sequences\n" + " --fastqout_notmerged_rev F FASTQ filename for non-merged reverse sequences\n" + " --label_suffix suffix to append to label of merged sequences\n" + " --reverse FILENAME specify FASTQ file with reverse reads\n" + "\n" + "FASTQ quality statistics\n" + " --fastq_stats FILENAME report FASTQ file statistics\n" + "Options\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_qmax INT maximum base quality value for FASTQ input (41)\n" + " --fastq_qmin INT minimum base quality value for FASTQ input (0)\n" + "\n" + "Masking (new)\n" + " --fastx_mask FILENAME mask sequences in the given FASTA or FASTQ file\n" + "Options\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_qmax INT maximum base quality value for FASTQ input (41)\n" + " --fastq_qmin INT minimum base quality value for FASTQ input (0)\n" + " --fastaout FILENAME output to specified FASTA file\n" + " --fastqout FILENAME output to specified FASTQ file\n" + " --hardmask mask by replacing with N instead of lower case\n" + " --max_unmasked_pct max unmasked %% of sequences to keep (100.0)\n" + " --min_unmasked_pct min unmasked %% of sequences to keep (0.0)\n" + " --qmask none|dust|soft mask seqs with dust, soft or no method (dust)\n" + "\n" + "Masking (old)\n" + " --maskfasta FILENAME mask sequences in the given FASTA file\n" + "Options\n" + " --hardmask mask by replacing with N instead of lower case\n" + " --output FILENAME output to specified FASTA file\n" + " --qmask none|dust|soft mask seqs with dust, soft or no method (dust)\n" + "\n" + "Pairwise alignment\n" + " --allpairs_global FILENAME perform global alignment of all sequence pairs\n" + "Options (most searching options also apply)\n" + " --alnout FILENAME filename for human-readable alignment output\n" + " --acceptall output all pairwise alignments\n" + "\n" + "Reverse complementation\n" + " --fastx_revcomp FILENAME Reverse-complement seqs in FASTA or FASTQ file\n" + "Options\n" + " --fastaout FILENAME FASTA output filename\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_qmax INT maximum base quality value for FASTQ input (41)\n" + " --fastq_qmin INT minimum base quality value for FASTQ input (0)\n" + " --fastqout FILENAME FASTQ output filename\n" + " --label_suffix STRING Label to append to identifier in the output\n" + "\n" + "Searching\n" + " --search_exact FILENAME filename of queries for exact match search\n" + " --usearch_global FILENAME filename of queries for global alignment search\n" + "Options\n" + " --alnout FILENAME filename for human-readable alignment output\n" + " --blast6out FILENAME filename for blast-like tab-separated output\n" + " --db FILENAME filename for FASTA formatted database for search\n" + " --dbmask none|dust|soft mask db with dust, soft or no method (dust)\n" + " --dbmatched FILENAME FASTA file for matching database sequences\n" + " --dbnotmatched FILENAME FASTA file for non-matching database sequences\n" + " --fastapairs FILENAME FASTA file with pairs of query and target\n" + " --fulldp full dynamic programming alignment (always on)\n" + " --gapext STRING penalties for gap extension (2I/1E)\n" + " --gapopen STRING penalties for gap opening (20I/2E)\n" + " --hardmask mask by replacing with N instead of lower case\n" + " --id REAL reject if identity lower\n" + " --iddef INT id definition, 0-4=CD-HIT,all,int,MBL,BLAST (2)\n" + " --idprefix INT reject if first n nucleotides do not match\n" + " --idsuffix INT reject if last n nucleotides do not match\n" + " --leftjust reject if terminal gaps at alignment left end\n" + " --match INT score for match (2)\n" + " --matched FILENAME FASTA file for matching query sequences\n" + " --maxaccepts INT number of hits to accept and show per strand (1)\n" + " --maxdiffs INT reject if more substitutions or indels\n" + " --maxgaps INT reject if more indels\n" + " --maxhits INT maximum number of hits to show (unlimited)\n" + " --maxid REAL reject if identity higher\n" + " --maxqsize INT reject if query abundance larger\n" + " --maxqt REAL reject if query/target length ratio higher\n" + " --maxrejects INT number of non-matching hits to consider (32)\n" + " --maxsizeratio REAL reject if query/target abundance ratio higher\n" + " --maxsl REAL reject if shorter/longer length ratio higher\n" + " --maxsubs INT reject if more substitutions\n" + " --mid REAL reject if percent identity lower, ignoring gaps\n" + " --mincols INT reject if alignment length shorter\n" + " --minqt REAL reject if query/target length ratio lower\n" + " --minsizeratio REAL reject if query/target abundance ratio lower\n" + " --minsl REAL reject if shorter/longer length ratio lower\n" + " --mintsize INT reject if target abundance lower\n" + " --minwordmatches INT minimum number of word matches required (10)\n" + " --mismatch INT score for mismatch (-4)\n" + " --notmatched FILENAME FASTA file for non-matching query sequences\n" + " --output_no_hits output non-matching queries to output files\n" + " --pattern STRING option is ignored\n" + " --qmask none|dust|soft mask query with dust, soft or no method (dust)\n" + " --query_cov REAL reject if fraction of query seq. aligned lower\n" + " --rightjust reject if terminal gaps at alignment right end\n" + " --rowlen INT width of alignment lines in alnout output (64)\n" + " --samheader include a header in the SAM output file\n" + " --samout FILENAME filename for SAM format output\n" + " --self reject if labels identical\n" + " --selfid reject if sequences identical\n" + " --sizeout write abundance annotation to dbmatched file\n" + " --slots INT option is ignored\n" + " --strand plus|both search plus or both strands (plus)\n" + " --target_cov REAL reject if fraction of target seq. aligned lower\n" + " --top_hits_only output only hits with identity equal to the best\n" + " --uc FILENAME filename for UCLUST-like output\n" + " --uc_allhits show all, not just top hit with uc output\n" + " --userfields STRING fields to output in userout file\n" + " --userout FILENAME filename for user-defined tab-separated output\n" + " --weak_id REAL include aligned hits with >= id; continue search\n" + " --wordlength INT length of words for database index 3-15 (8)\n" + "\n" + "Shuffling and sorting\n" + " --shuffle FILENAME shuffle order of sequences in FASTA file randomly\n" + " --sortbylength FILENAME sort sequences by length in given FASTA file\n" + " --sortbysize FILENAME abundance sort sequences in given FASTA file\n" + "Options\n" + " --maxsize INT maximum abundance for sortbysize\n" + " --minsize INT minimum abundance for sortbysize\n" + " --output FILENAME output to specified FASTA file\n" + " --randseed INT seed for PRNG, zero to use random data source (0)\n" + " --relabel STRING relabel sequences with this prefix string\n" + " --relabel_keep keep the old label after the new when relabelling\n" + " --relabel_md5 relabel with md5 digest of normalized sequence\n" + " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" + " --sizeout include abundance information when relabelling\n" + " --topn INT output just first n sequences\n" + " --xsize strip abundance information in output\n" + "\n" + "Subsampling\n" + " --fastx_subsample FILENAME subsample sequences from given FASTA/FASTQ file\n" + "Options\n" + " --fastaout FILENAME output FASTA file for subsamples\n" + " --fastq_ascii INT FASTQ input quality score ASCII base char (33)\n" + " --fastq_qmax INT maximum base quality value for FASTQ input (41)\n" + " --fastq_qmin INT minimum base quality value for FASTQ input (0)\n" + " --fastqout FILENAME output FASTQ file for subsamples\n" + " --randseed INT seed for PRNG, zero to use random data source (0)\n" + " --relabel STRING relabel sequences with this prefix string\n" + " --relabel_keep keep the old label after the new when relabelling\n" + " --relabel_md5 relabel with md5 digest of normalized sequence\n" + " --relabel_sha1 relabel with sha1 digest of normalized sequence\n" + " --sample_pct REAL sampling percentage between 0.0 and 100.0\n" + " --sample_size INT sampling size\n" + " --sizein consider abundance info from input, do not ignore\n" + " --sizeout update abundance information in output\n" + " --xsize strip abundance information in output\n" + ); + } +} + +void cmd_allpairs_global() +{ + /* check options */ + + if ((!opt_alnout) && (!opt_userout) && + (!opt_uc) && (!opt_blast6out) && + (!opt_matched) && (!opt_notmatched) && + (!opt_samout)) + fatal("No output files specified"); + + if (! (opt_acceptall || ((opt_id >= 0.0) && (opt_id <= 1.0)))) + fatal("Specify either --acceptall or --id with an identity from 0.0 to 1.0"); + + allpairs_global(cmdline, progheader); +} + +void cmd_usearch_global() +{ + /* check options */ + + if ((!opt_alnout) && (!opt_userout) && + (!opt_uc) && (!opt_blast6out) && + (!opt_matched) && (!opt_notmatched) && + (!opt_dbmatched) && (!opt_dbnotmatched) && + (!opt_samout)) + fatal("No output files specified"); + + if (!opt_db) + fatal("Database filename not specified with --db"); + + if ((opt_id < 0.0) || (opt_id > 1.0)) + fatal("Identity between 0.0 and 1.0 must be specified with --id"); + + usearch_global(cmdline, progheader); +} + +void cmd_search_exact() +{ + /* check options */ + + if ((!opt_alnout) && (!opt_userout) && + (!opt_uc) && (!opt_blast6out) && + (!opt_matched) && (!opt_notmatched) && + (!opt_dbmatched) && (!opt_dbnotmatched) && + (!opt_samout)) + fatal("No output files specified"); + + if (!opt_db) + fatal("Database filename not specified with --db"); + + search_exact(cmdline, progheader); +} + +void cmd_sortbysize() +{ + if (!opt_output) + fatal("FASTA output file for sortbysize must be specified with --output"); + + sortbysize(); +} + +void cmd_sortbylength() +{ + if (!opt_output) + fatal("FASTA output file for sortbylength must be specified with --output"); + + sortbylength(); +} + +void cmd_derep() +{ + if ((!opt_output) && (!opt_uc)) + fatal("Output file for derepl_fulllength must be specified with --output or --uc"); + + if (opt_derep_fulllength) + derep_fulllength(); + else + { + if (opt_strand > 1) + fatal("Option '--strand both' not supported with --derep_prefix"); + else + derep_prefix(); + } +} + +void cmd_shuffle() +{ + if (!opt_output) + fatal("Output file for shuffling must be specified with --output"); + + shuffle(); +} + +void cmd_subsample() +{ + if ((!opt_fastaout) && (!opt_fastqout)) + fatal("Specifiy output files for subsampling with --fastaout and/or --fastqout"); + + if ((opt_sample_pct > 0) == (opt_sample_size > 0)) + fatal("Specify either --sample_pct or --sample_size, not both"); + + subsample(); +} + +void cmd_maskfasta() +{ + if (!opt_output) + fatal("Output file for masking must be specified with --output"); + + maskfasta(); +} + +void cmd_fastx_mask() +{ + if ((!opt_fastaout) && (!opt_fastqout)) + fatal("Specifiy output files for masking with --fastaout and/or --fastqout"); + + fastx_mask(); +} + +void cmd_none() +{ + if (! opt_quiet) + fprintf(stderr, + "For help, please enter: %s --help\n" + "\n" + "For further details, please see the manual by entering: man vsearch\n" + "\n" + "Example commands:\n" + "\n" + "vsearch --allpairs_global FILENAME --id 0.5 --alnout FILENAME\n" + "vsearch --cluster_fast FILENAME --id 0.97 --centroids FILENAME\n" + "vsearch --cluster_size FILENAME --id 0.97 --centroids FILENAME\n" + "vsearch --cluster_smallmem FILENAME --usersort --id 0.97 --centroids FILENAME\n" + "vsearch --derep_fulllength FILENAME --output FILENAME\n" + "vsearch --derep_prefix FILENAME --output FILENAME\n" + "vsearch --fastq_chars FILENAME\n" + "vsearch --fastq_convert FILENAME --fastqout FILENAME --fastq_ascii 64\n" + "vsearch --fastq_filter FILENAME --fastqout FILENAME --fastq_truncqual 20\n" + "vsearch --fastq_mergepairs FILENAME --reverse FILENAME --fastqout FILENAME\n" + "vsearch --fastq_stats FILENAME --log FILENAME\n" + "vsearch --fastx_mask FILENAME --fastaout FILENAME\n" + "vsearch --fastx_revcomp FILENAME --fastqout FILENAME\n" + "vsearch --fastx_subsample FILENAME --fastaout FILENAME --sample_pct 1\n" + "vsearch --search_exact FILENAME --db FILENAME --alnout FILENAME\n" + "vsearch --shuffle FILENAME --output FILENAME\n" + "vsearch --sortbylength FILENAME --output FILENAME\n" + "vsearch --sortbysize FILENAME --output FILENAME\n" + "vsearch --uchime_denovo FILENAME --nonchimeras FILENAME\n" + "vsearch --uchime_ref FILENAME --db FILENAME --nonchimeras FILENAME\n" + "vsearch --usearch_global FILENAME --db FILENAME --id 0.97 --alnout FILENAME\n" + "\n", + progname); +} + +void cmd_fastx_revcomp() +{ + if ((!opt_fastaout) && (!opt_fastqout)) + fatal("No output files specified"); + + fastx_revcomp(); +} + +void cmd_fastq_convert() +{ + if (! opt_fastqout) + fatal("No output file specified with --fastqout"); + + fastq_convert(); +} + +void cmd_cluster() +{ + if ((!opt_alnout) && (!opt_userout) && + (!opt_uc) && (!opt_blast6out) && + (!opt_matched) && (!opt_notmatched) && + (!opt_centroids) && (!opt_clusters) && + (!opt_consout) && (!opt_msaout) && + (!opt_samout) && (!opt_profile)) + fatal("No output files specified"); + + if ((opt_id < 0.0) || (opt_id > 1.0)) + fatal("Identity between 0.0 and 1.0 must be specified with --id"); + + if (opt_cluster_fast) + cluster_fast(cmdline, progheader); + else if (opt_cluster_smallmem) + cluster_smallmem(cmdline, progheader); + else if (opt_cluster_size) + cluster_size(cmdline, progheader); +} + +void cmd_uchime() +{ + if ((!opt_chimeras) && (!opt_nonchimeras) && + (!opt_uchimeout) && (!opt_uchimealns)) + fatal("No output files specified"); + + if (opt_uchime_ref && ! opt_db) + fatal("Database filename not specified with --db"); + + if (opt_xn <= 1.0) + fatal("Argument to --xn must be > 1"); + + if (opt_dn <= 0.0) + fatal("Argument to --dn must be > 0"); + + if (opt_mindiffs <= 0) + fatal("Argument to --mindiffs must be > 0"); + + if (opt_mindiv <= 0.0) + fatal("Argument to --mindiv must be > 0"); + + if (opt_minh <= 0.0) + fatal("Argument to --minh must be > 0"); + + if (opt_abskew <= 1.0) + fatal("Argument to --abskew must be > 1"); + + chimera(); +} + +void cmd_fastq_filter() +{ + if ((!opt_fastqout) && (!opt_fastaout) && + (!opt_fastqout_discarded) && (!opt_fastaout_discarded)) + fatal("No output files specified"); + fastq_filter(); +} + +void cmd_fastq_mergepairs() +{ + if (!opt_reverse) + fatal("No reverse reads file specified with --reverse"); + if ((!opt_fastqout) && + (!opt_fastaout) && + (!opt_fastqout_notmerged_fwd) && + (!opt_fastqout_notmerged_rev) && + (!opt_fastaout_notmerged_fwd) && + (!opt_fastaout_notmerged_rev) && + (!opt_eetabbedout)) + fatal("No output files specified"); + fastq_mergepairs(); +} + +void fillheader() +{ + int numProcessors = 1; +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + numProcessors = sysconf(_SC_NPROCESSORS_ONLN) +#else + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + numProcessors = sysinfo.dwNumberOfProcessors; +#endif + + snprintf(progheader, 80, + "%s v%s_%s, %.1fGB RAM, %ld cores", + PROG_NAME, PROG_VERSION, PROG_ARCH, + arch_get_memtotal() / 1024.0 / 1024.0 / 1024.0, + numProcessors); +} + +void getentirecommandline(int argc, char** argv) +{ + int len = 0; + for (int i=0; i, - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway - - This software is dual-licensed and available under a choice - of one of two licenses, either under the terms of the GNU - General Public License version 3 or the BSD 2-Clause License. - - - GNU General Public License version 3 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - - The BSD 2-Clause License - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -*/ -#ifndef VSEARCH_H -#define VSEARCH_H - -#include -#include -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - #include -#endif -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "getopt_long.h" -#include "cityhash/city.h" -#include "md5.h" -#include "sha1.h" -#include "util.h" -#include "xstring.h" -#include "align_simd.h" -#include "maps.h" -#include "arch.h" -#include "abundance.h" -#include "db.h" -#include "align.h" -#include "unique.h" -#include "bitmap.h" -#include "dbindex.h" -#include "minheap.h" -#include "search.h" -#include "linmemalign.h" -#include "searchcore.h" -#include "showalign.h" -#include "userfields.h" -#include "results.h" -#include "sortbysize.h" -#include "sortbylength.h" -#include "derep.h" -#include "shuffle.h" -#include "mask.h" -#include "cluster.h" -#include "msa.h" -#include "chimera.h" -#include "cpu.h" -#include "allpairs.h" -#include "subsample.h" -#include "fasta.h" -#include "fastq.h" -#include "fastqops.h" -#include "fastxdetect.h" - - -//vsearch definitions - -#define PROG_NAME "vsearch" //PACKAGE -#define PROG_VERSION "1.9.7" //PACKAGE_VERSION -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "torognes@ifi.uio.no" - - -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) - - #include - #include - #include - #include - #include - - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - - - #if defined (__APPLE__) || (__MACH__) - #define PROG_ARCH "osx_x86_64" - #include - #else - #define PROG_ARCH "linux_x86_64" - #include - #endif -#else - #define PROG_ARCH "Windows_x86_64" - #include - #include -#endif - - -/* options */ - -extern bool opt_clusterout_id; -extern bool opt_clusterout_sort; -extern bool opt_eeout; -extern bool opt_quiet; -extern bool opt_relabel_md5; -extern bool opt_relabel_sha1; -extern bool opt_samheader; -extern bool opt_sizeorder; -extern bool opt_xsize; -extern char * opt_allpairs_global; -extern char * opt_alnout; -extern char * opt_blast6out; -extern char * opt_borderline; -extern char * opt_centroids; -extern char * opt_chimeras; -extern char * opt_cluster_fast; -extern char * opt_cluster_size; -extern char * opt_cluster_smallmem; -extern char * opt_clusters; -extern char * opt_consout; -extern char * opt_db; -extern char * opt_dbmatched; -extern char * opt_dbnotmatched; -extern char * opt_derep_fulllength; -extern char * opt_derep_prefix; -extern char * opt_fastaout; -extern char * opt_fastaout_discarded; -extern char * opt_fastapairs; -extern char * opt_fastq_chars; -extern char * opt_fastq_filter; -extern char * opt_fastq_stats; -extern char * opt_fastqout; -extern char * opt_fastqout_discarded; -extern char * opt_fastx_revcomp; -extern char * opt_fastx_subsample; -extern char * opt_label_suffix; -extern char * opt_log; -extern char * opt_maskfasta; -extern char * opt_matched; -extern char * opt_msaout; -extern char * opt_nonchimeras; -extern char * opt_notmatched; -extern char * opt_output; -extern char * opt_pattern; -extern char * opt_profile; -extern char * opt_relabel; -extern char * opt_samout; -extern char * opt_shuffle; -extern char * opt_sortbylength; -extern char * opt_sortbysize; -extern char * opt_uc; -extern char * opt_uchime_denovo; -extern char * opt_uchime_ref; -extern char * opt_uchimealns; -extern char * opt_uchimeout; -extern char * opt_usearch_global; -extern char * opt_userout; -extern double opt_abskew; -extern double opt_dn; -extern double opt_fastq_maxee; -extern double opt_fastq_maxee_rate; -extern double opt_id; -extern double opt_maxid; -extern double opt_maxqt; -extern double opt_maxsizeratio; -extern double opt_maxsl; -extern double opt_mid; -extern double opt_mindiv; -extern double opt_minh; -extern double opt_minqt; -extern double opt_minsizeratio; -extern double opt_minsl; -extern double opt_query_cov; -extern double opt_sample_pct; -extern double opt_target_cov; -extern double opt_weak_id; -extern double opt_xn; -extern int opt_acceptall; -extern int opt_alignwidth; -extern int opt_cons_truncate; -extern int opt_gap_extension_query_interior; -extern int opt_gap_extension_query_left; -extern int opt_gap_extension_query_right; -extern int opt_gap_extension_target_interior; -extern int opt_gap_extension_target_left; -extern int opt_gap_extension_target_right; -extern int opt_gap_open_query_interior; -extern int opt_gap_open_query_left; -extern int opt_gap_open_query_right; -extern int opt_gap_open_target_interior; -extern int opt_gap_open_target_left; -extern int opt_gap_open_target_right; -extern int opt_help; -extern int opt_mindiffs; -extern int opt_slots; -extern int opt_uchimeout5; -extern int opt_usersort; -extern int opt_version; -extern long opt_dbmask; -extern long opt_fasta_width; -extern long opt_fastq_ascii; -extern long opt_fastq_maxns; -extern long opt_fastq_minlen; -extern long opt_fastq_qmax; -extern long opt_fastq_qmaxout; -extern long opt_fastq_qmin; -extern long opt_fastq_stripleft; -extern long opt_fastq_tail; -extern long opt_fastq_trunclen; -extern long opt_fastq_truncqual; -extern long opt_fulldp; -extern long opt_hardmask; -extern long opt_iddef; -extern long opt_idprefix; -extern long opt_idsuffix; -extern long opt_leftjust; -extern long opt_match; -extern long opt_maxaccepts; -extern long opt_maxdiffs; -extern long opt_maxgaps; -extern long opt_maxhits; -extern long opt_maxqsize; -extern long opt_maxrejects; -extern long opt_maxseqlength; -extern long opt_maxsize; -extern long opt_maxsubs; -extern long opt_maxuniquesize; -extern long opt_mincols; -extern long opt_minseqlength; -extern long opt_minsize; -extern long opt_mintsize; -extern long opt_minuniquesize; -extern long opt_mismatch; -extern long opt_notrunclabels; -extern long opt_output_no_hits; -extern long opt_qmask; -extern long opt_randseed; -extern long opt_rightjust; -extern long opt_rowlen; -extern long opt_sample_size; -extern long opt_self; -extern long opt_selfid; -extern long opt_sizein; -extern long opt_sizeout; -extern long opt_strand; -extern long opt_threads; -extern long opt_top_hits_only; -extern long opt_topn; -extern long opt_uc_allhits; -extern long opt_wordlength; - -extern long mmx_present; -extern long sse_present; -extern long sse2_present; -extern long sse3_present; -extern long ssse3_present; -extern long sse41_present; -extern long sse42_present; -extern long popcnt_present; -extern long avx_present; -extern long avx2_present; - -extern FILE * fp_log; - -/* main function prototype */ -int vsearch_main(int, char**); - -#endif - - - +/* + + VSEARCH: a versatile open source tool for metagenomics + + Copyright (C) 2014-2015, Torbjorn Rognes, Frederic Mahe and Tomas Flouri + All rights reserved. + + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway + + This software is dual-licensed and available under a choice + of one of two licenses, either under the terms of the GNU + General Public License version 3 or the BSD 2-Clause License. + + + GNU General Public License version 3 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + + The BSD 2-Clause License + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __SSE2__ +#include +#endif + +#ifdef __SSSE3__ +#include +#define SSSE3 +#endif + +#ifdef HAVE_ZLIB_H +#include +#endif + +#ifdef HAVE_BZLIB_H +#include +#endif + +#include "dynlibs.h" +#include "city.h" +#include "citycrc.h" +#include "md5.h" +#include "sha1.h" +#include "util.h" +#include "xstring.h" +#include "align_simd.h" +#include "maps.h" +#include "arch.h" +#include "abundance.h" +#include "db.h" +#include "align.h" +#include "unique.h" +#include "bitmap.h" +#include "dbindex.h" +#include "minheap.h" +#include "search.h" +#include "linmemalign.h" +#include "searchcore.h" +#include "showalign.h" +#include "userfields.h" +#include "results.h" +#include "sortbysize.h" +#include "sortbylength.h" +#include "derep.h" +#include "shuffle.h" +#include "mask.h" +#include "cluster.h" +#include "msa.h" +#include "chimera.h" +#include "cpu.h" +#include "allpairs.h" +#include "subsample.h" +#include "fasta.h" +#include "fastq.h" +#include "fastx.h" +#include "fastqops.h" +#include "dbhash.h" +#include "searchexact.h" +#include "mergepairs.h" + +//vsearch definitions + +#define PROG_NAME "vsearch" //PACKAGE +#define PROG_VERSION "1.9.10" //PACKAGE_VERSION +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "torognes@ifi.uio.no" + + +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + + +#if defined (__APPLE__) || (__MACH__) +#define PROG_ARCH "osx_x86_64" +#include +#else +#define PROG_ARCH "linux_x86_64" +#include +#endif +#else +#define PROG_ARCH "Windows_x86_64" +#include +#include +#include +#endif + + + +/* options */ + +extern bool opt_clusterout_id; +extern bool opt_clusterout_sort; +extern bool opt_eeout; +extern bool opt_fastq_allowmergestagger; +extern bool opt_fastq_eeout; +extern bool opt_fastq_nostagger; +extern bool opt_quiet; +extern bool opt_relabel_keep; +extern bool opt_relabel_md5; +extern bool opt_relabel_sha1; +extern bool opt_samheader; +extern bool opt_sizeorder; +extern bool opt_xsize; +extern char * opt_allpairs_global; +extern char * opt_alnout; +extern char * opt_blast6out; +extern char * opt_borderline; +extern char * opt_centroids; +extern char * opt_chimeras; +extern char * opt_cluster_fast; +extern char * opt_cluster_size; +extern char * opt_cluster_smallmem; +extern char * opt_clusters; +extern char * opt_consout; +extern char * opt_db; +extern char * opt_dbmatched; +extern char * opt_dbnotmatched; +extern char * opt_derep_fulllength; +extern char * opt_derep_prefix; +extern char * opt_eetabbedout; +extern char * opt_fastaout_notmerged_fwd; +extern char * opt_fastaout_notmerged_rev; +extern char * opt_fastaout; +extern char * opt_fastaout_discarded; +extern char * opt_fastapairs; +extern char * opt_fastq_chars; +extern char * opt_fastq_convert; +extern char * opt_fastq_filter; +extern char * opt_fastq_mergepairs; +extern char * opt_fastqout_notmerged_fwd; +extern char * opt_fastqout_notmerged_rev; +extern char * opt_fastq_stats; +extern char * opt_fastqout; +extern char * opt_fastqout_discarded; +extern char * opt_fastx_mask; +extern char * opt_fastx_revcomp; +extern char * opt_fastx_subsample; +extern char * opt_label_suffix; +extern char * opt_log; +extern char * opt_maskfasta; +extern char * opt_matched; +extern char * opt_msaout; +extern char * opt_nonchimeras; +extern char * opt_notmatched; +extern char * opt_output; +extern char * opt_pattern; +extern char * opt_profile; +extern char * opt_relabel; +extern char * opt_reverse; +extern char * opt_samout; +extern char * opt_search_exact; +extern char * opt_shuffle; +extern char * opt_sortbylength; +extern char * opt_sortbysize; +extern char * opt_uc; +extern char * opt_uchime_denovo; +extern char * opt_uchime_ref; +extern char * opt_uchimealns; +extern char * opt_uchimeout; +extern char * opt_usearch_global; +extern char * opt_userout; +extern double opt_abskew; +extern double opt_dn; +extern double opt_fastq_maxee; +extern double opt_fastq_maxee_rate; +extern double opt_id; +extern double opt_max_unmasked_pct; +extern double opt_maxid; +extern double opt_maxqt; +extern double opt_maxsizeratio; +extern double opt_maxsl; +extern double opt_mid; +extern double opt_min_unmasked_pct; +extern double opt_mindiv; +extern double opt_minh; +extern double opt_minqt; +extern double opt_minsizeratio; +extern double opt_minsl; +extern double opt_query_cov; +extern double opt_sample_pct; +extern double opt_target_cov; +extern double opt_weak_id; +extern double opt_xn; +extern int opt_acceptall; +extern int opt_alignwidth; +extern int opt_cons_truncate; +extern int opt_gap_extension_query_interior; +extern int opt_gap_extension_query_left; +extern int opt_gap_extension_query_right; +extern int opt_gap_extension_target_interior; +extern int opt_gap_extension_target_left; +extern int opt_gap_extension_target_right; +extern int opt_gap_open_query_interior; +extern int opt_gap_open_query_left; +extern int opt_gap_open_query_right; +extern int opt_gap_open_target_interior; +extern int opt_gap_open_target_left; +extern int opt_gap_open_target_right; +extern int opt_help; +extern int opt_mindiffs; +extern int opt_slots; +extern int opt_uchimeout5; +extern int opt_usersort; +extern int opt_version; +extern long opt_dbmask; +extern long opt_fasta_width; +extern long opt_fastq_ascii; +extern long opt_fastq_asciiout; +extern long opt_fastq_maxdiffs; +extern long opt_fastq_maxmergelen; +extern long opt_fastq_maxns; +extern long opt_fastq_minlen; +extern long opt_fastq_minmergelen; +extern long opt_fastq_minovlen; +extern long opt_fastq_qmax; +extern long opt_fastq_qmaxout; +extern long opt_fastq_qmin; +extern long opt_fastq_qminout; +extern long opt_fastq_stripleft; +extern long opt_fastq_tail; +extern long opt_fastq_trunclen; +extern long opt_fastq_truncqual; +extern long opt_fulldp; +extern long opt_hardmask; +extern long opt_iddef; +extern long opt_idprefix; +extern long opt_idsuffix; +extern long opt_leftjust; +extern long opt_match; +extern long opt_maxaccepts; +extern long opt_maxdiffs; +extern long opt_maxgaps; +extern long opt_maxhits; +extern long opt_maxqsize; +extern long opt_maxrejects; +extern long opt_maxseqlength; +extern long opt_maxsize; +extern long opt_maxsubs; +extern long opt_maxuniquesize; +extern long opt_mincols; +extern long opt_minseqlength; +extern long opt_minsize; +extern long opt_mintsize; +extern long opt_minuniquesize; +extern long opt_minwordmatches; +extern long opt_mismatch; +extern long opt_notrunclabels; +extern long opt_output_no_hits; +extern long opt_qmask; +extern long opt_randseed; +extern long opt_rightjust; +extern long opt_rowlen; +extern long opt_sample_size; +extern long opt_self; +extern long opt_selfid; +extern long opt_sizein; +extern long opt_sizeout; +extern long opt_strand; +extern long opt_threads; +extern long opt_top_hits_only; +extern long opt_topn; +extern long opt_uc_allhits; +extern long opt_wordlength; + +extern long mmx_present; +extern long sse_present; +extern long sse2_present; +extern long sse3_present; +extern long ssse3_present; +extern long sse41_present; +extern long sse42_present; +extern long popcnt_present; +extern long avx_present; +extern long avx2_present; + +extern FILE * fp_log; + +extern abundance_t * global_abundance; diff --git a/source/vsearch_src/vsearchfileparser.cpp b/source/vsearch_src/vsearchfileparser.cpp deleted file mode 100644 index d938fc06d..000000000 --- a/source/vsearch_src/vsearchfileparser.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// -// vsearchfileparser.cpp -// Mothur -// -// Created by Sarah Westcott on 10/13/15. -// Copyright (c) 2015 Schloss Lab. All rights reserved. -// - -#include "vsearchfileparser.h" -#include "deconvolutecommand.h" -#include "sequence.hpp" -#include "rabundvector.hpp" -#include "sabundvector.hpp" - -/***********************************************************************/ -VsearchFileParser::VsearchFileParser(string f){ - try { - m = MothurOut::getInstance(); - fastafile = f; - namefile = ""; - countfile = ""; - format = "count"; - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "VsearchFileParser"); - exit(1); - } -} -/***********************************************************************/ -VsearchFileParser::VsearchFileParser(string f, string nameOrCount, string forma) { - try { - m = MothurOut::getInstance(); - fastafile = f; - namefile = ""; - countfile = ""; - format = forma; - - if (format == "name") { namefile = nameOrCount; } - else if (format == "count") { countfile = nameOrCount; } - else { m->mothurOut("[ERROR]: " + format + " is not a valid file format for the VsearchFileParser, quitting.\n"); m->control_pressed = true; } - - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "VsearchFileParser"); - exit(1); - } -} -/***********************************************************************/ -string VsearchFileParser::getVsearchFile() { - try { - //Run unique.seqs on the data if a name or count file is not given - if ((namefile == "") && (countfile == "")) { countfile = getNamesFile(fastafile); } - else if (namefile != "") { counts = m->readNames(namefile); } - - if (countfile != "") { CountTable countTable; countTable.readTable(countfile, false, false); counts = countTable.getNameMap(); } - - if (m->control_pressed) { return 0; } - - //Remove gap characters from each sequence if needed - //Append the number of sequences that each unique sequence represents to the end of the fasta file name - //Sorts by abundance - string vsearchFastafile = createVsearchFasta(fastafile); - - return vsearchFastafile; - - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "getVsearchFile"); - exit(1); - } -} -/**********************************************************************/ - -string VsearchFileParser::createVsearchFasta(string inputFile){ - try { - string vsearchFasta = m->getSimpleName(fastafile) + ".sorted.fasta.temp"; - - vector seqs; - map::iterator it; - - ifstream in; - m->openInputFile(inputFile, in); - - while (!in.eof()) { - - if (m->control_pressed) { in.close(); return vsearchFasta; } - - Sequence seq(in); m->gobble(in); - - it = counts.find(seq.getName()); - if (it == counts.end()) { - m->mothurOut("[ERROR]: " + seq.getName() + " is not in your name or countfile, quitting.\n"); m->control_pressed = true; - }else { - seqPriorityNode temp(it->second, seq.getUnaligned(), it->first); - seqs.push_back(temp); - } - - } - in.close(); - - m->printVsearchFile(seqs, vsearchFasta); - - return vsearchFasta; - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "createVsearchFasta"); - exit(1); - } -} -/*************************************************************************/ - -string VsearchFileParser::getNamesFile(string& inputFile){ - try { - string nameFile = ""; - - m->mothurOutEndLine(); m->mothurOut("No namesfile given, running unique.seqs command to generate one."); m->mothurOutEndLine(); m->mothurOutEndLine(); - - //use unique.seqs to create new name and fastafile - string inputString = "fasta=" + inputFile + ", format=count"; - m->mothurOut("/******************************************/"); m->mothurOutEndLine(); - m->mothurOut("Running command: unique.seqs(" + inputString + ")"); m->mothurOutEndLine(); - m->mothurCalling = true; - - Command* uniqueCommand = new DeconvoluteCommand(inputString); - uniqueCommand->execute(); - - map > filenames = uniqueCommand->getOutputFiles(); - - delete uniqueCommand; - m->mothurCalling = false; - m->mothurOut("/******************************************/"); m->mothurOutEndLine(); - - countfile = filenames["count"][0]; - fastafile = filenames["fasta"][0]; - - return nameFile; - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "getNamesFile"); - exit(1); - } -} -/*************************************************************************/ -//S 1 275 * * * * * GQY1XT001C44N8/ab=3677/ * -int VsearchFileParser::createListFile(string inputFile, string listFile, string sabundFile, string rabundFile, int numBins, string label){ - try { - map::iterator itName; - if (format == "name") { counts.clear(); m->readNames(namefile, nameMap); } - - ifstream in; - m->openInputFile(inputFile, in); - - ListVector list(numBins); list.setLabel(label); - - int clusterNumber; - string seqName, recordType, length, percentIdentity, strand, notUsed1, notUsed2, compressedAlignment, repSequence; - - while(!in.eof()) { - if (m->control_pressed) { break; } - - in >> recordType >> clusterNumber >> length >> percentIdentity >> strand >> notUsed1 >> notUsed2 >> compressedAlignment >> seqName >> repSequence; m->gobble(in); - - seqName = removeAbundances(seqName); - - if (format == "name") { - itName = nameMap.find(seqName); - if (itName == nameMap.end()) { m->mothurOut("[ERROR]: " + seqName + " is not in your name file. Parsing error???\n"); m->control_pressed = true; } - else{ seqName = itName->second; } - } - - string bin = list.get(clusterNumber); - if (bin == "") { bin = seqName; } - else { bin += ',' + seqName; } - list.set(clusterNumber, bin); - - } - in.close(); - - ofstream out; - m->openOutputFile(listFile, out); - list.printHeaders(out); - - if (countfile != "") { - list.print(out, counts); - }else { - list.print(out); - - if ((sabundFile != "") && (rabundFile != "")){ - //print sabund and rabund - ofstream sabund, rabund; - m->openOutputFile(sabundFile, sabund); - m->openOutputFile(rabundFile, rabund); - - list.getRAbundVector().print(rabund); rabund.close(); - list.getSAbundVector().print(sabund); sabund.close(); - } - } - out.close(); - - return 0; - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "createListFile"); - exit(1); - } -} -/*************************************************************************/ -//GQY1XT001C44N8/ab=3677/ * -string VsearchFileParser::removeAbundances(string seqName){ - try { - - int pos = seqName.find_last_of("/", seqName.length()-2); //don't look at the last / - if (pos != string::npos) { seqName = seqName.substr(0, pos); } - - return seqName; - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "removeAbundances"); - exit(1); - } -} -/*************************************************************************/ -//GQY1XT001C44N8/ab=3677/ * -int VsearchFileParser::getNumBins(string logfile){ - try { - - int numBins = 0; - - ifstream in; - m->openInputFile(logfile, in); - - string line; - while(!in.eof()) { - if (m->control_pressed) { break; } - - line = m->getline(in); m->gobble(in); - - int pos = line.find("Clusters:"); - if (pos != string::npos) { - vector pieces = m->splitWhiteSpace(line); - if (pieces.size() > 1) { m->mothurConvert(pieces[1], numBins); } - break; - } - } - in.close(); - - return numBins; - } - catch(exception& e) { - m->errorOut(e, "VsearchFileParser", "getNumBins"); - exit(1); - } -} -/***********************************************************************/ - diff --git a/source/vsearch_src/vsearchfileparser.h b/source/vsearch_src/vsearchfileparser.h deleted file mode 100644 index 551ee4548..000000000 --- a/source/vsearch_src/vsearchfileparser.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// vsearchfileparser.h -// Mothur -// -// Created by Sarah Westcott on 10/13/15. -// Copyright (c) 2015 Schloss Lab. All rights reserved. -// - -#ifndef __Mothur__vsearchfileparser__ -#define __Mothur__vsearchfileparser__ - -#include "mothurout.h" - - -/**************************************************************************************************/ - -class VsearchFileParser { - - public: - VsearchFileParser(string f); //fastafile - VsearchFileParser(string f, string n, string format); //fastafile, name or count file, format("name" or "count") - ~VsearchFileParser(){} - - string getVsearchFile(); //creates vsearch formatted file. degapped, abundance appended, and sorted. - string getCountFile(); //returns count filename. If no names or count file is given, then a count file is generated. - int createListFile(string uc, string listfile, string, string, int numbins, string label); //takes vsearch output and creates list file - int getNumBins(string logfile); - - private: - MothurOut* m; - map nameMap; - map counts; - string fastafile, namefile, countfile, format; - string getNamesFile(string& inputFile); - string createVsearchFasta(string); - string removeAbundances(string seqName); - - -}; - -/**************************************************************************************************/ - - -#endif /* defined(__Mothur__vsearchfileparser__) */ diff --git a/source/vsearch_src/xstring.h b/source/vsearch_src/xstring.h old mode 100644 new mode 100755