[med-svn] [fsa] 07/10: Imported Upstream version 1.15.9+dfsg
Andreas Tille
tille at debian.org
Mon Dec 21 18:43:33 UTC 2015
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository fsa.
commit 5dd84fe710be9a73091d930c3a55149693c1968c
Author: Andreas Tille <tille at debian.org>
Date: Mon Dec 21 19:41:12 2015 +0100
Imported Upstream version 1.15.9+dfsg
---
COPYING | 674 ++
LICENSE | 18 +
MW/COPYING | 0
MW/INSTALL | 55 +
MW/Makefile.in | 119 +
MW/README | 15 +
MW/acinclude.m4 | 21 +
MW/aclocal.m4 | 15 +
MW/configure | 5669 ++++++++++++
MW/configure.in | 268 +
MW/doxygen.conf | 1117 +++
MW/install-sh | 251 +
MW/missing | 0
MW/mkinstalldirs | 40 +
MW/src/BlackBox/MWDriver_blackbox.C | 92 +
MW/src/BlackBox/MWDriver_blackbox.h | 77 +
MW/src/BlackBox/MWTask_blackbox.C | 247 +
MW/src/BlackBox/MWTask_blackbox.h | 95 +
MW/src/BlackBox/MWWorkerMain_blackbox.C | 57 +
MW/src/BlackBox/MWWorker_blackbox.C | 138 +
MW/src/BlackBox/MWWorker_blackbox.h | 49 +
MW/src/BlackBox/Makefile.in | 181 +
MW/src/MW.C | 24 +
MW/src/MW.h | 136 +
MW/src/MWControlTasks/MWNWSTask.C | 229 +
MW/src/MWControlTasks/MWNWSTask.h | 110 +
MW/src/MWControlTasks/Makefile.in | 133 +
MW/src/MWDriver.C | 4517 ++++++++++
MW/src/MWDriver.h | 1274 +++
MW/src/MWGroup.C | 99 +
MW/src/MWGroup.h | 49 +
MW/src/MWList.C | 873 ++
MW/src/MWList.h | 1088 +++
MW/src/MWMasterMain.C | 43 +
MW/src/MWStats.C | 539 ++
MW/src/MWStats.h | 153 +
MW/src/MWSystem.h | 15 +
MW/src/MWTask.C | 129 +
MW/src/MWTask.h | 191 +
MW/src/MWTaskContainer.C | 157 +
MW/src/MWTaskContainer.h | 112 +
MW/src/MWUnixSystem.C | 52 +
MW/src/MWWinSystem.C | 47 +
MW/src/MWWorker.C | 541 ++
MW/src/MWWorker.h | 190 +
MW/src/MWWorkerID.C | 659 ++
MW/src/MWWorkerID.h | 395 +
MW/src/MWWorkerMain.C | 42 +
MW/src/MWprintf.C | 106 +
MW/src/MWprintf.h | 82 +
MW/src/Makefile.in | 171 +
MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.C | 1290 +++
MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.h | 287 +
MW/src/RMComm/MW-CondorPVM/Makefile.in | 140 +
MW/src/RMComm/MW-File/MWFileError.h | 35 +
MW/src/RMComm/MW-File/MWFileRC.C | 2992 +++++++
MW/src/RMComm/MW-File/MWFileRC.h | 397 +
MW/src/RMComm/MW-File/MWFileRCSymbol.h | 37 +
MW/src/RMComm/MW-File/MWFileSend.h | 58 +
MW/src/RMComm/MW-File/MWFileTypes.h | 42 +
MW/src/RMComm/MW-File/MWFileWorker.h | 68 +
MW/src/RMComm/MW-File/Makefile.in | 143 +
MW/src/RMComm/MW-File/chirp_client.c | 623 ++
MW/src/RMComm/MW-File/chirp_client.h | 202 +
MW/src/RMComm/MW-File/chirp_protocol.h | 50 +
MW/src/RMComm/MW-Independent/MWIndRC.C | 500 ++
MW/src/RMComm/MW-Independent/MWIndRC.h | 230 +
MW/src/RMComm/MW-Independent/Makefile.in | 122 +
MW/src/RMComm/MW-Socket/MWSocketRC.C | 2114 +++++
MW/src/RMComm/MW-Socket/MWSocketRC.h | 434 +
MW/src/RMComm/MW-Socket/Makefile.in | 139 +
MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.C | 754 ++
MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.h | 371 +
MW/src/RMComm/MW-StaticMPI/Makefile.in | 120 +
MW/src/RMComm/MWRMComm.C | 457 +
MW/src/RMComm/MWRMComm.h | 493 ++
MW/src/RMComm/Makefile.in | 155 +
Makefile.am | 91 +
Makefile.in | 872 ++
README | 357 +
acinclude.m4 | 114 +
aclocal.m4 | 1210 +++
build-aux/ar-lib | 270 +
build-aux/compile | 347 +
build-aux/config.guess | 1501 ++++
build-aux/config.sub | 1705 ++++
build-aux/depcomp | 630 ++
build-aux/install-sh | 520 ++
build-aux/missing | 376 +
build-aux/test-driver | 127 +
config.h.in | 167 +
configure | 8958 +++++++++++++++++++
configure.ac | 303 +
debian/changelog | 10 -
debian/compat | 1 -
debian/control | 50 -
debian/copyright | 53 -
debian/docs | 3 -
debian/examples | 1 -
debian/patches/no-display.patch | 17 -
debian/patches/removed-pdf-only-docs.patch | 22 -
debian/patches/series | 2 -
debian/rules | 50 -
debian/source/format | 1 -
debian/upstream/metadata | 12 -
debian/watch | 2 -
display/Makefile.am | 78 +
display/Makefile.in | 503 ++
display/classnoinst.stamp | 1 +
display/mad/AlignDAG.java | 641 ++
display/mad/Alignment.java | 328 +
display/mad/AlignmentPanel.java | 337 +
display/mad/Alignments.java | 364 +
display/mad/BatchDocument.java | 87 +
display/mad/JpegImagesToMovie.java | 530 ++
display/mad/MAD.java | 67 +
display/mad/MadApplet.java | 37 +
display/mad/MadPanel.java | 792 ++
display/mad/Node.java | 618 ++
display/mad/ProbabilityMatrices.java | 169 +
display/mad/PropertyChangeHandler.java | 37 +
display/mad/PropertyChangeIDs.java | 11 +
display/mad/SaveAsFastaAction.java | 59 +
display/mad/SaveAsMovAction.java | 31 +
display/mad/SaveAsTiffAction.java | 53 +
display/mad/SparseMatrix.java | 257 +
display/mad/legend.jpg | Bin 0 -> 2289 bytes
display/mad/manifest.mf | 4 +
display/mad/manifest.mf.in | 4 +
examples/Makefile.am | 23 +
examples/Makefile.in | 431 +
examples/README | 36 +
examples/RV12.BBS12030.fasta | 36 +
examples/RV12.BBS12030.fasta.gui | 2599 ++++++
examples/RV12.BBS12030.fasta.probs | 12627 +++++++++++++++++++++++++++
examples/RV12.BBS12030.mfa | 13 +
examples/RV12.BBS12030.reference.mfa | 36 +
examples/RV12.BBS12030.reference.stock | 8 +
examples/RV12.BBS12030.stock | 10 +
examples/U5.aln1.fasta | 20 +
examples/U5.aln1.fasta.gui | 1048 +++
examples/U5.aln1.fasta.probs | 5984 +++++++++++++
examples/U5.aln1.mfa | 11 +
examples/U5.aln1.reference.mfa | 20 +
examples/U5.aln1.reference.stock | 13 +
examples/U5.aln1.stock | 9 +
examples/tRNA.aln1.fasta | 15 +
examples/tRNA.aln1.fasta.gui | 636 ++
examples/tRNA.aln1.fasta.probs | 3731 ++++++++
examples/tRNA.aln1.mfa | 11 +
examples/tRNA.aln1.reference.mfa | 15 +
examples/tRNA.aln1.reference.stock | 13 +
examples/tRNA.aln1.stock | 9 +
html/FAQ.html | 532 ++
html/Makefile.am | 3 +
html/Makefile.in | 411 +
html/pretty.css | 12 +
perl/FSA/Model.pm | 493 ++
perl/FSA/SparseMatrices.pm | 490 ++
perl/GFF.pm | 271 +
perl/GFF/Database.pm | 201 +
perl/Makefile.am | 14 +
perl/Makefile.in | 422 +
perl/Stockholm.pm | 1788 ++++
perl/Stockholm/Database.pm | 284 +
perl/accuracy.pl | 97 +
perl/cmpalign.pl | 277 +
perl/dartlog.pl | 168 +
perl/fasta2stockholm.pl | 59 +
perl/prettify.pl | 36 +
perl/seqdotplot.pl | 173 +
perl/stockholm2fasta.pl | 63 +
src/annealing/Makefile.am | 35 +
src/annealing/Makefile.in | 569 ++
src/annealing/SparseMatrix.h | 530 ++
src/annealing/alignment_DAG.cc | 1666 ++++
src/annealing/alignment_DAG.h | 742 ++
src/annealing/dotplot.cc | 53 +
src/annealing/dotplot.h | 62 +
src/annealing/tree_weights.cc | 100 +
src/annealing/tree_weights.h | 96 +
src/fsa/Makefile.am | 37 +
src/fsa/Makefile.in | 583 ++
src/fsa/algebras.cc | 52 +
src/fsa/algebras.h | 554 ++
src/fsa/aminoacid_indel2dp.cc | 2445 ++++++
src/fsa/aminoacid_indel2dp.h | 315 +
src/fsa/aminoaciddp.cc | 2205 +++++
src/fsa/aminoaciddp.h | 315 +
src/fsa/anchors.cc | 1536 ++++
src/fsa/anchors.h | 818 ++
src/fsa/constraints.cc | 101 +
src/fsa/constraints.h | 195 +
src/fsa/dptables.h | 438 +
src/fsa/fsa.cc | 1887 ++++
src/fsa/fsa.h | 406 +
src/fsa/model.cc | 392 +
src/fsa/model.h | 915 ++
src/fsa/mybanding.h | 111 +
src/fsa/nucleotide_indel2dp.cc | 2253 +++++
src/fsa/nucleotide_indel2dp.h | 315 +
src/fsa/nucleotidedp.cc | 2013 +++++
src/fsa/nucleotidedp.h | 315 +
src/fsa/sequence_pair_selector.cc | 360 +
src/fsa/sequence_pair_selector.h | 122 +
src/main/Makefile.am | 55 +
src/main/Makefile.in | 806 ++
src/main/gapcleaner.cc | 116 +
src/main/isect_mercator_alignment_gff.cc | 244 +
src/main/main.cc | 59 +
src/main/map_coords.cc | 205 +
src/main/map_gff_coords.cc | 204 +
src/main/percentid.cc | 108 +
src/main/prot2codon.cc | 133 +
src/main/slice_fasta.cc | 170 +
src/main/slice_fasta_gff.cc | 173 +
src/main/slice_mercator_alignment.cc | 227 +
src/main/translate.cc | 107 +
src/manager/Makefile.am | 49 +
src/manager/Makefile.in | 585 ++
src/manager/db_adapter.cc | 263 +
src/manager/db_adapter.h | 108 +
src/manager/db_misc.cc | 36 +
src/manager/db_misc.h | 162 +
src/manager/db_postgres.cc | 1011 +++
src/manager/db_postgres.h | 301 +
src/manager/manager.cc | 772 ++
src/manager/manager.h | 217 +
src/manager/mw_adapter.cc | 31 +
src/manager/mw_adapter.h | 54 +
src/manager/mw_master.cc | 530 ++
src/manager/mw_master.h | 93 +
src/manager/mw_task.cc | 62 +
src/manager/mw_task.h | 63 +
src/manager/mw_worker.cc | 232 +
src/manager/mw_worker.h | 63 +
src/manager/transfer_data.cc | 634 ++
src/math/Makefile.am | 10 +
src/math/Makefile.in | 549 ++
src/math/mathematics.cc | 36 +
src/math/mathematics.h | 195 +
src/math/mst.cc | 101 +
src/math/mst.h | 166 +
src/seq/Makefile.am | 22 +
src/seq/Makefile.in | 567 ++
src/seq/alignment.cc | 1154 +++
src/seq/alignment.h | 729 ++
src/seq/alphabet.cc | 193 +
src/seq/alphabet.h | 320 +
src/seq/gff.cc | 364 +
src/seq/gff.h | 531 ++
src/seq/interval.h | 130 +
src/seq/mercator.cc | 856 ++
src/seq/mercator.h | 465 +
src/seq/sequence.cc | 587 ++
src/seq/sequence.h | 506 ++
src/seq/similarity_matrix.cc | 204 +
src/seq/similarity_matrix.h | 198 +
src/util/Makefile.am | 24 +
src/util/Makefile.in | 570 ++
src/util/array2d.h | 421 +
src/util/dexception.cc | 120 +
src/util/dexception.h | 58 +
src/util/hash_fcn.h | 200 +
src/util/logfile.cc | 337 +
src/util/logfile.h | 277 +
src/util/logtags.h | 13 +
src/util/macros.h | 84 +
src/util/memcheck.cc | 51 +
src/util/memcheck.h | 17 +
src/util/misc.cc | 90 +
src/util/misc.h | 390 +
src/util/opts_list.cc | 433 +
src/util/opts_list.h | 160 +
src/util/regexp.cc | 1758 ++++
src/util/regexp.h | 49 +
src/util/sstring.cc | 159 +
src/util/sstring.h | 131 +
tests/Makefile.am | 3 +
tests/Makefile.in | 1198 +++
version.m4 | 1 +
281 files changed, 134147 insertions(+), 224 deletions(-)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..bca5e08
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,18 @@
+
+==================================================================
+ LICENSE
+==================================================================
+
+FSA is licensed under the GNU GPL.
+MAD is licensed under the GNU GPL.
+
+Please see the file COPYING for the text of version 3 of the
+GNU General Public License.
+
+The bundled Java Media Framework 2.1.1e API,
+located in display/JMF-2.1.1e/
+is covered by the
+JavaTM Media Framework (JMF) 2.1.x Binary Code License Agreement.
+
+Please see the file display/JMF-2.1.1e/readme.html for a
+copy of the JavaTM Media Framework (JMF) 2.1.x Binary Code License Agreement.
diff --git a/MW/COPYING b/MW/COPYING
new file mode 100644
index 0000000..e69de29
diff --git a/MW/INSTALL b/MW/INSTALL
new file mode 100644
index 0000000..38f41d7
--- /dev/null
+++ b/MW/INSTALL
@@ -0,0 +1,55 @@
+#$Id: INSTALL,v 1.3 2004/05/28 18:35:47 linderot Exp $
+
+# ------------- Prepare to install MW -----------------------
+1) Install Condor first, and make sure that the condor execs
+ are in your path. For example, you can add the following
+ lines in your .cshrc file.
+
+ set path = ( $path /unsup/condor/bin )
+ set path = ( $path /unsup/condor/sbin )
+
+ For bash and other sh type shells, the command would be
+ export PATH = $PATH:/unsup/condor/bin:/unsup/condor/sbin
+
+2) Install Condor-PVM or PVM with proper changes (refer the
+ README.Condor-PVM file under /afs/cs.wisc.edu/p/condor/workspaces/pvm)
+ so that it works with Condor. Also update your environment variables:
+ setenv PVM_ROOT /p/condor/workspaces/pvm/pvm3.4.2
+ setenv PVM_ARCH <proper_name: LINUX X86SOL2 SGI6 etc>
+
+ sh style shells
+
+ export PVM_ROOT=/p/condor/workspaces/pvm/pvm3.4.2
+ export PVM_ARCH=LINUX
+
+3) There are several options for debugging:
+ -- The default result of "make check" will produce master and worker
+ application using MW-Independent (which is developed for debugging).
+ You can "setenv MW_DEBUG no" to turn this off.
+ -- You can also use Insure to detect memory related bugs. To do this,
+ you need to "setenv DEBUG_BUILD insure" and setup the path variable.
+ As insure doesn't work with MW-File, this setting will produce
+ master and worker app using MW-File.
+
+
+# -------------- How to build MW -----------------------------
+tar zxf mw.tar.gz
+cd mw; ./configure #--prefix=/tmp/mw
+make; make check # The typical command to build MW
+
+ --with-condor Use the given condor installation path
+ --with-pvm Use the given pvm installation path
+ --with-measure Build with -DMEASURE
+ --with-independent Build MW-Independent library
+
+
+# -------------- Other targets --------------------------------
+make # Build MW libraries, without installing them
+make install # (Build and) install MW libraries
+make check # Build examples (after building libraries)
+make clean # Cleanup the exes, libs, and object files
+make distclean # Cleanup for distribution
+
+# ------------- How to run the examples ----------------------
+cd examples/fib
+condor_submit submit_mwfile # submit the job using MW File
diff --git a/MW/Makefile.in b/MW/Makefile.in
new file mode 100644
index 0000000..ebfa06d
--- /dev/null
+++ b/MW/Makefile.in
@@ -0,0 +1,119 @@
+#-------------------------------------------------------------------------
+#
+# $Id: Makefile.in,v 1.5 2005/06/10 15:39:49 gthain Exp $
+#
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+PVM_ROOT = @PVM_ROOT@
+PVM_ARCH = @PVM_ARCH@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(DEBUG_CHECKER) $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+
+# Subdirectories
+SUBDIRS = src # examples
+LIBRARIES =
+
+# Files to be cleaned
+CLEANFILES = $(MW_LIBDIR)/* src/MWDriverInd.ii src/MWWorkerInd.ii src/RMComm/MW-File/MWFileRCW.ii src/RMComm/MW-File/MWFileRCM.ii src/RMComm/MW-CondorPVM/MWCondorPvmRCM.ii src/RMComm/MW-CondorPVM/MWCondorPvmRCW.ii src/RMComm/MW-Socket/MWSocketRCM.ii src/RMComm/MW-Socket/MWSocketRCW.ii
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all:
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.SUFFIXES:
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules
+#-------------------------------------------------------------------------
+
+install:
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+clean:
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+ -test -z "$(CLEANFILES)" || rm -fr $(CLEANFILES)
+
+distclean:
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+ -test -z "$(CLEANFILES)" || rm -fr $(CLEANFILES)
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps lib lib_debug debug_lib
+ -rm -f config.cache config.status config.log stamp-h stamp-h[0-9]*
+ -rm -rf autom4te.cache/
+ -rm -f ${PACKAGE}-${VERSION}.tar.gz
+ -find . -name "tca.map" -exec rm {} \;
+ -find . -name ".inslog2" -exec rm {} \;
+ -find . -name "*~" -exec rm {} \;
+ -find . -name "*#*#" -exec rm {} \;
+ @ echo "Cleaning intermediate results"
+ -find . -name "out_master.*" -exec rm {} \;
+ -find . -name "out_worker.*" -exec rm {} \;
+ -find . -name "submitfiles" -exec rm -r {} \;
+ -find . -name "worker_input" -exec rm -r {} \;
+ -find . -name "worker_output" -exec rm -r {} \;
+
+#
+# A target to build a (clean) source distribution
+#
+srcdist: distclean
+ echo -e "AUTHORS\nBUGS\nChangeLog\nCHANGES\nCVS\nNEWS\nTAGS\nTODO\nnmi_glue" > ../exclude-list
+ cd ..; tar cvzf ${PACKAGE}-${VERSION}.tgz --exclude-from=exclude-list mw
+ rm -f ../exclude-list
+
+#
+# A target for doc
+#
+doc:
+ doxygen doxygen.conf
+
+Makefile: configure.in
+ ./configure
+
+.PHONY: all check clean distclean doc srcdist install
diff --git a/MW/README b/MW/README
new file mode 100644
index 0000000..b453869
--- /dev/null
+++ b/MW/README
@@ -0,0 +1,15 @@
+$Id: README,v 1.2 2004/04/05 19:54:19 linderot Exp $
+
+For how to build MW, please read INSTALL;
+
+To run the existing examples, go to examples/ directory, and try
+ the fib, matmul or n-queen. There is also a skel subdirectory
+ that contains skeleton files to build your own simple MW app;
+
+For how to write your MW applications, please read matmul.html
+ in examples/matmul directory;
+
+For details of MW API, please refer to the DOC++ files in doc
+ directory;
+
+For other information, please email to mw at cs.wisc.edu.
diff --git a/MW/acinclude.m4 b/MW/acinclude.m4
new file mode 100644
index 0000000..0f5cae8
--- /dev/null
+++ b/MW/acinclude.m4
@@ -0,0 +1,21 @@
+dnl Starting here is a bunch of local macros
+
+
+
+AC_DEFUN([AC_CXX_DYNAMIC_CAST],
+ [AC_CACHE_CHECK(whether the compiler supports dynamic_cast<>,
+ ac_cv_cxx_dynamic_cast,
+ [AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <typeinfo>
+ class Base { public : Base () {} virtual void f () = 0;};
+ class Derived : public Base { public : Derived () {} virtual void f () {} };],[
+ Derived d; Base& b=d; return dynamic_cast<Derived*>(&b) ? 0 : 1;],
+ ac_cv_cxx_dynamic_cast=yes, ac_cv_cxx_dynamic_cast=no)
+ AC_LANG_RESTORE
+ ])
+ if test "$ac_cv_cxx_dynamic_cast" = yes; then
+ AC_DEFINE(HAVE_DYNAMIC_CAST,,[define if the compiler supports dynamic_cast<>])
+ fi
+ ])
+
diff --git a/MW/aclocal.m4 b/MW/aclocal.m4
new file mode 100644
index 0000000..44df97e
--- /dev/null
+++ b/MW/aclocal.m4
@@ -0,0 +1,15 @@
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_include([acinclude.m4])
diff --git a/MW/configure b/MW/configure
new file mode 100755
index 0000000..475f193
--- /dev/null
+++ b/MW/configure
@@ -0,0 +1,5669 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf at gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="src/MWDriver.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+MW_LIBDIR_DEBUG
+MW_LIBDIR
+ENABLE_MWINDEPENDENT
+MEASURE_DEFN
+MISC_LIB
+MISC_DEFN
+USE_POLL
+SOCKET_LIB
+MPICXX
+JUNK5
+PVM_ARCH
+PVM_ROOT
+JUNK3
+USE_CHIRP
+USE_MWFILE
+CONDOR_DIR
+JUNK1
+EGREP
+GREP
+CPP
+ac_ct_CC
+CFLAGS
+CC
+AUTOCONF
+RANLIB
+SET_MAKE
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+VERSION
+PACKAGE
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_condor
+with_mwfile
+with_chirp
+with_pvm_arch
+with_pvm
+with_mpi
+with_measure
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CC
+CFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-condor Use the given condor installation path --without-condor means only build indp
+ --with-mwfile Use MWfile RMCOMM
+ --with-chirp Use chirp for mw-file on clipped platforms
+ --with-pvm-arch Use the given pvm architectures
+ --with-pvm Use the given pvm installation path
+ --with-mpi Build the Static MPI RMComm
+ --with-measure Build with -DMEASURE
+
+Some influential environment variables:
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CC C compiler command
+ CFLAGS C compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+PACKAGE=mw
+VERSION=0.3.0
+
+
+
+
+
+
+
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5
+$as_echo_n "checking whether the C++ compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C++ compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5
+$as_echo_n "checking for C++ compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+# Extract the first word of "g++", so it can be a program name with args.
+set dummy g++; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $CXX in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_CXX="$CXX" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+CXX=$ac_cv_path_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "autoconf", so it can be a program name with args.
+set dummy autoconf; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_AUTOCONF+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $AUTOCONF in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_AUTOCONF="$AUTOCONF" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_AUTOCONF="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+AUTOCONF=$ac_cv_path_AUTOCONF
+if test -n "$AUTOCONF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AUTOCONF" >&5
+$as_echo "$AUTOCONF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in fcntl.h limits.h sys/time.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if ${ac_cv_c_const+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this sort of thing. */
+ typedef int charset[2];
+ const charset cs = { 0, 0 };
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this sort of thing. */
+ char tx;
+ char *t = &tx;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; } bx;
+ struct s *b = &bx; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_const=yes
+else
+ ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if ${ac_cv_header_time+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_time=yes
+else
+ ac_cv_header_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
+$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if ${ac_cv_struct_tm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_struct_tm=time.h
+else
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
+$as_echo "$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
+$as_echo_n "checking for uid_t in sys/types.h... " >&6; }
+if ${ac_cv_type_uid_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "uid_t" >/dev/null 2>&1; then :
+ ac_cv_type_uid_t=yes
+else
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
+$as_echo "$ac_cv_type_uid_t" >&6; }
+if test $ac_cv_type_uid_t = no; then
+
+$as_echo "#define uid_t int" >>confdefs.h
+
+
+$as_echo "#define gid_t int" >>confdefs.h
+
+fi
+
+
+for ac_func in vprintf
+do :
+ ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
+if test "x$ac_cv_func_vprintf" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VPRINTF 1
+_ACEOF
+
+ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
+if test "x$ac_cv_func__doprnt" = xyes; then :
+
+$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
+
+fi
+
+fi
+done
+
+
+for ac_func in getcwd gethostname gettimeofday mkdir strstr
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports dynamic_cast<>" >&5
+$as_echo_n "checking whether the compiler supports dynamic_cast<>... " >&6; }
+if ${ac_cv_cxx_dynamic_cast+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <typeinfo>
+ class Base { public : Base () {} virtual void f () = 0;};
+ class Derived : public Base { public : Derived () {} virtual void f () {} };
+int
+main ()
+{
+
+ Derived d; Base& b=d; return dynamic_cast<Derived*>(&b) ? 0 : 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_cxx_dynamic_cast=yes
+else
+ ac_cv_cxx_dynamic_cast=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_dynamic_cast" >&5
+$as_echo "$ac_cv_cxx_dynamic_cast" >&6; }
+ if test "$ac_cv_cxx_dynamic_cast" = yes; then
+
+$as_echo "#define HAVE_DYNAMIC_CAST /**/" >>confdefs.h
+
+ fi
+
+
+
+# Check whether --with-condor was given.
+if test "${with_condor+set}" = set; then :
+ withval=$with_condor; CONDOR_DIR=$withval
+fi
+
+if test -z "$CONDOR_DIR"; then
+ # Extract the first word of "condor_status", so it can be a program name with args.
+set dummy condor_status; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JUNK1+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $JUNK1 in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_JUNK1="$JUNK1" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_JUNK1="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+JUNK1=$ac_cv_path_JUNK1
+if test -n "$JUNK1"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JUNK1" >&5
+$as_echo "$JUNK1" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -z "$JUNK1"; then
+ echo "-- Can't build MW without Condor, please install Condor first."
+ exit 1
+ else
+ JUNK2=`dirname $JUNK1`
+ CONDOR_DIR=`dirname $JUNK2`
+ echo "-- Using Condor installed in $CONDOR_DIR"
+
+ fi
+else
+ echo "-- Using Condor installed in $CONDOR_DIR"
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define CONDOR_DIR "$CONDOR_DIR"
+_ACEOF
+
+
+
+# Check whether --with-mwfile was given.
+if test "${with_mwfile+set}" = set; then :
+ withval=$with_mwfile; USE_MWFILE=$withval
+else
+ USE_MWFILE=no
+fi
+
+if test -z $USE_MWFILE
+then
+ USE_MWFILE=true
+ echo "-- configuring MW to use MW-FILE RMCOMM Layer"
+else
+ if test $USE_MWFILE = no
+ then
+ USE_MWFILE=no
+ echo "-- configuring MW not to use MW-FILE RMCOMM Layer"
+ else
+ USE_MWFILE=true
+ echo "-- configuring MW to use MW-FILE RMCOMM Layer"
+ fi
+fi
+
+
+machtype=`uname -m`
+case $machtype in
+ x86_64)
+ echo "On x86_64, forcing mwfile implementation off"
+ USE_MWFILE=no
+ ;;
+esac
+
+
+
+# Check whether --with-chirp was given.
+if test "${with_chirp+set}" = set; then :
+ withval=$with_chirp; USE_CHIRP=$withval
+fi
+
+
+if test -z $USE_CHIRP
+then
+echo "-- Not using chirp with MW-File"
+else
+echo "-- Using chirp with MW-File"
+$as_echo "#define USE_CHIRP 1" >>confdefs.h
+
+
+fi
+
+
+
+# Check whether --with-pvm-arch was given.
+if test "${with_pvm_arch+set}" = set; then :
+ withval=$with_pvm_arch; PVM_ARCH=$withval
+fi
+
+
+# Check whether --with-pvm was given.
+if test "${with_pvm+set}" = set; then :
+ withval=$with_pvm; PVM_ROOT=$withval
+else
+ PVM_ROOT=no
+fi
+
+if test -z "$PVM_ROOT"; then
+ # Extract the first word of "pvm", so it can be a program name with args.
+set dummy pvm; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JUNK3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $JUNK3 in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_JUNK3="$JUNK3" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_JUNK3="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+JUNK3=$ac_cv_path_JUNK3
+if test -n "$JUNK3"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JUNK3" >&5
+$as_echo "$JUNK3" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -z "$JUNK3"; then
+ echo "-- Can't build MW without PVM, please install CondorPvm first."
+ exit 1
+ else
+ JUNK4=`dirname $JUNK3`
+ PVM_ROOT=`dirname $JUNK4`/
+ echo "-- Using PVM lib installed in $PVM_ROOT/lib/$PVM_ARCH"
+
+
+ fi
+else
+ if test $PVM_ROOT = no
+ then
+ echo "-- Not using PVM"
+ else
+ echo "-- Using PVM lib installed in $PVM_ROOT/lib/$PVM_ARCH"
+ fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mpi-directory" >&5
+$as_echo_n "checking for mpi-directory... " >&6; }
+
+# Check whether --with-mpi was given.
+if test "${with_mpi+set}" = set; then :
+ withval=$with_mpi; USE_MPI=$withval
+else
+ USE_MPI=no
+fi
+
+if test -z $USE_MPI
+then
+ # Extract the first word of "mpicxx", so it can be a program name with args.
+set dummy mpicxx; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JUNK5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $JUNK5 in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_JUNK5="$JUNK5" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_JUNK5="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+JUNK5=$ac_cv_path_JUNK5
+if test -n "$JUNK5"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JUNK5" >&5
+$as_echo "$JUNK5" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -z "$JUNK5"; then
+ echo "-- Can't find mpicxx, please install mpi first."
+ exit 1
+ else
+ echo "-- MPI is set to $USE_MPI"
+ echo "-- Using MPI lib $JUNK5"
+ MPICXX=mpicxx
+
+ echo "-- The MPI Compiler MPICXX is set at $MPICXX"
+ fi
+ else
+ if test $USE_MPI = no
+ then
+ echo "-- Not using MPI"
+ else
+ MPICXX=mpicxx
+
+ echo "-- The MPI Compiler MPICXX is set at $MPICXX"
+ fi
+fi
+
+
+if opsys=`uname -s`
+then
+ echo "-- Operating system is $opsys"
+else
+ echo "-- Can't find the 'uname' program!"
+ exit 1
+fi
+
+case $opsys in
+ SunOS*)
+ SOCKET_LIB="-lnsl -lsocket " ;;
+ *)
+ SOCKET_LIB= ;;
+esac
+
+
+if test $opsys = "Linux"
+then
+ echo "-- Using poll instead of select for supporting > 1024 socket workers"
+ $as_echo "#define USE_POLL 1" >>confdefs.h
+
+
+fi
+
+
+USE_NWS=no
+
+case $USE_NWS in
+ yes*)
+ MISC_DEFN=-DNWSENABLED;
+ NWS_SENSOR_PATH=`dirname $NWS_SENSOR_PING`
+ NWS_PATH=`dirname $NWS_SENSOR_PATH`
+ MISC_LIB=$NWS_PATH/libnws
+ ;;
+ *)
+ MISC_DEFN=
+ MISC_LIB=-lNWS;
+ ;;
+esac
+
+
+
+
+
+# Check whether --with-measure was given.
+if test "${with_measure+set}" = set; then :
+ withval=$with_measure; MEASURE_DEFN='-DMEASURE'
+fi
+
+
+
+ENABLE_MWINDEPENDENT=yes
+
+
+MW_LIBDIR=`pwd`/lib
+
+MW_LIBDIR_DEBUG=`pwd`/debug_lib
+
+
+if test -d lib; then
+ echo "-- The lib directory already exists, no need to create"
+else
+ echo "-- Creating lib directory"
+ mkdir lib
+fi
+
+if test -d debug_lib; then
+ echo "-- The debug_lib directory already exists, no need to create"
+else
+ echo "-- Creating debug_lib directory"
+ mkdir debug_lib
+fi
+
+EXTRA_MAKEFILES=`echo "src/RMComm/MW-Independent/Makefile"`
+ac_config_files="$ac_config_files Makefile src/Makefile src/RMComm/Makefile src/RMComm/MW-File/Makefile src/RMComm/MW-CondorPVM/Makefile src/RMComm/MW-Socket/Makefile src/RMComm/MW-StaticMPI/Makefile src/MWControlTasks/Makefile src/BlackBox/Makefile $EXTRA_MAKEFILES"
+
+ac_config_commands="$ac_config_commands default"
+
+
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "src/RMComm/Makefile") CONFIG_FILES="$CONFIG_FILES src/RMComm/Makefile" ;;
+ "src/RMComm/MW-File/Makefile") CONFIG_FILES="$CONFIG_FILES src/RMComm/MW-File/Makefile" ;;
+ "src/RMComm/MW-CondorPVM/Makefile") CONFIG_FILES="$CONFIG_FILES src/RMComm/MW-CondorPVM/Makefile" ;;
+ "src/RMComm/MW-Socket/Makefile") CONFIG_FILES="$CONFIG_FILES src/RMComm/MW-Socket/Makefile" ;;
+ "src/RMComm/MW-StaticMPI/Makefile") CONFIG_FILES="$CONFIG_FILES src/RMComm/MW-StaticMPI/Makefile" ;;
+ "src/MWControlTasks/Makefile") CONFIG_FILES="$CONFIG_FILES src/MWControlTasks/Makefile" ;;
+ "src/BlackBox/Makefile") CONFIG_FILES="$CONFIG_FILES src/BlackBox/Makefile" ;;
+ "$EXTRA_MAKEFILES") CONFIG_FILES="$CONFIG_FILES $EXTRA_MAKEFILES" ;;
+ "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "default":C) echo timestamp > stamp-h ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/MW/configure.in b/MW/configure.in
new file mode 100644
index 0000000..d9b9dc1
--- /dev/null
+++ b/MW/configure.in
@@ -0,0 +1,268 @@
+<<<<<<<dnl Caching is usually WRONG for systems with cross-mounted file systems
+dnl (the cache file may correspond to a different system). Since configure
+dnl is not on a performance-critical path, go for robustness over speed.
+dnl
+
+define([AC_CACHE_LOAD], )dnl
+define([AC_CACHE_SAVE], )dnl
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(src/MWDriver.h)
+
+PACKAGE=mw
+VERSION=0.3.0
+
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+dnl Check for the autoconf version
+AC_PREREQ(2.13)
+
+dnl Set the header
+dnl AM_CONFIG_HEADER(config.h)
+
+AC_ARG_PROGRAM
+
+dnl Checks for programs.
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AC_PATH_PROG(CXX,g++)
+AC_PATH_PROG(AUTOCONF,autoconf)
+
+AC_SUBST(CXX)
+AC_SUBST(AUTOCONF)
+
+dnl Checks for libraries.
+dnl We're just build libraries now, so you shouldn't
+dnl need to check all these until you build the exec
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h unistd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_HEADER_TIME
+AC_STRUCT_TM
+AC_TYPE_UID_T
+
+dnl Checks for library functions.
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(getcwd gethostname gettimeofday mkdir strstr)
+
+dnl
+dnl Starting here are Jeff's (non-auto) additions
+dnl
+
+dnl Some C++ support macros
+AC_CXX_DYNAMIC_CAST
+
+dnl Jeff's check for condor
+AC_ARG_WITH(condor, [ --with-condor Use the given condor installation path --without-condor means only build indp], CONDOR_DIR=$withval)
+if test -z "$CONDOR_DIR"; then
+ AC_PATH_PROG(JUNK1, condor_status)
+ if test -z "$JUNK1"; then
+ echo "-- Can't build MW without Condor, please install Condor first."
+ exit 1
+ else
+ JUNK2=`dirname $JUNK1`
+ dnl -- better if we can report condor versioni, will add later.
+ CONDOR_DIR=`dirname $JUNK2`
+ echo "-- Using Condor installed in $CONDOR_DIR"
+ AC_SUBST(CONDOR_DIR)
+ fi
+else
+ echo "-- Using Condor installed in $CONDOR_DIR"
+fi
+AC_DEFINE_UNQUOTED(CONDOR_DIR, "$CONDOR_DIR", [condor release directory])
+
+dnl Check for mw-file RMCOMM usage
+AC_ARG_WITH(mwfile, [ --with-mwfile Use MWfile RMCOMM], USE_MWFILE=$withval, USE_MWFILE=no)
+if test -z $USE_MWFILE
+then
+ USE_MWFILE=true
+ echo "-- configuring MW to use MW-FILE RMCOMM Layer"
+else
+ if test $USE_MWFILE = no
+ then
+ USE_MWFILE=no
+ echo "-- configuring MW not to use MW-FILE RMCOMM Layer"
+ else
+ USE_MWFILE=true
+ echo "-- configuring MW to use MW-FILE RMCOMM Layer"
+ fi
+fi
+
+
+machtype=`uname -m`
+case $machtype in
+ x86_64)
+ echo "On x86_64, forcing mwfile implementation off"
+ USE_MWFILE=no
+ ;;
+esac
+AC_SUBST(USE_MWFILE)
+
+dnl Check for chirp-file support
+AC_ARG_WITH(chirp, [ --with-chirp Use chirp for mw-file on clipped platforms], USE_CHIRP=$withval)
+
+if test -z $USE_CHIRP
+then
+echo "-- Not using chirp with MW-File"
+else
+echo "-- Using chirp with MW-File"
+AC_DEFINE(USE_CHIRP)
+AC_SUBST(USE_CHIRP)
+fi
+
+
+dnl Jeff's check for (Condor) PVM
+dnl -- Probably this should check if it really is
+dnl a Condor PVM library, or just a PVM library
+AC_ARG_WITH(pvm-arch, [ --with-pvm-arch Use the given pvm architectures], PVM_ARCH=$withval)
+AC_ARG_WITH(pvm, [ --with-pvm Use the given pvm installation path], PVM_ROOT=$withval, PVM_ROOT=no)
+if test -z "$PVM_ROOT"; then
+ AC_PATH_PROG(JUNK3, pvm)
+ if test -z "$JUNK3"; then
+ echo "-- Can't build MW without PVM, please install CondorPvm first."
+ exit 1
+ else
+ JUNK4=`dirname $JUNK3`
+ PVM_ROOT=`dirname $JUNK4`/
+ echo "-- Using PVM lib installed in $PVM_ROOT/lib/$PVM_ARCH"
+ AC_SUBST(PVM_ROOT)
+ AC_SUBST(PVM_ARCH)
+ fi
+else
+ if test $PVM_ROOT = no
+ then
+ echo "-- Not using PVM"
+ else
+ echo "-- Using PVM lib installed in $PVM_ROOT/lib/$PVM_ARCH"
+ fi
+fi
+
+dnl Some rudimentary stuff to setup for MPI build if required
+AC_MSG_CHECKING([for mpi-directory])
+AC_ARG_WITH(mpi, [ --with-mpi Build the Static MPI RMComm], USE_MPI=$withval, USE_MPI=no)
+if test -z $USE_MPI
+then
+dnl Check if it is setup
+ AC_PATH_PROG(JUNK5, mpicxx)
+ if test -z "$JUNK5"; then
+ echo "-- Can't find mpicxx, please install mpi first."
+ exit 1
+ else
+ echo "-- MPI is set to $USE_MPI"
+ echo "-- Using MPI lib $JUNK5"
+ MPICXX=mpicxx
+ AC_SUBST(MPICXX)
+ echo "-- The MPI Compiler MPICXX is set at $MPICXX"
+ fi
+ else
+ if test $USE_MPI = no
+ then
+ echo "-- Not using MPI"
+ else
+ MPICXX=mpicxx
+ AC_SUBST(MPICXX)
+ echo "-- The MPI Compiler MPICXX is set at $MPICXX"
+ fi
+fi
+
+
+dnl Check for System and Socket
+if opsys=`uname -s`
+then
+ echo "-- Operating system is $opsys"
+else
+ echo "-- Can't find the 'uname' program!"
+ exit 1
+fi
+
+case $opsys in
+ SunOS*)
+ SOCKET_LIB="-lnsl -lsocket " ;;
+ *)
+ SOCKET_LIB= ;;
+esac
+AC_SUBST(SOCKET_LIB)
+
+if test $opsys = "Linux"
+then
+ echo "-- Using poll instead of select for supporting > 1024 socket workers"
+ AC_DEFINE(USE_POLL)
+ AC_SUBST(USE_POLL)
+fi
+
+dnl Check for NWS library
+dnl if nwspresence=`nm $CONDOR_DIR/lib/libcondorsyscall.a | grep callBack`
+dnl then
+dnl echo "-- You have fork capable condor_compile version, will check NWS."
+dnl AC_PATH_PROG(NWS_SENSOR_PING, nws_ping)
+dnl if test -z "$NWS_SENSOR_PING"; then
+dnl USE_NWS=no
+dnl else
+dnl USE_NWS=yes
+dnl fi
+dnl else
+dnl echo "-- You don't have fork capable condor_compile version, won't use NWS."
+dnl USE_NWS=no
+dnl fi
+
+dnl Jeff changed to NOT use nws -- ever (and thus print no warning message)
+USE_NWS=no
+
+case $USE_NWS in
+ yes*)
+ MISC_DEFN=-DNWSENABLED;
+ NWS_SENSOR_PATH=`dirname $NWS_SENSOR_PING`
+ NWS_PATH=`dirname $NWS_SENSOR_PATH`
+ MISC_LIB=$NWS_PATH/libnws
+ ;;
+ *)
+ MISC_DEFN=
+ MISC_LIB=-lNWS;
+ ;;
+esac
+
+AC_SUBST(MISC_DEFN)
+AC_SUBST(MISC_LIB)
+
+dnl Whether to support runtime measurement (ifdef MEASURE)
+AC_ARG_WITH(measure, [ --with-measure Build with -DMEASURE], MEASURE_DEFN='-DMEASURE')
+AC_SUBST(MEASURE_DEFN)
+
+dnl Check for --with-independent
+dnl AC_ARG_WITH(independent, [ --with-independent Build MW-Independent library],
+dnl ENABLE_MWINDEPENDENT=yes)
+dnl We now always build independent
+ENABLE_MWINDEPENDENT=yes
+AC_SUBST(ENABLE_MWINDEPENDENT)
+
+dnl Define the MW_LIBDIR
+MW_LIBDIR=`pwd`/lib
+AC_SUBST(MW_LIBDIR)
+MW_LIBDIR_DEBUG=`pwd`/debug_lib
+AC_SUBST(MW_LIBDIR_DEBUG)
+
+if test -d lib; then
+ echo "-- The lib directory already exists, no need to create"
+else
+ echo "-- Creating lib directory"
+ mkdir lib
+fi
+
+if test -d debug_lib; then
+ echo "-- The debug_lib directory already exists, no need to create"
+else
+ echo "-- Creating debug_lib directory"
+ mkdir debug_lib
+fi
+
+dnl Generate output files
+EXTRA_MAKEFILES=`echo "src/RMComm/MW-Independent/Makefile"`
+dnl AC_OUTPUT(Makefile src/Makefile src/RMComm/Makefile src/RMComm/MW-File/Makefile src/RMComm/MW-CondorPVM/Makefile src/RMComm/MW-Socket/Makefile src/RMComm/MW-StaticMPI/Makefile src/MWControlTasks/Makefile src/BlackBox/Makefile examples/Makefile examples/fib/Makefile examples/n-queens/Makefile examples/matmul/Makefile $EXTRA_MAKEFILES, echo timestamp > stamp-h )
+AC_OUTPUT(Makefile src/Makefile src/RMComm/Makefile src/RMComm/MW-File/Makefile src/RMComm/MW-CondorPVM/Makefile src/RMComm/MW-Socket/Makefile src/RMComm/MW-StaticMPI/Makefile src/MWControlTasks/Makefile src/BlackBox/Makefile $EXTRA_MAKEFILES, echo timestamp > stamp-h )
diff --git a/MW/doxygen.conf b/MW/doxygen.conf
new file mode 100644
index 0000000..eddb90f
--- /dev/null
+++ b/MW/doxygen.conf
@@ -0,0 +1,1117 @@
+# Doxyfile 1.3.6-20040222
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = MW
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 0.2
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src/MW.h src/MWprintf.h src/MWDriver.h src/MWDriver.C src/MWTask.h src/MWTask.C src/MWWorker.h src/MWWorker.C src/RMComm/MWRMComm.h src/RMComm/MWRMComm.h
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = examples
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/MW/install-sh b/MW/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/MW/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/MW/missing b/MW/missing
new file mode 100644
index 0000000..e69de29
diff --git a/MW/mkinstalldirs b/MW/mkinstalldirs
new file mode 100644
index 0000000..ffce33c
--- /dev/null
+++ b/MW/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman at prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2004/02/10 22:29:30 psilord Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/MW/src/BlackBox/MWDriver_blackbox.C b/MW/src/BlackBox/MWDriver_blackbox.C
new file mode 100644
index 0000000..8fb470f
--- /dev/null
+++ b/MW/src/BlackBox/MWDriver_blackbox.C
@@ -0,0 +1,92 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* These methods will be implemented to reflect the application behavior */
+
+#include "MW.h"
+#include "MWDriver_blackbox.h"
+#include "MWWorker_blackbox.h"
+#include <unistd.h>
+
+/* Statstics for how many bytes are packed (sent) and unpacked (received) */
+extern double RMCOMM_bytes_packed;
+extern double RMCOMM_bytes_unpacked;
+
+/* initialization */
+MWDriver_blackbox::MWDriver_blackbox()
+{
+}
+
+/* destruction */
+MWDriver_blackbox::~MWDriver_blackbox()
+{
+}
+
+/* */
+MWReturn
+MWDriver_blackbox::pack_worker_init_data( void )
+{
+ string exe = get_executable();
+ list<string> l;
+ l.push_back(exe);
+
+ for (set<string>::const_iterator it = stageFiles_.begin();
+ it != stageFiles_.end(); ++it) {
+ l.push_back(*it);
+ }
+
+ MWTask_blackbox::send_files(l);
+
+
+
+ return OK;
+}
+
+/* Print out the result when MW is done. MW assume that the application
+ * is keeping track of the results :-) */
+void
+MWDriver_blackbox::printresults()
+{
+ MWprintf ( 10, "BlackBox Driver Complete\n");
+}
+
+/* Return a new application task object */
+MWTask*
+MWDriver_blackbox::gimme_a_task()
+{
+ return new MWTask_blackbox;
+}
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/BlackBox/MWDriver_blackbox.h b/MW/src/BlackBox/MWDriver_blackbox.h
new file mode 100644
index 0000000..f8e2635
--- /dev/null
+++ b/MW/src/BlackBox/MWDriver_blackbox.h
@@ -0,0 +1,77 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef _blackbox_DRIVER_H
+#define _blackbox_DRIVER_H
+
+#include "MWDriver.h"
+#include "MWTask_blackbox.h"
+
+#include <set>
+
+/** Blackbox Driver subclass derived from MWDriver */
+
+class MWDriver_blackbox : public MWDriver
+{
+public:
+ MWDriver_blackbox();
+ ~MWDriver_blackbox();
+
+ virtual MWReturn get_userinfo( int argc, char *argv[] ) = 0;
+ virtual MWReturn setup_initial_tasks( int *, MWTask *** ) = 0;
+ virtual MWReturn act_on_completed_task( MWTask * ) = 0;
+
+ // Made final here -- you pass the executable -- worker can't pack initial data.
+ // Rather, they are allowed set set the "stage files"
+ MWReturn pack_worker_init_data( void );
+ virtual void printresults();
+ virtual void write_master_state(FILE *fp) {}
+ virtual void read_master_state(FILE *fp) {}
+
+ void add_staged_file(const string &s) { stageFiles_.insert(s); }
+ string get_executable() const { return theExecutable_; }
+ void set_executable(const string &s) { theExecutable_ = s; }
+ MWTask* gimme_a_task();
+
+private:
+ string theExecutable_;
+ std::set<string> stageFiles_;
+
+};
+
+#endif
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq c-tab-always-indent nil)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/BlackBox/MWTask_blackbox.C b/MW/src/BlackBox/MWTask_blackbox.C
new file mode 100644
index 0000000..3d9dd0a
--- /dev/null
+++ b/MW/src/BlackBox/MWTask_blackbox.C
@@ -0,0 +1,247 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWTask_blackbox.h"
+#include "MW.h"
+#include <fstream>
+
+/* init */
+MWTask_blackbox::MWTask_blackbox()
+{
+}
+
+
+MWTask_blackbox::MWTask_blackbox(const list<string> &args,
+ const list<string> &input_files,
+ const list<string> &output_files)
+{
+ this->args_ = args;
+ this->input_files_ = input_files;
+ this->output_files_ = output_files;
+}
+
+
+/* destruction */
+MWTask_blackbox::~MWTask_blackbox() {
+}
+
+/* print the task to stdout */
+void
+MWTask_blackbox::printself( int level )
+{
+ printList( level, "args: ", args_);
+ printList( level, "inputs: ", input_files_);
+ printList( level, "outputs: ", output_files_);
+}
+
+void
+MWTask_blackbox::printList(int level, char *prefix, list<string>& l) {
+ MWprintf(level, "%s", prefix);
+ for (list<string>::iterator it = l.begin();
+ it != l.end();
+ it++) {
+ MWprintf(level, "%s ", (*it).c_str());
+ }
+ MWprintf (level, "\n");
+}
+
+/* The driver packs the input data via RMC, the data which will be sent to a worker. */
+void
+MWTask_blackbox::pack_work( void )
+{
+ int size = args_.size();
+
+ RMC->pack(&size, 1);
+ MWprintf(30, "MWTask::pack_work packed arg size of %d\n", size);
+ for (list<string>::iterator it = args_.begin();
+ it != args_.end();
+ it++) {
+ RMC->pack((char *)(*it).c_str());
+ }
+ MWprintf(30, "MWTask::pack_work packing input files\n");
+ send_files(input_files_);
+
+ int num_output_files = output_files_.size();
+ RMC->pack(&num_output_files, 1);
+ for (list<string>::iterator it = output_files_.begin();
+ it != output_files_.end();
+ it++) {
+ RMC->pack((char *)(*it).c_str());
+ }
+}
+
+/* The worker unpacks input data via RMC, need to allocate space for data */
+void
+MWTask_blackbox::unpack_work( void )
+{
+ args_.clear();
+ int size;
+ RMC->unpack(&size, 1);
+ MWprintf(30,"MWTask::unpack_work unpacked arg size of %d\n", size);
+ while (size--) {
+ char str[8096];
+ RMC->unpack(str);
+ args_.push_back(str);
+ }
+ MWprintf(30, "MWTask::pack_work unpacking input files\n");
+ recv_files(input_files_);
+
+ int num_output_files = 0;
+ output_files_.clear();
+ RMC->unpack(&num_output_files, 1);
+ while (num_output_files--) {
+ char str[8096];
+ RMC->unpack(str);
+ output_files_.push_back(str);
+ }
+}
+
+/* The worker packs result data via RMC, the result will be sent back to driver */
+void
+MWTask_blackbox::pack_results( void )
+{
+ RMC->pack(&retVal_, 1);
+ send_files(output_files_);
+ remove("stdout");
+ remove("stderr");
+}
+
+/* The driver unpacks result data via RMC */
+void
+MWTask_blackbox::unpack_results( void )
+{
+ RMC->unpack(&retVal_, 1);
+ recv_files(output_files_);
+}
+
+/* write checkpoint info per task, for each task haven't been finished */
+void
+MWTask_blackbox::write_ckpt_info( FILE *fp )
+{
+ //list<string> args_;
+ //list<string> input_files_;
+ //list<string> output_files_;
+ //int retVal_;
+
+ fprintf(fp, "%d\n", retVal_);
+ saveStringList(fp, args_);
+ saveStringList(fp, input_files_);
+ saveStringList(fp, output_files_);
+}
+
+/* Read checkpoint info, in the order written into the file */
+void
+MWTask_blackbox::read_ckpt_info( FILE *fp )
+{
+ fscanf(fp, "%d", &retVal_);
+ restoreStringList(fp, args_);
+ restoreStringList(fp, input_files_);
+ restoreStringList(fp, output_files_);
+}
+
+
+void
+MWTask_blackbox::send_files(list<string> &files) {
+ int num_files = files.size();
+ RMC->pack(&num_files, 1);
+ for (list<string>::iterator i = files.begin(); i != files.end(); i++) {
+ const char *file_name = i->c_str();
+
+ fstream file(file_name);
+ file.seekg(0, ios::end);
+ size_t file_size = file.tellg();
+
+ // If file doesn't exist, force file_size to 0
+ if (file_size == (size_t) -1) {
+ file_size = 0;
+ }
+
+ char *b = new char[file_size];
+ file.seekg(0, ios::beg);
+ file.read(b, file_size);
+
+ RMC->pack((char *)file_name);
+ RMC->pack(&file_size, 1, 1);
+ RMC->pack(b, file_size, 1);
+
+ delete [] b;
+ MWprintf(30, "packed file named %s of length %d\n", i->c_str(), file_size);
+ }
+}
+
+void
+MWTask_blackbox::recv_files(list<string> &files) {
+ int num_files;
+ RMC->unpack(&num_files, 1);
+ for ( int i = 0; i < num_files; i++) {
+ char file_name[4096];
+ int file_size;
+
+ RMC->unpack(file_name);
+ RMC->unpack(&file_size, 1);
+ MWprintf(30, "unpacked file named %s of size %d\n", file_name, file_size);
+
+ ofstream file(file_name);
+ char *b = new char[file_size];
+ RMC->unpack(b, file_size, 1);
+ file.write(b, file_size);
+ delete [] b;
+
+ files.push_back(string(file_name));
+ }
+}
+
+void
+MWTask_blackbox::saveStringList(FILE *fp, list<string> &sl) {
+ fprintf(fp, "%d\n", sl.size());
+ for (list<string>::iterator i = sl.begin(); i != sl.end(); i++) {
+ const char *name = i->c_str();
+ fprintf(fp, "%s\n", name);
+ }
+}
+
+void
+MWTask_blackbox::restoreStringList(FILE *fp, list<string> &sl) {
+ int size = 0;
+ fscanf(fp, "%d", &size);
+ while (size--) {
+ char name[4096];
+ fscanf(fp, "%s", name);
+ sl.push_back(string(name));
+ }
+}
+
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/BlackBox/MWTask_blackbox.h b/MW/src/BlackBox/MWTask_blackbox.h
new file mode 100644
index 0000000..2b548b1
--- /dev/null
+++ b/MW/src/BlackBox/MWTask_blackbox.h
@@ -0,0 +1,95 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef _blackbox_TASK_H
+#define _blackbox_TASK_H
+
+#include "MWTask.h"
+
+using namespace std;
+
+#include <string>
+#include <list>
+
+class MWTask_blackbox : public MWTask
+{
+public:
+ /* constructors */
+ MWTask_blackbox();
+ MWTask_blackbox(const list<string> &args,
+ const list<string> &input_files,
+ const list<string> &output_files);
+
+ /* destructor */
+ virtual ~MWTask_blackbox();
+
+ const std::list<string> & getArgs() const { return args_; }
+ const std::list<string> & getInputFiles() const { return input_files_; }
+ const std::list<string> & getOutputFiles() const { return output_files_; }
+
+ int getReturnVal() const { return retVal_; }
+ void setReturnVal(int rv){ retVal_ = rv; }
+
+ /* App is required to implement the following functions. */
+ void pack_work( void );
+ void unpack_work( void );
+ void pack_results( void );
+ void unpack_results( void );
+
+ /* The following functions have default implementation. */
+ void printself( int level = 70 );
+ void printList(int level, char *prefix, list<string>& l);
+ void write_ckpt_info( FILE *fp );
+ void read_ckpt_info( FILE *fp );
+
+ /* The application specific information goes here */
+ static void send_files(list<string> &files);
+ static void recv_files(list<string> &files);
+
+ static void saveStringList(FILE *fp, list<string> &sl);
+ static void restoreStringList(FILE *fp, list<string> &sl);
+
+protected:
+ list<string> args_;
+ list<string> input_files_;
+ list<string> output_files_;
+ int retVal_;
+};
+
+#endif
+
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq c-tab-always-indent nil)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/BlackBox/MWWorkerMain_blackbox.C b/MW/src/BlackBox/MWWorkerMain_blackbox.C
new file mode 100644
index 0000000..e6b7a5a
--- /dev/null
+++ b/MW/src/BlackBox/MWWorkerMain_blackbox.C
@@ -0,0 +1,57 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* The main() of worker executable. Simply instantiate a Worker_blackbox
+ * class and go()! */
+
+#include "MW.h"
+#include "MWWorker_blackbox.h"
+
+int main(int argc, char *argv[])
+{
+ /* init a worker object */
+ MWWorker_blackbox graduate_student;
+
+ /* How much information you want the workers to print */
+ set_MWprintf_level ( 75 );
+ MWprintf ( 10, "A worker is starting.\n" );
+
+ /* Go ! */
+ graduate_student.go(argc, argv);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/BlackBox/MWWorker_blackbox.C b/MW/src/BlackBox/MWWorker_blackbox.C
new file mode 100644
index 0000000..d52065e
--- /dev/null
+++ b/MW/src/BlackBox/MWWorker_blackbox.C
@@ -0,0 +1,138 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWWorker_blackbox.h"
+#include "MWTask_blackbox.h"
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* init */
+MWWorker_blackbox::MWWorker_blackbox()
+{
+ workingTask = new MWTask_blackbox;
+}
+
+/* destruct */
+MWWorker_blackbox::~MWWorker_blackbox()
+{
+ delete workingTask;
+}
+
+/* Do benchmark and return result (usually the time to task t), t is supposed
+ * to be a benchmark task. In this app, it just send back a PI. */
+double
+MWWorker_blackbox::benchmark( MWTask *t )
+{
+ MWTask_blackbox *bb = dynamic_cast<MWTask_blackbox *> ( t );
+ bb->printself(30);
+ return 1.0;
+}
+
+/* unpack the init data from the driver */
+MWReturn
+MWWorker_blackbox::unpack_init_data( void )
+{
+ // Get the executable
+ list<string> l;
+ MWTask_blackbox::recv_files(l);
+ MWprintf(10, "Worker_blackbox got %d files\n", l.size());
+ if (l.size() < 1) {
+ MWprintf(1, "Warning!?! Where is your executable!?!?!\n");
+ }
+ else {
+ list<string>::const_iterator i = l.begin();
+ const char *c = i->c_str();
+ executable_ = *i;
+ MWprintf(20, "marking worker executable %s as 0755\n", c);
+ ::chmod(c, 0755); // and make it executable
+ }
+ return OK;
+}
+
+/* Execute each task */
+void
+MWWorker_blackbox::execute_task( MWTask *t )
+{
+ int retVal;
+
+ MWprintf(30, "Enter Worker_blackbox::execute_task\n");
+ MWTask_blackbox *bb = dynamic_cast<MWTask_blackbox *> ( t );
+
+ MWprintf(40, " task is \n");
+ bb->printself(40);
+
+ const list<string>& args = bb->getArgs();
+ int argc = args.size() + 2;
+
+ char **argv = (char **)malloc( sizeof(char *) * argc);
+
+ int index = 0;
+ argv[index] = (char *) executable_.c_str();
+ index++;
+
+ for (list<string>::const_iterator i = args.begin(); i != args.end(); i++) {
+ argv[index] = (char *) (*i).c_str();
+ MWprintf(50, "execute_task:: argv[%d] is %s\n", index, argv[index]);
+ index++;
+ }
+ argv[index] = 0;
+
+ int pid = fork();
+ if (pid == 0) {
+ // Child
+
+ // make stdout to to the file named "stdout"
+ close(1);
+ close(2);
+
+ open("stdout", O_CREAT | O_TRUNC);
+ open("stderr", O_CREAT | O_TRUNC);
+
+ execve(argv[0], argv, 0);
+ MWprintf(10, "execute_task failed to exec %s errno = %d (%s)\n",
+ argv[0], errno, strerror(errno));
+
+ exit(-1);
+ }
+
+ ::waitpid(pid, &retVal, 0);
+ bb->setReturnVal(retVal);
+ MWprintf(30, "Leave Worker_blackbox::execute_task retVal was %d\n", retVal);
+}
+
+MWTask*
+MWWorker_blackbox::gimme_a_task()
+{
+ return new MWTask_blackbox;
+}
+
+/* Just return a newly created application worker object */
+MWWorker*
+gimme_a_worker ()
+{
+ return new MWWorker_blackbox;
+}
diff --git a/MW/src/BlackBox/MWWorker_blackbox.h b/MW/src/BlackBox/MWWorker_blackbox.h
new file mode 100644
index 0000000..c76e991
--- /dev/null
+++ b/MW/src/BlackBox/MWWorker_blackbox.h
@@ -0,0 +1,49 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef _blackbox_WORKER_H
+#define _blackbox_WORKER_H
+
+#include "MWWorker.h"
+#include "MWTask_blackbox.h"
+
+class MWWorker_blackbox : public MWWorker
+{
+public:
+ MWWorker_blackbox();
+ ~MWWorker_blackbox();
+
+ /* Benchmarking */
+ double benchmark( MWTask *t );
+
+ /* unpack init data */
+ MWReturn unpack_init_data( void );
+
+ /* do the real work for each task */
+ void execute_task( MWTask * );
+
+ MWTask* gimme_a_task();
+
+private:
+ string executable_;
+};
+#endif
diff --git a/MW/src/BlackBox/Makefile.in b/MW/src/BlackBox/Makefile.in
new file mode 100644
index 0000000..3afbdb1
--- /dev/null
+++ b/MW/src/BlackBox/Makefile.in
@@ -0,0 +1,181 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+ENABLE_MWINDEPENDENT = @ENABLE_MWINDEPENDENT@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+MW_BASICLIB = -lMW -lMWRMComm -lMWutil -lNWS $(SOCKET_LIB)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(DEBUG_CHECKER) $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+
+# Subdirectories
+SUBDIRS =
+
+# Make independent?
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+LIBRARIES = libMWblackbox_indp.a libMWblackbox.a
+else
+LIBRARIES = libMWblackbox.a
+endif
+
+# If building without Condor, you need not build the worker executable
+EXECUTABLES :=
+ifeq ($(CONDOR_DIR), no)
+EXECUTABLES :=
+else
+EXECUTABLES = worker_blackbox_socket
+endif
+
+
+libMWblackbox_a_SOURCES = MWDriver_blackbox.C MWTask_blackbox.C
+libMWblackbox_a_OBJECTS = MWDriver_blackbox.o MWTask_blackbox.o
+
+libMWblackbox_indp_a_SOURCES = MWWorker_blackbox.C
+libMWblackbox_indp_a_OBJECTS = MWWorker_blackbox.o
+
+worker_blackbox_socket_SOURCES = MWWorker_blackbox.C MWTask_blackbox.C MWWorkerMain_blackbox.C
+worker_blackbox_socket_OBJECTS = MWWorker_blackbox.o MWTask_blackbox.o MWWorkerMain_blackbox.o
+worker_blackbox_socket_LDADD = -L$(MW_LIBDIR) $(MW_BASICLIB) -lMWsocketworker
+worker_blackbox_socket_DEPENDENCIES =
+worker_blackbox_socket_LDFLAGS =
+
+
+
+INCLUDES = -I. -I.. -I../RMComm
+INCLUDEFILES = MWDriver_blackbox.h MWTask_blackbox.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES) $(EXECUTABLES)
+
+libMWblackbox.a: $(libMWblackbox_a_OBJECTS)
+ -rm -f libMWblackbox.a
+ $(AR) cru libMWblackbox.a $(libMWblackbox_a_OBJECTS)
+ $(RANLIB) libMWblackbox.a
+# cp libMWblackbox.a $(MW_LIBDIR)
+
+libMWblackbox_indp.a: $(libMWblackbox_indp_a_OBJECTS)
+ -rm -f libMWblackbox_indp.a
+ $(AR) cru libMWblackbox_indp.a $(libMWblackbox_indp_a_OBJECTS)
+ $(RANLIB) libMWblackbox_indp.a
+# cp libMWblackbox.a $(MW_LIBDIR)
+
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+libMWblackbox_indp.a: $(libMWblackbox_indp_a_OBJECTS)
+ -rm -f libMWblackbox_indp.a
+ $(AR) cru libMWblackbox_indp.a $(libMWblackbox_indp_a_OBJECTS)
+ $(RANLIB) libMWblackbox_indp.a
+# Install should copy lib file, no?
+# cp libMWblackbox.a $(MW_LIBDIR)
+endif
+
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+worker_blackbox_indp: $(worker_blackbox_indp_OBJECTS)
+ $(CXXLINK) $(worker_blackbox_indp_LDFLAGS) $(worker_blackbox_indp_OBJECTS) $(worker_blackbox_indp_LDADD) $(LIBS)
+endif
+
+# This just builds your worker executable...
+worker_blackbox_socket: $(worker_blackbox_socket_OBJECTS) $(worker_blackbox_socket_DEPENDENCIES)
+ @rm -f worker_blackbox_socket
+ $(CXXLINK) $(worker_blackbox_socket_LDFLAGS) $(worker_blackbox_socket_OBJECTS) $(worker_blackbox_socket_LDADD) $(LIBS)
+
+# (Probably need better handling of dependencies?)
+MWDriver_blackbox.o: MWDriver_blackbox.C MWDriver_blackbox.h MWTask_blackbox.h
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $< -o $@
+
+MWTask_blackbox.o: MWTask_blackbox.C MWTask_blackbox.h
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $< -o $@
+
+# (Probably need better handling of dependencies?)
+MWDriver_blackbox_indp.o: MWDriver_blackbox.C MWDriver_blackbox.h MWTask_blackbox.h
+ $(CXX) -c -DINDEPENDENT $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $< -o $@
+
+MWTask_blackbox_indp.o: MWTask_blackbox.C MWTask_blackbox.h
+ $(CXX) -c -DINDEPENDENT $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $< -o $@
+
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $< -o $@
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
diff --git a/MW/src/MW.C b/MW/src/MW.C
new file mode 100644
index 0000000..f313790
--- /dev/null
+++ b/MW/src/MW.C
@@ -0,0 +1,24 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MW.h"
+
diff --git a/MW/src/MW.h b/MW/src/MW.h
new file mode 100644
index 0000000..64092cf
--- /dev/null
+++ b/MW/src/MW.h
@@ -0,0 +1,136 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MW_H
+#define MW_H
+
+
+#include "MWprintf.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <float.h>
+
+/// FALSE is defined as 0
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/// TRUE is defined as 1
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/// UNDEFINED is defined as -1
+#ifndef UNDEFINED
+#define UNDEFINED -1
+#endif
+
+/** An upper limit on the number of workers -- so we can allocated arrays
+ to keep statistics */
+const int MW_MAX_WORKERS = 8192;
+
+/**@name Introduction.
+
+ MW is a class library that can be a useful tool for building
+ opportunistic, fault-tolerant applications for high throughput
+ computing.
+
+ In order to build an application, there are three classes
+ that the user {\rm must} rederive.
+
+ \begin{itemize}
+ \item \Ref{MWDriver}
+ \item \Ref{MWWorker}
+ \item \Ref{MWTask}
+ \end{itemize}
+
+ The documentation of these classes includes a description
+ of the pure virtual methods that must be implemented for
+ a user's particular application.
+
+ Using the MW library allows the user to focus on the application
+ specific implementation at hand. All details related to
+ being fault tolerant and opportunistic are implemented in the
+ MW library.
+
+ Also included is a small, naive, example of how to create
+ an application with the MW class library. The three classes
+
+ \begin{itemize}
+ \item \Ref{Driver_Fib}
+ \item \Ref{Worker_Fib}
+ \item \Ref{Task_Fib}
+ \end{itemize}
+
+ are concrete classes derived from MW's abstract classes.
+ Using these classes, a simple program that makes a lot of
+ fibonacci sequences is created.
+
+ */
+
+/**
+ A list of the message tags that the Master-Worker application
+ will send and receive. See the switch statement in master_mainloop
+ for more information.
+ */
+
+enum MWmessages{
+ HOSTADD = 33,
+ HOSTDELETE,
+ HOSTSUSPEND,
+ HOSTRESUME,
+ TASKEXIT,
+ DO_THIS_WORK,
+ RESULTS,
+ INIT,
+ INIT_REPLY,
+ BENCH_RESULTS,
+ KILL_YOURSELF,
+ CHECKSUM_ERROR,
+ RE_INIT,
+ REFRESH,
+ SUBRESULTS,
+ /* added for async message: */
+ UPDATE_FROM_WORKER, /* worker send to driver a update message */
+ UPDATE_FROM_DRIVER, /* driver send to worker a new message */
+ NO_MESSAGE,
+ STOP_WORK
+};
+
+/** Possible return values from many virtual functions */
+enum MWReturn {
+ /// Normal return
+ OK,
+ /// We want to exit, not an error.
+ QUIT,
+ /// We want to exit immediately; a bad error ocurred
+ ABORT,
+ /// by jae
+ /// Some job is still running
+ PENDING
+};
+
+typedef enum { MWNORMAL, MWNWS, MWNUMTASKTYPES } MWTaskType;
+
+#endif
diff --git a/MW/src/MWControlTasks/MWNWSTask.C b/MW/src/MWControlTasks/MWNWSTask.C
new file mode 100644
index 0000000..65d40e4
--- /dev/null
+++ b/MW/src/MWControlTasks/MWNWSTask.C
@@ -0,0 +1,229 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MW.h"
+#include "MWNWSTask.h"
+#include "MWSystem.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <strings.h>
+
+
+MWNWSTask::MWNWSTask ( int nu, double interval, int length, int port, char *addr )
+{
+ taskType = MWNWS;
+ timeInterval = interval;
+ iterations = length;
+ min = max = median = -1;
+ portNo = port;
+ number = nu;
+ strcpy ( machineAddress, addr );
+}
+
+MWNWSTask::MWNWSTask ( )
+{
+ taskType = MWNWS;
+ min = max = median = -1;
+ portNo = 7;
+ number = -1;
+}
+
+MWNWSTask::~MWNWSTask()
+{
+}
+
+void
+MWNWSTask::pack_work( void )
+{
+ RMC->pack ( &timeInterval, 1, 1 );
+ RMC->pack ( &iterations, 1, 1 );
+ RMC->pack ( &portNo, 1, 1 );
+ RMC->pack ( machineAddress );
+}
+
+void
+MWNWSTask::unpack_work( void )
+{
+ RMC->unpack ( &timeInterval, 1, 1 );
+ RMC->unpack ( &iterations, 1, 1 );
+ RMC->unpack ( &portNo, 1, 1 );
+ RMC->unpack ( machineAddress );
+}
+
+void
+MWNWSTask::pack_results( void )
+{
+ RMC->pack ( &max, 1, 1 );
+ RMC->pack ( &min, 1, 1 );
+ RMC->pack ( &median, 1, 1 );
+}
+
+void
+MWNWSTask::unpack_results( void )
+{
+ double temp;
+ MWprintf ( 10, "NWS Unpacking results\n");
+ RMC->unpack ( &temp, 1, 1 );
+ MWprintf ( 10, "%f\n", temp );
+ max = temp;
+ RMC->unpack ( &min, 1, 1 );
+ RMC->unpack ( &median, 1, 1 );
+}
+
+void
+MWNWSTask::pack_subresults( int )
+{
+}
+
+void
+MWNWSTask::unpack_subresults( int )
+{
+}
+
+void
+MWNWSTask::printself(int level)
+{
+ MWprintf ( level, "Interval:%f Iterations:%d PortNum:%d \n", timeInterval,
+ iterations, portNo );
+ if ( max > 0 )
+ MWprintf ( level, "results:- min:%f max:%f median:%f\n",
+ min, max, median );
+}
+
+void
+MWNWSTask::write_ckpt_info( FILE *fp )
+{
+ fprintf ( fp, "%f %d ", timeInterval, iterations );
+ if ( max >= 0 )
+ fprintf ( fp, "%f %f %f", max, min, median );
+ else
+ fprintf ( fp, "-1 " );
+}
+
+void
+MWNWSTask::read_ckpt_info( FILE *fp )
+{
+ fscanf ( fp, "%lf %d ", &timeInterval, &iterations );
+ fscanf ( fp, "%lf ", &max );
+ if ( max >= 0 )
+ fscanf ( fp, "%lf %lf ", &min, &median );
+}
+
+void
+NWSControlTask ( MWTask *task )
+{
+ int listenFd;
+ struct sockaddr_in servaddr;
+ struct sockaddr_in cliaddr;
+ MWNWSTask *nwsTask = (MWNWSTask *)task;
+ char sendData = 'a';
+ char recvData;
+ double startTime, endTime;
+ double tempStart, tempEnd;
+ int cc;
+ int iter = 0;
+ int temp;
+
+ MWprintf (10, "In NWSControlTask\n");
+
+ listenFd = socket( AF_INET, SOCK_DGRAM, 0);
+ if ( listenFd < 0 )
+ {
+ MWprintf( 10, "TCP socket creation error. %d\n", errno);
+ ::exit(1);
+ }
+
+ bzero( &cliaddr, sizeof(cliaddr));
+ cliaddr.sin_family = AF_INET;
+ cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ cliaddr.sin_port = htons(0);
+
+
+ if ( bind( listenFd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0)
+ {
+ MWprintf( 10, "TCP socket bind error %d.\n", errno);
+ ::exit(2);
+ }
+
+ bzero( &servaddr, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = inet_addr( nwsTask->machineAddress);
+ servaddr.sin_port = htons(nwsTask->portNo);
+
+ startTime = MWSystem::gettimeofday();
+ nwsTask->min = -1;
+ nwsTask->max = -1;
+ nwsTask->median = -1;
+ do
+ {
+ tempStart = MWSystem::gettimeofday();
+ cc = sendto ( listenFd, &sendData, 1, 0, (struct sockaddr *)&servaddr, sizeof(servaddr) );
+ if ( cc < 0 )
+ {
+ MWprintf ( 10, "Could not sendto %d\n", errno);
+ // XXX Instead of
+ // ::exit(4);
+ // which will cause a worker goes down (because the master's portNo is not open.
+ //
+ // We probably just need to ignore the error.
+
+ }
+
+ temp = sizeof(servaddr); // XXX Added because error when checkpointing
+ cc = recvfrom ( listenFd, &recvData, 1, 0, (struct sockaddr *)&servaddr,
+ (socklen_t *)&temp);
+ if ( cc < 0 )
+ {
+ MWprintf ( 10, "Could not recvfrom %d\n", errno);
+ // XXX Instead of
+ // ::exit(5);
+ // which will cause a worker goes down (because the master's portNo is not open.
+ //
+ // We probably just need to ignore the error.
+ }
+ tempEnd = MWSystem::gettimeofday();
+ iter++;
+
+ if ( nwsTask->min < 0 || tempEnd - tempStart < nwsTask->min )
+ nwsTask->min = tempEnd - tempStart;
+ if ( nwsTask->max < 0 || tempEnd - tempStart > nwsTask->max )
+ nwsTask->max = tempEnd - tempStart;
+ } while ( iter < nwsTask->iterations );
+
+ endTime = MWSystem::gettimeofday();
+ nwsTask->median = ( endTime - startTime ) / nwsTask->iterations;
+
+ close(listenFd);
+}
+
+MWTask*
+NWSNewTask ( )
+{
+ return new MWNWSTask ( );
+}
diff --git a/MW/src/MWControlTasks/MWNWSTask.h b/MW/src/MWControlTasks/MWNWSTask.h
new file mode 100644
index 0000000..7aee838
--- /dev/null
+++ b/MW/src/MWControlTasks/MWNWSTask.h
@@ -0,0 +1,110 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWNWSTASK_H
+#define MWNWSTASK_H
+
+#include <stdio.h>
+#include "MWTask.h"
+
+/** The task class specific to NWS weather monitoring
+*/
+
+class MWNWSTask : public MWTask {
+
+ public:
+
+ /// Default Constructor
+ MWNWSTask();
+
+ /**
+ */
+ MWNWSTask( int, double, int, int, char* );
+
+ MWNWSTask( const MWNWSTask& );
+
+ /// Default Destructor
+ ~MWNWSTask();
+
+ MWNWSTask& operator = ( const MWNWSTask& );
+
+ /**@name Implemented methods
+
+ These are the task methods that must be implemented
+ in order to create an application.
+ */
+ //@{
+ /// Pack the work for this task into the PVM buffer
+ void pack_work( void );
+
+ /// Unpack the work for this task from the PVM buffer
+ void unpack_work( void );
+
+ /// Pack the results from this task into the PVM buffer
+ void pack_results( void );
+
+ /// Unpack the results from this task into the PVM buffer
+ void unpack_results( void );
+ //@}
+
+ // not used in this class
+ void pack_subresults( int );
+ void unpack_subresults( int );
+
+ /// dump self to screen:
+ void printself( int level = 60 );
+
+ /**@name Checkpointing Implementation
+ These members used when checkpointing. */
+ //@{
+ /// Write state
+ void write_ckpt_info( FILE *fp );
+ /// Read state
+ void read_ckpt_info( FILE *fp );
+ //@}
+
+ /**@name Input Parameters.
+ These parameters are sent to the other side */
+ //@{
+ /// the number of measurements.
+ int iterations;
+ /// the interval between measurements
+ double timeInterval;
+ /// the port to connect to.
+ int portNo;
+ /// the machine name.
+ char machineAddress[1024];
+ //@}
+
+ /**@name Output Parameters.
+ These parameters are returned by the workers */
+ //@{
+ /// the maximum latency observed.
+ double max;
+ /// the minimum latency observed.
+ double min ;
+ /// the median latency observed.
+ double median ;
+ //@}
+};
+
+#endif
diff --git a/MW/src/MWControlTasks/Makefile.in b/MW/src/MWControlTasks/Makefile.in
new file mode 100644
index 0000000..57953ad
--- /dev/null
+++ b/MW/src/MWControlTasks/Makefile.in
@@ -0,0 +1,133 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+DOCXX = @DOCXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+ENABLE_MWINDEPENDENT = @ENABLE_MWINDEPENDENT@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# Subdirectories
+SUBDIRS =
+
+### Libraries to be built, and dependent source files
+# If ENDABLE_INDEPENDENT is yes (you can do that by configure --with-independent).
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+LIBRARIES = libNWS.a libNWS_indp.a
+else
+LIBRARIES = libNWS.a
+endif
+
+libNWS_a_SOURCES = MWNWSTask.C
+libNWS_a_OBJECTS = MWNWSTask.o
+libNWS_indp_a_OBJECTS = MWNWSTaskInd.o
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+INCLUDES = -I. -I.. -I../RMComm -I../RMComm/MW-File -I../RMComm/MW-CondorPVM -I../RMComm/MW-Socket $(MISC_DEFN) $(MEASURE_DEFN)
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+INDP_CXXCOMPILE = $(CXXCOMPILE) -DINDEPENDENT
+
+INCLUDEFILES = MWNWSTask.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+libNWS.a: $(libNWS_a_OBJECTS) $(libNWS_a_DEPENDENCIES)
+ -rm -f libNWS.a
+ $(AR) cru libNWS.a $(libNWS_a_OBJECTS) $(libNWS_a_LIBADD)
+ $(RANLIB) libNWS.a
+ cp libNWS.a $(MW_LIBDIR)
+
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+libNWS_indp.a: $(libNWS_indp_a_OBJECTS)
+ -rm -f libNWS_indp.a
+ $(AR) cru libNWS_indp.a $(libNWS_indp_a_OBJECTS)
+ $(RANLIB) libNWS_indp.a
+ cp libNWS_indp.a $(MW_LIBDIR)
+MWNWSTaskInd.o:MWNWSTask.C
+ $(INDP_CXXCOMPILE) -o MWNWSTaskInd.o -c MWNWSTask.C
+endif
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a core
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a core
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
diff --git a/MW/src/MWDriver.C b/MW/src/MWDriver.C
new file mode 100644
index 0000000..57f1cfa
--- /dev/null
+++ b/MW/src/MWDriver.C
@@ -0,0 +1,4517 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#include <cassert>
+#include <cerrno>
+#include <cstdarg>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+//by jae
+#include <pthread.h>
+#include <sys/time.h>
+
+#include "MW.h"
+#include "MWDriver.h"
+#include "MWWorkerID.h"
+#include "MWWorker.h"
+#include "MWTask.h"
+#include "MWGroup.h"
+#include "MWSystem.h"
+
+#ifndef NWSENABLED
+#include "MWNWSTask.h"
+#endif
+
+/* 8/28/00
+ Qun Chen wrote signal handling code that Michael likes.
+ We add it here */
+
+#include <setjmp.h>
+
+void statsgather ( MWList<MWWorkerID>* workers, MWStatistics * st );
+MWTask * first_task_in_group(MWList<MWTask> * tasks, MWGroup * grp);
+
+/// Indication of how many workers in each group.
+int MWworkClasses = 0;
+int *MWworkClassWorkers;
+int *MWworkClassTasks;
+MWWorkerID *MWcurrentWorker;
+
+
+//by jae
+pthread_mutex_t global_mw_mutex = PTHREAD_MUTEX_INITIALIZER;
+int num_completed_tasks = 0;
+// Signal code not used now
+// jmp_buf env;
+// static void signal_handler(int sig){
+
+// switch ( sig ){
+// case SIGINT: /* process for interrupt */
+// longjmp(env,sig);
+// /* break never reached */
+// case SIGCONT: /* process for alarm */
+// longjmp(env,sig);
+// /* break never reached */
+// default: exit(sig);
+// }
+
+// return;
+// }
+/* end Qun */
+
+MWDriver::MWDriver()
+{
+ stats = new MWStatistics();
+ workers = new MWList<MWWorkerID>("workers");
+ todo = new MWList<MWTask>("TODO_tasks");
+ running = new MWList<MWTask>("running_tasks");
+
+ /* Task_Swap */
+ has_task_swapped = false;
+ max_task_key = DBL_MAX;
+
+ /* XXX DEBUG value for swap for ATR */
+ MIN_IN_MEM = 256; /* == 256 */
+ MAX_IN_MEM = MIN_IN_MEM * 800; /* == MIN_IN_MEM*800 */
+ NUM_IN_MEM_LO = MIN_IN_MEM * 8; /* == MIN_IN_MEM*8 */
+ NUM_IN_MEM_HI = MIN_IN_MEM * 100; /* == MIN_IN_MEM*100 */
+
+ // XXX reassigned
+ reassigned_tasks = new MWList<int>();
+ reassigned_tasks_done = new MWList<int>();
+ normal_tasks_all_done = false;
+
+ task_counter = 0;
+
+ checkpoint_frequency = 0;
+ checkpoint_time_freq = 0;
+ next_ckpt_time = 0;
+ bench_task = NULL;
+
+ // These are for list management
+ addmode = ADD_AT_END;
+ getmode = GET_FROM_BEGIN;
+ machine_ordering_policy = NO_ORDER;
+ listsorted = false;
+ task_key = NULL;
+ worker_key = NULL;
+
+ ckpt_filename = "checkpoint";
+
+ suspensionPolicy = DEFAULT;
+
+ worker_timeout = false;
+ worker_timeout_limit = 0.0;
+ worker_timeout_check_frequency = 0;
+ next_worker_timeout_check = 0;
+
+ defaultTimeInterval = 10;
+ defaultIterations = 5;
+ defaultPortNo = 7;
+
+ MWworkClasses = 0;
+ MWworkClassWorkers = NULL;
+ MWworkClassTasks = NULL;
+ MWcurrentWorker = NULL;
+
+#if defined( XML_OUTPUT )
+
+ xml_menus_filename = "menus";
+ xml_jobinfo_filename = "job_info";
+ xml_pbdescrib_filename = "pbdescrib";
+ xml_filename = "/u/m/e/metaneos/public/html/iMW/status.xml";
+
+ CondorLoadAvg = NO_VAL;
+ LoadAvg = NO_VAL;
+ Memory = NO_VAL;
+ Cpus = NO_VAL;
+ VirtualMemory = NO_VAL;
+ Disk = NO_VAL;
+ KFlops = NO_VAL;
+ Mips = NO_VAL;
+
+ memset(OpSys, 0, sizeof(OpSys));
+ memset(Arch, 0 , sizeof(Arch));
+ memset(mach_name, 0 , sizeof(mach_name));
+
+ get_machine_info();
+#endif
+
+ normal_tasks_all_done = false;
+
+#ifdef MEASURE
+ strcpy(_measure_opt_file_name, "_measure_opt");
+ strcpy(_measure_rec_fname_prefix, "_measure_rec");
+ strcpy(_measure_ProcID_prefix, "_ProcID.");
+ _measure_read_opt_interval = 1200;
+ _measure_dump_rec_interval = 10;
+ _measure_use_adaptation = 0;
+ _measure_read_options(_measure_opt_file_name);
+#endif //MEASURE
+
+ m_pending_num = 0;
+ pthread_mutex_init(&m_pending_mutex, NULL);
+ pthread_cond_init(&m_pending_cond, NULL);
+}
+
+
+MWDriver::~MWDriver()
+{
+ MWTask *t;
+ MWWorkerID *w;
+
+ while ( ( t = (MWTask *)todo->Remove() ) != NULL )
+ delete t;
+ delete todo;
+
+ while ( ( t = (MWTask *)running->Remove() ) != NULL )
+ delete t;
+ delete running;
+
+ while ( ( w = (MWWorkerID *)workers->Remove() ) != NULL )
+ delete w;
+ delete workers;
+
+ if ( bench_task )
+ {
+ delete bench_task;
+ }
+
+ if ( MWworkClassWorkers )
+ delete [] MWworkClassWorkers;
+ if ( MWworkClassTasks )
+ delete [] MWworkClassTasks;
+ if ( stats )
+ delete stats;
+}
+
+void
+MWDriver::go( int argc, char *argv[] )
+{
+ MWReturn ustat;
+
+ // do some setup when we start:
+
+ ustat = master_setup( argc, argv );
+
+ if ( ustat != OK )
+ {
+ MWprintf(10, "master_setup did not return OK, exiting\n");
+ RMC->exit(1);
+ return;
+ }
+
+ // the main processing loop:
+ ustat = master_mainloop ();
+
+ if( ustat == OK || ustat == QUIT || ustat == PENDING )
+ {
+ // We're done - now print the results.
+
+ printresults();
+
+ //JTL Since kill_workers can take a long time --we like
+ // to collect the statistics beforehand. Therefore,
+ // we gather all the stats from the currently workign workers,
+ // then call makestats here (before kill_workers).
+
+ statsgather(workers, stats);
+ // tell the stats class to do its magic
+ stats->makestats();
+ }else{
+ MWprintf(10,"no print results because ustat is %d %d\n",ustat,HOSTRESUME);
+ }
+
+ kill_workers();
+
+ // remove checkpoint file.
+ //remove(ckpt_filename);
+
+ /* Does not return. */
+ RMC->exit(0);
+}
+
+void
+statsgather ( MWList<MWWorkerID>* workers, MWStatistics * st )
+{
+ MWWorkerID * w = workers->First();
+ while ( workers->AfterEnd() == false ) {
+ w = workers->Current();
+ st->gather(w);
+ workers->Next();
+ }
+}
+
+MWReturn
+MWDriver::master_setup( int argc, char *argv[] )
+{
+ MWReturn ustat = OK;
+ int myid, master_id;
+ int num_curr_hosts, i;
+ MWWorkerID **tempWorkers = NULL;
+
+ MWprintf ( 70, "MWDriver is pid %ld.\n", MWSystem::getpid() );
+
+ RMC->setup( argc, argv, &myid, &master_id );
+
+#ifdef MEASURE
+ {
+ // First set the file name for the measurement records
+ int hasProcID = 0;
+ for (i=0; i<argc; i++) {
+ if ( strstr(argv[i], _measure_ProcID_prefix) != NULL ) {
+ // Use the %(ProcID)
+ hasProcID = 1;
+ sprintf(_measure_rec_file_name, "%s%s", _measure_rec_fname_prefix, argv[i]);
+ }
+ }
+ if (hasProcID == 0) {
+ // No ProcID info from the arguments, so use getpid()
+ sprintf(_measure_rec_file_name, "%s.%d", _measure_rec_fname_prefix, getpid());
+ }
+ MWprintf(31, "MEASURE|Setting measurement record fname = %s\n", _measure_rec_file_name);
+ }
+
+ // Now start counting until next time read-opt-file/dump_rec-file
+ _measure_last_read_opt_time = _measure_last_dump_rec_time = time(0);
+ // Write the header lines into the record file
+ _measure_dump_header();
+
+ // Init/Reset the measurement data
+ _measure_reset();
+#endif // MEASURE
+
+ // See if checkpoint file exists
+ FILE *chp_file = NULL;
+ if ( (chp_file = fopen(ckpt_filename, "r")) == NULL)
+ {
+ // checkpoint file not found - start from scratch:
+ MWprintf ( 50, "Starting from the beginning.\n" );
+ MWprintf ( 50, "argc=%d, argv[0]=%s\n", argc, argv[0] );
+
+ ustat = get_userinfo( argc, argv );
+
+ if( ustat == OK )
+ {
+ if ( RMC->MW_exec_class_num_workers == NULL )
+ {
+ MWprintf ( 10, "In Get User Info set_exec_classes not called\n");
+ MWprintf ( 10, "Aborting\n");
+ assert(0);
+ }
+ ustat = create_initial_tasks();
+ /* Memory for workers allocated in here: */
+ RMC->init_beginning_workers ( &num_curr_hosts, &tempWorkers );
+ }
+ else
+ {
+ return ustat;
+ }
+ }
+ else
+ { // restart from that checkpoint file.
+ fclose(chp_file);
+ MWprintf ( 50, "Restarting from a checkpoint.\n" );
+
+#if 0
+ // Yet another Hack for Michael
+ get_userinfo( argc, argv );
+#endif
+ restart_from_ckpt();
+ /* Memory for workers allocated in here: */
+ RMC->restart_beginning_workers ( &num_curr_hosts, &tempWorkers, RE_INIT );
+ }
+
+ MWprintf ( 70, "Good to go.\n" );
+
+ if ( tempWorkers )
+ { /* there are indeed workers... */
+
+ for ( i=0 ; i<num_curr_hosts ; i++ )
+ {
+ if ( tempWorkers[i]->get_id1() == -1 )
+ {
+ /* There was a problem with this worker! */
+ tempWorkers[i]->started();
+ tempWorkers[i]->ended();
+ stats->gather( tempWorkers[i] );
+ }
+ else
+ {
+ /* Success! */
+ /* Memory now taken care of by list... */
+ addWorker ( tempWorkers[i] );
+ }
+ }
+ /* don't forget to remove the array of ptrs .. */
+ delete [] tempWorkers;
+ }
+
+ return OK;
+}
+
+MWReturn
+MWDriver::create_initial_tasks()
+{
+ int orig_ntasks;
+ MWTask **orig_tasks;
+
+ MWReturn ustat = setup_initial_tasks( &orig_ntasks, &orig_tasks );
+ if ( MWworkClassWorkers == NULL )
+ workClasses_set ( 1 );
+ if( ustat == OK )
+ {
+ addTasks( orig_ntasks, orig_tasks );
+ }
+ else
+ {
+ MWprintf( 10, "setup_initial_tasks() returned %d\n", ustat );
+ }
+ delete [] orig_tasks;
+
+ return ustat;
+}
+
+
+MWReturn
+MWDriver::master_mainloop()
+{
+
+ call_hostaddlogic();
+#ifdef INDEPENDENT
+
+ ControlPanel ( );
+ return OK;
+#else
+
+ MWReturn ustat = OK;
+
+ while(1) {
+
+ bool need_continue = false;
+
+ // while there is at least one job in the todo or running queue:
+ bool has_something = !is_TODO_empty() ||
+ ( !running->isEmpty() && (ustat == OK || ustat == PENDING)
+ && !normal_tasks_all_done );
+
+ if( has_something ) {
+
+ // while there is at least one job in the todo or running queue:
+ int buf_id = 0;
+ int sending_host = 0;
+ ustat = master_mainloop_oneshot(buf_id, sending_host);
+ if (ustat != OK && ustat != PENDING ) {
+ break;
+ }
+
+ }else {
+
+ struct timespec ts;
+ struct timeval tp;
+
+ pthread_mutex_lock(&m_pending_mutex);
+ while( m_pending_num > 0 ) {
+
+ // Get current Time
+ gettimeofday(&tp, NULL);
+
+ // Convert from timeval to timespec
+ ts.tv_sec = tp.tv_sec;
+ ts.tv_nsec = tp.tv_usec * 1000;
+ ts.tv_sec += 5; // pthread_cond_wait will wake up every 5 secs
+
+ pthread_mutex_lock(&global_mw_mutex);
+ if( !is_TODO_empty() ) {
+ need_continue = true;
+ pthread_mutex_unlock(&global_mw_mutex);
+ break;
+ }
+ pthread_mutex_unlock(&global_mw_mutex);
+
+ pthread_cond_timedwait(&m_pending_cond,
+ &m_pending_mutex, &ts);
+
+ pthread_mutex_lock(&global_mw_mutex);
+ if( !is_TODO_empty() ) {
+ need_continue = true;
+ pthread_mutex_unlock(&global_mw_mutex);
+ break;
+ }
+ pthread_mutex_unlock(&global_mw_mutex);
+ }
+ pthread_mutex_unlock(&m_pending_mutex);
+
+ if( need_continue ) {
+ continue;
+ }
+
+ // Now, we have no todo, running, and pending jobs
+ break;
+ }
+ }
+
+ return ustat;
+#endif
+}
+
+MWReturn
+MWDriver::master_mainloop_oneshot(int buf_id, int sending_host)
+{
+ MWWorkerID *w = NULL;
+ MWReturn ustat = OK;
+ int len, tag, info;
+
+ int tasknum=0;
+ int subtasknum=0;
+ MWTask *t;
+#ifdef MEASURE
+ double _task_recv_time = 0.0;
+ double _task_recv_cpu_time = 0.0;
+#endif
+
+
+ MWprintf(90, "num_TODO = %d, num_run = %d, num_done = %d\n",
+ todo->Number(), running->Number(), num_completed_tasks );
+
+ /* if (todo->Number() > MAX_IN_MEM)
+ swap_out_todo_tasks(NUM_IN_MEM_LO, MAX_IN_MEM);
+ else if (todo->Number() < MIN_IN_MEM)
+ swap_in_todo_tasks(MIN_IN_MEM, NUM_IN_MEM_HI);
+ */
+ if( !todo->isEmpty() )
+ MWprintf( 99, " CONTINUE -- todo list has at least task number: %d\n", todo->number());
+ else if( !running->isEmpty() )
+ MWprintf( 60, " CONTINUE -- running list has at least task number: %d\n", running->number() );
+
+#ifdef MEASURE
+ // _measure: accumulate the _measure_master_recv_time value
+ double _recv_start_time = _measure_cur_wall_time();
+ double _recv_start_cpu_time = _measure_cur_cpu_time();
+#endif // MEASURE
+
+ // get any message from anybody
+ // MWList<void> * recv_buf_list = RMC->recv_buffers();
+
+ // BUFFER: move to the next buffer
+ // RMC->recv_all(-1, -1);
+
+ // if (recv_buf_list == NULL || recv_buf_list->number()==0) {
+ buf_id = RMC->recv( -1, -1 );
+ // MWprintf(91, "BUFFER: Have to use the blocking recv(), got buffer %d.\n", buf_id);
+ // } else {
+ // int* bid = (int*) recv_buf_list->Remove();
+ // buf_id = *bid;
+ // recv_buf_list->Prepend(bid);
+ // }
+
+#ifdef MEASURE
+ _measure_master_recv_time += _measure_cur_wall_time() - _recv_start_time;
+ _measure_master_recv_cpu_time += _measure_cur_cpu_time() - _recv_start_cpu_time;
+#endif // MEASURE
+
+ if ( buf_id < 0 )
+ {
+ MWprintf ( 10, "ERROR, Problem with RMC->recv!\n" );
+#ifdef INDEPENDENT
+ return QUIT;
+#else
+ // GGT -- was continue
+ //continue;
+
+ //by jae
+ rematch_tasks_to_workers(NULL);
+ return OK;
+#endif
+ }
+
+ info = RMC->bufinfo ( buf_id, &len, &tag, &sending_host );
+
+ /* 8/28/00
+ Qun Chen's signal handling code for Michael Ferris
+ */
+/*
+
+int returned_from_longjump, processing = 1;
+
+if ((returned_from_longjump = setjmp(env)) != 0)
+switch (returned_from_longjump) {
+case SIGINT:
+MWprintf( 10, "!!!! Get user interruption.\n" );
+checkpoint();
+ //printresults();
+ return QUIT;
+ case SIGCONT: //Our program normally won't have this signal
+ MWprintf( 10, "FATCOP was signaled to checkpoint...\n" );
+ checkpoint();
+ MWprintf( 10, "finish checkpointing ...\n" );
+ break;
+ }
+ (void) signal(SIGINT, signal_handler);
+ (void) signal(SIGCONT, signal_handler);
+ // alarm( 10 );
+ */
+ switch ( tag )
+ {
+ case INIT:
+#ifdef MEASURE
+ if (_measure_target_num_workers < workers->number()) {
+ MWprintf ( 31, "MEASURE|Got INIT message, but we need to remove workers ...\n");
+ RMC->initsend ( );
+ RMC->send ( sending_host, KILL_YOURSELF );
+ break;
+ }
+#endif // MEASURE
+ if ( (w = lookupWorker ( sending_host )) == NULL )
+ {
+ MWprintf ( 10, "We got an INIT message from worker %08x "
+ "who we don't have records for.\n", sending_host);
+ RMC->initsend ( );
+ RMC->send ( sending_host, KILL_YOURSELF );
+ break;
+ }
+ ustat = worker_init( w );
+ break;
+
+ case BENCH_RESULTS:
+#ifdef MEASURE
+ if (_measure_target_num_workers < workers->number()) {
+ MWprintf ( 31, "MEASURE|Got BENCH_RESULTS message, but we need to remove workers ...\n");
+ RMC->initsend ( );
+ RMC->send ( sending_host, KILL_YOURSELF );
+ break;
+ }
+#endif // MEASURE
+ if ( (w = lookupWorker ( sending_host )) == NULL )
+ {
+ MWprintf ( 10, "We got an BENCH_RESULTS message from (%08x), "
+ "who we don't have records for.\n", sending_host);
+ RMC->initsend ( );
+ RMC->send ( sending_host, KILL_YOURSELF );
+ break;
+ }
+
+ ustat = handle_benchmark( w );
+ if ( ustat == OK )
+ {
+ printWorkers();
+ //send_task_to_worker( w );
+ lockSendTaskToWorker( w );
+ }
+ else
+ {
+ ustat = OK; // we don't want to shut down...
+ }
+ break;
+
+ case SUBRESULTS:
+ if ( (w = lookupWorker ( sending_host )) == NULL )
+ {
+ MWprintf ( 10, "We got a RESULTS message from worker %08x who we don't have records for.\n",sending_host);
+ RMC->initsend ();
+ RMC->send ( sending_host, KILL_YOURSELF );
+ break;
+ }
+ // deal with subresults
+ RMC->unpack( &tasknum, 1, 1 );
+ MWprintf(51,"Received SUBRESULT message for tasknum %d\n",tasknum);
+ RMC->unpack( &subtasknum, 1,1);
+ t = rmFromRunQ( tasknum );
+ if(t == NULL) MWprintf(51,"huh, task is not in runQ\n");
+ w->runningtask->unpack_subresults(tasknum);
+ // computational steering
+/*
+ if(subtasknum==t->randomstop)
+ {
+ RMC->initsend();
+ RMC->pack(&tasknum, 1, 1);
+ RMC->send(sending_host, STOP_WORK);
+ }
+*/
+ act_on_completed_subtask(t);
+ //act_on_completed_task(t);
+ putOnRunQ(t); // return task to run queue to complete the other tasks - with task container model, this task is done
+ break;
+
+ case RESULTS:
+
+ MWprintf ( 10, "We got a RESULTS message from worker %08x.\n", sending_host);
+
+ if ( (w = lookupWorker ( sending_host )) == NULL )
+ {
+ MWprintf ( 10, "We got a RESULTS message from worker %08x who we don't have records for.\n",
+ sending_host);
+ RMC->initsend ();
+ RMC->send ( sending_host, KILL_YOURSELF );
+ break;
+ }
+
+ ustat = handle_worker_results ( w );
+
+ if ( w->is_doomed() )
+ {
+ /* This worker has been marked for removal */
+ worker_last_rites ( w );
+ }
+ else
+ {
+ if ( ustat == OK )
+ {
+ //send_task_to_worker( w );
+ lockSendTaskToWorker( w );
+ }
+ else if( ustat != PENDING )
+ {
+ RMC->initsend ( );
+ RMC->send ( w->get_id1(), KILL_YOURSELF );
+ worker_last_rites ( w );
+ call_hostaddlogic ( );
+ }
+ }
+
+#ifdef MEASURE
+ // Summarize the measurement results
+ _measure_current_worker = w;
+ _measure();
+#endif // MEASURE
+ break;
+
+ case HOSTADD:
+ {
+ MWWorkerID *w = new MWWorkerID;
+
+ int r=0;
+ r = RMC->start_worker( w );
+ if ( r >= 0 )
+ addWorker( w );
+ else
+ {
+ delete w;
+ }
+
+ MWprintf(50, "Got a HOSTADD message.\n");
+ call_hostaddlogic();
+ break;
+ }
+
+ case HOSTDELETE:
+ handle_hostdel();
+ break;
+
+ case TASKEXIT:
+ handle_taskexit();
+ break;
+
+ case CHECKSUM_ERROR:
+ handle_checksum();
+ break;
+
+ case HOSTSUSPEND:
+ handle_hostsuspend();
+ break;
+
+ case HOSTRESUME:
+ handle_hostresume();
+ break;
+
+ default:
+ MWprintf ( 10, "Unknown message %d. What the heck?\n", tag );
+
+ } // switch
+
+ /* Jeff's addition. At this point, we need to do some assigning of
+ tasks. If many tasks are added all in a batch, then many
+ "SEND_WORK" commands are ignored, and the workers sit
+ idle. Checking again here whether or not there are workers
+ waiting (or suspended) is a good idea.
+ */
+ rematch_tasks_to_workers( w );
+
+#if defined( SIMULATE_FAILURE )
+ // Fail with probability p
+ const double p = 0.0025;
+
+ if( drand48() < p )
+ {
+ MWprintf ( 10, "Simulating FAILURE!\n" );
+ kill_workers();
+ RMC->exit(1);
+ }
+#endif
+
+ // If there is a worker_timeout_limit check all workers if there are
+ // timed-out workers in working state
+
+ if (worker_timeout)
+ {
+ time_t now = time(0);
+
+ if (next_worker_timeout_check <= now)
+ {
+ next_worker_timeout_check = now + worker_timeout_check_frequency;
+ MWprintf ( 80, "About to check timedout workers\n");
+ reassign_tasks_timedout_workers();
+ }
+ }
+
+ if( ustat != OK )
+ {
+ MWprintf( 10, "The user signalled %d to stop execution.\n", ustat );
+ }
+
+ return ustat;
+}
+
+int
+MWDriver::stop_work()
+{
+ int who;
+ RMC->who ( &who );
+ MWWorkerID *w = lookupWorker ( who );
+ RMC->initsend();
+ RMC->send ( w->get_id1(), STOP_WORK );
+ return 0;
+}
+
+void
+MWDriver::printresults ( )
+{
+ MWprintf ( 0, "In MWDriver packed %lf and unpacked %lf\n", RMC->get_bytes_packed(),
+ RMC->get_bytes_unpacked() );
+ MWprintf ( 0, "The MWDriver is done\n");
+}
+
+int
+MWDriver::refreshWorkers ( int i, MWREFRESH_TYPE type )
+{
+ // send only to idle workers
+ MWWorkerID *so = MWcurrentWorker;
+ int j;
+
+ if ( type == MW_NONE )
+ return 0;
+ if ( type == MW_THIS )
+ {
+ for ( j = 0; j < MWworkClasses; j++ )
+ {
+ if ( MWcurrentWorker->doesBelong ( j ) )
+ MWcurrentWorker->deleteGroup ( j );
+ }
+ RMC->initsend ( );
+ pack_worker_init_data ( );
+ RMC->send ( MWcurrentWorker->get_id1(), REFRESH );
+ return 0;
+ }
+
+ int num = 0;
+ int max = workers->number();
+ MWWorkerID *w;
+
+ while ( num < max )
+ {
+ w = (MWWorkerID *)workers->Remove();
+ if ( w != MWcurrentWorker && w->currentState() != IDLE )
+ workers->Append ( w );
+ else if ( !w->doesBelong ( i ) )
+ workers->Append ( w );
+ else
+ {
+ // You have to remove them from the list.
+ for ( j = 0; j < MWworkClasses; j++ )
+ {
+ if ( w->doesBelong ( j ) )
+ w->deleteGroup ( j );
+ }
+ RMC->initsend();
+ MWcurrentWorker = w;
+ pack_worker_init_data ( );
+ RMC->send ( w->get_id1(), REFRESH );
+ workers->Append ( w );
+ }
+ num++;
+ }
+ MWcurrentWorker = so;
+ return 0;
+}
+
+void
+MWDriver::worker_last_rites ( MWWorkerID *w )
+{
+ w->ended();
+ stats->gather(w);
+ rmWorker ( w->get_id1() );
+ RMC->removeWorker ( w );
+ RMC->MW_exec_class_num_workers[w->get_exec_class()]--;
+
+ /* Commented out by Jichuan, to avoid calling deleteGroup() twice */
+ /*
+ for ( int i = 0; i < MWworkClasses; i++ )
+ {
+ if ( w->doesBelong ( i ) )
+ w->deleteGroup ( i );
+ }
+ */
+}
+
+MWReturn
+MWDriver::worker_init( MWWorkerID *w )
+{
+ char workerhostname[64];
+ MWReturn ustat = OK;
+
+ /* We pack the hostname on the worker side... */
+ RMC->unpack( workerhostname );
+
+ MWprintf ( 40, "The MWDriver recognizes the existence of worker \"%s\".\n",
+ workerhostname );
+
+ // 9/5/00 Jeff changes this at Jim Basney's behest.
+ // Now, MWPvmRC will return the proper hostname, so we
+ // check to see if the name has already been set before
+ // setting it here
+
+ w->set_machine_name( workerhostname );
+ w->started();
+
+ unpack_worker_initinfo( w );
+
+ w->get_machine_info();
+
+ int stat = RMC->initsend();
+ if( stat < 0 )
+ {
+ MWprintf( 10, "Error in initializing send in pack_worker_init_data\n");
+ worker_last_rites ( w );
+ return OK;
+ }
+
+ if ( RMC->pack ( getHostName() ) != 0 )
+ {
+ MWprintf ( 10, "packing of hostName returned !OK.\n");
+ worker_last_rites ( w );
+ return ustat;
+ }
+ MWcurrentWorker = w;
+ if ( (ustat = pack_worker_init_data()) != OK )
+ {
+ MWprintf ( 10, "pack_worker_init_data returned !OK.\n" );
+ w->printself(10);
+ worker_last_rites ( w );
+ return ustat;
+ }
+
+ MWTask *b = get_benchmark_task();
+ int benchmarking = b ? TRUE : FALSE;
+
+ RMC->pack( &benchmarking, 1 );
+ if ( b )
+ {
+ b->pack_work();
+ }
+
+ MWprintf ( 10, "Master sending an INIT_REPLY\n");
+ RMC->send( w->get_id1(), INIT_REPLY );
+ // Note the fact that the worker is doing a benchmark.
+ w->benchmark();
+ return ustat;
+}
+
+MWReturn
+MWDriver::handle_benchmark ( MWWorkerID *w )
+{
+ int okay = TRUE;
+ double bres = 0.0;
+
+ RMC->unpack( &okay, 1 );
+ if ( okay == -1 )
+ {
+ /* Very bad! */
+ MWprintf ( 10, "A worker failed to initialize!\n" );
+ w->printself(10);
+ worker_last_rites ( w );
+ return QUIT;
+ }
+
+ RMC->unpack( &bres, 1 );
+ w->set_bench_result( bres );
+
+ MWprintf( 10, "Received bench result %lf from %s (%08x)\n",
+ bres, w->machine_name(), w->get_id1() );
+
+ stats->update_best_bench_results( bres );
+
+ w->benchmarkOver();
+
+ //JTL -- Now you need to order the workerlist
+ sort_worker_list();
+
+ return OK;
+}
+
+void
+MWDriver::kill_workers()
+{
+
+ MWprintf( 40, "Killing workers:\n");
+
+ MWWorkerID *w = (MWWorkerID *)workers->Remove();
+
+ while ( w )
+ {
+ RMC->initsend ( );
+ RMC->send ( w->get_id1(), KILL_YOURSELF );
+ w->ended();
+ stats->gather(w);
+ RMC->MW_exec_class_num_workers[w->get_exec_class()]--;
+ for ( int i = 0; i < MWworkClasses; i++ )
+ {
+ if ( w->doesBelong ( i ) )
+ w->deleteGroup ( i );
+ }
+ RMC->removeWorker( w );
+
+ w = (MWWorkerID *)workers->Remove();
+ }
+}
+
+void
+MWDriver::give_work ( MWWorkerID *w, MWTask *t)
+{
+ RMC->initsend();
+ int itmp = t->taskType;
+ RMC->pack ( &itmp, 1, 1 );
+ RMC->pack( &(t->number), 1, 1 );
+ pack_driver_task_data();
+ t->pack_work();
+ RMC->send( w->get_id1(), DO_THIS_WORK );
+}
+
+void
+MWDriver::lockSendTaskToWorker( MWWorkerID *w )
+{
+ pthread_mutex_lock(&global_mw_mutex);
+ send_task_to_worker(w);
+ pthread_mutex_unlock(&global_mw_mutex);
+}
+
+void
+MWDriver::send_task_to_worker( MWWorkerID *w )
+{
+
+ /* Jeff added this! Due to the "rematch" function,
+ * it can be the case that a worker who asks for work might
+ * already have some work, in which case we don't want to give
+ * him another task. (If he goes down then only one of the tasks
+ * will be rescheduled.
+ */
+
+ MWTask *t = NULL;
+ if( w->currentState() != IDLE )
+ {
+ return;
+ }
+ /* End of Jeff's kludgy fix */
+
+ double lastMeasured;
+ double nowTime;
+ w->getNetworkConnectivity ( lastMeasured );
+ nowTime = MWSystem::gettimeofday();
+
+#ifndef NWSENABLED
+/*
+ if ( nowTime > lastMeasured + 60 * 120 )
+ {
+ MWprintf ( 10, "Creating NWSTask: nowTime = %f, lastMeasured = %f\n", nowTime, lastMeasured);
+ t = new MWNWSTask ( task_counter++, defaultTimeInterval, defaultIterations, defaultPortNo, getHostName() );
+ // t->printself ( 10 );
+ MWprintf ( 10, "Sending MWNWSTask %f %d\n", defaultTimeInterval, defaultIterations);
+ }
+ else
+*/
+ // in the future, there will be some policy to determine how many tasks go into one container
+ int tasks_per_container = 1;
+ for(int i = 0; i < tasks_per_container; i++)
+ {
+ t = getNextTask( w->getGroup() );
+ if( t != NULL) {
+ w->gottask(t->number);
+ putOnRunQ(t);
+ }
+ }
+#else
+ int tasks_per_container = 1;
+ for(int i = 0; i < tasks_per_container; i++)
+ {
+ t = getNextTask( w->getGroup() );
+ if( t == NULL)
+ break;
+ tc->addTask(t);
+ w->gottask(t->number);
+ putOnRunQ(t);
+ }
+#endif
+
+ if ( t != 0)
+ {
+ give_work ( w, t);
+ w->runningtask = t;
+ t->worker = w;
+
+ MWprintf ( 10, "Sent following task to %s (%08x).\n",
+ w->machine_name(), w->get_id1() );
+ MWprintf(10,"%d\n",t->number);
+
+ //MWprintf ( 10, "Sent task (%d-%d) to %s (%08x).\n",
+ // tc->FirstNum(), tc->LastNum(), w->machine_name(), w->get_id1() );
+ //remember to delete tc when you are done
+ }
+/*
+ if ( t != NULL )
+ {
+ give_work ( w, tc );
+ w->gottask( t->number );
+ w->runningtask = t;
+ t->worker = w;
+ putOnRunQ( t );
+
+ MWprintf ( 10, "Sent task %d to %s (%08x).\n",
+ t->number, w->machine_name(), w->get_id1() );
+
+ }
+ else
+ {
+ this added to make things work better at program's end:
+ The end result will be that a suspended worker will have its
+ task adopted. We first look for a task with a suspended worker.
+ We call it t. The suspended worker's 'runningtask' pointer
+ will still point to t, but t->worker will point to this
+ worker (w). Now there will be two workers working on the
+ same task. The first one to finish reports the results, and
+ the other worker's results get discarded when (if) they come in.
+
+
+ if ( !running->isEmpty() )
+ {
+ // here there are no tasks on the todo list, but there are
+ // tasks in the run queue. See if any of those tasks are
+ // being held by a suspended worker. If so, adopt that task.
+
+ // will reimplement later
+ //reassignSuspendedTask(running, w);
+ }
+
+ XXX Jichuan's hack to avoid the master and workers busy working on
+ * NWSTasks only, this happens if there are many workers starting from
+ * different time which happen to make this cycle of NWSTasks overlap
+ * with the next. So we will check to see if all the tasks in runQ are
+ * NWSTasks, and stop the application if so!
+ *
+
+ XXX A fix to solve the waiting for already finished task problem.
+ * The problem is that because a task can be assigned to more than one workers,
+ * it can happen that the some of the workers already return the result, but
+ * either the master is waiting for the other workers to finish (if the task is
+ * the last one), or the master will reassign the task to more workers.
+ *
+ * To fix it, we use two marker lists to record the set (no dup) of tasks that
+ * can were reassigned and already finished: List "reassigned_tasks" and List
+ * "reassigned_tasks_done". A task id is inserted to "reassigned_tasks" when
+ * a its worker is suspended or timed-out, and inserted to "reassigned_tasks_done"
+ * when a result is reported back. The difference of two set can be problematic
+ * tasks.
+ *
+ * If the TODO list is empty, and all running task is in the "reassigned_tasks_done"
+ * set, then QUIT; if a task is suspended or timed-out, and it's in the
+ * "reassigned_tasks_done" set, it will not be reassigned.
+ *
+
+ bool all_NWS = true, all_reassigned = true, all_done = true;
+
+ // MWprintf ( 60, "Now that no task in TODO list, let's see if all tasks in the runQ are NWSTaks.\n");
+ MWTask *tmp_t = running->First();
+
+ while (running->AfterEnd() == false) {
+ tmp_t = running->Current();
+ if (tmp_t->taskType != MWNWS )
+ all_NWS = false;
+ if (!in_set(reassigned_tasks, tmp_t->number))
+ all_reassigned = false;
+ else if (!in_set(reassigned_tasks_done, tmp_t->number))
+ all_done = false;
+ running->Next();
+ }
+
+ if (all_NWS) {
+ MWprintf( 10, "Since all running tasks are NWSTask, and no TODO task, we are done! \n");
+ normal_tasks_all_done = true;
+ } else if (all_reassigned && all_done) {
+ MWprintf( 10, "Since all running tasks are reassigned and all done, and no TODO task, we are done! \n");
+ normal_tasks_all_done = true;
+ }
+ }
+*/
+}
+
+void
+MWDriver::reassignSuspendedTask ( MWList<MWTask> * running, MWWorkerID * w )
+{
+ MWGroup *grp1, *grp2;
+ grp2 = w->getGroup();
+
+ MWTask *t = running->First();
+ while (running->AfterEnd() == false) {
+ t = running->Current();
+ grp1 = t->getGroup();
+
+ if ( grp1->doesOverlap ( grp2 ) && t->worker->isSusp() )
+ {
+ MWprintf ( 60, "Re-assigning task %d to %s (%08x).\n",
+ t->number, w->machine_name(), w->get_id1() );
+ t->worker->printself( 60 ); // temp
+ w->gottask( t->number );
+ t->worker = w;
+ w->runningtask = t;
+ // note that old wkr->runningtask points to t also.
+ give_work ( w, t );
+ break;
+ }
+
+ running->Next();
+ }
+}
+
+void
+MWDriver::handle_hostdel ()
+{
+
+ // Here we find out a host has gone down.
+ // this tells us who died:
+ int who;
+ RMC->who ( &who );
+
+ MWWorkerID *w = rmWorker( who );
+ if ( w == NULL )
+ {
+ MWprintf ( 40, "Got HOSTDELETE of worker %08x, but it isn't in the worker list.\n", who );
+ }
+ else
+ {
+ MWprintf ( 40, "Got HOSTDELETE! \" %s \" (%08x) went down.\n",
+ w->machine_name(), who );
+
+ hostPostmortem ( w );
+ MWprintf ( 40, "There are now %d workers\n", workers->number() );
+
+ /* We may have to ask for some hosts at this time... */
+ delete w;
+ call_hostaddlogic();
+ }
+}
+
+void
+MWDriver::handle_taskexit ()
+{
+
+ /* I have found that we usually get this message just before a HOSTDELETE,
+ so I'm not going to do anything like remove that host...
+ */
+
+ int who;
+ RMC->who ( &who );
+ // search workers for that id2.
+ MWWorkerID *w = rmWorker ( who );
+ if ( w == NULL )
+ {
+ MWprintf ( 40, "Got TASKEXIT of worker %08x, but it isn't in "
+ "the worker list.\n", who );
+ return;
+ }
+
+ MWprintf ( 40, "Got TASKEXIT from machine %s (%08x).\n",
+ w->machine_name(), w->get_id1());
+
+ hostPostmortem( w );
+ RMC->removeWorker ( w );
+ /* We may have to ask for some hosts at this time... */
+ call_hostaddlogic();
+}
+
+MWReturn
+MWDriver::act_on_starting_worker ( MWWorkerID *wid )
+{
+ return OK;
+}
+
+void
+MWDriver::handle_checksum ( )
+{
+ // Some worker returned us a checksum error message
+ // Actually there may be some bootstrapping problem here
+ int who;
+ RMC->who ( &who );
+
+ MWReturn ustat = OK;
+ MWWorkerID *w = lookupWorker ( who );
+
+ MWprintf( 10, "Worker \" %s \" (%08x) returned a checksum error!\n",
+ w->machine_name(), who );
+
+ if ( w == NULL )
+ {
+ MWprintf ( 10, "Got CHECKSUM_ERROR from worker %08x, but it isn't in "
+ "the worker list.\n", who );
+ return;
+ }
+ else
+ {
+ switch ( w->currentState ( ) )
+ {
+ case BENCHMARKING:
+ {
+ int stat = RMC->initsend();
+ if( stat < 0 )
+ {
+ MWprintf( 10, "Error in initializing send in pack_worker_init_data\n");
+ }
+ MWcurrentWorker = w;
+ if ( (ustat = pack_worker_init_data()) != OK )
+ {
+ MWprintf ( 10, "pack_worker_init_data returned !OK.\n" );
+ w->printself(10);
+ w->started();
+ w->ended();
+ RMC->MW_exec_class_num_workers[w->get_exec_class()]--;
+ rmWorker ( w->get_id1() );
+ RMC->removeWorker ( w );
+ return;
+ }
+
+ MWTask *b = get_benchmark_task();
+ int benchmarking = b ? TRUE : FALSE;
+
+ RMC->pack( &benchmarking, 1 );
+ if ( b )
+ {
+ b->pack_work();
+ }
+
+ RMC->send( w->get_id1(), INIT_REPLY );
+ // Note the fact that the worker is doing a benchmark.
+ w->benchmark();
+ return;
+ break;
+ }
+ case WORKING:
+ {
+ if ( w->runningtask )
+ {
+ // It was running a task
+ // See if this task is there in the done list
+ // implement this later
+ // if ( w->runningtask->taskType == MWNORMAL )
+ // pushTask ( w->runningtask );
+
+ //send_task_to_worker( w );
+ lockSendTaskToWorker( w );
+ return;
+ }
+ else
+ {
+ // How is this possible that a worker is not working on something
+ MWprintf ( 10, "Worker was not working on any task but still gave a CHECKSUM_ERROR\n");
+ return;
+ }
+ break;
+ }
+
+ default:
+ MWprintf(30, "MWDriver::handle_checksum() - other worker state.\n");
+ }
+ }
+}
+
+void
+MWDriver::handle_hostsuspend ()
+{
+ int who;
+ RMC->who ( &who );
+ MWprintf(40,"Got HOSTSUSPEND\n");
+
+ MWWorkerID *w = lookupWorker ( who );
+ if ( w != NULL )
+ {
+ w->suspended();
+ MWprintf ( 40, "Got HOSTSUSPEND! \"%s\" is suspended.\n", w->machine_name() );
+
+ int task;
+ if ( w->runningtask && w->runningtask->taskType == MWNORMAL )
+ {
+ task = w->runningtask->number;
+ MWprintf ( 60, " --> It was running task %d.\n", task );
+
+ switch ( suspensionPolicy )
+ {
+ case REASSIGN:
+ {
+ // remove task from running list; push on todo.
+
+// First see if it's *on* the running list. If it's
+// not, then it's either back on the todo list or
+// its already done. If this is the case, ignore.
+
+ MWTask *rmTask = rmFromRunQ( task );
+ if ( !rmTask )
+ {
+ MWprintf ( 60, "Not Re-Assigning task %d.\n", task );
+ break;
+ }
+ MWTask *rt = w->runningtask;
+ if ( rt != rmTask )
+ {
+ MWprintf ( 10, "REASSIGN: something big-time screwy.\n");
+ }
+
+// Now we put that task on the todo list and rematch
+// the tasks to workers, in case any are waiting around.
+
+ if (!in_set(reassigned_tasks_done, rt->number)) {
+ insert_into_set(reassigned_tasks, rt->number);
+ MWprintf(60,"REASSIGN: Will reassign task %d.\n", rt->number);
+ pushTask( rt );
+ // just in case...
+ rematch_tasks_to_workers ( w );
+ }
+ break;
+ }
+ case DEFAULT:
+ {
+ // we only take action if the todo list is empty.
+ if ( todo->isEmpty() )
+ {
+ // here there are no more tasks left to do, we want
+ // to re-allocate this job. First, find idle worker:
+ //will reimplement later
+ //reassignIdleTask(workers, w);
+ }
+ }
+ } // switch
+ }
+ else if ( w->runningtask && w->runningtask->taskType != MWNORMAL )
+ {
+ MWprintf ( 60, " --> It was running a control task.\n");
+ }
+ else
+ {
+ MWprintf ( 60, " --> It was not running a task.\n" );
+ }
+ }
+ else
+ {
+ MWprintf ( 40, "Got HOSTSUSPEND of worker %08x, but it isn't in "
+ "the worker list.\n", who );
+ }
+}
+
+void
+MWDriver::reassignIdleTask (MWList<MWWorkerID> * workers, MWWorkerID * w)
+{
+ MWGroup *grp1, *grp2;
+ grp2 = w->runningtask->getGroup();
+
+ MWWorkerID *o = workers->First();
+ while (workers->AfterEnd() == false) {
+ o = workers->Current();
+ grp1 = o->getGroup();
+
+ if ( o->isIdle() && grp1->doesOverlap ( grp2 ) )
+ {
+ MWprintf ( 60, "Reassigning task %d. to %s\n",
+ w->runningtask->number, o->machine_name() );
+ w->runningtask->worker = o;
+ o->runningtask = w->runningtask;
+ o->gottask( o->runningtask->number );
+
+ give_work ( o, o->runningtask );
+ break;
+ }
+ o = workers->Next();
+ }
+}
+
+void
+MWDriver::handle_hostresume ()
+{
+
+ /* Do nothing; applaud politely */
+
+ int who;
+ RMC->who ( &who );
+
+ MWWorkerID *w = lookupWorker ( who );
+ if ( w != NULL )
+ {
+ w->resumed();
+ MWprintf ( 40, "Got HOSTRESUME. \"%s\" has resumed.\n",
+ w->machine_name() );
+ if ( w->runningtask != NULL )
+ {
+ MWprintf ( 60, " --> It's still running task %d.\n",
+ w->runningtask->number );
+ }
+ else
+ {
+ MWprintf ( 60, " --> It's not running a task.\n" );
+ }
+ }
+ else
+ {
+ MWprintf ( 40, "Got HOSTRESUME of worker %08x, but it isn't in "
+ "the worker list.\n", who );
+ }
+}
+
+void
+MWDriver::hostPostmortem ( MWWorkerID *w )
+{
+ MWTask *t = 0;
+ w->ended();
+ RMC->MW_exec_class_num_workers[w->get_exec_class()]--;
+ for ( int i = 0; i < MWworkClasses; i++ )
+ {
+ if ( w->doesBelong ( i ) )
+ w->deleteGroup ( i );
+ }
+ t = w->runningtask;
+
+ if ( t == NULL )
+ {
+ MWprintf ( 60, " %s (%08x) was not running a task.\n",
+ w->machine_name(), w->get_id1() );
+ }
+ else if ( t->taskType == MWNORMAL )
+ {
+ MWprintf ( 60, " %s (%08x) was running task %d.\n",
+ w->machine_name(), w->get_id1(), t->number );
+ // remove that task from the running queue...iff that
+ // task hasn't ALREADY been reassigned.
+
+ w->runningtask = NULL;
+ MWWorkerID *o;
+ if ( !(o = task_assigned( t )) )
+ {
+ MWTask *check = rmFromRunQ( t->number );
+ if ( t == check )
+ {
+ t->worker = NULL;
+ rmFromRunQ(t->number);
+ pushTask( t );
+ }
+ }
+ else
+ {
+ t->worker = o;
+ MWprintf ( 60, " Task %d already has been reassigned\n",
+ t->number );
+ }
+ }
+ else
+ {
+ // It is a control task
+ // XXX Maybe also need to delete the task from RunQ, Insure complained about this.
+ MWTask *check = rmFromRunQ( t->number );
+ if ( t == check ) // GGT gcc complains about t used before set here, I think this is a bug
+ MWprintf(21, "The control task IS in the RunQ, and should haven't been deleted!");
+ delete t;
+ }
+ stats->gather( w );
+}
+
+MWReturn
+MWDriver::handle_worker_results( MWWorkerID *w )
+{
+ MWReturn ustat = OK;
+
+ int tasknum;
+ double wall_time = 0;
+ double cpu_time = 0;
+
+ RMC->unpack( &tasknum, 1, 1 );
+
+#ifdef MEASURE
+ // get the _task_recv_time
+ double _task_recv_time = 0.0;
+ double _task_recv_cpu_time = 0.0;
+ RMC->unpack( &_task_recv_time, 1, 1);
+ RMC->unpack( &_task_recv_cpu_time, 1, 1);
+#endif // MEASURE
+
+ RMC->unpack( &wall_time, 1, 1 );
+ RMC->unpack( &cpu_time, 1, 1 );
+
+ // We once received CPU times that were NAN from a worker,
+ // and this messes EVERYTHING up
+
+ if( cpu_time != cpu_time )
+ {
+ MWprintf( 10, "Error. cpu_time of %lf, assigning to wall_time of %lf\n",
+ cpu_time, wall_time );
+ }
+
+ // Jeff's CPU time sanity check!!!!
+ if( cpu_time > 0.1 && (cpu_time > 1.1 * wall_time || cpu_time < 0.01 * wall_time ))
+ {
+ MWprintf( 10, "Warning. Cpu time =%lf, wall time = %lf seems weird.\n",
+ cpu_time, wall_time );
+ MWprintf( 10, "Assigning cpu time to be %lf\n", wall_time );
+ cpu_time = wall_time;
+ }
+ // total_time = now - start_time;
+
+
+ MWprintf ( 60, "Unpacked task %d result from %s (%08x).\n",
+ tasknum, w->machine_name(), w->get_id1() );
+
+ MWprintf ( 81, "It took %5.2f secs wall clock and %5.2f secs cpu time\n",
+ wall_time, cpu_time );
+
+ int mwtasknum = w->runningtask ? w->runningtask->number : -2;
+ if( tasknum != mwtasknum )
+ {
+ MWprintf( 10, "What the $%!^$!^!!!. MW thought that %s (%08x) was running %d, not %d\n",
+ w->machine_name(), w->get_id1(), mwtasknum, tasknum );
+ return QUIT;
+ }
+
+ if ( w->isSusp() )
+ {
+ MWprintf ( 60, "Got results from a suspended worker!\n" );
+ }
+
+ MWTask *t = rmFromRunQ( tasknum );
+
+ /* The task *could* have been suspended, REASSIGNed, and put
+ on the todo list. Let's just check the first entry on the
+ todo list and see if it's there. If so, remove it and handle. */
+ if ( suspensionPolicy == REASSIGN )
+ {
+ MWTask * tmp_t = todo->First();
+ while (todo->AfterEnd() == false) {
+ tmp_t = todo->Current();
+ if (tmp_t->number == t->number)
+ todo->RemoveCurrent();
+ else todo->Next();
+ }
+ }
+
+ // in_TODO inited to be 0
+ int in_TODO = 0;
+
+ if ( t == NULL ) {
+ // XXX Check to see if the task is in TODO list
+ // It is possible that when re-assigning a task for many times,
+ // the task can be temporarily in TODO list, but a worker at the
+ // same time can return the result for this task. In this case,
+ // we will just process the result (t = tmp_t) and remove the task from TODO
+ // list.
+ // -- Reported by Jeff
+ // -- temp fix by Jichuan
+
+ if (in_set(reassigned_tasks_done, tasknum))
+ MWprintf ( 60, "Task %d already done, no need to process it.\n", tasknum);
+ else {
+ if (!in_set(reassigned_tasks, tasknum))
+ MWprintf ( 30, "Something wrong with REASSIGN, task %d.\n", tasknum);
+
+ MWTask * tmp_t = todo->First();
+ while (todo->AfterEnd() == false) {
+ tmp_t = todo->Current();
+ if (tmp_t->number == tasknum) { /* found */
+ todo->RemoveCurrent();
+ in_TODO = 1;
+ t = tmp_t;
+ MWprintf(60, "Done task %d found in TODO, delete from it.\n", tasknum);
+ } else todo->Next();
+ }
+ }
+ }
+
+ if ( ( !in_TODO ) && ( t == NULL ) ) {
+
+ w->completedtask( wall_time, cpu_time );
+
+ // XXX Delete the task if there is no other workers are running it.
+ // It's possible that the same task is assigned to many different
+ // workers (everytime a worker suspend, it's running task may be
+ // reassigned to another worker).
+ //
+ // if ( w->runningtask )
+ //
+ // The original statement assumes that the number of workers running
+ // task t is maximally 2, so when the second worker report result,
+ // MW delete the task. If a new task is created using the same region
+ // of memory, the runningtask pointer is corrupted.
+
+ if (w->runningtask ) {
+ if (task_assigned(w->runningtask) == NULL) {
+ delete w->runningtask;
+ }
+ w->runningtask = NULL;
+ }
+ }
+ else
+ {
+ // tell t the results
+ t->unpack_results();
+ /* give these to the task class; now the user can use them. */
+ t->working_time = wall_time;
+ t->cpu_time = cpu_time;
+ stats->update_best_task_results( cpu_time);
+
+#ifdef MEASURE
+ // set the task's _measure_MP_worker_time
+ t->_measure_MP_worker_time = _task_recv_time;
+ t->_measure_MP_worker_cpu_time = _task_recv_cpu_time;
+#endif // MEASURE
+
+ if ( t->taskType == MWNORMAL )
+ {
+ MWcurrentWorker = w;
+#ifdef MEASURE
+ // _measure: accumulate the _measure_master_act_on_completed_task_time (and cpu)values
+ double act_start_time = _measure_cur_wall_time();
+ double act_start_cpu_time = _measure_cur_cpu_time();
+#endif // MEASURE
+
+ ustat = act_on_completed_task( t );
+#ifdef MEASURE
+ _measure_master_act_on_completed_task_time += _measure_cur_wall_time() - act_start_time;
+ _measure_master_act_on_completed_task_cpu_time += _measure_cur_cpu_time() - act_start_cpu_time;
+ _measure_num_task_Done ++;
+#endif // MEASURE
+
+ if (in_set(reassigned_tasks, t->number)) {
+ insert_into_set(reassigned_tasks_done, t->number);
+ MWprintf(60, "REASSIGN: Task %d once reassigned and now finished.\n", t->number);
+ }
+
+ num_completed_tasks++;
+
+ if ( (checkpoint_frequency > 0) &&
+ (num_completed_tasks % checkpoint_frequency) == 0 )
+ {
+ checkpoint();
+ }
+ else
+ {
+ if ( checkpoint_time_freq > 0 )
+ {
+ time_t now = time(0);
+ MWprintf ( 91, "Trying ckpt-time, %d %d\n",
+ next_ckpt_time, now );
+ if ( next_ckpt_time <= now )
+ {
+ next_ckpt_time = now + checkpoint_time_freq;
+ MWprintf ( 80, "About to...next_ckpt_time = %d\n",
+ next_ckpt_time );
+ checkpoint();
+ }
+ }
+ }
+ }
+ else
+ {
+#ifndef NWSENABLED
+ if ( t->taskType == MWNWS )
+ {
+ if ( w )
+ w->setNetworkConnectivity ( ((MWNWSTask *)t)->median );
+ MWprintf ( 10, "Got results of NWSTask\n");
+ }
+#endif
+ }
+
+ if ( t->worker == NULL )
+ {
+ MWprintf ( 40, "Task had no worker...huh?\n" );
+ }
+
+ if ( w != t->worker )
+ {
+ MWprintf ( 90, "This task not done by 'primary' worker, "
+ "but that's ok.\n" );
+ }
+ else
+ {
+ MWprintf ( 90, "Task from 'primary' worker %s.\n",
+ w->machine_name() );
+ }
+
+ //by jae
+ if( ustat != PENDING ) {
+ w->runningtask = NULL;
+ w->completedtask( wall_time, cpu_time );
+ t->worker = NULL;
+
+ if( ! task_assigned( t ) )
+ {
+ MWprintf( 80, "Deleting task %d\n", t->number );
+
+ for ( int tempi = 0; tempi < MWworkClasses; tempi++ )
+ {
+ if ( t->doesBelong ( tempi ) )
+ t->deleteGroup ( tempi );
+ }
+
+#ifdef MEASURE
+ // When a task is done, accumulate the following values:
+ // _measure_num_task_Done, task-related summary values
+ // _measure_task_RoundTrip_time += _measure_cur_wall_time() - t->_measure_start_time;
+ _measure_task_Exe_wall_time += t->working_time;
+ _measure_task_Exe_cpu_time += t->cpu_time;
+ // _measure_task_MP_master_time += t->_measure_MP_master_time;
+ _measure_task_MP_worker_time += t->_measure_MP_worker_time;
+ _measure_task_MP_worker_cpu_time += t->_measure_MP_worker_cpu_time;
+#endif // MEASURE
+ delete t;
+ }
+ }
+ }
+ return ustat;
+}
+
+void
+MWDriver::rematch_tasks_to_workers( MWWorkerID *nosend )
+{
+ pthread_mutex_lock(&global_mw_mutex);
+
+ // For each worker that is "waiting for work", you can safely(?)
+ // now do a send_task_to_worker. Don't send it to the id "nosend"
+ // (He just reported in).
+ MWWorkerID *w;
+ int ns = nosend ? nosend->get_id1() : -1;
+
+ w = workers->First();
+ while (workers->AfterEnd() == false) {
+ w = workers->Current();
+ if ( (w->currentState() == IDLE) && ( (w->get_id1() != ns) || (w->get_id2() != ns) ) ) {
+ MWprintf ( 90, "In rematch_tasks_to_workers(), trying send...\n" );
+ send_task_to_worker(w);
+ }
+ workers->Next();
+ }
+
+ pthread_mutex_unlock(&global_mw_mutex);
+}
+
+MWTask *
+MWDriver::getNextTask( MWGroup *grp )
+{
+ MWTask *t = NULL;
+ // return next task to do. NULL if none.
+ if ( todo->isEmpty() )
+ return NULL;
+
+ switch( getmode ) {
+
+ case GET_FROM_BEGIN:
+ {
+ t = first_task_in_group(todo, grp);
+ break;
+ }
+ case GET_FROM_KEY:
+ {
+ if( task_key == NULL )
+ {
+ MWprintf ( 10, " GET_FROM_KEY retrieval mode, "
+ "but no key function set.\n");
+ MWprintf ( 10, " Returning task at head of list\n");
+ t = first_task_in_group(todo, grp);
+ }
+ else
+ {
+ if ( listsorted )
+ t = first_task_in_group(todo, grp);
+ else
+ {
+ MWKey retval;
+
+ if( task_key == NULL )
+ {
+ MWprintf( 10, " return_bst_keyval: no task key "
+ "function defined!\n");
+ assert(0);
+ }
+ else
+ {
+ retval = -DBL_MAX;
+ t = NULL;
+ MWListElement<MWTask> * pos = NULL;
+ todo->ToHead();
+ while (todo->AfterEnd() == false) {
+ MWTask * tt = todo->Current();
+ MWKey tmp = (*task_key) (tt);
+ MWGroup * g = tt->getGroup();
+ if ( (retval < tmp) && g->doesOverlap ( grp ) ) {
+ pos = todo->CurPosition();
+ retval = tmp;
+ t = tt;
+ }
+ todo->Next();
+ }
+ todo->Remove(pos);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ MWprintf ( 10, "Unknown getmode %d\n", getmode );
+ assert( 0 );
+ }
+ } // switch
+ return t;
+}
+
+MWTask *
+first_task_in_group ( MWList<MWTask> * tasks, MWGroup * grp)
+{
+ MWTask *t = tasks->First();
+ MWGroup *grp2;
+ while (tasks->AfterEnd() == false) {
+ t = tasks->Current();
+ grp2 = t->getGroup();
+ if ( grp->doesOverlap ( grp2 ) ) {
+ tasks->RemoveCurrent();
+ return t;
+ }
+ else tasks->Next();
+ }
+ return NULL;
+}
+
+void
+MWDriver::pushTask( MWTask *push_task )
+{
+ switch( addmode )
+ {
+ case ADD_AT_BEGIN:
+ {
+ todo->Prepend ( push_task );
+ break;
+ }
+ case ADD_AT_END:
+ {
+ todo->Append ( push_task );
+ break;
+ }
+ case ADD_BY_KEY:
+ {
+ // This will insert at the first key WORSE than the
+ // given one
+ if( task_key == NULL )
+ {
+ MWprintf ( 10, "ERROR! Adding by key, but no key "
+ "function defined!\n" );
+ assert(0);
+ }
+
+ if ((*task_key)(push_task)<=max_task_key) {
+ todo->SortedInsert ( push_task, (*task_key)(push_task) );
+ }
+ else {
+ MWprintf(10, "Won't insert task whose key value %f > max_task_key %f.\n",
+ (*task_key)(push_task), max_task_key);
+ }
+ break;
+ }
+ default:
+ {
+ MWprintf ( 10, "What the heck kinda addmode is %d?\n", addmode );
+ assert( 0 );
+ }
+ } // switch
+}
+
+void
+MWDriver::addTasks( int n, MWTask **add_tasks )
+{
+ if ( n <= 0 )
+ {
+ MWprintf ( 10, "Please add a positive number of tasks!\n" );
+ RMC->exit(1);
+ }
+
+ for ( int i = 0; i < n; i++ )
+ {
+ add_tasks[i]->number = task_counter++;
+ if ( MWworkClasses <= 1 )
+ {
+ add_tasks[i]->initGroups ( MWworkClasses );
+ add_tasks[i]->addGroup ( 0 );
+ }
+
+ pushTask ( add_tasks[i] );
+ }
+}
+
+void
+MWDriver::addTask( MWTask *add_task )
+{
+ add_task->number = task_counter++;
+ if ( MWworkClasses <= 1 )
+ {
+ add_task->initGroups ( MWworkClasses );
+ add_task->addGroup ( 0 );
+ }
+ pushTask ( add_task );
+}
+
+void
+MWDriver::ckpt_addTask( MWTask *add_task )
+{
+ pushTask ( add_task );
+}
+
+void
+MWDriver::set_task_key_function( MWKey (*t)( MWTask * ) )
+{
+ if ( ( t != task_key ) && (task_key == NULL) ) {
+ sort_task_list();
+ listsorted = true;
+ } else if ( t != task_key )
+ listsorted = false;
+
+ task_key = t;
+}
+
+int
+MWDriver::set_task_add_mode( MWTaskAdditionMode mode )
+{
+ int errcode = 0;
+ if( mode < ADD_AT_END || mode > ADD_BY_KEY ) {
+ errcode = UNDEFINED;
+ MWprintf( 10, " Bad Add Task Mode. Switching to ADD_AT_END\n");
+ addmode = ADD_AT_END;
+ }
+ else {
+ addmode = mode;
+ }
+ return errcode;
+}
+
+int
+MWDriver::set_task_retrieve_mode( MWTaskRetrievalMode mode )
+{
+ int errcode = 0;
+ if( mode < GET_FROM_BEGIN || mode > GET_FROM_KEY ) {
+ errcode = UNDEFINED;
+ MWprintf( 10, " Bad Retrive Task Mode. "
+ "Switching to GET_FROM_BEGIN\n" );
+ getmode = GET_FROM_BEGIN;
+ }
+ else {
+ getmode = mode;
+ if( ( mode == GET_FROM_KEY ) && ( task_key == NULL ) ) {
+ MWprintf( 10, " Warning. Call set_task_key() function before ");
+ MWprintf( 10, " retrieving task\n");
+ }
+ }
+
+ return errcode;
+}
+
+int
+MWDriver::set_machine_ordering_policy( MWMachineOrderingPolicy mode )
+{
+ int errcode = 0;
+ if( mode < NO_ORDER || mode > BY_KFLOPS ) {
+ errcode = UNDEFINED;
+ MWprintf( 10, "Bad machine ordering policy %d. Switching to NO_ORDER\n",
+ (int) mode );
+ machine_ordering_policy = NO_ORDER;
+ worker_key = NULL;
+ }
+ else {
+ MWprintf( 30, "Set machine ordering policy to %d\n", (int) mode );
+ machine_ordering_policy = mode;
+ if( mode == BY_USER_BENCHMARK ) {
+ worker_key = &benchmark_result;
+ }
+ else {
+ worker_key = &kflops;
+ }
+
+ }
+ return errcode;
+}
+
+
+void
+MWDriver::set_worker_timeout_limit( double timeout_limit, int timeout_freq )
+{
+ if (timeout_limit > 0)
+ {
+ worker_timeout = true;
+ worker_timeout_limit = timeout_limit;
+
+ worker_timeout_check_frequency = timeout_freq ;
+ next_worker_timeout_check = time(0) + timeout_freq ;
+
+ MWprintf( 30, "Set worker timeout limit to %lf\n", timeout_limit);
+ MWprintf( 30, "Set worker timeout frequency to %d\n", timeout_freq);
+
+ }
+ else
+ {
+ MWprintf(10, "Urgh, Timeout limit has to be > 0\n");
+ }
+}
+
+void MWDriver::reassign_tasks_timedout_workers()
+{
+ MWprintf ( 10, "Enter : reassign_tasks_timedout_workers()\n");
+ MWWorkerID *tempw;
+ int total = 0;
+
+ if (worker_timeout_limit > 0)
+ {
+ double now = MWSystem::gettimeofday();
+ MWprintf( 60, "Now: %lf\n", now );
+
+ while( total < workers->number() )
+ {
+ total++;
+ tempw = (MWWorkerID *)workers->Remove();
+ if (tempw->currentState() == WORKING)
+ {
+ MWprintf( 50, "Last event from %s (%08x) : %lf\n", tempw->machine_name(),
+ tempw->get_id1(), tempw->get_last_event() );
+
+ if ( (now - tempw->get_last_event() ) > worker_timeout_limit )
+ {
+ // this worker is timed out
+ if (tempw->runningtask)
+ {
+ int task = tempw->runningtask->number;
+
+ MWTask *rmTask = rmFromRunQ( task );
+ if ( rmTask )
+ {
+ MWprintf ( 10, "Worker %08x is timed-out\n",tempw->get_id1());
+ MWprintf ( 10, "Task %d rescheduled \n",rmTask->number);
+ }
+ else
+ {
+ MWprintf ( 60, "Task not found in running list; assumed done or in todo list.\n" );
+ }
+
+ if ( !rmTask || rmTask->taskType != MWNORMAL )
+ {
+ MWprintf ( 60, "No need to reassign task %d.\n", task );
+ }
+ else
+ {
+ MWTask *rt = tempw->runningtask;
+ if ( rt != rmTask )
+ {
+ MWprintf ( 10, "REASSIGN: something big-time screwy.\n");
+ }
+ // We don't need to do that.
+ // tempw->runningtask = NULL;
+
+ // Now we put that task on the todo list and rematch
+ // the tasks to workers, in case any are waiting around.
+ if (!in_set(reassigned_tasks_done, rt->number)) {
+ insert_into_set(reassigned_tasks, rt->number);
+ MWprintf(60, "REASSIGN: Will assign task %d.\n", rt->number);
+ pushTask( rt );
+ // just in case...
+ rematch_tasks_to_workers ( tempw );
+ }
+ }
+ }
+ }
+ }
+ workers->Append ( tempw );
+ }
+
+/*
+ This is Jeff's code. We go through the *running* list
+ too to see if there is a task there that needs to be reassigned.
+ For example -- if there is a task in the running list
+ not assigned to anyone. This can happen. For example...
+*/
+
+ total = 0;
+ MWTask *tempr;
+
+ while( total < running->number() )
+ {
+ total++;
+ tempr = (MWTask *)running->Remove();
+ if ( tempr->taskType != MWNORMAL )
+ {
+ running->Append ( tempr );
+ continue;
+ }
+
+ // Find the worker running this task.
+ bool foundworker = false;
+ int subtotal = 0;
+ MWWorkerID *tempw = NULL;
+
+ // XXX // while( subtotal < workers->number() )
+ while( (foundworker == false) && (subtotal < workers->number()) )
+ {
+ subtotal++;
+ tempw = (MWWorkerID *)workers->Remove();
+ if( tempw->runningtask )
+ {
+ MWprintf(99, "worker=%08x, task=%d, worker->runningTask=%d\n",
+ tempw->get_id1(), tempr->number, tempw->runningtask->number);
+ if( tempw->runningtask->number == tempr->number )
+ {
+ foundworker = true;
+ MWprintf(99, "Found worker!\n");
+ }
+ }
+
+ // XXX Should be the bug that Steve reported - jichuan
+ // running->Append ( tempw );
+ workers->Append ( tempw );
+ }
+
+ if( foundworker )
+ {
+ assert( tempw != NULL );
+ MWprintf( 60, "Worker id %08x has task %d\n", tempw->get_id1(),
+ tempr->number );
+ running->Append ( tempr );
+ }
+ else
+ {
+ MWprintf( 10, "Woah!!! Task number %08x lost his worker. Rescheduling\n",
+ tempr->number );
+ // First remove him from the run queue
+ MWTask *check = rmFromRunQ( tempr->number);
+ if( check != tempr )
+ {
+ MWprintf( 10, "There is a HUGE logic error in the code. Aborting\n" );
+ assert( 0 );
+ }
+ pushTask( tempr );
+ break;
+ }
+ }
+ }
+}
+
+int
+MWDriver::print_task_keys()
+{
+ int retcode = 0;
+
+ if( task_key == NULL )
+ {
+ retcode = UNDEFINED;
+ MWprintf( 10, " No key function assigned to tasks -- Can't print\n");
+ }
+ else
+ {
+ MWprintf( 10, "Task Keys:\n");
+ MWTask *t;
+
+ /* Won't print the keys if todo->number() too large */
+ if (todo->number() <= 10000) {
+ t = todo->First();
+ while (todo->AfterEnd() == false) {
+ t = todo->Current();
+ MWprintf(10, " %f\t(%d)\n", (*task_key)(t), t->number);
+ todo->Next();
+ }
+ } else {
+ MWprintf(10, "Too many task keys (%d), skip the printing.\n",
+ todo->number());
+ }
+ }
+ return retcode;
+}
+
+int
+MWDriver::delete_tasks_worse_than( MWKey key )
+{
+ if( task_key == NULL )
+ {
+ MWprintf( 10, " delete_task_worse_than: no task key "
+ "function defined!\n");
+ return UNDEFINED;
+ }
+
+ MWTask *t = todo->First();
+
+ while( todo->AfterEnd() == false) {
+ t = todo->Current();
+ if( (*task_key)( t ) > key ) {
+ todo->RemoveCurrent();
+ delete t;
+ } else todo->Next();
+ }
+
+ //Jeff says -- DO NOT save this state! What if the user changes the
+ // task key?
+ /* Update max_task_key */
+#if 0
+ if (key < max_task_key)
+ max_task_key = key;
+#endif
+ return 0;
+}
+
+void
+MWDriver::putOnRunQ( MWTask *t )
+{
+
+ // Here's the deal: running points to the head of the runQ,
+ // runningend points at the last element in the runQ.
+ // we insert tasks at the end.
+ running->Append ( t );
+}
+
+MWTask *
+MWDriver::rmFromRunQ( int jobnum )
+{
+ MWTask *t;
+
+ running->First();
+ while (running->AfterEnd() == false) {
+ t = running->Current();
+ if (t->number == jobnum) {
+ running->RemoveCurrent();
+ return t;
+ } else running->Next();
+ }
+ return NULL;
+}
+
+MWWorkerID *
+MWDriver::task_assigned( MWTask *t )
+{
+ MWWorkerID * w;
+
+ workers->ToHead();
+ while (workers->AfterEnd() == false) {
+ w = workers->Current();
+ if ( (w->runningtask) && (w->runningtask->number == t->number) )
+ return w;
+ else workers->Next();
+ }
+ return NULL;
+}
+
+bool
+MWDriver::task_in_todo_list( MWTask *t )
+{
+ // Before rescheduling a task on a TASKEXIT message, we need
+ // to see that the task is still in the todo list
+ // Tasks NOT in the todo list have already been finished,
+ // hence they should not be reassigned and this function should
+ // return false.
+
+ MWTask * tt;
+ todo->ToHead();
+
+ while (todo->AfterEnd() == false) {
+ tt = todo->Current();
+ if (tt->number == t->number)
+ return true;
+ else todo->Next();
+ }
+ return false;
+}
+
+int
+MWDriver::matchTask ( void *arg1, void *arg2 )
+{
+ MWTask *t1 = (MWTask *)arg1;
+ MWTask *t2 = (MWTask *)arg2;
+ if ( t1 == t2 )
+ return 1;
+ return 0;
+}
+
+void
+MWDriver::printRunQ()
+{
+ MWprintf ( 60, "PrintRunQ start:\n" );
+ MWTask *t = running->First();
+ while ( running->AfterEnd() == false )
+ {
+ t = running->Current();
+ t->printself();
+ running->Next();
+ }
+ MWprintf ( 60, "PrintRunQ end.\n\n" );
+}
+
+void
+MWDriver::addWorker( MWWorkerID *w )
+{
+ // put a worker on the workers list. Add to front.
+ // At this point, no benchmark information or machine information
+ // is known, so it is impossible to put the new machine in its proper
+ // place
+
+ w->initGroups ( MWworkClasses );
+ MWcurrentWorker = w;
+ act_on_starting_worker ( w );
+ if ( MWworkClasses <= 1 )
+ w->addGroup ( 0 );
+ RMC->MW_exec_class_num_workers[w->get_exec_class()]++;
+
+ workers->Append ( w );
+}
+
+
+// This could be more efficient, since we would need only insert items
+// in order to ensure that things are sorted. But this gives us
+// more flexibility for later, and we will likely rewrite these classes anyway
+
+void
+MWDriver::sort_worker_list()
+{
+ if( machine_ordering_policy == NO_ORDER || worker_key == NULL )
+ return;
+
+ MWWorkerID *w;
+ MWList<MWWorkerID> * newList = new MWList<MWWorkerID>;
+ while ( !workers->isEmpty() )
+ {
+ w = (MWWorkerID *)workers->Remove();
+ newList->SortedInsert ( w, (*worker_key)( w ) );
+ }
+ delete workers;
+ workers = newList;
+}
+
+MWWorkerID*
+MWDriver::lookupWorker ( int id )
+{
+ MWWorkerID * w = workers->First();
+ while (workers->AfterEnd() == false) {
+ w = workers->Current();
+ if ( (w->get_id1() == id) || (w->get_id2() == id) )
+ return w;
+ else workers->Next();
+ }
+ return NULL;
+}
+
+void
+MWDriver::call_hostaddlogic()
+{
+ /* This is a wrapper around the lower level's hostaddlogic(),
+ which will return 0 as a basic OK value, and a positive number
+ of hosts to delete if it thinks we should delete hosts. This
+ can happen if the user changes the target number of workers
+ to a lower value. */
+
+ int *num_workers = new int[RMC->get_num_exec_classes()];
+ int j, numtodelete;
+ int total = 0;
+ MWWorkerID *w; // , *wx, *wn;
+ for ( j=0 ; j < RMC->get_num_exec_classes() ; j++ ) {
+ num_workers[j] = numWorkers( j );
+ }
+
+ numtodelete = RMC->hostaddlogic( num_workers );
+ delete [] num_workers;
+
+
+ /* Make sure we don't count already doomed machines: */
+ if ( numtodelete > 0 )
+ {
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if ( w->is_doomed() ) numtodelete--;
+ workers->Append ( w );
+ }
+ }
+
+ if ( numtodelete > 0 )
+ {
+ MWprintf ( 40, "Deleting %d hosts.\n", numtodelete );
+ MWprintf ( 40, "Ignore the HOSTDELETE or TASKEXIT messages.\n" );
+
+ /* Walk thru list and kill idle workers. */
+ total = 0;
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if ( numtodelete > 0 && w->isIdle() )
+ {
+ MWprintf ( 80, "Idle worker:\n" );
+ worker_last_rites ( w );
+ numtodelete--;
+ }
+ else
+ {
+ workers->Append ( w );
+ }
+ }
+ if ( numtodelete <= 0 ) return;
+
+ /* Now walk thru workers and remove suspended machines */
+ total = 0;
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if ( numtodelete > 0 && w->isSusp() )
+ {
+ MWprintf ( 80, "Suspended worker:\n" );
+ w->printself ( 80 );
+
+ hostPostmortem( w ); /* this really does do what we want! */
+ RMC->removeWorker( w );
+ numtodelete--;
+ }
+ else
+ {
+ workers->Append ( w );
+ }
+ }
+ if ( numtodelete <= 0 ) return;
+
+ /* At this point, we could do something really cool like
+ sort the workers based on some attributes.... */
+
+ /* Next, walk thru list and mark working workers for removal */
+ total = 0;
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if ( numtodelete > 0 && !(w->is_doomed()) )
+ {
+ w->mark_for_removal();
+ MWprintf ( 40, "Host %s marked for removal.\n",
+ w->machine_name() );
+ numtodelete--;
+ }
+ workers->Append ( w );
+ }
+ }
+
+}
+
+int
+MWDriver::numWorkers()
+{
+ return workers->number();
+}
+
+int
+MWDriver::numWorkers( int ex_cl )
+{
+ int count = 0;
+ int total = 0;
+ MWWorkerID *w;
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if ( w->get_exec_class() == ex_cl )
+ {
+ count++;
+ }
+ workers->Append ( w );
+ }
+ return count;
+}
+
+
+int
+MWDriver::numWorkersInState( int ThisState )
+{
+ // We handle the case WORKING separately such that
+ // we don't count the workers with no runningtask
+
+ int total = 0;
+ int count = 0;
+ MWWorkerID *w;
+
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if (ThisState == WORKING)
+ {
+ if ( (w->currentState() == ThisState) && (w->runningtask != NULL) )
+ {
+ count++;
+ }
+ }
+ else
+ {
+ if ( w->currentState() == ThisState )
+ {
+ count++;
+ }
+ }
+ workers->Append ( w );
+ }
+ return count;
+}
+
+void
+MWDriver::printWorkers()
+{
+ MWprintf ( 10, "---- A list of Workers follows: ----------------\n" );
+
+ MWWorkerID *w = workers->First();
+
+ while ( workers->AfterEnd() == false )
+ {
+ w = workers->Current();
+ w->printself( 10 );
+ MWprintf( 10, "\n" );
+ workers->Next();
+ }
+
+ MWprintf ( 10, "---- End worker list --- %d workers ------------\n", workers->number() );
+}
+
+MWKey
+MWDriver::return_best_todo_keyval()
+{
+ MWKey retval = DBL_MAX;
+
+ if( task_key == NULL ) {
+ MWprintf( 10, " return_bst_keyval: no task key "
+ "function defined!\n");
+ }
+ else {
+ if ( todo->isEmpty() )
+ return retval;
+ if ( listsorted ) {
+ //XXX Jeff -- fixed the bug, if you take something off the list that has a key,
+ // You'd better damn well put it back with the same key (not 0.0)
+ // but I don't know if it is the best way to remove
+ // and put the key back on the list. I know I didn' write it this way
+ MWTask *t = (MWTask *)todo->Remove();
+ double val = (*task_key)(t);
+ todo->Prepend(t, val);
+ return (*task_key)( t );
+ }
+ else {
+ MWTask * t = todo->First();
+ while ( todo->AfterEnd() == false ) {
+ t = todo->Current();
+ MWKey tmp = (*task_key) ( t );
+ if ( retval > tmp )
+ retval = tmp;
+ todo->Next();
+ }
+ return retval;
+ }
+ }
+ return retval;
+}
+
+MWKey MWDriver::return_best_running_keyval()
+{
+ MWKey retval = DBL_MAX;
+
+ if( task_key == NULL )
+ {
+ MWprintf( 10, " return_bst_keyval: no task key "
+ "function defined!\n");
+ }
+ else
+ {
+ if ( running->isEmpty() ) return retval;
+ MWTask * t = running->First();
+ while ( running->AfterEnd() == false )
+ {
+ t = running->Current();
+ if ( t->taskType == MWNORMAL )
+ {
+ MWKey tmp = (*task_key)( t );
+ if( tmp < retval )
+ retval = tmp;
+ }
+ running->Next();
+ }
+ return retval;
+ }
+ return retval;
+}
+
+
+
+MWWorkerID *
+MWDriver::rmWorker ( int id )
+{
+ // search for a worker with the given id and remove it.
+ // The id can refer to either the primary or secondary id.
+
+ MWWorkerID * w = workers->First();
+ while (workers->AfterEnd() == false) {
+ w = workers->Current();
+ if ( (w->get_id1() == id) || (w->get_id2() == id) ) {
+ workers->RemoveCurrent();
+ return w;
+ }
+ else workers->Next();
+ }
+ return NULL;
+}
+
+int
+MWDriver::set_checkpoint_frequency( int freq ) {
+ if ( checkpoint_time_freq != 0 ) {
+ MWprintf ( 10, "Cannot set_checkpoint_frequency while time-based "
+ "frequency is not zero!\n" );
+ return checkpoint_frequency;
+ }
+ int old = checkpoint_frequency;
+ checkpoint_frequency = freq;
+ return old;
+}
+
+int
+MWDriver::set_checkpoint_time ( int secs ) {
+ if ( checkpoint_frequency != 0 ) {
+ MWprintf ( 10, "Cannot set_checkpoint_time while task-based "
+ "frequency is not zero!\n" );
+ return checkpoint_time_freq;
+ }
+ int old = checkpoint_time_freq;
+ checkpoint_time_freq = secs;
+ next_ckpt_time = time(0) + secs;
+ return old;
+}
+
+void
+MWDriver::set_suspension_policy( MWSuspensionPolicy policy ) {
+ if ( (policy!=DEFAULT) && (policy!=REASSIGN) ) {
+ MWprintf ( 10, "Bad suspension policy %d. Using DEFAULT.\n" );
+ suspensionPolicy = DEFAULT;
+ return;
+ }
+ suspensionPolicy = policy;
+}
+
+void
+MWDriver::checkpoint()
+{
+ FILE *cfp; // Checkpoint File Pointer
+ /* We're going to write the checkpoint to a temporary file,
+ then move the file to "ckpt_filename" */
+
+ /* We're not going to use tempnam(), because it sometimes
+ gives us a filename in /var/tmp, which is bad for rename() */
+
+ char *tempName = "mw_tmp_ckpt_file";
+
+ if ( ( cfp=fopen( tempName, "w" ) ) == NULL ) {
+ MWprintf ( 10, "Failed to open %s for writing! errno %d\n",
+ tempName, errno );
+ return;
+ }
+
+ MWprintf ( 50, "Beginning checkpoint()\n" );
+
+ // header
+ fprintf ( cfp, "MWDriver Checkpoint File. %ld\n", time(0) );
+
+ // some internal MWDriver state:
+ fprintf ( cfp, "%d %d %d %d\n%d %d %d %d %d %lf %d\n", task_counter,
+ checkpoint_frequency, checkpoint_time_freq,
+ num_completed_tasks,
+ (int)addmode, (int)getmode, (int)suspensionPolicy,
+ (int) machine_ordering_policy,
+ worker_timeout,worker_timeout_limit, worker_timeout_check_frequency);
+
+ if ( bench_task ) {
+ fprintf ( cfp, "1 " );
+ bench_task->write_ckpt_info ( cfp );
+ } else {
+ fprintf ( cfp, "0\n" );
+ }
+
+ MWprintf ( 80, "Wrote internal MWDriver state.\n" );
+
+ RMC->write_checkpoint( cfp );
+
+ MWprintf ( 80, "Wrote RMC state.\n" );
+
+ /* Yes, I really am passing it the list of workers... */
+ stats->write_checkpoint ( cfp, workers );
+
+ MWprintf ( 80, "Wrote the Worker stats.\n" );
+
+ // Write the user master's state:
+ write_master_state( cfp );
+
+ MWprintf ( 80, "Wrote the user master's state.\n" );
+
+ // write the number of work classes
+ fprintf ( cfp, "%d\n", MWworkClasses );
+
+ int tempnum = 0;
+ MWTask * ttt = running->First();
+ while ( running->AfterEnd() == false )
+ {
+ ttt = running->Current();
+ if ( ttt->taskType == MWNORMAL )
+ tempnum++;
+ running->Next();
+ }
+ int num_tasks = tempnum + todo->number();
+
+ // Tasks separator:
+ fprintf ( cfp, "Tasks: %d \n", num_tasks );
+
+ /* Write ordered todo before unsorted running tasks */
+ MWTask *t;
+
+ fprintf ( cfp, "TODO_num: %d \n", todo->number() );
+ t = todo->First();
+ while ( todo->AfterEnd() == false )
+ {
+ t = todo->Current();
+ fprintf ( cfp, "%d ", t->number );
+ t->write_ckpt_info( cfp );
+ t->write_group_info ( cfp );
+ todo->Next();
+ }
+
+ fprintf( cfp, "running_num: %d \n", running->number() );
+ t = running->First();
+ while ( running->AfterEnd() == false)
+ {
+ t = running->Current();
+ if ( t->taskType == MWNORMAL )
+ {
+ fprintf ( cfp, "%d ", t->number );
+ t->write_ckpt_info( cfp );
+ t->write_group_info ( cfp );
+ }
+ running->Next();
+ }
+
+ MWprintf ( 80, "Wrote task list.\n" );
+
+ fclose ( cfp );
+
+ /* Now we rename our temp file to the real thing. Atomicity! */
+ if ( rename( tempName, ckpt_filename ) == -1 ) {
+ MWprintf ( 10, "rename( %s, %s ) failed! errno %d.\n",
+ tempName, ckpt_filename, errno );
+ }
+
+ MWprintf ( 50, "Done checkpointing.\n" );
+}
+
+void
+MWDriver::restart_from_ckpt()
+{
+
+ int i;
+
+ FILE *cfp;
+ if ( ( cfp=fopen( ckpt_filename, "r" ) ) == NULL ) {
+ MWprintf ( 10, "Failed to open %s for reading! errno %d\n",
+ ckpt_filename, errno );
+ return;
+ }
+
+ char buf[128];
+ time_t then;
+ fscanf( cfp, "%s %s %s %ld", buf, buf, buf, &then );
+
+ MWprintf ( 10, "This checkpoint made on %s\n", ctime( &then ) );
+
+ fscanf( cfp, "%d %d %d %d", &task_counter,
+ &checkpoint_frequency, &checkpoint_time_freq,
+ &num_completed_tasks );
+
+ fscanf( cfp, "%d %d %d %d",
+ (int*) &addmode, (int*) &getmode, (int*) &suspensionPolicy,
+ (int*) &machine_ordering_policy );
+
+ int worker_timeout_int;
+ fscanf( cfp, "%d %lf %d", &worker_timeout_int,
+ &worker_timeout_limit, &worker_timeout_check_frequency);
+ worker_timeout_int ? worker_timeout = true : worker_timeout = false;
+
+ int hasbench = 0;
+ fscanf( cfp, "%d ", &hasbench );
+ if ( hasbench ) {
+ bench_task = gimme_a_task();
+ bench_task->read_ckpt_info( cfp );
+ MWprintf ( 10, "Got benchmark task:\n" );
+ bench_task->printself( 10 );
+ }
+
+ MWprintf ( 10, "Read internal MW info.\n" );
+
+ RMC->read_checkpoint( cfp );
+
+ MWprintf ( 10, "Read RMC state.\n" );
+
+ // read old stats
+ stats->read_checkpoint( cfp );
+
+ MWprintf ( 10, "Read defunct workers' stats.\n" );
+
+ read_master_state( cfp );
+
+ MWprintf ( 10, "Read the user master's state.\n" );
+
+ fscanf ( cfp, "%d", &MWworkClasses );
+ MWworkClassWorkers = new int[MWworkClasses];
+ MWworkClassTasks = new int[MWworkClasses];
+ MWcurrentWorker = NULL;
+ for ( i = 0; i < MWworkClasses; i++ )
+ {
+ MWworkClassWorkers[i] = 0;
+ MWworkClassTasks[i] = 0;
+ }
+
+ int num_tasks;
+ fscanf ( cfp, "%s %d", buf, &num_tasks );
+
+ if ( strcmp( buf, "Tasks:" ) ) {
+ MWprintf ( 10, "Problem in reading Tasks separator. buf = %s\n", buf );
+ fclose ( cfp );
+ return;
+ }
+
+ MWTask *t;
+
+ int num_todo;
+ fscanf( cfp, "%s %d", buf, &num_todo);
+ if ( strcmp( buf, "TODO_num:" ) ) {
+ MWprintf ( 10, "Problem in reading TODO_num separator. buf = %s\n", buf );
+ fclose( cfp );
+ return;
+ }
+
+ if (task_key != NULL) {
+ /* Add all tasks by key, if user has set it. */
+ set_task_add_mode( ADD_BY_KEY );
+ }
+ else {
+ set_task_add_mode( ADD_AT_END );
+ }
+
+ for ( i=0 ; i<num_todo ; i++ ) {
+ t = gimme_a_task(); // return a derived task class...
+ fscanf( cfp, "%d ", &(t->number) );
+ t->read_ckpt_info( cfp );
+ t->read_group_info ( cfp );
+ t->printself( 90 );
+ pushTask(t);
+ }
+
+ int num_running;
+ fscanf( cfp, "%s %d", buf, &num_running);
+ if ( strcmp( buf, "running_num:" ) ) {
+ MWprintf ( 10, "Problem in reading running_num separator. buf = %s\n", buf );
+ fclose( cfp );
+ return;
+ }
+
+ for ( i=0 ; i<num_running ; i++ )
+ {
+ t = gimme_a_task(); // return a derived task class...
+ fscanf( cfp, "%d ", &(t->number) );
+ t->read_ckpt_info( cfp );
+ t->read_group_info ( cfp );
+ t->printself( 90 );
+ pushTask(t);
+ }
+
+ MWprintf ( 10, "Read the task list.\n" );
+
+ // This is debugging code for Michael
+
+#if 1
+ if( task_key != NULL ) {
+ MWprintf( 10, "Sort the TODO task list...\n" );
+ sort_task_list();
+ MWprintf( 10, "Printing keys of user's task list...\n" );
+ print_task_keys();
+ }
+#endif
+ fclose( cfp );
+
+ FILE *swapfile;
+ if ( (swapfile = fopen(todo->Name(), "r")) == NULL ) {
+ MWprintf(90, "Task_Swap:: No task swap file exists, has_task_swapped = false.\n");
+ has_task_swapped = false;
+ } else {
+ fclose(swapfile);
+ }
+
+ /* Task_Swap testing code */
+ if (todo->Number() > MAX_IN_MEM) {
+ swap_out_todo_tasks();
+ checkpoint();
+ }
+
+ MWprintf ( 10, "We are done restarting.\n" );
+}
+
+/* Read/write task */
+MWTask*
+MWDriver::read_mem_task(MWList<MWTask> *tasks)
+{
+ if (tasks->AfterEnd())
+ return NULL;
+
+ MWTask * t = tasks->RemoveCurrent();
+ todo->Next();
+ return t;
+}
+
+MWTask*
+MWDriver::read_file_task(FILE *f)
+{
+ char strbuf[128];
+
+ fscanf(f, "%s ", strbuf);
+ if (strcmp(strbuf, "~~Task~~")) {
+ MWprintf(10, "Problem in reading ~~Task~~ separator, buf=%s\n", strbuf);
+ return NULL;
+ }
+
+ MWTask *t = gimme_a_task();
+ fscanf(f, "%d ", &(t->number));
+ t->read_ckpt_info(f);
+ t->read_group_info(f);
+ MWprintf(90, "Read task %d\n", t->number);
+ return t;
+}
+
+void
+MWDriver::write_task(FILE *f, MWTask *t)
+{
+ fprintf(f, "%s \n", "~~Task~~");
+ fprintf(f, "%d \n", t->number);
+ t->write_ckpt_info(f);
+ t->write_group_info(f);
+ MWprintf(90, "Written task %d\n", t->number);
+}
+
+/* Remember to update (1) how to check whether we are done;
+ * (2) give each list a "name", so that they can be dumped into
+ * a file; (3) change remove_tasks_worse_than() to update the
+ * max_task_key value; (4) add logic to trigger the swapping */
+
+/** TODO Tasks Swapping **/
+bool
+MWDriver::swap_out_todo_tasks(int num_in_mem, int max_in_mem, double max_key)
+{
+ char strbuf[128];
+ MWTask *mem_t = NULL, *file_t = NULL;
+ double mem_key = -DBL_MAX, file_key = -DBL_MAX;
+ FILE *swap, *new_swap;
+ int num_swapped, num_to_skip, num_file_task=0, num_total;
+
+ if ( (task_key == NULL)||(todo->isSorted()==false) ) {
+ MWprintf(10, "Task_Swap:: No task_key func defined for the list.\n");
+ MWprintf(10, "Task_Swap:: I won't swap these tasks are not sorted.\n");
+ return false;
+ }
+
+ if (todo->number() < max_in_mem)
+ return true;
+ if (todo->number() < num_in_mem) /* just in case :=) */
+ return true;
+
+ /* Skip the first num_in_mem tasks */
+ mem_t = todo->First();
+ for (int i=0; i<num_in_mem; i++)
+ todo->Next();
+
+ FILE *swapfile;
+ if ( (swapfile = fopen(todo->Name(), "r")) == NULL) {
+ MWprintf(10, "Task_Swap:: No existing swap file, dump memory directly into the file.\n");
+
+ /* Create the swap file for the first time */
+ swap = Open(todo->Name(), "a");
+ if (swap == NULL) {
+ MWprintf(10, "Task_Swap:: Can't create swap file.\n");
+ return false;
+ }
+
+ /* As will rebuild index, we ClearIndex() first */
+ todo->ClearIndex();
+
+ /* First write the num_to_skip to 0 */
+ fprintf(swap, "num_to_skip %10d\n", 0);
+ fprintf(swap, "num_of_file_task %10d\n", todo->number()-num_in_mem);
+
+ /* Remove tasks until we only have num_in_mem in list */
+ num_swapped = 0;
+ while ( (mem_t=read_mem_task(todo)) != NULL ) {
+ write_task(swap, mem_t);
+ delete mem_t;
+ num_swapped ++;
+ }
+ fflush(swap);
+ Close(swap);
+
+ /* rebuild index for todo */
+ todo->BuildIndex();
+
+ /* Remember that we have tasks swapped out */
+ has_task_swapped = true;
+
+ MWprintf(10, "Task_Swap:: Done swapping, swapped out %d tasks, keep %d tasks in memory.\n",
+ num_swapped, todo->number());
+ } else {
+
+ MWprintf(10, "Task_Swap:: Will merge tasks in memory with those in file.\n");
+
+ fclose(swapfile);
+ /* As will rebuild index, we ClearIndex() first */
+ todo->ClearIndex();
+
+ /* Create new temp file */
+ new_swap = Open("tmp_TODO_swap", "w");
+ if (new_swap == NULL) {
+ MWprintf(10, "Task_Swap:: Can't create tmp swap file.\n");
+ return false;
+ }
+
+ fprintf(new_swap, "num_to_skip %10d\n", 0);
+ fprintf(new_swap, "num_of_file_task %10d\n", 0);
+
+ /* Open the swap file, read num_to_skip */
+ swap = Open(todo->Name(), "r");
+ if (swap == NULL) {
+ MWprintf(10, "Task_Swap:: Can't open swap file to read.\n");
+ return false;
+ }
+
+ fscanf(swap, "%s %10d", strbuf, &num_to_skip);
+ if ( strcmp(strbuf, "num_to_skip") ) {
+ MWprintf(10, "Task_Swap:: problem in reading num_to_skip marker.\n");
+ Close(swap);
+ return false;
+ }
+
+ /* Read num_of_file_task */
+ fscanf(swap, "%s %10d", strbuf, &num_file_task);
+ if ( strcmp(strbuf, "num_of_file_task") ) {
+ MWprintf(10, "Task_Swap:: problem in reading num_of_file_task marker.\n");
+ Close(swap);
+ return false;
+ }
+
+ /* Skip tasks at the beginning */
+ for (int i=0; i<num_to_skip; i++) {
+ file_t = read_file_task(swap);
+ if (file_t != NULL)
+ delete file_t;
+ }
+
+ if ( (mem_t = read_mem_task(todo)) != NULL ) {
+ mem_key = (*task_key)(mem_t);
+ }
+
+ if ( (file_t = read_file_task(swap)) != NULL ) {
+ file_key = (*task_key)(file_t);
+ num_file_task --;
+ }
+
+ /* Begin merging the rest of the file and the rest of the list */
+ num_total = 0;
+ while ( mem_t && file_t ) /* while both valid */ {
+ if (mem_key <= file_key) {
+ /* dump current mem_t */
+ if (mem_key < max_task_key) {
+ write_task(new_swap, mem_t);
+ num_total ++;
+ }
+ delete mem_t;
+ if ( (mem_t = read_mem_task(todo)) != NULL ) {
+ mem_key = (*task_key)(mem_t);
+ }
+ } else {
+ /* dump current file_t */
+ if (file_key < max_task_key) {
+ write_task(new_swap, file_t);
+ num_total ++;
+ }
+ delete file_t;
+
+ if (num_file_task > 0) {
+ if ( (file_t = read_file_task(swap) ) != NULL ) {
+ file_key = (*task_key)(file_t);
+ num_file_task --;
+ }
+ } else file_t = NULL;
+ }
+ }
+
+ /* dump the remaining */
+ if ((mem_t != NULL)) {
+ write_task(new_swap, mem_t);
+ num_total ++;
+ delete mem_t;
+
+ while ( (mem_t = read_mem_task(todo)) != NULL ) {
+ mem_key = (*task_key)(mem_t);
+ if (mem_key < max_task_key) {
+ write_task(new_swap, mem_t);
+ num_total ++;
+ }
+ delete mem_t;
+ }
+ } else if (file_t != NULL) {
+ write_task(new_swap, file_t);
+ num_total ++;
+ delete file_t;
+
+ while ( num_file_task > 0) {
+ if ( (file_t = read_file_task(swap)) != NULL ) {
+ file_key = (*task_key)(file_t);
+ if (file_key < max_task_key) {
+ write_task(new_swap, file_t);
+ num_total ++;
+ }
+ delete file_t;
+ }
+ num_file_task --;
+ }
+ } else {
+ MWprintf(10, "Task_Swap:: Write task error, either mem_t or file_t should be NULL.\n");
+ }
+
+ MWprintf(10, " num_file_task now is %d\n", num_file_task);
+ Close(swap);
+
+ fflush(new_swap);
+ Close(new_swap);
+
+ /* Update header info */
+ new_swap = Open("tmp_TODO_swap", "r+");
+ if (new_swap == NULL) {
+ MWprintf(10, "Task_Swap:: Can't open swap file to read.\n");
+ return false;
+ }
+
+ fprintf(new_swap, "num_to_skip %10d\n", 0);
+ fprintf(new_swap, "num_of_file_task %10d\n", num_total);
+ fflush(new_swap);
+ Close(new_swap);
+
+ /* Swith the files */
+ char cmd[1024];
+ sprintf(cmd, "mv %s old_TODO_tasks", todo->Name());
+ if (system(cmd) < 0) {
+ MWprintf(10, "Task_Swap:: Can't rename the old swap file, errno = %d.\n", errno);
+ return false;
+ }
+
+ sprintf(cmd, "mv -f tmp_TODO_swap %s", todo->Name());
+ if (system(cmd) < 0) {
+ MWprintf(10, "Task_Swap:: Can't rename the new swap file, errno = %d.\n", errno);
+ return false;
+ }
+
+ remove("old_TODO_tasks");
+
+ /* rebuild index for todo */
+ todo->BuildIndex();
+
+ /* Remember that we have tasks swapped out */
+ has_task_swapped = true;
+
+ /* Print some trash */
+ MWprintf(10, "Task_Swap:: Done swapping, swapped out %d tasks, keep %d tasks in memory.\n",
+ num_total, todo->number());
+ }
+
+ /* Keep a snapshot */
+ checkpoint();
+ return true;
+}
+
+bool
+MWDriver::swap_in_todo_tasks(int min_in_mem, int num_in_mem)
+{
+ char strbuf[128];
+ MWTask *file_t = NULL, * mem_t = NULL;
+ MWList<MWTask> * todo_new, * todo_old;
+ FILE *swap;
+ int num_swapped, num_to_skip, num_file_task = 0;
+
+ if ( (todo->number() > num_in_mem) )
+ return true;
+
+ FILE *swapfp;
+ if ( (swapfp = fopen(todo->Name(), "r")) == NULL) {
+ MWprintf(90, "Task_Swap:: No task swap file exists, will not swap in.\n");
+ has_task_swapped = false;
+ return true;
+ }
+
+ fclose(swapfp);
+ /* Now need to bring more task on disk into mem */
+ /* Open the swap file, read num_to_skip */
+ swap = Open(todo->Name(), "r+");
+ if (swap == NULL) {
+ MWprintf(10, "Task_Swap:: Can't open swap file to read.\n");
+ return false;
+ }
+
+ fscanf(swap, "%s %10d", strbuf, &num_to_skip);
+ if ( strcmp(strbuf, "num_to_skip") ) {
+ MWprintf(10, "Task_Swap:: problem in reading num_to_skip marker.\n");
+ Close(swap);
+ return false;
+ }
+
+ /* Read num_of_file_task */
+ fscanf(swap, "%s %10d", strbuf, &num_file_task);
+ if ( strcmp(strbuf, "num_of_file_task") ) {
+ MWprintf(10, "Task_Swap:: problem in reading num_of_file_task marker.\n");
+ Close(swap);
+ return false;
+ }
+
+ /* Skip tasks at the beginning */
+ file_t = gimme_a_task();
+ if (file_t == NULL) {
+ MWprintf(10, "Task_Swap:: Can't allocate a task.\n");
+ return false;
+ }
+
+ /* Skip some tasks */
+ for (int i=0; i<num_to_skip; i++) {
+ file_t = read_file_task(swap);
+ if (file_t != NULL)
+ delete file_t;
+ }
+
+ /* Now begin read into mem */
+ todo_new = new MWList<MWTask>("TODO_tasks");
+ if (todo_new == NULL) {
+ MWprintf(10, "Task_Swap:: Can't allocate a new task list.\n");
+ Close(swap);
+ return false;
+ }
+
+ num_swapped = (num_in_mem < num_file_task) ? num_in_mem : num_file_task;
+ for (int ii=0; ii<num_swapped; ii++)
+ if ( (file_t = read_file_task(swap)) != NULL )
+ todo_new->SortedInsert(file_t, (*task_key)(file_t));
+
+ /* Update header info */
+ if (num_swapped == num_file_task) { /* No task on disk then */
+ Close(swap);
+ remove(todo->Name());
+ has_task_swapped = false;
+ } else {
+ if (fseek(swap, 0L, SEEK_SET) == -1) {
+ MWprintf(10, "Task_Swap:: Can update header_info in the swap file, errno = %d.\n", errno);
+ return false;
+ }
+
+ fprintf(swap, "num_to_skip %10d\n", num_to_skip + num_swapped);
+ fprintf(swap, "num_of_file_task %10d\n", num_file_task-num_swapped);
+ fflush(swap);
+
+ /* Close new swap file and switch */
+ Close(swap);
+ }
+
+ /* Sorted insert old tasks into new todo list */
+ todo->First();
+ while ( (mem_t = read_mem_task(todo))!=NULL ) {
+ todo_new->SortedInsert(mem_t, (*task_key)(mem_t));
+ }
+
+ todo_old = todo;
+ delete todo_old;
+ todo = todo_new;
+
+ MWprintf(10, "Task_Swap:: done swap in, moved %d tasks into memory. num_todo = %d.\n",
+ num_swapped, todo->Number());
+
+ /* Keep a snapshot */
+ checkpoint();
+ return true;
+}
+
+bool
+MWDriver::is_TODO_empty()
+{
+ if (todo->number() > 0)
+ return false;
+
+ if (has_task_swapped)
+ return false;
+
+ return true;
+}
+
+int /* Added as in $GAMS */
+MWDriver::sort_task_list ( )
+{
+ /* check and only sort the list when listsorted is FALSE */
+ if ( (task_key == NULL) || (listsorted) )
+ return 0;
+
+ MWList<MWTask> * newList = new MWList<MWTask>;
+ while ( todo->number() > 0 )
+ {
+ MWTask *t = (MWTask *)todo->Remove();
+ newList->SortedInsert ( t, (*task_key)(t) );
+ }
+ delete todo;
+
+ todo = newList;
+
+ /* reset listsorted as TRUE */
+ listsorted = true;
+ return 0;
+}
+
+
+int
+MWDriver::get_number_tasks()
+{
+ return todo->number();
+}
+
+int MWDriver::get_number_running_tasks()
+{
+ return running->number();
+}
+
+void
+MWDriver::workClasses_set ( int num )
+{
+ if ( num < 1 )
+ {
+ MWprintf ( 10, "Use of workClasses_set with <= 1 classes not allowed\n");
+ assert ( 0 );
+ }
+ MWworkClasses = num;
+ MWworkClassWorkers = new int[MWworkClasses];
+ MWworkClassTasks = new int[MWworkClasses];
+
+ for ( int i = 0; i < MWworkClasses; i++ )
+ {
+ MWworkClassWorkers[i] = 0;
+ MWworkClassTasks[i] = 0;
+ }
+}
+
+int
+MWDriver::workClasses_get ( )
+{
+ return MWworkClasses;
+}
+
+int
+MWDriver::workClasses_getworkers ( int num )
+{
+ return MWworkClassWorkers[num];
+}
+
+int
+MWDriver::workClasses_gettasks ( int num )
+{
+ return MWworkClassTasks[num];
+}
+
+
+/* 8/28/00
+
+Qun added Jeff's idea of adding a SORTED list of tasks.
+This can greatly improve the efficiency in many applications.
+
+XXX I haven't debugged this, and probably there needs to be more
+checking that the list is actually sorted.
+*/
+
+/* added by Qun: for insert a list of sorted tasks */
+
+void
+MWDriver::addSortedTasks( int n, MWTask **add_tasks )
+{
+ if ( n <= 0 ) {
+ MWprintf ( 10, "Please add a positive number of tasks!\n" );
+ RMC->exit(1);
+ }
+
+ for ( int i = 0; i < n; i++ )
+ {
+ add_tasks[i]->number = task_counter++;
+ if ( MWworkClasses <= 1 )
+ {
+ add_tasks[i]->initGroups ( MWworkClasses );
+ add_tasks[i]->addGroup ( 0 );
+ }
+ pushTask ( add_tasks[i] );
+ }
+}
+
+
+void
+MWDriver::addTaskByKey( MWTask *add_task )
+{
+ add_task->number = task_counter++;
+ if ( MWworkClasses <= 1 )
+ {
+ add_task->initGroups ( MWworkClasses );
+ add_task->addGroup ( 0 );
+ }
+ if ( task_key == NULL )
+ {
+ MWprintf ( 10, "ERROR! Adding by key, but no key "
+ "function defined!\n" );
+ assert(0);
+ }
+ todo->SortedInsert ( add_task, (*task_key)(add_task) );
+}
+
+//end the changes done by Qun
+
+extern MWWorker *gimme_a_worker ();
+
+void
+MWDriver::ControlPanel ( )
+{
+
+#ifdef INDEPENDENT
+ MWReturn ustat = OK;
+ RMC->hostadd ();
+ master_mainloop_oneshot ( 0, 2 );
+ MWWorker *worker = gimme_a_worker();
+ worker->go( 1, NULL );
+ master_mainloop_oneshot ( 0, 2 );
+ worker->do_benchmark_cmd( );
+ ustat = master_mainloop_oneshot ( 0, 2 );
+
+ // while ( ( (todo != NULL) || (running != NULL) ) && ( ustat == OK ) )
+ while ( ( (!todo->isEmpty()) || (!running->isEmpty()) ) && ( ustat == OK ) )
+ {
+ ustat = worker->worker_mainloop_oneshot ( );
+ ustat = master_mainloop_oneshot ( 0, 2 );
+ }
+
+ MWprintf(71, "\n\n\n ***** Almost done ***** \n\n\n\n");
+
+ // found LEAK_SCOPE! need to deallocate worker
+ delete worker;
+#endif
+ return;
+}
+
+
+MWKey
+kflops( MWWorkerID *w )
+{
+ return (MWKey) w->KFlops;
+}
+
+MWKey
+benchmark_result( MWWorkerID *w )
+{
+ return (MWKey) w->get_bench_result();
+}
+
+// These are functions that might be useful, but I am not sure if they should
+// be included in the final release.
+
+double
+MWDriver::get_instant_pool_perf( )
+{
+ double total_perf = 0;
+ int total = 0;
+ MWWorkerID *w;
+
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+ if ( (w->currentState() == WORKING) && (w->runningtask != NULL) )
+ {
+ total_perf += w->get_bench_result();
+ }
+ workers->Append ( w );
+ }
+ return total_perf;
+}
+
+MWTask*
+MWDriver::get_todo_head ( )
+{
+ MWTask *t = (MWTask *)todo->Remove();
+ todo->Prepend ( t );
+ return t;
+}
+
+MWWorkerID*
+MWDriver::get_workers_head ( )
+{
+ MWWorkerID *w = (MWWorkerID *)workers->Remove();
+ workers->Prepend ( w );
+ return w;
+}
+
+
+#if defined( XML_OUTPUT )
+
+void MWDriver::write_XML_status()
+{
+ ofstream xmlfile("/u/m/e/metaneos/public/html/iMW/status.xml",
+ ios::trunc|ios::out);
+
+
+ if( ! xmlfile ) {
+ cerr << "Cannot open 'status.xml data file' file!\n";
+ }
+
+ //system("/bin/rm -f ~/public/html/iMW/status.xml");
+ //system("/bin/mv -f ./status.xml ~/public/html/iMW/");
+
+ // system("/bin/more status.xml");
+
+ char *temp_ptr ;
+ temp_ptr = get_XML_status();
+
+ xmlfile << temp_ptr;
+ delete temp_ptr;
+
+ // xmlfile << ends;
+
+ xmlfile.close();
+
+ //system("/bin/rm -f ~/public/html/iMW/status.xml");
+ //system("/bin/cp -f status.xml /u/m/e/metaneos/public/html/iMW/");
+ // system("/bin/cp -f status.xml ~metaneos/public/html/iMW/");
+}
+
+#include <strstream.h>
+
+char* MWDriver::get_XML_status(){
+
+ ifstream menus(xml_menus_filename);
+
+ ostrstream xmlstr;
+
+ xmlstr << "<?xml version=\"1.0\"?>" << endl;
+ xmlstr << "<?xml:stylesheet type=\"text/xsl\" href=\"menus-QAP.xsl\"?>" << endl;
+ xmlstr << "<INTERFACE TYPE=\"iMW-QAP\">" << endl;
+
+ // xmlstr << menus;
+
+ char ch;
+ while (menus.get(ch)) xmlstr.put(ch);
+
+ // menus >> xmlstr ;
+
+ xmlstr << "<MWOutput TYPE=\"QAP\">" << endl;
+
+ char *temp_ptr ;
+
+ temp_ptr = get_XML_job_information();
+
+ xmlstr << temp_ptr;
+ delete temp_ptr;
+
+ temp_ptr = get_XML_problem_description();
+
+ xmlstr << temp_ptr;
+ delete temp_ptr;
+
+ temp_ptr = get_XML_interface_remote_files();
+
+ xmlstr << temp_ptr;
+ delete temp_ptr;
+
+ temp_ptr = get_XML_resources_status();
+
+ xmlstr << temp_ptr;
+ delete temp_ptr;
+
+ temp_ptr = get_XML_results_status();
+
+ xmlstr << temp_ptr;
+ delete temp_ptr;
+
+ xmlstr << "</MWOutput>" << endl;
+ xmlstr << "</INTERFACE>" << endl;
+
+ xmlstr << ends;
+
+
+
+ menus.close();
+
+
+ return xmlstr.str();
+
+}
+
+char* MWDriver::get_XML_job_information()
+{
+
+ ifstream jobinfo(xml_jobinfo_filename);
+
+ ostrstream xmlstr;
+
+ char ch;
+ while (jobinfo.get(ch)) xmlstr.put(ch);
+
+ xmlstr << ends;
+
+ jobinfo.close();
+
+
+ return xmlstr.str();
+
+};
+
+char* MWDriver::get_XML_problem_description(){
+
+ ifstream pbdescrib(xml_pbdescrib_filename);
+
+ ostrstream xmlstr;
+
+ char ch;
+ while (pbdescrib.get(ch)) xmlstr.put(ch);
+
+ xmlstr << ends;
+
+ pbdescrib.close();
+
+
+ return xmlstr.str();
+
+};
+
+char* MWDriver::get_XML_interface_remote_files(){
+
+ ostrstream xmlstr;
+
+ xmlstr << "<InterfaceRemoteFiles>" << endl;
+
+ // dump here content of file
+
+ xmlstr << "</InterfaceRemoteFiles>" << endl;
+
+ xmlstr << ends;
+
+ return xmlstr.str();
+
+}
+
+
+char* MWDriver::get_XML_resources_status()
+{
+
+ int total;
+ int i;
+ ostrstream xmlstr;
+
+ // Begin XML string
+
+ xmlstr << "<ResourcesStatus>" << endl;
+
+ double average_bench;
+ double equivalent_bench;
+ double min_bench;
+ double max_bench;
+ double av_present_workers;
+ double av_nonsusp_workers;
+ double av_active_workers;
+ double equi_pool_performance;
+ double equi_run_time;
+ double parallel_performance;
+ double wall_time;
+
+ stats->get_stats(&average_bench,
+ &equivalent_bench,
+ &min_bench,
+ &max_bench,
+ &av_present_workers,
+ &av_nonsusp_workers,
+ &av_active_workers,
+ &equi_pool_performance,
+ &equi_run_time,
+ ¶llel_performance,
+ &wall_time,
+ workers
+ );
+
+ // MWStats Information
+
+ xmlstr << "<MWStats>" << endl;
+
+ xmlstr << "<WallClockTime>" << wall_time << "</WallClockTime>" << endl;
+ xmlstr << "<NormalizedTotalCPU>" << equi_run_time << "</NormalizedTotalCPU>" << endl;
+ xmlstr << "<ParallelEff>" << parallel_performance << "</ParallelEff>" << endl;
+
+ xmlstr << "<BenchInfo>" << endl;
+ xmlstr << "<InstantPoolPerf>" << get_instant_pool_perf() << "</InstantPoolPerf>" << endl;
+ xmlstr << "<EquivalentPoolPerf>" << equi_pool_performance << "</EquivalentPoolPerf>" << endl;
+ xmlstr << "<AverageBench>" << average_bench << "</AverageBench>" << endl;
+ xmlstr << "<EquivalentBench>" << equivalent_bench << "</EquivalentBench>" << endl;
+ xmlstr << "<MinBench>" << min_bench << "</MinBench>" << endl;
+ xmlstr << "<MaxBench>" << max_bench << "</MaxBench>" << endl;
+ xmlstr << "</BenchInfo>" << endl;
+
+ xmlstr << "<AverageWorkersStats>" << endl;
+ xmlstr << "<AveragePresentWorkers>" << av_present_workers << "</AveragePresentWorkers>" << endl;
+ xmlstr << "<AverageNonSuspWorkers>" << av_nonsusp_workers << "</AverageNonSuspWorkers>" << endl;
+ xmlstr << "<AverageActiveWorkers>" << av_nonsusp_workers << "</AverageActiveWorkers>" << endl;
+ xmlstr << "</AverageWorkersStats>" << endl;
+
+
+ xmlstr << "</MWStats>" << endl;
+
+ // Master Information
+
+ xmlstr << "<Master>" << endl;
+
+ xmlstr << "<MasterPhysicalProperties>" << endl;
+ xmlstr << "<Name>" << mach_name << "</Name>" << endl;
+ // xmlstr << "<IPAddress>" << get_IPAddress() << "</IPAddress>" << endl;
+ xmlstr << "<OpSys>" << get_OpSys() << "</OpSys>" << endl;
+ xmlstr << "<Arch>" << get_Arch() <<"</Arch>" << endl;
+ xmlstr << "<Memory>" << get_Memory() << "</Memory>" << endl;
+ xmlstr << "<VirtualMemory>" << get_VirtualMemory() << "</VirtualMemory>" << endl;
+ xmlstr << "<DiskSpace>" << get_Disk() << "</DiskSpace>" << endl;
+ xmlstr << "<KFlops>" << get_KFlops() << "</KFlops>" << endl;
+ xmlstr << "<Mips>" << get_Mips() << "</Mips>" << endl;
+ xmlstr << "<CPUs>" << get_Cpus() << "</CPUs>" << endl;
+ xmlstr << "<NWSinfos/>" << endl;
+ xmlstr << "</MasterPhysicalProperties>" << endl;
+
+
+
+ xmlstr << "<MasterUsageProperties>" << endl;
+ xmlstr << "<StartTime>July 1st 1999, 18:21:12s GMT</StartTime>" << endl;
+ xmlstr << "</MasterUsageProperties>" << endl;
+
+ xmlstr << "</Master>" << endl;
+
+ // Worker Information
+
+ xmlstr << "<Workers>" << endl;
+
+ int numworkers = numWorkersInState( INITIALIZING ) + numWorkersInState( BENCHMARKING ) + numWorkersInState( IDLE ) + numWorkersInState( WORKING ) ;
+
+ xmlstr << "<WorkersNumber>" << numworkers << "</WorkersNumber>" << endl;
+
+ xmlstr << "<WorkersStats>" << endl;
+
+ xmlstr << "<WorkersInitializing>" << numWorkersInState( INITIALIZING ) << "</WorkersInitializing>" << endl;
+ xmlstr << "<WorkersBenchMarking>" << numWorkersInState( BENCHMARKING ) << "</WorkersBenchMarking>" << endl;
+ xmlstr << "<WorkersWaiting>" << numWorkersInState( IDLE ) << "</WorkersWaiting>" << endl;
+ xmlstr << "<WorkersWorking>" << numWorkersInState( WORKING ) << "</WorkersWorking>" << endl;
+ xmlstr << "<WorkersSuspended>" << numWorkersInState( SUSPENDED ) << "</WorkersSuspended>" << endl;
+ xmlstr << "<WorkersDone>" << numWorkersInState( EXITED ) << "</WorkersDone>" << endl;
+
+ xmlstr << "</WorkersStats>" << endl;
+
+ xmlstr << "<WorkersList>" << endl;
+
+ total = 0;
+ MWWorkerID *w;
+
+ while ( total < workers->number() )
+ {
+ total++;
+ w = (MWWorkerID *)workers->Remove();
+
+ if ((w->currentState() != SUSPENDED) || (w->currentState() != EXITED))
+ {
+
+ xmlstr << "<Worker>" << endl;
+
+ xmlstr << "<WorkerPhysicalProperties>" << endl;
+
+ xmlstr << "<Name>" << w->machine_name() << "</Name>" << endl;
+ // xmlstr << "<IPAddress>" << w->get_IPAddress() << "</IPAddress>" << endl;
+ xmlstr << "<Status>" << MWworker_statenames[w->currentState()] << "</Status>" << endl;
+ xmlstr << "<OpSys>" << w->OpSys << "</OpSys>" << endl;
+ xmlstr << "<Arch>" << w->Arch << "</Arch>" << endl;
+ xmlstr << "<Bandwidth>" << "N/A" << "</Bandwidth>" << endl;
+ xmlstr << "<Latency>" << "N/A" << "</Latency>" << endl;
+ xmlstr << "<Memory>" << w->Memory << "</Memory>" << endl;
+ xmlstr << "<VirtualMemory>" << w->VirtualMemory << "</VirtualMemory>" << endl;
+ xmlstr << "<DiskSpace>" << w->Disk << "</DiskSpace>" << endl;
+ xmlstr << "<BenchResult>" << w->get_bench_result() <<"</BenchResult>" << endl;
+ xmlstr << "<KFlops>" << w->KFlops <<"</KFlops>" << endl;
+ xmlstr << "<Mips>" << w->Mips <<"</Mips>" << endl;
+ xmlstr << "<CPUs>" << w->Cpus <<"</CPUs>" << endl;
+ xmlstr << "<NWSinfos>" << "N/A" << "</NWSinfos>" << endl;
+
+ xmlstr << "</WorkerPhysicalProperties>" << endl;
+
+ xmlstr << "<WorkerUsageProperties>" << endl;
+
+ xmlstr << "<TotalTime>" << "N/A" << "</TotalTime>" << endl;
+ xmlstr << "<TotalWorking>" << w->get_total_working() << "</TotalWorking>" << endl;
+ xmlstr << "<TotalSuspended>" << w->get_total_suspended() << "</TotalSuspended>" << endl;
+
+ xmlstr << "</WorkerUsageProperties>" << endl;
+
+ xmlstr << "</Worker>" << endl;
+ }
+ workers->Append ( w );
+ }
+
+ xmlstr << "</WorkersList>" << endl;
+
+ xmlstr << "</Workers>" << endl;
+
+ // Global Worker Statistics
+
+ xmlstr << "<GlobalStats>" << endl;
+
+
+
+ xmlstr << "</GlobalStats>" << endl;
+
+ // Task Pool Information
+
+
+ xmlstr << "<TaskPoolInfos>" << endl;
+
+ int nrt = get_number_running_tasks();
+ int tt = get_number_tasks();
+ int tdt = tt - nrt;
+
+ xmlstr << "<TotalTasks>" << tt << "</TotalTasks>" << endl;
+ xmlstr << "<TodoTasks>" << tdt << "</TodoTasks>" << endl;
+ xmlstr << "<RunningTasks>" << nrt << "</RunningTasks>" << endl;
+ xmlstr << "<NumberCompletedTasks>" << num_completed_tasks << "</NumberCompletedTasks>" << endl;
+ //xmlstr << "<MaxNumberTasks>" << max_number_tasks << "</MaxNumberTasks>" << endl;
+ xmlstr << "</TaskPoolInfos>" << endl;
+
+ // Memory Info
+
+ // Secondary storage info
+
+
+ // End XML string
+
+ xmlstr << "</ResourcesStatus>" << endl;
+ xmlstr << ends ;
+
+ return xmlstr.str();
+
+}
+
+char* MWDriver::get_XML_results_status(){
+
+ ostrstream xmlstr;
+
+ xmlstr << "<ResultsStatus>" << endl;
+ xmlstr << "</ResultsStatus>" << endl;
+
+ xmlstr << ends;
+
+ return xmlstr.str();
+
+}
+
+/* The following (until the end of the file) was written by one of
+ Jean-Pierre's students. It isn't exactly efficient, dumping
+ a condor_status output to a file and reading from that. I understand
+ that it does work, however. -MEY (8-18-99) */
+
+/* UPDATE: Note that it doesn't work for flocked machines - GGT 9/26/06 */
+
+int MWDriver::check_for_int_val(char* name, char* key, char* value) {
+ if (strcmp(name, key) == 0)
+ return atoi(value);
+ else return NO_VAL;
+}
+
+double MWDriver::check_for_float_val(char* name, char* key, char* value) {
+ if (strcmp(name, key) == 0)
+ return atof(value);
+ else return NO_VAL;
+}
+
+int MWDriver::check_for_string_val(char* name, char* key, char* value) {
+ if (strcmp(name, key) == 0)
+ return 0;
+ else return NO_VAL;
+}
+
+
+void MWDriver::get_machine_info()
+{
+ FILE* inputfile;
+ char filename[50];
+ char key[200];
+ char value[1300];
+ char raw_line[1500];
+ char* equal_pos;
+ int found;
+ char temp_str[256];
+
+ char zero_string[2];
+
+ memset(zero_string, 0 , sizeof(zero_string));
+
+ memset(filename, '\0', sizeof(filename));
+ memset(key, '\0', sizeof(key));
+ memset(value, '\0', sizeof(value));
+
+ strcpy(filename, "/tmp/metaneos_file2");
+
+ memset(temp_str, '\0', sizeof(temp_str));
+ sprintf(temp_str, "%s/bin/condor_status -l %s > %s", CONDOR_DIR, mach_name, filename);
+
+ if (system(temp_str) < 0)
+ {
+
+ MWprintf( 10, "Error occurred during attempt to get condor_status for %s.\n", mach_name );
+ return;
+ }
+
+ if ((inputfile = fopen(filename, "r")) == 0)
+ {
+ MWprintf( 10, "Failed to open condor_status file!\n");
+ return;
+ }
+ else
+ {
+ MWprintf( 90, "Successfully opened condor_status file.\n");
+ }
+
+ while (fgets(raw_line, 1500, inputfile) != 0)
+ {
+ found = 0;
+ equal_pos = strchr(raw_line, '=');
+
+ if (equal_pos != NULL)
+ {
+ strncpy(key, raw_line, equal_pos - (raw_line+1));
+ strcpy(value, equal_pos+2);
+
+ if (CondorLoadAvg == NO_VAL && !found)
+ {
+ CondorLoadAvg = check_for_float_val("CondorLoadAvg", key, value);
+ if (CondorLoadAvg != NO_VAL)
+ found = 1;
+ }
+
+ if (LoadAvg == NO_VAL && !found)
+ {
+ LoadAvg = check_for_float_val("LoadAvg", key, value);
+ if (LoadAvg != NO_VAL)
+ found = 1;
+ }
+
+ if (Memory == NO_VAL && !found)
+ {
+ Memory = check_for_int_val("Memory", key, value);
+ if (Memory != NO_VAL)
+ found = 1;
+ }
+
+ if (Cpus == NO_VAL && !found)
+ {
+ Cpus = check_for_int_val("Cpus", key, value);
+ if (Cpus != NO_VAL)
+ found = 1;
+ }
+
+ if (VirtualMemory == NO_VAL && !found)
+ {
+ VirtualMemory = check_for_int_val("VirtualMemory", key, value);
+ if (VirtualMemory != NO_VAL)
+ found = 1;
+ }
+
+ if (Disk == NO_VAL && !found)
+ {
+ Disk = check_for_int_val("Disk", key, value);
+ if (Disk != NO_VAL)
+ found = 1;
+ }
+
+ if (KFlops == NO_VAL && !found)
+ {
+ KFlops = check_for_int_val("KFlops", key, value);
+ if (KFlops != NO_VAL)
+ found = 1;
+ }
+
+ if (Mips == NO_VAL && !found)
+ {
+ Mips = check_for_int_val("Mips", key, value);
+ if (Mips != NO_VAL)
+ found = 1;
+ }
+
+
+ if ( (strncmp(Arch, zero_string, 1) == 0) && !found)
+ {
+ if (check_for_string_val("Arch", key, value) == 0){
+ strncpy( Arch, value, sizeof(Arch) );
+ }
+
+ if (strncmp(Arch, zero_string, 1) != 0)
+ found = 1;
+ }
+
+ if ( (strncmp(OpSys, zero_string, 1) == 0) && !found)
+ {
+ if (check_for_string_val("OpSys", key, value) == 0){
+ strncpy( OpSys, value, sizeof(OpSys) );
+ }
+
+ if (strncmp(OpSys, zero_string, 1) != 0)
+ found = 1;
+ }
+
+ if ( (strncmp(IPAddress, zero_string, 1) == 0) && !found)
+ {
+ if (check_for_string_val("StartdIpAddr", key, value) == 0){
+ strncpy(IPAddress , value, sizeof(IPAddress) );
+ }
+
+ if (strncmp(IPAddress, zero_string, 1) != 0)
+ found = 1;
+ }
+
+
+ memset(key, '\0', sizeof(key));
+ memset(value, '\0', sizeof(value));
+
+ }
+
+ }
+
+ MWprintf(90,"CURRENT MACHINE : %s \n", mach_name);
+ MWprintf(90,"Architecture : %s \n", Arch);
+ MWprintf(90,"Operating System : %s \n", OpSys);
+ MWprintf(90,"IP address : %s \n", IPAddress);
+
+ MWprintf(90,"CondorLoadAvg : %f\n", CondorLoadAvg);
+ MWprintf(90,"LoadAvg : %f\n", LoadAvg);
+ MWprintf(90,"Memory : %d\n", Memory);
+ MWprintf(90,"Cpus : %d\n", Cpus);
+ MWprintf(90,"VirtualMemory : %d\n", VirtualMemory);
+ MWprintf(90,"Disk : %d\n", Disk);
+ MWprintf(90,"KFlops : %d\n", KFlops);
+ MWprintf(90,"Mips : %d\n", Mips);
+
+ fclose( inputfile );
+
+ if (remove(filename) != 0)
+ {
+ MWprintf(10,"Condor status file NOT removed!\n");
+ }
+ else
+ {
+ MWprintf(90,"Condor status file removed.\n");
+ }
+
+
+}
+#endif
+
+
+static char hostname[255];
+
+char*
+MWDriver::getHostName ()
+{
+ MWSystem::gethostname(hostname, 255);
+ return hostname;
+}
+
+int
+MWDriver::getNumWorkers()
+{
+ return workers->number();
+}
+
+#ifdef MEASURE
+void
+MWDriver::_measure()
+{
+ time_t now_time = time(0);
+ if ( now_time - _measure_last_read_opt_time >= _measure_read_opt_interval ) {
+ // Need to read the option file again
+ _measure_read_options(_measure_opt_file_name);
+ _measure_last_read_opt_time = now_time;
+ } else if ( now_time - _measure_last_dump_rec_time >= _measure_dump_rec_interval ) {
+ if (_measure_num_task_Done == 0)
+ return;
+
+ // Need to dump measurement result again
+ // First collect the information
+ statsgather(workers, stats);
+
+ _measure_master_wall_time += _measure_cur_wall_time();
+ _measure_master_cpu_time += _measure_cur_cpu_time();
+ if (_measure_master_cpu_time < 0.0001)
+ _measure_master_cpu_time = 0.0;
+ if (_measure_master_recv_cpu_time < 0.0001)
+ _measure_master_recv_cpu_time = 0.0;
+ if (_measure_master_act_on_completed_task_cpu_time < 0.0001)
+ _measure_master_act_on_completed_task_cpu_time = 0.0;
+ if (_measure_task_MP_worker_cpu_time < 0.0001)
+ _measure_task_MP_worker_cpu_time = 0.0;
+
+ // Dump record to file
+ _measure_dump_records();
+
+ if (_measure_use_adaptation == 1) {
+ // Adapt the number of workers when necessary
+ _measure_adapt();
+ }
+
+ // Reset the measurement numbers for the next run
+ _measure_reset();
+ }
+}
+
+void MWDriver::_measure_reset()
+{
+ // Reset the measurements for the next interval
+ MWprintf(91, "MEASURE: reset all measurement related values to default.\n");
+ _measure_num_task_Done = 0;
+ _measure_master_wall_time = 0.0 - _measure_cur_wall_time();
+ _measure_master_cpu_time = 0.0 - _measure_cur_cpu_time();
+ _measure_master_recv_time = 0.0;
+ _measure_master_recv_cpu_time = 0.0;
+ _measure_master_act_on_completed_task_time = 0.0;
+ _measure_master_act_on_completed_task_cpu_time = 0.0;
+ _measure_task_RoundTrip_time = 0.0;
+ _measure_task_MP_master_time = 0.0;
+ _measure_task_MP_worker_time = 0.0;
+ _measure_task_MP_worker_cpu_time = 0.0;
+ _measure_task_Exe_wall_time = 0.0;
+ _measure_task_Exe_cpu_time = 0.0;
+ _measure_target_num_workers = 99999;
+}
+
+void
+MWDriver::_measure_dump_header()
+{
+ // Create the file and write the first several lines
+ FILE *rec;
+ if ( (rec = fopen(_measure_rec_file_name, "a")) == NULL ) {
+ MWprintf(31, "MEASURE|Failed to open %s for measurement records! errno = %d\n",
+ _measure_rec_file_name, errno);
+ } else {
+ fprintf(rec, "Start_time = %s\n", ctime(&_measure_last_read_opt_time));
+ fprintf(rec, "NOW_TIME LastDump #Wkr #RUN #TODO #Done(sum) *M_wall(-CPU-) *M_recv(-CPU-) *W_recv(-CPU-) *M_exec(-CPU-) *W_exec(-CPU-) #MSGS\n");
+ fclose(rec);
+ }
+}
+
+void
+MWDriver::_measure_dump_records()
+{
+ time_t now_time = time(0);
+
+ FILE *rec;
+ if ( (rec = fopen(_measure_rec_file_name, "a")) == NULL ) {
+ MWprintf(31, "MEASURE|Failed to open %s for measurement records! errno = %d \n", _measure_rec_file_name, errno);
+ return;
+ }
+
+ // NOW_TIME LastDump
+ char *now = ctime(&now_time);
+ now[19] = '\0';
+ fprintf(rec, "%s ", &now[11]);
+ char *last = ctime(&_measure_last_dump_rec_time);
+ last[19] = '\0';
+ fprintf(rec, "%s ", &last[11]);
+ // Then the numbers
+ // #Wkr #RUN #TODO #Done(sum) *M_wall(-CPU-) *M_recv(-CPU-) *W_recv(-CPU-) *M_exec(-CPU-) *W_exec(-CPU-) *T_RTrp
+ if (_measure_num_task_Done) {
+ fprintf(rec, "%3d %3d %6d %3d(%6d) %7.2f(%5.1f) %7.2f(%5.1f) %7.2f(%5.1f) %7.2f(%5.1f) %7.2f(%5.1f)\n",
+ (workers->number()>999)?999:workers->number(), // %3d #Wkr
+ (running->number()>999)?999:running->number(), // %3d #RUN
+ (todo->number()>999999)?999999:todo->number(), // %6d #TODO
+ _measure_num_task_Done, // %3d #Done
+ (num_completed_tasks>999999)?999999:num_completed_tasks,// %6d (sum)
+
+ _measure_master_wall_time, // %7.2f *M_wall
+ _measure_master_cpu_time, // %5.1f (-CPU-)
+ _measure_master_recv_time, // %7.2f *M_recv
+ _measure_master_recv_cpu_time, // %5.1f (-CPU-)
+ _measure_task_MP_worker_time/_measure_num_task_Done, // %7.2f *W_recv
+ _measure_task_MP_worker_cpu_time/_measure_num_task_Done,// %5.1f (-CPU-)
+ _measure_master_act_on_completed_task_time, // %7.2f *M_exec
+ _measure_master_act_on_completed_task_cpu_time, // %5.1f (-CPU-)
+ _measure_task_Exe_wall_time/_measure_num_task_Done, // %7.2f *T_exec
+ _measure_task_Exe_cpu_time/_measure_num_task_Done // %5.1f (-CPU-)
+ // _measure_task_RoundTrip_time/_measure_num_task_Done // %7.2f *T_RTrp
+ );
+ MWList<void> * recv_buf_list = RMC->recv_buffers();
+ if (recv_buf_list) {
+ fprintf(rec, "BUFFER: size = %4d\n", RMC->recv_buffers()->number() );
+ }
+ } else {
+ fprintf(rec, "%3d %3d %6d %3d(%6d) %7.2f(%5.1f) %7.2f(%5.1f) %7.2f(%5.1f) %7.2f(%5.1f) %7.2f(%5.1f)\n",
+ (workers->number()>999)?999:workers->number(), // %3d #Wkr
+ (running->number()>999)?999:running->number(), // %3d #RUN
+ (todo->number()>999999)?999999:todo->number(), // %6d #TODO
+ _measure_num_task_Done, // %3d #Done
+ (num_completed_tasks>999999)?999999:num_completed_tasks,// %6d (sum)
+
+ _measure_master_wall_time, // %7.2f *M_wall
+ _measure_master_cpu_time, // %5.1f (-CPU-)
+ _measure_master_recv_time, // %7.2f *M_recv
+ _measure_master_recv_cpu_time, // %5.1f (-CPU-)
+ 0.0, // %7.2f *W_recv
+ 0.0, // %5.1f (-CPU-)
+ _measure_master_act_on_completed_task_time, // %7.2f *M_exec
+ _measure_master_act_on_completed_task_cpu_time, // %5.1f (-CPU-)
+ 0.0, // %7.2f *T_exec
+ 0.0 // %5.1f (-CPU-)
+ // 0.0 // %7.2f *T_RTrp
+ );
+ MWList<void> * recv_buf_list = RMC->recv_buffers();
+ if (recv_buf_list) {
+ fprintf(rec, "BUFFER: size = %4d\n", RMC->recv_buffers()->number() );
+ }
+ }
+
+ fclose(rec);
+ _measure_last_dump_rec_time = now_time;
+
+ /*
+ if (num_completed_tasks > 20000) {
+ MWprintf(31, "Jichuan's hack - exit when running too long!");
+ assert(0);
+ exit(1);
+ }
+ */
+
+}
+
+void
+MWDriver::_measure_read_options(const char* opt_fname)
+{
+ FILE *opt;
+ if ( (opt = fopen(opt_fname, "r")) == NULL ) {
+ MWprintf (31, "MEASURE|%s not found, uses default.\n", opt_fname);
+ return;
+ }
+
+ char str[512];
+ char *ret = NULL;
+ while (fgets(str, 512, opt)) {
+ if ((str[0] == '#')||(str[0] == ' ')) // comments
+ continue;
+ ret = strchr(str, '\n');
+ if (ret) *ret = '\0';
+ if (strstr(str, "dump_record_interval") != NULL) {
+ _measure_dump_rec_interval = atoi( &(str[strlen("dump_record_interval")+1]) );
+ MWprintf(31, "MEASURE|Setting dump_record_interval = %d\n", _measure_dump_rec_interval);
+ } else if (strstr(str, "read_option_interval") != NULL) {
+ _measure_read_opt_interval = atoi( &(str[strlen("read_option_interval")+1]) );
+ MWprintf(31, "MEASURE|Setting read_option_interval = %d\n", _measure_read_opt_interval);
+ } else if (strstr(str, "use_adaptation") != NULL) {
+ _measure_use_adaptation = 1;
+ MWprintf(21, "MEASURE|Setting use_adaptation to yes. \n");
+ }
+
+ }
+ fclose(opt);
+}
+
+void
+MWDriver::_measure_remove_worker()
+{
+ MWWorkerID * w = _measure_current_worker;
+ MWprintf(31, "MEASURE|ADAPT|Removing worker id1 = %08x \n", w->get_id1());
+ RMC->initsend ( );
+ RMC->send ( w->get_id1(), KILL_YOURSELF );
+ worker_last_rites ( w );
+}
+
+void
+MWDriver::_measure_adapt()
+{
+ if (_measure_num_task_Done == 0) {
+ return;
+ }
+
+ if (_measure_target_num_workers < workers->number()) {
+ // need to remove more workers, still adapting ...
+ _measure_remove_worker();
+ return;
+ }
+
+ _measure_master_wait_rate = _measure_master_recv_time/_measure_master_wall_time;
+ if (_measure_master_wait_rate < 0.001) { // then the workers MIGHT BE WAITING
+ _measure_master_busy_times ++ ;
+ } else if (_measure_master_wait_rate > 0.50) { // then the master is WAITING
+ _measure_master_wait_times ++;
+ }
+
+ if (_measure_master_busy_times > workers->number()/10 ) {
+ // reduce target worker numbers
+ _measure_master_busy_times = 0;
+
+ _measure_target_num_workers = (workers->number()>12)? workers->number()-12 : 6;
+ RMC->set_target_num_workers(_measure_target_num_workers);
+
+ _measure_remove_worker();
+
+ call_hostaddlogic();
+ MWprintf(31, "MEASURE|ADAPT|decrease worker number to %d\n", _measure_target_num_workers);
+ }
+
+ if (_measure_master_wait_times > 10) {
+ // ask for more workers
+ _measure_master_wait_times = 0;
+
+ if (RMC->get_num_exec_classes() == 0) {
+ int target = RMC->get_target_num_workers(-1);
+ if (workers->number() == target) {
+ RMC->set_target_num_workers(target + 6);
+ MWprintf(31, "MEASURE|ADAPT|increase worker number to %d\n", target+6);
+ }
+ }
+ }
+}
+#endif // MEASURE
+
+void
+MWDriver::prepare_update(int mode)
+{
+ MWWorkerID *w = workers->First();
+ switch(mode)
+ {
+ case -2:
+ while ( workers->AfterEnd() == false )
+ {
+ if( w->currentState() != BENCHMARKING && w->currentState() != INITIALIZING )
+ {
+ w = workers->Current();
+ RMC->initsend();
+ pack_update();
+ RMC->send(w->get_id1(), UPDATE_FROM_DRIVER);
+ }
+ workers->Next();
+ }
+ break;
+ case -1:
+ RMC->initsend();
+ pack_update();
+ send_update_message();
+ break;
+ default:
+ RMC->initsend();
+ pack_update();
+ send_update_message_to(mode);
+ }
+}
+
+/* send a UPDATE_FROM_DRIVER message to MWcurrentWorker, assuming the user has
+ * already called RMC->initsend(), and RMC->pack() for the read data. */
+int
+MWDriver::send_update_message()
+{
+ if (MWcurrentWorker == NULL)
+ return -1;
+
+ return RMC->send(MWcurrentWorker->get_id1(), UPDATE_FROM_DRIVER);
+}
+
+/* send a UPDATE_FROM_DRIVER message to a specific worker, assuming the user has
+ * already called RMC->initsend(), and RMC->pack() for the read data. */
+int
+MWDriver::send_update_message_to(int worker)
+{
+ return RMC->send(worker, UPDATE_FROM_DRIVER);
+}
+
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq c-tab-always-indent nil)
+ eval: (setq tab-width 4)
+ End:
+*/
+
+void
+MWDriver::increasePendingNum(void)
+{
+ pthread_mutex_lock(&m_pending_mutex);
+ m_pending_num++;
+ pthread_mutex_unlock(&m_pending_mutex);
+}
+void
+MWDriver::decreasePendingNum(void)
+{
+ pthread_mutex_lock(&m_pending_mutex);
+ m_pending_num--;
+ pthread_cond_signal(&m_pending_cond);
+ pthread_mutex_unlock(&m_pending_mutex);
+}
+
+void
+MWDriver::getGlobalLock(void)
+{
+ pthread_mutex_lock(&global_mw_mutex);
+}
+
+void
+MWDriver::getGlobalUnLock(void)
+{
+ pthread_mutex_unlock(&global_mw_mutex);
+}
diff --git a/MW/src/MWDriver.h b/MW/src/MWDriver.h
new file mode 100644
index 0000000..82d5574
--- /dev/null
+++ b/MW/src/MWDriver.h
@@ -0,0 +1,1274 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWDRIVER_H
+#define MWDRIVER_H
+
+#include "MWTask.h"
+#include "MWWorker.h"
+#include "MWStats.h"
+#include "MWList.h"
+#include "MW.h"
+#include <MWRMComm.h>
+#include <pthread.h>
+
+/// This is the "key" by which the task list can be managed.
+#define MWKey double
+//typedef double MWKey;
+
+/// This is if you wish to have XML output.
+//#define XML_OUTPUT
+// (Note -- it should be included in 'configure' output later)
+
+/** The ways in which tasks may be added to the list.
+*/
+enum MWTaskAdditionMode {
+ /// Tasks will be added at the end of the list
+ ADD_AT_END,
+ /// Tasks will be added at the beginning
+ ADD_AT_BEGIN,
+ /// Tasks will be added based on their key (low keys before high keys)
+ ADD_BY_KEY
+};
+
+/** The ways in which tasks may be removed from the list.
+*/
+enum MWTaskRetrievalMode {
+ /// Task at head of list will be returned.
+ GET_FROM_BEGIN,
+ /// Task with lowest key will be retrieved
+ GET_FROM_KEY
+};
+
+enum MWREFRESH_TYPE
+{
+ MW_ALL,
+ MW_THIS,
+ MW_NONE
+};
+
+/** The suspension policy to use - What do we do when it happens? */
+enum MWSuspensionPolicy {
+ /// Normally do nothing unless there are idle workers.
+ DEFAULT,
+ /** Always reassign the task; move it to the front of the
+ todo list */
+ REASSIGN
+};
+
+/** Tasks are always assigned to he first "IDLE" machine. By ordering
+ the machine list, we can implement a number of scheduling policies.
+ Insert your own favorite policy here.
+*/
+enum MWMachineOrderingPolicy {
+
+ /// The machines are ordered simply as they become available
+ NO_ORDER,
+
+ /** Machines are ordered by the "benchmark" result. Larger benchmark results
+ go first, so if using time to complete a task as the benchmark, you
+ should return 1/time as the benchmark value.
+ */
+ BY_USER_BENCHMARK,
+
+ /// Machines are ordered by KFLOPS reported by Condor.
+ BY_KFLOPS
+
+};
+
+/* TASK CLUSTERING / WORK CYCLE */
+
+/** This class is responsible for managing an application in an
+ opportunistic environment. The goal is to be completely fault -
+ tolerant, dealing with all possiblities of host (worker) problems.
+ To do this, the MWDriver class manages a set of tasks and a set
+ of workers. It monitors messages about hosts coming up and
+ going down, and assigns tasks appropriately.
+
+ This class is built upon some sort of resource management and
+ message passing lower layer. Previously, it was built directly
+ on top of Condor - PVM, but the interface to that has been
+ abstracted away so that it can use any facility that provides
+ for resource management and message passing. See the abstract
+ MWRMComm class for details of this lower layer. When interfacing
+ with this level, you'll have use the RMC object that's a static
+ member of the MWDriver, MWTask, and MWWorker class.
+
+ To implement an application, a user must derive a class from this
+ base class and implement the following methods:
+
+ - get_userinfo()
+ - setup_initial_tasks()
+ - pack_worker_init_data()
+ - act_on_completed_task()
+
+
+ For a higher level of control regarding distribution of tasks to workers,
+ tasks and workers may be enrolled to workclasses/groups by calling the
+ following methods:
+
+ - MWWorkerID::addGroup()
+ - MWWorkerID::deleteGroup()
+ - MWTask::addGroup()
+ - MWTask::deleteGroup()
+
+ These methods can be called by an application using workclasses:
+
+ - workClasses_set() (Required)
+ - workClasses_get()
+ - workClasses_gettasks()
+ - workClasses_getworkers()
+
+ To enroll workers in workclasses, there are two options:
+ - act_on_starting_worker() can be implemented to enroll workers to
+ workclasses based on MWWorkerID info at the start of execution
+ - pack_worker_init_data() can be implemented to enroll workers. When used
+ in conjunction with refreshWorkers(), can change workclass of workers in the middle of execution.
+
+ Similar application dependent methods must be implemented
+ for the "Task" of work to be done and the "Worker" who performs
+ the tasks.
+
+ @see MWTask
+ @see MWWorker
+ @see MWRMComm
+ @author Mike Yoder, Jeff Linderoth, Jean-Pierre Goux, Sanjeev Kulkarni
+*/
+
+
+class MWDriver {
+
+ friend class MWTask;
+
+ public:
+
+ /// Default constructor
+ MWDriver();
+
+ /** Destructor - walks through lists of tasks & workers and
+ deletes them. */
+ virtual ~MWDriver();
+
+ /** This method runs the entire fault-tolerant
+ application in the condor environment. What is *really* does
+ is call setup_master(), then master(), then printresults(),
+ and then ends. See the other functions for details.
+ */
+ void go( int argc, char *argv[] );
+
+ /** This version of go simply calls go(0, NULL).*/
+ void go() { go ( 0, NULL ); };
+
+ /**
+ Prints the Results. Applications may re-implement this
+ to print their application specific results.
+ It is meant to be over-ridden.
+ */
+ virtual void printresults();
+
+
+ /** A static instance of our Resource Management / Communication
+ class. It's a member of this class because that way derived
+ classes can use it easily; it's static because there should
+ only be one instance EVER. The instance of RMC in the MWTask
+ class is actually a pointer to this one... */
+ static MWRMComm * RMC;
+
+
+ protected:
+
+ /**@name A. Pure Virtual Methods
+ These are the methods from the MWDriver class that a user
+ {\bf must} reimplement in order to have to create an application.
+ */
+
+ //@{
+ /** This function is called to read in all information
+ specific to a user's application and do any initialization on
+ this information.
+ */
+ virtual MWReturn get_userinfo( int argc, char *argv[] )=0;
+
+ /** This function must return a number n > 0 of pointers
+ to Tasks to "jump start" the application.
+
+ The MWTasks pointed to should be of the task type derived
+ for your application
+ */
+ virtual MWReturn setup_initial_tasks( int *n, MWTask ***task ) = 0;
+
+ /**
+ This function performs actions that happen
+ once the Driver receives notification of a completed task.
+ You will need to cast the MWTask * to a pointer of the Task type
+ derived for your application. For example
+
+ \begin{verbatim}
+ My_Task *dt = dynamic_cast<My_Task *> ( t );
+ assert( dt );
+ \end{verbatim}
+ */
+ virtual MWReturn act_on_completed_task( MWTask * ) = 0;
+
+ /**
+ This is called once the Worker is done with the TaskContainer.
+ - Put the logic for this in MWDriver
+ */
+ //virtual MWReturn act_on_completed_task( MWTaskContainer * ) = 0;
+
+ /**
+ This function should be implemented by the application
+ to assign the workClass number to the worker if it is doing
+ intelligent work scheduling.
+ */
+ virtual MWReturn act_on_starting_worker ( MWWorkerID *w );
+
+
+ /**
+ A common theme of Master-Worker applications is that there is
+ a base amount of "initial" data defining the problem, and then
+ just incremental data defining "Tasks" to be done by the Workers.
+
+ This one packs all the user's initial data. It is unpacked
+ int the worker class, in unpack_init_data().
+ */
+ virtual MWReturn pack_worker_init_data( void ) = 0;
+
+ /**
+ This one unpacks the "initial" information sent to the driver
+ once the worker initializes.
+
+ Potential "initial" information that might be useful is...
+ \begin{itemize}
+ \item Information on the worker characteristics etc...
+ \item Information on the bandwith between MWDriver and worker
+ \end{itemize}
+
+ These sorts of things could be useful in building some
+ scheduling intelligence into the driver.
+
+ */
+ virtual void unpack_worker_initinfo( MWWorkerID *w ) {};
+
+ /**
+ OK, This one is not pure virtual either, but if you have some
+ "driver" data that is conceptually part of the task and you wish
+ not to replicate the data in each task, you can pack it in a
+ message buffer by implementing this function. If you do this,
+ you must implement a matching unpack_worker_task_data()
+ function.
+ */
+
+ virtual void pack_driver_task_data( void ) {};
+
+ /**@name Data streaming/subtasks
+ These are the methods that must be implemented to enable data streaming/
+ subtasks.
+ - act_on_completed_subtask()
+ - MWWorker::execute_subtask
+ - MWWorker::set_num_subtask
+ - MWTask::pack_subresults
+ - MWTask::unpack_subresults
+
+ A subtask is identified by a MWTask and a subtask id. The subtask id
+ starts at 0 and ends at n-1 subtasks.
+
+ When subtasks are enabled, the Master sends the task to the Worker as
+ usual. But instead of calling execute_task once, execute_subtask is
+ called once per subtask id (starting at 0). At the end of each call, the
+ result will be returned to the Master. After all subtasks have completed,
+ the Master is notified that the Task has completed.
+ */
+
+ /**
+ This function performs an action that happens once the
+ Driver receives notification of a completed subtask.
+ */
+ virtual MWReturn act_on_completed_subtask(MWTask *) { return ABORT; }
+ //@}
+
+
+ /**@name B. Task List Management
+
+ These functions are to manage the list of Tasks. MW provides
+ default useful functionality for managing the list of tasks.
+
+ */
+
+ //@{
+
+ /// Set number of workclasses
+ void workClasses_set ( int num );
+
+ /// Get the number of workclasses
+ int workClasses_get ( );
+
+ /// Stop the worker working on this task container and send it a new task container. This should only be called in act_on_completed_task(MWTask*)
+ int stop_work();
+
+ /// get number of workers in the specified work class
+ int workClasses_getworkers ( int num );
+ /// get number of tasks in the specified work class
+ int workClasses_gettasks ( int num );
+ /// Pack new init data for all workers in group i
+ int refreshWorkers ( int i, MWREFRESH_TYPE );
+
+
+ /// Add a task to the list
+ void addTask( MWTask * );
+
+ /** Add a bunch of tasks to the list. You do this by making
+ an array of pointers to MWTasks and giving that array to
+ this function. The MWDriver will take over memory
+ management for the MWTasks, but not for the array of
+ pointers, so don't forget to delete [] it! */
+ void addTasks( int, MWTask ** );
+
+ /** This will add a list of tasks that are sorted by key. Efficiency can
+ be greatly improved by using this function */
+ void addSortedTasks( int n, MWTask **add_tasks );
+
+private:
+ /// This is a helper function for addSortedTasks().
+ void addTaskByKey( MWTask *add_task );
+
+public:
+ /// Sets the function that MWDriver users to get the "key" for a task
+ void set_task_key_function( MWKey (*)( MWTask * ) );
+
+ /// Set the mode you wish for task addition.
+ int set_task_add_mode( MWTaskAdditionMode );
+
+ /// Set the mode you wish for task retrieval.
+ int set_task_retrieve_mode( MWTaskRetrievalMode );
+
+ /// This sorts the task list by the key that is set
+ int sort_task_list( void );
+
+ /** This deletes all tasks in the task list with a key worse than
+ the one specified */
+ int delete_tasks_worse_than( MWKey );
+
+ /// returns the number of tasks on the todo list.
+ int get_number_tasks();
+
+ int getNumWorkers ( );
+
+ /// returns the number of running tasks.
+ int get_number_running_tasks();
+
+ /// (Mostly for debugging) -- Prints the task keys in the todo list
+ int print_task_keys( void );
+
+
+ //@}
+ void reassignSuspendedTask ( MWList<MWTask> * running, MWWorkerID * w );
+ void reassignIdleTask ( MWList<MWWorkerID> * workers, MWWorkerID * w );
+ int matchTask ( void *arg1, void *arg2 );
+ MWWorkerID* numberworker ( void *arg1, void *arg2 );
+
+
+ /** @name C. Worker Policy Management */
+ //@{
+ /** Set the policy to use when suspending. Currently
+ this can be either DEFAULT or REASSIGN */
+ void set_suspension_policy( MWSuspensionPolicy );
+
+ /// Sets the machine ordering policy.
+ int set_machine_ordering_policy( MWMachineOrderingPolicy );
+
+ //@}
+
+ /** @name. task timeout policy.
+
+ MW provides a mechanism for performing tasks on workers that are
+ potentially "lost". If the RMComm fails to notify MW of a worker
+ going away in a timely fashion, the state of the computing platform
+ and MW's vision of its state may become out of synch. In order to
+ make sure that all tasks are done in a timely fashion, the user may set
+ a time limit after which a task running on a "lost" worker
+ may be rescheduled.
+ */
+
+ //@{
+
+private:
+
+ /** If false : workers never timeout and can potentially work forever on a task
+ If true : workers time out after worker_timeout_limit seconds */
+ bool worker_timeout;
+
+ /** Limit of seconds after which workers are considered time out and
+ tasks are re-assigned */
+ double worker_timeout_limit;
+
+ /** frequency at which we check if there are timed out workers */
+ int worker_timeout_check_frequency;
+
+ /** based on the time out frequency, next timeout check time*/
+ int next_worker_timeout_check;
+
+ /** Go through the list of timed out WORKING workers and reschedule tasks */
+ void reassign_tasks_timedout_workers();
+
+public:
+
+ /** Sets the timeout_limit and turn worker_timeout to 1 */
+ void set_worker_timeout_limit(double timeout_limit, int timeout_frequency);
+
+ //@}
+
+
+ /**@name D. Event Handling Methods
+
+ In the case that the user wants to take specific actions
+ when notified of processors going away, these methods
+ may be reimplemented. Care must be taken when
+ reimplementing these, or else things may get messed up.
+
+ Probably a better solution in the long run is to provide
+ users hooks into these functions or something.
+
+ Basic default functionality that updates the known
+ status of our virtual machine is provided.
+
+ */
+
+ //@{
+
+ /** Here, we get back the benchmarking
+ results, which tell us something about the worker we've got.
+ Also, we could get some sort of error back from the worker
+ at this stage, in which case we remove it. */
+
+ virtual MWReturn handle_benchmark( MWWorkerID *w );
+
+ /** This is what gets called when a host goes away. We figure out
+ who died, remove that worker from our records, remove its task
+ from the running queue (if it was running one) and put that
+ task back on the todo list. */
+
+ virtual void handle_hostdel();
+
+ /** Implements a suspension policy. Currently either DEFAULT or
+ REASSIGN, depending on how suspensionPolicy is set. */
+ virtual void handle_hostsuspend();
+
+ /** Here's where you go when a host gets resumed. Usually,
+ you do nothing...but it's nice to know...*/
+ virtual void handle_hostresume();
+
+ /** We do basically the same thing as handle_hostdel(). One might
+ {\em think} that we could restart something on that host;
+ in practice, however -- especially with the Condor-PVM RMComm
+ implementation -- it means that the host has gone down, too.
+ We put that host's task back on the todo list.
+ */
+ virtual void handle_taskexit();
+
+ /** Routine to handle when the communication layer says that a
+ checksum error happened. If the underlying Communitor
+ gives a reliably reliable communication then this messge
+ need not be generated. But for some Communicators like
+ MW-File we may need some thing like this.
+ */
+ virtual void handle_checksum ();
+
+ //@}
+
+ /** @name E. Checkpoint Handling Functions
+
+ These are logical checkpoint handling functions. They are
+ virtual, and are *entirely* application-specific. In them, the
+ user must save the "state" of the application to permanent
+ storage (disk). To do this, you need to:
+
+ \begin{itemize}
+ \item Implement the methods write_master_state() and
+ read_master_state() in your derived MWDriver app.
+ \item Implement the methods write_ckpt_info() and
+ read_ckpt_info() in your derived MWTask class.
+ \end{itemize}
+
+ Then MWDriver does the rest for you. When checkpoint() is
+ called (see below) it opens up a known filename for writing.
+ It passes the file pointer of that file to write_master_state(),
+ which dumps the "state" of the master to that fp. Here
+ "sate" includes all the variables, info, etc of YOUR
+ CLASS THAT WAS DERIVED FROM MWDRIVER. All state in
+ MWDriver.C is taken care of (there's not much). Next,
+ checkpoint will walk down the running queue and the todo
+ queue and call each member's write_ckpt_info().
+
+ Upon restart, MWDriver will detect the presence of the
+ checkpoint file and restart from it. It calls
+ read_master_state(), which is the inverse of
+ write_master_state(). Then, for each task in the
+ checkpoint file, it creates a new MWTask, calls
+ read_ckpt_info() on it, and adds it to the todo queue.
+
+ We start from there and proceed as normal.
+
+ One can set the "frequency" that checkpoint files will be
+ written (using set_checkpoint_frequency()). The default
+ frequency is zero - no checkpointing. When the frequency is
+ set to n, every nth time that act_on_completed_task gets
+ called, we checkpoint immediately afterwards. If your
+ application involves "work steps", you probably will want to
+ leave the frequency at zero and call checkpoint yourself
+ at the end of a work step.
+
+ */
+ //@{
+
+ /** This function writes the current state of the job to disk.
+ See the section header to see how it does this.
+ @see MWTask
+ */
+ void checkpoint();
+
+
+ /** This function does the inverse of checkpoint.
+ It opens the checkpoint file, calls read_master_state(),
+ then, for each task class in the file, creates a MWTask,
+ calls read_ckpt_info on it, and adds that class to the
+ todo list. */
+ void restart_from_ckpt();
+
+
+ /** This function sets the frequency with with checkpoints are
+ done. It returns the former frequency value. The default
+ frequency is zero (no checkpoints). If the frequency is n,
+ then a checkpoint will occur after the nth call to
+ act_on_completed_task(). A good place to set this is in
+ get_userinfo().
+ @param freq The frequency to set checkpoints to.
+ @return The former frequency value.
+ */
+
+ int set_checkpoint_frequency( int freq );
+
+ /** Set a time-based frequency for checkpoints. The time units
+ are in seconds. A value of 0 "turns off" time-based
+ checkpointing. Time-based checkpointing cannot be "turned
+ on" unless the checkpoint_frequency is set to 0. A good
+ place to do this is in get_userinfo().
+ @param secs Checkpoint every "secs" seconds
+ @return The former time frequency value.
+ */
+ int set_checkpoint_time( int secs );
+
+ /** Here you write out all 'state' of the driver to fp.
+ @param fp A file pointer that has been opened for writing. */
+ virtual void write_master_state( FILE *fp ) {};
+
+ /** Here, you read in the 'state' of the driver from fp. Note
+ that this is the reverse of write_master_state().
+ @param fp A file pointer that has been opened for reading. */
+ virtual void read_master_state( FILE *fp ) {};
+
+
+ /** Swap the unused part of the (sorted and indexed) TODO list
+ onto disk (file name: TODO_tasks.id), so that the TODO tasks
+ with smaller key values are kept in memory, and others are kept
+ in a file. When there are too many tasks in memory, we swap most
+ of them out; when there are too few tasks in memory, we swap in
+ more. The MW application will be done only when all TODO tasks
+ are done. When checkpointing, it only saves TODO tasks in memory,
+ and the pointers (the file name) to the swap file.
+
+ To help swapping in tasks, we will record the number of tasks
+ swapped in at the beginning of the file, and skip then when read
+ to swap file. The num_to_skip is initially set to 0.
+
+ The swap file for TODO tasks is fully-sorted, and looks like:
+
+ num_to_skip
+ trash_task1
+ trash_task2
+ ...
+ ...
+ task1
+ task2
+ ...
+ ...
+ task[num_tasks]
+ **/
+
+ /** When swapping out, we walk through the sorted TODO list, keep the first
+ num_in_mem tasks in memory (copy into a newly created list). For the
+ rest of the list, merge it in order with existing tasks in the file
+ TODO_tasks, and write them into a newly created swap file. Tasks
+ in swap file whose key values are larger than max_key are removed. When
+ done, delete the old TODO list and swap file, switch to the new ones.
+
+ If the old TODO list is not too large (<max_in_mem), won't swap out.
+ Return value indicates whether the swapping is successful or not.
+ **/
+
+int MIN_IN_MEM; /* == 256 */
+int NUM_IN_MEM_LO; /* == MIN_IN_MEM*8 */
+int NUM_IN_MEM_HI; /* == MIN_IN_MEM*100 */
+int MAX_IN_MEM; /* == MIN_IN_MEM*800 */
+
+public:
+ bool swap_out_todo_tasks(int num_in_mem = 2048,
+ int max_in_mem = 204800,
+ double max_key = DBL_MAX);
+
+ /** When swapping in, we first read first num_in_mem (or all tasks if not so
+ many tasks in swap file) tasks from the swap file, create tasks and
+ append to a newly created list. Then we sorted insert the existing tasks
+ in memory into the new list. When done, switch the list and file.
+
+ If the old TODO list is not too small (>num_in_mem), won't swap in.
+ Return value indicates whether the swapping is successful or not.
+ **/
+ bool swap_in_todo_tasks(int min_in_mem = 256,
+ int num_in_mem = 25600);
+
+ /** See whether we still have TODO tasks */
+ bool is_TODO_empty();
+
+ /* Read and write tasks */
+ MWTask * read_mem_task(MWList<MWTask> *tasks);
+ MWTask * read_file_task(FILE *f);
+ void write_task(FILE *f, MWTask *t);
+
+private:
+ bool has_task_swapped; /* inited as false */
+ double max_task_key; /* inited as -DBL_MAX,
+ tasks with larger key values should be removed */
+
+public:
+ /** It's really annoying that the user has to do this, but
+ they do. The thing is, we have to make a new task of the
+ user's derived type when we read in the checkpoint file.
+
+ If your application coredumps when trying to restart from
+ a checkpoint, it might be becasue you haven't implemented this function.
+
+ \begin{verbatim}
+ MWTask* gimme_a_task() {
+ return new <your derived task class>;
+ }
+ \end{verbatim}
+ */
+ virtual MWTask *gimme_a_task() = 0;
+ //@}
+
+ /** @name Benchmarking
+ We now have a user-defined benchmarking phase.
+ The user can "register" a task that is sent to each worker upon startup.
+ This way, the user knows which machines are fastest, and MW can perform
+ can automatic "normalization" of the equivalent CPU time.
+ */
+ //@{
+
+ /** register the task that will be used for benchmarking. */
+ void register_benchmark_task( MWTask *t ) { bench_task = t; };
+
+ /** get the benchmark task */
+ MWTask * get_benchmark_task() { return bench_task; };
+
+ //@}
+
+private:
+
+ /** @name Main Internal Handling Routines */
+ //@{
+
+ /** This method is called before master_mainloop() is. It does
+ some setup, including calling the get_userinfo() and
+ create_initial_tasks() methods. It then figures out how
+ many machines it has and starts worker processes on them.
+ @param argc The argc from the command line
+ @param argv The argv from the command line
+ @return This is the from the user's get_userinfo() routine.
+ If get_userinfo() returns OK, then the return value is from
+ the user's setup_initial_tasks() function.
+ */
+
+ MWReturn master_setup( int argc, char *argv[] );
+
+ /** This is the main controlling routine of the master. It sits
+ in a loop that accepts a message and then (in a big switch
+ statement) calls routines to deal with that message. This loop
+ ends when there are no jobs on either the running or todo queues.
+ It is probably best to see the switch staement yourself to see
+ which routines are called when. */
+
+ MWReturn master_mainloop();
+
+ /**
+ unpacks the initial worker information, and sends the
+ application startup information (by calling pure virtual
+ {\tt pack_worker_init_data()}
+
+ The return value is taken as the return value from the user's
+ {\tt pack_worker_init_data()} function.
+
+ */
+
+ MWReturn worker_init( MWWorkerID *w );
+
+ /**
+ This routine sets up the list of initial tasks to do on the
+ todo list. In calls the pure virtual function
+ {\tt setup_initial_tasks()}.
+ @return Is taken from the return value of
+ {\tt setup_initial_tasks()}.
+ */
+ MWReturn create_initial_tasks();
+
+ /**
+ Act on a "completed task" message from a worker.
+ Calls pure virtual function {\tt act_on_completed_task()}.
+ @return Is from the return value of {\tt act_on_completed_task()}.
+ */
+ MWReturn handle_worker_results( MWWorkerID *w );
+
+
+ /** We grab the next task off the todo list, make and send a work
+ message, and send it to a worker. That worker is marked as
+ "working" and has its runningtask pointer set to that task. The
+ worker pointer in the task is set to that worker. The task
+ is then placed on the running queue. */
+ void send_task_to_worker( MWWorkerID *w );
+
+ //by jae
+ void lockSendTaskToWorker( MWWorkerID *w );
+
+ /** After each result message is processed, we try to match up
+ tasks with workers. (New tasks might have been added to the list
+ during processing of a message). Don't send a task to
+ "nosend", since he just reported in.
+ */
+ void rematch_tasks_to_workers( MWWorkerID *nosend );
+
+ /** A wrapper around the lower level's hostaddlogic. Handles
+ things like counting machines and deleting surplus */
+ void call_hostaddlogic();
+
+ /// Kill all the workers
+ void kill_workers();
+
+ /** This is called in both handle_hostdelete and handle_taskexit.
+ It removes the host from our records and cleans up
+ relevent pointers with the task it's running. */
+
+ void hostPostmortem ( MWWorkerID *w );
+
+
+
+ /** The control panel that controls the execution of the
+ independent mode. */
+ void ControlPanel ( );
+
+ MWReturn master_mainloop_oneshot ( int buf_id, int sending_host);
+
+ int outstanding_spawn;
+
+ //@}
+
+ /**@name Internal Task List Routines
+
+ These methods and data are responsible for managing the
+ list of tasks to be done
+ */
+
+ //@{
+
+ /// This puts a (generally failed) task at the beginning of the list
+ void pushTask( MWTask * );
+
+ /// Get a Task.
+ MWTask *getNextTask( MWGroup *grp );
+
+ /// This puts a task at the end of the running list
+ void putOnRunQ( MWTask *t );
+
+ /// Removes a task from the queue of things to run
+ MWTask * rmFromRunQ ( int jobnum );
+
+ /// Print the tasks in the list of tasks to do
+ void printRunQ();
+
+ /** Add one task to the todo list; do NOT set the 'number' of
+ the task - useful in restarting from a checkpoint */
+ void ckpt_addTask( MWTask * );
+
+ /// returns the worker this task is assigned to, NULL if none.
+ MWWorkerID * task_assigned( MWTask *t );
+
+ /// Returns true if "t" is still in the todo list
+ bool task_in_todo_list( MWTask *t );
+
+ /** A pointer to a (user written) function that takes an MWTask
+ and returns the "key" for this task. The user is allowed to
+ change the "key" by simply changing the function
+ */
+protected:
+ MWKey (*task_key)( MWTask * );
+
+ void give_work ( MWWorkerID *w, MWTask *t );
+
+private:
+
+ /// Where should tasks be added to the list?
+ MWTaskAdditionMode addmode;
+
+ /// Where should tasks by retrived from the list
+ MWTaskRetrievalMode getmode;
+
+ /** A pointer to the function that returns the "key" by which machines are ranked.
+ Right now, we offer only some (hopefully useful) default functions that are
+ set through the machine_ordering_policy
+ */
+
+ MWKey (*worker_key)( MWWorkerID * );
+
+
+ MWMachineOrderingPolicy machine_ordering_policy;
+
+ /** MWDriver keeps a unique identifier for each task --
+ here's the counter */
+ int task_counter;
+
+ /// Is the list sorted by the current key function
+ bool listsorted;
+
+ /// The head of the list of tasks to do
+ MWList<MWTask> * todo;
+
+public:
+ /// This is Jeff's nasty addition so that he can get access
+ /// to the tasks on the master
+ MWTask *get_todo_head();
+
+ //by jae
+ void increasePendingNum(void);
+ void decreasePendingNum(void);
+ int getPendingNum(void) { return m_pending_num; }
+
+ void getGlobalLock(void);
+ void getGlobalUnLock(void);
+
+private:
+ //by jae
+ int m_pending_num;
+ pthread_mutex_t m_pending_mutex;
+ pthread_cond_t m_pending_cond;
+
+ /// The head of the list of tasks that are actually running
+ MWList<MWTask> * running;
+
+ /// The reassigned task list
+ MWList<int> * reassigned_tasks;
+ /// The reassigned and done task list
+ MWList<int> * reassigned_tasks_done;
+ /// All running tasks are reassigned_done
+ bool normal_tasks_all_done;
+
+ /// Insert a task with an id of tid into a int* list
+ inline void insert_into_set(MWList<int> * list, int tid) {
+ int i, num = list->number();
+ int *t;
+ bool found = false;
+
+ for (i=0; i<num; i++) {
+ t = (int*)list->Remove();
+ if (*t==tid)
+ found = true;
+ list->Append(t);
+ }
+ if (!found) {
+ t = new int;
+ *t = tid;
+ list->Append(t);
+ }
+ }
+ /// See if a task is in a given int* list
+ inline bool in_set(MWList<int> * list, int tid) {
+ int i, num = list->number();
+ int *t;
+
+ for (i=0; i<num; i++) {
+ t = (int*)list->Remove();
+ list->Append(t);
+ if (*t==tid)
+ return true;
+ }
+ return false;
+ }
+ //@}
+
+ /**@name Worker management methods
+
+ These methods act on the list of workers
+ (or specifically) ID's of workers, that the
+ driver knows about.
+
+ */
+
+ //@{
+
+ /// Adds a worker to the list of avaiable workers
+ void addWorker ( MWWorkerID *w );
+
+ /// Looks up information about a worker given its task ID
+ MWWorkerID * lookupWorker( int tid );
+
+ /// Removes a worker from the list of available workers
+ MWWorkerID * rmWorker ( int tid );
+
+ /// This function removes worker from the list, removes it and deletes
+ /// the structure.
+ void worker_last_rites ( MWWorkerID *w );
+
+public:
+ /// Prints the available workers
+ void printWorkers();
+
+ /** Another terrible addition so that Jeff can print out the worker list
+ in his own format */
+ MWWorkerID *get_workers_head();
+
+private:
+
+ /// The head of the list of workers.
+ MWList<MWWorkerID> * workers;
+
+ /// Here's where we store what should happen on a suspension...
+ MWSuspensionPolicy suspensionPolicy;
+
+ /// Based on the ordering policy, place w in the worker list appropriately
+ void sort_worker_list();
+public:
+ /// Counts the existing workers
+ int numWorkers();
+
+ /// Counts the number of workers in the given arch class
+ int numWorkers( int arch );
+
+ /// Counts the number of workers in the given state
+ int numWorkersInState( int ThisState );
+
+ /// Returns the value (only) of the best key in the Todo list
+ MWKey return_best_todo_keyval( void );
+
+ /// Returns the best value (only) of the best key in the Running list.
+ MWKey return_best_running_keyval( void );
+
+private:
+
+ //@}
+
+ /** @name Checkpoint internal helpers... */
+ //@{
+
+ /** How often to checkpoint? Task frequency based. */
+ int checkpoint_frequency;
+
+ /** How often to checkpoint? Time based. */
+ int checkpoint_time_freq;
+ /** Time to do next checkpoint...valid when using time-based
+ checkpointing. */
+
+ long next_ckpt_time;
+
+ /** The number of tasks acted upon up to now. Used with
+ checkpoint_frequency */
+ //int num_completed_tasks;
+
+ /** The benchmark task. */
+ MWTask *bench_task;
+
+ /** The name of the checkpoint file */
+ const char *ckpt_filename; // JGS
+
+ /** When submitting multiple jobs from the same directory, the checkpoint files all the
+ * the same name if we use the fixed ckpt_filename. So we made some changes:
+ * (1) Allow the user set their checkpoint file name by calling
+ * set_ckpt_filename(const char*) before finishing get_user_info()
+ * (2) If the user doesn't specify the ckpt_filename, then use
+ * $(master_exec_name)-ckpt.$(Process)
+ * (3) When reading checkpoints during execution, MW will just read the file. When the
+ * application restarts, it will find the file with the same name as user specified,
+ * or as the default name (choose the first one when there are multiple files).
+ */
+ // char *ckpt_filename;
+
+
+ //@}
+
+ /** The instance of the stats class that takes workers and later
+ prints out relevant stats... */
+ // Changed into MWStatistics * to make insure happy (then I can new and delete it).
+ MWStatistics* stats;
+
+ /// This returns the sum of the bench results for the currently working machines
+
+ double get_instant_pool_perf();
+
+ /// This returns the hostname
+ char *getHostName ();
+
+
+
+#if defined( XML_OUTPUT )
+
+ /**@name XML and Status Methods.
+
+ This function is called by the CORBA layer to get the
+ XML status of the MWDriver.
+ */
+
+ //@{
+
+public:
+ ///
+ void write_XML_status();
+
+
+ /**
+ If you want to display information about status of some
+ results variables of your solver, you have to dump a string in
+ ASCII, HTML or XML format out of the following method.
+ The iMW interface will be in charge of displaying this information
+ on the user's browser.
+ */
+
+ virtual char* get_XML_results_status(void );
+
+private:
+
+ ///
+ char* get_XML_status();
+
+ ///
+ char* get_XML_job_information();
+
+ ///
+ char* get_XML_problem_description();
+
+ ///
+ char* get_XML_interface_remote_files();
+
+ ///
+ char* get_XML_resources_status();
+
+ ///
+ const char *xml_filename; // JGS
+
+ ///
+ const char *xml_menus_filename;
+
+ ///
+ const char *xml_jobinfo_filename;
+
+ ///
+ const char *xml_pbdescrib_filename;
+
+ /// Set the current machine information
+ void get_machine_info();
+
+ /// Returns a pointer to the machine's Arch
+ char *get_Arch(){ return Arch; }
+
+ /// Returns a pointer to the machine's OpSys
+ char *get_OpSys(){ return OpSys; }
+
+ /// Returns a pointer to the machine's IPAddress
+ char *get_IPAddress(){ return IPAddress; }
+
+ ///
+ double get_CondorLoadAvg(){ return CondorLoadAvg; }
+
+ ///
+ double get_LoadAvg(){ return LoadAvg; }
+
+ ///
+ int get_Memory(){return Memory;}
+
+ ///
+ int get_Cpus(){return Cpus;}
+
+ ///
+ int get_VirtualMemory(){return VirtualMemory;}
+
+ ///
+ int get_Disk(){return Disk;}
+
+ ///
+ int get_KFlops(){return KFlops;}
+
+ ///
+ int get_Mips(){return Mips;}
+
+ ///
+ char Arch[64];
+
+ ///
+ char OpSys[64];
+
+ ///
+ char IPAddress[64];
+
+ ///
+ double CondorLoadAvg;
+
+ ///
+ double LoadAvg;
+
+ ///
+ int Memory;
+
+ ///
+ int Cpus;
+
+ ///
+ int VirtualMemory;
+
+ ///
+ int Disk;
+
+ ///
+ int KFlops;
+
+ ///
+ int Mips;
+
+ /// Utility functions used by get_machine info
+ int check_for_int_val(char* name, char* key, char* value);
+ double check_for_float_val(char* name, char* key, char* value);
+ int check_for_string_val(char* name, char* key, char* value);
+
+#endif
+
+ /// The name of the machine the worker is running on.
+ char mach_name[64];
+
+ /// for measuring network connectivity
+ double defaultTimeInterval;
+ int defaultIterations;
+ int defaultPortNo;
+
+#ifdef MEASURE
+ // Gather performance measurement information at runtime
+public:
+ // read/write measurement files
+ void _measure_read_options(const char* opt_fname);
+ void _measure_dump_header();
+ void _measure_dump_records();
+private:
+ // Do the measurement
+ void _measure();
+ // Reset the numbers
+ void _measure_reset();
+
+private:
+ // Names for the measurement option and record files
+ // We want to make the record file unique across different runs, so better
+ // add the ProcID part. But how to get the $(Cluster).$(Process) part?
+ // Here is Peter's method: use _ProcID_$(Cluster).$(Process) in the
+ // argument line in the master's submit file, and Condor will substitute
+ // them into the real ProcID before it executes the master executable,
+ // so that I can read this from argv.
+ // Suggestion from Peter: don't make this with fixed argc position.
+ char _measure_opt_file_name[_POSIX_PATH_MAX]; // = "_measure_opt";
+ char _measure_rec_fname_prefix[_POSIX_PATH_MAX]; // = "_measure_rec";
+ char _measure_ProcID_prefix[_POSIX_PATH_MAX]; // = "_ProcID.";
+ char _measure_rec_file_name[_POSIX_PATH_MAX];
+
+ // Time intervals to read options and dump measurement record (append)
+ int _measure_read_opt_interval; // = 300;
+ int _measure_dump_rec_interval; // = 120;
+ time_t _measure_last_read_opt_time;
+ time_t _measure_last_dump_rec_time;
+
+ // Recent queue statistics
+ // int _measure_num_worker; // = workers->number();
+ // int _measure_num_task_TODO; // = todo->number();
+ int _measure_num_task_Done;
+
+ // Recent master performance
+ double _measure_master_recv_time; // time used for mainloop's recv()
+ double _measure_master_recv_cpu_time; // CPU time used for mainloop's recv()
+ double _measure_master_wall_time; // time elapsed
+ double _measure_master_cpu_time; // CPU time (both user and system)
+ double _measure_master_act_on_completed_task_time; // Time in user code
+ double _measure_master_act_on_completed_task_cpu_time;// CPU time in user code
+
+ // Performance of recent finished tasks
+ double _measure_task_RoundTrip_time; // time from sending task to deleting it
+ double _measure_task_MP_master_time; // time used when master packing/sending
+ double _measure_task_MP_worker_time; // time used when worker unpacking/recving
+ double _measure_task_MP_worker_cpu_time; // CPU time used when worker unpacking/recving
+ double _measure_task_Exe_wall_time; // time elapsed when worker executing task
+ double _measure_task_Exe_cpu_time; // CPU time when worker executing task
+
+ // Below are adaptation logic
+ int _measure_use_adaptation;
+ // To keep track of the master and worker utilization
+ double _measure_master_wait_rate;
+ int _measure_master_busy_times;
+ int _measure_master_wait_times;
+ MWWorkerID *_measure_current_worker;
+ int _measure_target_num_workers;
+
+ // Adapt the number of workers when necessary:
+ // assumes that it's called in the mainloop (can access w that just returns a RESULT)
+ // also assumes that it can access the most recent measurement numbers
+ void _measure_adapt();
+ void _measure_remove_worker();
+#endif
+
+public:
+ /* Send an asynchronous UPDATE_FROM_DRIVER message to the worker
+ -2 to send to all workers
+ -1 to send to current worker
+ >0 to send to a specific worker
+ User should override pack_update if some data needs to be sent with update.
+ */
+ void prepare_update(int mode);
+
+ /* user packs update data here. Used in conjunction with prepare_update */
+ virtual void pack_update(){};
+
+ /* user tells Driver to send a DRIVER_UPDATE message to the current worker
+ * from who a task result or async message has been send */
+ int send_update_message();
+
+ /* user tells Driver to send a DRIVER_UPDATE message to a specific worker */
+ int send_update_message_to(int worker);
+};
+
+/// This is the function allowing the workers to be sorted by KFlops
+MWKey kflops( MWWorkerID * );
+
+/// This is the function allowing the workers to be sorted by benchmarkresult
+MWKey benchmark_result( MWWorkerID * );
+
+#endif
+
+
diff --git a/MW/src/MWGroup.C b/MW/src/MWGroup.C
new file mode 100644
index 0000000..2909bc7
--- /dev/null
+++ b/MW/src/MWGroup.C
@@ -0,0 +1,99 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#include "MWGroup.h"
+
+MWGroup::MWGroup ( int grps )
+{
+ maxGroups = grps;
+ group = new bool[maxGroups];
+ for ( int i = 0; i < maxGroups; i++ )
+ group[i] = FALSE;
+}
+
+MWGroup::~MWGroup ( )
+{
+ delete []group;
+}
+
+void
+MWGroup::join ( int num )
+{
+ if ( num >= 0 && num < maxGroups )
+ group[num] = TRUE;
+}
+
+void
+MWGroup::leave ( int num )
+{
+ if ( num >= 0 && num < maxGroups )
+ group[num] = FALSE;
+}
+
+bool
+MWGroup::belong ( int num )
+{
+ if ( num >= 0 && num < maxGroups )
+ return group[num];
+
+ return FALSE;
+}
+
+bool
+MWGroup::doesOverlap ( MWGroup *grp )
+{
+ for ( int i = 0; i < maxGroups; i++ )
+ {
+ if ( belong ( i ) && grp->belong ( i ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+MWGroup::write_checkpoint ( FILE *fp )
+{
+ int num = 0;
+ int i;
+ for ( i = 0; i < maxGroups; i++ )
+ if ( belong ( i ) ) num++;
+ fprintf ( fp, "%d ", num );
+
+ for ( i = 0; i < maxGroups; i++ )
+ if ( belong ( i ) )
+ fprintf ( fp, "%d ", i );
+ fprintf ( fp, "\n" );
+}
+
+void
+MWGroup::read_checkpoint ( FILE *fp )
+{
+ int i, temp;
+ int gp;
+ fscanf ( fp, "%d ", &temp );
+ for ( i = 0; i < temp; i++ )
+ {
+ fscanf ( fp, "%d ", &gp );
+ join ( gp );
+ }
+}
diff --git a/MW/src/MWGroup.h b/MW/src/MWGroup.h
new file mode 100644
index 0000000..0a1ef84
--- /dev/null
+++ b/MW/src/MWGroup.h
@@ -0,0 +1,49 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWGROUP_H
+#define MWGROUP_H
+
+#include "MW.h"
+
+/** This is a simple class to keep track of what workclass/group a
+ task or worker belongs to. It is not called directly by the application.
+*/
+
+class MWGroup
+{
+ private:
+ bool *group;
+ int maxGroups;
+
+ public:
+ MWGroup ( int grp );
+ ~MWGroup ( );
+ void join ( int num );
+ void leave ( int num );
+ bool belong ( int num );
+ bool doesOverlap ( MWGroup *grp );
+ void write_checkpoint ( FILE *fp );
+ void read_checkpoint ( FILE *fp );
+};
+#endif /*MWGROUP_H*/
diff --git a/MW/src/MWList.C b/MW/src/MWList.C
new file mode 100644
index 0000000..9598cd3
--- /dev/null
+++ b/MW/src/MWList.C
@@ -0,0 +1,873 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/**************************************************************************
+ * Implementation of MWListElement, MWIndex, MWIndexList, MWList *
+ **************************************************************************/
+
+#include "MWList.h"
+
+#if 0
+
+/** Implementation of MWListElement<ObjType> **/
+
+template <class ObjType>
+MWListElement<ObjType>::MWListElement(ObjType *itemPtr, double sortKey)
+{
+ obj= itemPtr;
+ key = sortKey;
+ next = this;
+ prev = this;
+}
+
+template <class ObjType>
+MWListElement<ObjType>::~MWListElement()
+{
+ /* Nothing */
+}
+
+/** Implementation of MWIndex<ObjType> **/
+template <class ObjType>
+MWIndex<ObjType>::MWIndex<ObjType>()
+{
+ /* Nothing */
+}
+
+template <class ObjType>
+MWIndex<ObjType>::~MWIndex<ObjType>()
+{
+ /* Nothing */
+}
+
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndex<ObjType>::Split()
+{
+ int i;
+
+ if (this->num<2)
+ return NULL;
+
+ MWListElement<ObjType> * current = this->first->prev;
+
+ /* Walk through the list until we meet the half point */
+ for (i=0; i<num/2; i++)
+ current = current->next;
+
+ /* Create a new index for the second half */
+ MWIndex<ObjType> * i2 = new MWIndex<ObjType>;
+ if (i2 == NULL)
+ return NULL;
+
+ i2->num = num - i;
+ i2->first = current->next;
+ i2->lower = current->key; /* must not leave space between boundaries */
+ i2->last = this->last;
+ i2->upper = this->upper;
+
+ /* Update the current index */
+ this->num = num/2;
+ this->last = current;
+ this->upper = current->key;
+
+ /* return the new index, which should be inserted into index list */
+ return i2;
+}
+
+/* split an index into many smaller ones whose sizes <= bucket_size */
+template <class ObjType>
+void
+MWIndex<ObjType>::SplitTo(MWIndexList<ObjType>* ilist, int bucket_size)
+{
+ if (num < bucket_size)
+ return;
+ else {
+ ilist->Split(this);
+ this->SplitTo(ilist, bucket_size);
+ this->next->SplitTo(ilist, bucket_size);
+ }
+}
+
+/* Balance the current index with the next index, either split or merge,
+ * to make small buckets together, and cut large buckets into halves.
+ * Return ptr to new index (current when splitting or next when merging) */
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndex<ObjType>::BalanceNext(MWIndexList<ObjType>* ilist, int bucket_size)
+{
+ /* Need to split */
+ if (this->num > bucket_size) {
+ MWIndex<ObjType> * next = this->next;
+ this->SplitTo(ilist, bucket_size+1);
+ return next;
+ }
+
+ /* Already the end of index list */
+ if (this->next == ilist->dummy)
+ return this->next;
+
+ /* Need to merget */
+ MWIndex<ObjType>* next_ind = this->next;
+ if (this->num + next_ind->num < bucket_size+1) {
+ return ilist->Merge(this);
+ } else {
+ /* Nothing to be changed */
+ return this->next;
+ }
+}
+
+/** Implementation of MWIndexList<ObjType> **/
+template <class ObjType>
+MWIndexList<ObjType>::MWIndexList()
+{
+ dummy = new MWIndex<ObjType>();
+ if (dummy == NULL) {
+ MWprintf(10, "MWList::Can't initialize the list during object construction.\n");
+ return;
+ }
+ dummy->num = 0;
+ dummy->next = dummy;
+ dummy->prev = dummy;
+ dummy->lower = -DBL_MAX;
+ dummy->upper = DBL_MAX;
+ dummy->first = NULL;
+ dummy->last = NULL;
+
+ num = 0;
+}
+
+template <class ObjType>
+MWIndexList<ObjType>::~MWIndexList()
+{
+ MWIndex<ObjType>* ptr = dummy;
+
+ while (num !=0) {
+ ptr = ptr->next;
+ delete ptr;
+ num --;
+ }
+ delete dummy;
+
+ MWprintf(10, "MWIndexList destructed.\n");
+}
+
+/* Build index for the list, split index whose number >= bucket_size,
+ * and merge adjacent index whose number < 0.25 * bucket_size */
+template <class ObjType>
+void
+MWIndexList<ObjType>::BuildIndex(MWList<ObjType>* list, int bucket_size)
+{
+ MWprintf(10, "MWIndexList::BuildIndex()\n");
+
+ if (list->Number() < BUCKET_SIZE/2) {
+ MWprintf(10, "MWIndexList:: \
+ Will not build index when the list is still short.\n");
+ return;
+ }
+
+ if (num == 0) { /* create index */
+ list->Sort();
+
+ /* create the first index for the whole list */
+ MWIndex<ObjType> * ind = new MWIndex<ObjType>;
+ ind->num = list->Number();
+ ind->upper = DBL_MAX;
+ ind->lower = -DBL_MAX;
+ ind->first = list->dummy->next;
+ ind->last= list->dummy->prev;
+
+ /* Insert into index list */
+ dummy->next = ind;
+ ind->next = dummy;
+ dummy->prev = ind;
+ ind->prev = dummy;
+
+ num ++;
+
+ /* split into small enough buckets */
+ ind->SplitTo(this, bucket_size);
+
+ } else {
+ /* balance index items */
+ MWIndex<ObjType> * ind = dummy->next;
+
+ while ( (ind != this->dummy) && (ind != NULL) ) {
+ ind = ind->BalanceNext(this, bucket_size);
+ }
+ }
+}
+
+template <class ObjType>
+void
+MWIndexList<ObjType>::Split(MWIndex<ObjType>* index)
+{
+ MWIndex<ObjType> * another = index->Split();
+ index->next->prev = another;
+ another->next = index->next;
+ index->next = another;
+ another->prev = index;
+
+ num ++;
+}
+
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndexList<ObjType>::IndexFor(double key)
+{
+ MWIndex<ObjType> * ptr = dummy;
+ for (int i=0; i<num; i++) {
+ ptr = ptr->next;
+ if ( (ptr->upper >= key) && (ptr->lower <= key) )
+ return ptr;
+ }
+ return NULL;
+}
+
+/* Merge two index, and delete any empty index */
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndexList<ObjType>::Merge(MWIndex<ObjType> * i1)
+{
+ if (num == 1) {/* Can't merge */
+ if (i1->num == 0) { /* Delete i1 then */
+ dummy->next = dummy->prev = dummy;
+ num = 0;
+ delete i1;
+ return NULL;
+ }
+ }
+
+ if (i1->next != dummy) {
+ /* need to merge with it's next */
+ MWIndex<ObjType> * next_ind = i1->next;
+ i1->num = i1->num + next_ind->num;
+ i1->last = next_ind->last;
+ i1->upper = next_ind->upper;
+
+ /* remove the item from the list */
+ next_ind->next->prev = i1;
+ i1->next = next_ind->next;
+ delete next_ind;
+ num --;
+ }
+
+ return i1;
+}
+
+template <class ObjType>
+void
+MWIndexList<ObjType>::Display()
+{
+ MWIndex<ObjType> * ind = dummy;
+ int total = 0;
+ for (int i=0; i<num; i++) {
+ ind = ind->next;
+ if (ind == NULL) {
+ MWprintf(10, "MWList:: Bad problem, index list broken.\n");
+ }
+
+ total += ind->num;
+ if (ind->num > 0) {
+ MWprintf(10, "[%d] num=%4d lower=%12.2f\tupper=%12.2f\tfirst=%12.2f\tlast=%12.2f\n",
+ i, ind->num, ind->lower, ind->upper, ind->first->key, ind->last->key);
+ }
+ }
+ MWprintf(10, "Total num = %d.\n", total);
+}
+
+/** Implementation of MWList<ObjType> **/
+
+/* The empty list contains a dummy element which has a null ptr
+ * to an object. dummy->next will be the first obj, dummy->prev
+ * will be the last obj when the list is not empty. */
+template <class ObjType>
+MWList<ObjType>::MWList()
+{
+ dummy = new MWListElement<ObjType>(NULL, -DBL_MAX);
+ if (dummy == NULL) {
+ MWprintf(10, "MWList::Can't initialize the list during object construction.\n");
+ return;
+ }
+ dummy->next = dummy;
+ dummy->prev = dummy;
+
+ current = dummy;
+ num = 0;
+
+ /* Indexing */
+ sorted = false;
+ index = NULL;
+}
+
+template <class ObjType>
+MWList<ObjType>::~MWList()
+{
+ if (num == 0)
+ return;
+ current = dummy->next;
+ while (RemoveCurrent() != NULL); // delete all the list elements
+ delete dummy;
+}
+
+template <class ObjType>
+bool
+MWList<ObjType>::IsEmpty()
+{
+ return (num == 0);
+}
+
+template <class ObjType>
+int
+MWList<ObjType>::Number()
+{
+ return num;
+}
+
+template <class ObjType>
+ObjType*
+MWList<ObjType>::First()
+{
+ if (num == 0)
+ return NULL;
+
+ current = dummy->next;
+ return current->obj;
+}
+
+template <class ObjType>
+ObjType*
+MWList<ObjType>::Last()
+{
+ if (num == 0)
+ return NULL;
+
+ current = dummy->prev;
+ return current->obj;
+}
+
+template <class ObjType>
+bool
+MWList<ObjType>::BeforeHead()
+{
+ return (current == dummy);
+}
+
+template <class ObjType>
+bool
+MWList<ObjType>::AfterEnd()
+{
+ return (current == dummy);
+}
+
+template <class ObjType>
+void
+MWList<ObjType>::ToHead()
+{
+ current = dummy->next;
+}
+
+template <class ObjType>
+void
+MWList<ObjType>::ToEnd()
+{
+ current = dummy->prev;
+}
+
+/* Return the current object, unless currently at head or end */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Current()
+{
+ if (num==0)
+ return NULL;
+
+ if (current == dummy)
+ return NULL;
+
+ return current->obj;
+}
+
+/* Return the position, can be used to remove a particular element */
+template <class ObjType>
+MWListElement<ObjType> *
+MWList<ObjType>::CurPosition()
+{
+ return current;
+}
+
+/* Advance the current ptr, and return the new obj that current pointed to */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Next()
+{
+ current = current->next;
+ if (current== dummy)
+ return NULL;
+ else return current->obj;
+}
+
+/* Retreat the current ptr, and return the new obj that current pointed to */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Prev()
+{
+ current = current->prev;
+ if (current->prev == dummy)
+ return NULL;
+ else return current->obj;
+}
+
+/* Remove an element from the list */
+template <class ObjType>
+void
+MWList<ObjType>::Remove(MWListElement<ObjType> * item)
+{
+ if ((item == dummy)||(num == 0)) {
+ MWprintf(10, "MWList::Can't remove the current element from empty list.\n");
+ return;
+ }
+
+ /* Update index */
+ if (index != NULL) {
+ MWIndex<ObjType> * ind = index->IndexFor(item->key);
+ if (ind->num == 1)
+ index->Merge(ind);
+
+ if (ind->num > 1) {
+ if (item == ind->last)
+ ind->last = item->prev;
+ if (item == ind->first)
+ ind->first = item->next;
+ } else {
+ ind->first = ind->last = NULL;
+ }
+
+ ind->num --;
+ }
+
+ /* Remove the item */
+ item->prev->next = item->next;
+ item->next->prev = item->prev;
+ delete item;
+ num --;
+
+ if ((num == 0))
+ ClearIndex();
+}
+
+/* Remove the current element, and return the obj it points to.
+ * The current pointer will become the previous element, or if removing
+ * the first element, the dummy position */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::RemoveCurrent()
+{
+ if (num == 0) {
+ MWprintf(10, "MWList::Can't remove any element from empty list.\n");
+ return NULL;
+ }
+
+ ObjType * newObj = current->obj;
+ current = current->prev;
+ Remove(current->next);
+ return newObj;
+}
+
+/* Rewind to head position, remove the first element,
+ * and return the object it points to. - to keep compatible with the old API*/
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Remove()
+{
+ if (num == 0) {
+ MWprintf(10, "MWList::Can't remove any element from empty list.\n");
+ return NULL;
+ }
+
+ ObjType * newObj = dummy->next->obj;
+ Remove(dummy->next);
+ current = dummy;
+ return newObj;
+}
+
+/* Pop the first element from the list */
+template <class ObjType>
+ObjType*
+MWList<ObjType>::Pop()
+{
+ return Remove();
+}
+
+/* Append an object at the end of the list */
+template <class ObjType>
+MWListElement<ObjType>*
+MWList<ObjType>::Append(ObjType *obj)
+{
+ MWListElement<ObjType> * item = new MWListElement<ObjType>(obj, 0.0);
+
+ if (item == NULL)
+ return NULL;
+
+ dummy->prev->next = item;
+ item->prev = dummy->prev;
+ dummy->prev = item;
+ item->next = dummy;
+ current = item;
+ num ++;
+
+ if (num == 1)
+ sorted = true;
+
+ if (sorted) { /* Update sorted */
+ if ( (num>1) && (dummy->prev->prev->key > 0.0) ) {
+ sorted = false;
+ if (index != NULL)
+ ClearIndex();
+ } else if (index != NULL) { /* Update index */
+ MWIndex<ObjType> * ind = index->IndexFor(0.0);
+ if (ind->num == 1)
+ index->Merge(ind);
+
+ if (ind->num > 1) {
+ if (item == ind->last)
+ ind->last = item->prev;
+ if (item == ind->first)
+ ind->first = item->next;
+ } else {
+ ind->first = ind->last = NULL;
+ }
+
+ ind->num --;
+ }
+ }
+
+ return item;
+}
+
+/* Prepend an object at the head of the list */
+template <class ObjType>
+MWListElement<ObjType>*
+MWList<ObjType>::Prepend(ObjType *obj)
+{
+ MWListElement<ObjType> * item = new MWListElement<ObjType>(obj, 0.0);
+
+ if (item == NULL)
+ return NULL;
+
+ dummy->next->prev = item;
+ item->next = dummy->next;
+ dummy->next = item;
+ item->prev = dummy;
+ current = item;
+ num ++;
+
+ if (num == 1)
+ sorted = true;
+
+ if (sorted) { /* Update sorted */
+ if ( (num>1) && (dummy->next->next->key < 0.0) ) {
+ sorted = false;
+ MWprintf(10, "MWList becomes not sorted.\n");
+ if (index != NULL)
+ ClearIndex();
+ } else if (index != NULL) { /* Update index */
+ MWIndex<ObjType> * ind = index->IndexFor(0.0);
+ if (ind->num == 1)
+ index->Merge(ind);
+
+ if (ind->num > 1) {
+ if (item == ind->last)
+ ind->last = item->prev;
+ if (item == ind->first)
+ ind->first = item->next;
+ } else {
+ ind->first = ind->last = NULL;
+ }
+
+ ind->num --;
+ }
+ }
+
+ return item;
+}
+
+template <class ObjType>
+void
+MWList<ObjType>::Display()
+{
+ MWprintf(80, "Number = %d\n", num);
+#if 0
+ MWListElement<ObjType> *p;
+
+ MWprintf(80, "<< -- \n");
+ p = dummy->next;
+ while (p!=dummy){
+ MWprintf(80, " %f\t", p->key);
+ p->obj->Display();
+ p = p->next;
+ }
+ MWprintf(80, "-- >>\n");
+#endif
+}
+
+/* Add an object into the list in a sorted order */
+template <class ObjType>
+void
+MWList<ObjType>::SortedInsert(ObjType *obj, double key)
+{
+ MWListElement<ObjType> * ptr;
+
+ if ( (sorted == false) && (num > 0) ) {
+ MWprintf(10, "MWList::SortedInsert into unsorted list.\n");
+ exit(1);
+ }
+
+ if (index != NULL) { /* indexed */
+ IndexedInsert(obj, key);
+ return;
+ }
+
+ /* If not indexed */
+ if (num == 0) {
+ MWListElement<ObjType>* ele = new MWListElement<ObjType>(obj, key);
+ dummy->next = dummy->prev = ele;
+ ele->next = ele->prev = dummy;
+ num ++;
+ sorted = true;
+ } else {
+ /* walk through the list to find a place to insert */
+ ptr = dummy->next;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ MWListElement<ObjType> * item =
+ new MWListElement<ObjType>(obj, key);
+ /* Insert before ptr */
+ ptr->prev->next = item;
+ item->prev = ptr->prev;
+ item->next = ptr;
+ ptr->prev = item;
+ num ++;
+
+ /* Build index when there are already many elements */
+ if ( (num > BUCKET_SIZE) && (index == NULL) )
+ this->BuildIndex();
+ }
+}
+
+/* Delete the first item with given key from the sorted list */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::SortedRemove(double key)
+{
+ MWListElement<ObjType> * ptr;
+
+ if ( (sorted == false) && (num > 0) ) {
+ MWprintf(10, "MWList::SortedRemove from unsorted list.\n");
+ return NULL;
+ }
+
+ if (index != NULL) /* indexed */
+ return IndexedRemove(key);
+
+ /* If not indexed */
+ if (num == 0) {
+ return NULL;
+ } else {
+ /* walk through the list to find the element with given key */
+ ptr = dummy->next;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ if ( (key < ptr->key) || (ptr == dummy) ) /* not found */
+ return NULL;
+
+ /* delete ptr*/
+ ObjType * obj = ptr->obj;
+
+ ptr->prev->next = ptr->next;
+ ptr->next->prev = ptr->prev;
+ delete ptr;
+ num --;
+
+ return obj;
+ }
+}
+
+/* With the help of index, add an object into an ordered list */
+template <class ObjType>
+void
+MWList<ObjType>::IndexedInsert(ObjType *obj, double key)
+{
+ static int newly_inserted = 0;
+
+ MWIndex<ObjType> * ind = index->IndexFor(key);
+ if (ind == NULL) {
+ MWprintf(10, "MWList::IndexedInsert() can't find an index for key = %f.\n", key);
+ return;
+ }
+ /* walk through the list to find a place to insert */
+ MWListElement<ObjType>* ptr = ind->first;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ MWListElement<ObjType> * item =
+ new MWListElement<ObjType>(obj, key);
+
+ /* Insert before ptr */
+ ptr->prev->next = item;
+ item->prev = ptr->prev;
+ item->next = ptr;
+ ptr->prev = item;
+ ind->num ++;
+ num ++;
+
+ /* Need to update the index */
+ if (ptr == ind->last->next)
+ ind->last = item;
+ if (ptr == ind->first)
+ ind->first = item;
+
+ /* Balance */
+ newly_inserted ++;
+
+ if (newly_inserted > BUCKET_SIZE) {
+ BuildIndex();
+ newly_inserted = 0;
+ }
+
+}
+
+/* With the help of index, add an object into an ordered list */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::IndexedRemove(double key)
+{
+ static int newly_removed = 0;
+
+ if (num == 0)
+ return NULL;
+
+ MWIndex<ObjType> * ind = index->IndexFor(key);
+ if (ind == NULL) {
+ MWprintf(10, "MWList::IndexedRemove() can't find an index.\n");
+ return NULL;
+ }
+
+ /* walk through the list to find the element with given key */
+ MWListElement<ObjType> * ptr = ind->first;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ if ( (key < ptr->key) || (ptr == dummy) ) /* not found */
+ return NULL;
+
+ /* Need to update the index */
+ if (ind->num == 1)
+ index->Merge(ind);
+
+ if (ind->num > 1) {
+ if (ptr == ind->last)
+ ind->last = ptr->prev;
+ if (ptr == ind->first)
+ ind->first = ptr->next;
+ } else {
+ ind->first = ind->last = NULL;
+ }
+
+ /* delete ptr*/
+ ObjType * obj = ptr->obj;
+ ptr->prev->next = ptr->next;
+ ptr->next->prev = ptr->prev;
+ delete ptr;
+ ind->num --;
+ num --;
+
+ /* Balance */
+ if (num == 0)
+ ClearIndex();
+ else {
+ newly_removed ++;
+ if (newly_removed > BUCKET_SIZE) {
+ BuildIndex();
+ newly_removed = 0;
+ }
+ }
+
+ return obj;
+}
+
+/* Sort the list */
+template <class ObjType>
+void
+MWList<ObjType>::Sort()
+{
+ if (sorted == true)
+ return;
+
+ MWList<ObjType> * list = new MWList<ObjType>;
+ ObjType * obj;
+ double key;
+
+ int inserted = 0;
+ while (num > 0) {
+ obj = dummy->next->obj;
+ key = dummy->next->key;
+ list->SortedInsert(obj, key);
+ Remove(dummy->next);
+ inserted ++;
+
+ /* Use index to accelerate insertion */
+ if ( (index == NULL)&&(inserted > BUCKET_SIZE/2) ) {
+ list->BuildIndex();
+ inserted = 0;
+ }
+ }
+
+ sorted = true;
+}
+
+/* Build index */
+template <class ObjType>
+void
+MWList<ObjType>::BuildIndex()
+{
+ if (index == NULL)
+ index = new MWIndexList<ObjType>;
+
+ index->BuildIndex(this);
+ index->Display();
+}
+
+/* Build index */
+template <class ObjType>
+void
+MWList<ObjType>::ClearIndex()
+{
+ if (index == NULL)
+ return;
+
+ delete index;
+ index = NULL;
+}
+
+#endif
diff --git a/MW/src/MWList.h b/MW/src/MWList.h
new file mode 100644
index 0000000..1d8f77a
--- /dev/null
+++ b/MW/src/MWList.h
@@ -0,0 +1,1088 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* MWList.h: rewrite to make MWListElement and MWList into template classes.
+ */
+
+#ifndef MWLIST_H
+#define MWLIST_H
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+#include "MW.h"
+
+#define BUCKET_SIZE 4096
+
+/* MWListElement defines the <key, item> pair for actual data.
+ * The key is used as priority, item is the ptr to actual object. */
+template <class ObjType> class MWList;
+template <class ObjType> class MWIndex;
+template <class ObjType> class MWIndexList;
+
+template <class ObjType>
+class MWListElement
+{
+friend class MWList<ObjType>;
+friend class MWIndex<ObjType>;
+friend class MWIndexList<ObjType>;
+
+public:
+ MWListElement(ObjType *itemPtr = NULL, double key = 0.0);
+ ~MWListElement();
+
+private:
+ MWListElement<ObjType> *next;
+ MWListElement<ObjType> *prev;
+ ObjType *obj;
+ double key;
+};
+
+/* MWIndex defines an index into MWList */
+template <class ObjType>
+class MWIndex
+{
+friend class MWList<ObjType>;
+friend class MWIndexList<ObjType>;
+
+public:
+ MWIndex();
+ ~MWIndex();
+
+ /* split the index into two halves, create a new index to the
+ * second half and returns the ptr to the new index */
+ MWIndex<ObjType>* Split();
+ void SplitTo(MWIndexList<ObjType>* ilist, int bucket_size);
+
+ /* Split the index, or merge it with the next index to make
+ * the index involved have their size close to bucket_size.
+ * Return value:
+ * * if splitted, then return the ptr to newly created index;
+ * * if merged, then return the ptr to merged index;
+ * * if not changed, then return the ptr to the next index. */
+ MWIndex<ObjType>* BalanceNext(MWIndexList<ObjType>* ilist, int bucket_size);
+
+private:
+ /* How many elements are included by this index */
+ int num;
+
+ /* bounds and boundary ptr to the actual elements */
+ double upper;
+ double lower;
+ MWListElement<ObjType> * first;
+ MWListElement<ObjType> * last;
+
+ /* ptr to other index */
+ MWIndex<ObjType> * next;
+ MWIndex<ObjType> * prev;
+};
+
+/* MWIndexList defines a list of index for a list */
+template <class ObjType>
+class MWIndexList
+{
+friend class MWList<ObjType>;
+friend class MWIndex<ObjType>;
+
+public:
+ MWIndexList();
+ ~MWIndexList();
+
+ /* Build index for the list, split index whose number >= bucket_size,
+ * and merge adjacent index whose number < 0.25 * bucket_size */
+ void BuildIndex(MWList<ObjType>* list, int bucket_size = BUCKET_SIZE);
+
+ /* Split an index and insert the new index into the list */
+ void Split(MWIndex<ObjType>* index);
+
+ /* Search for the index for key */
+ MWIndex<ObjType>* IndexFor(double key);
+
+ /* Merge an index with its neibough */
+ MWIndex<ObjType>* Merge(MWIndex<ObjType>* i1);
+
+ /* Remove an empty index */
+ bool RemoveEmptyIndex(MWIndex<ObjType> * ind);
+
+ void Display();
+
+private:
+ /* number of index in the list */
+ int num;
+ MWIndex<ObjType> * dummy;
+};
+
+/* MWList defines a list of items */
+template <class ObjType>
+class MWList
+{
+friend class MWIndexList<ObjType>;
+
+public:
+ MWList(char * name = "dummy_list");
+ virtual ~MWList();
+
+ /* Query */
+ inline char* Name() { return name; };
+ inline bool isSorted() { return sorted; };
+ inline int number() { return num; };
+ inline bool isEmpty() { return num == 0; };
+ int Number(); // number of elements in the list
+ bool IsEmpty(); // is the list empty?
+
+ ObjType * First();
+ ObjType * Last();
+
+ /* Scans */
+ bool BeforeHead();
+ bool AfterEnd();
+
+ void ToHead();
+ void ToEnd();
+
+ ObjType * Current(); /* return the current object */
+ MWListElement<ObjType> * CurPosition();
+ ObjType * Next(); /* advance ptr, return the next object */
+ ObjType * Prev(); /* backup prt, return the prev object */
+
+ /* Removal */
+ ObjType * Pop();
+ /* Rewind, and take item off the front of the list*/
+ ObjType * Remove();
+
+ /* Take the given item off the list */
+ void Remove(MWListElement<ObjType>* item);
+ /* remove the current object from the list */
+ ObjType * RemoveCurrent();
+
+ MWListElement<ObjType>* Append(ObjType *item, double key = 0.0); /* Put item at the end of the list */
+ MWListElement<ObjType>* Prepend(ObjType *obj, double key = 0.0); /* Put item at the head of the list */
+
+ /* Put item into list by order */
+ void SortedInsert(ObjType *item, double key);
+
+ /* Remove first item with key value from list */
+ ObjType* SortedRemove(double key);
+
+ /* Sort and Indexing */
+ void Sort();
+ void BuildIndex();
+ void ClearIndex();
+
+ /* Debug, display */
+ void Display();
+
+ private:
+ int num;
+ char *name;
+ MWListElement<ObjType> *dummy;
+ MWListElement<ObjType> *current;
+
+ /* indexing */
+ bool sorted; /* true after calling Sort() */
+ MWIndexList<ObjType> * index; /* indexed if not NULL */
+
+ /* Indexed insertion */
+ void IndexedInsert(ObjType *item, double key);
+ /* Indexed removal */
+ ObjType * IndexedRemove(double key);
+};
+
+/**************************************************************************
+ * Implementation of MWListElement, MWIndex, MWIndexList, MWList *
+ **************************************************************************/
+
+/** Implementation of MWListElement<ObjType> **/
+
+template <class ObjType>
+MWListElement<ObjType>::MWListElement(ObjType *itemPtr, double sortKey)
+{
+ obj= itemPtr;
+ key = sortKey;
+ next = this;
+ prev = this;
+}
+
+template <class ObjType>
+MWListElement<ObjType>::~MWListElement()
+{
+ /* Nothing */
+}
+
+/** Implementation of MWIndex<ObjType> **/
+template <class ObjType>
+MWIndex<ObjType>::MWIndex()
+{
+ /* Nothing */
+}
+
+template <class ObjType>
+MWIndex<ObjType>::~MWIndex()
+{
+ /* Nothing */
+}
+
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndex<ObjType>::Split()
+{
+ int i;
+
+ if (this->num<2)
+ return NULL;
+
+ MWListElement<ObjType> * current = this->first->prev;
+
+ /* Walk through the list until we meet the half point */
+ for (i=0; i<num/2; i++)
+ current = current->next;
+
+ /* Create a new index for the second half */
+ MWIndex<ObjType> * i2 = new MWIndex<ObjType>;
+ if (i2 == NULL)
+ return NULL;
+
+ i2->num = num - i;
+ i2->first = current->next;
+ i2->lower = current->key; /* must not leave space between boundaries */
+ i2->last = this->last;
+ i2->upper = this->upper;
+
+ /* Update the current index */
+ this->num = num/2;
+ this->last = current;
+ this->upper = current->key;
+
+ /* return the new index, which should be inserted into index list */
+ return i2;
+}
+
+/* split an index into many smaller ones whose sizes <= bucket_size */
+template <class ObjType>
+void
+MWIndex<ObjType>::SplitTo(MWIndexList<ObjType>* ilist, int bucket_size)
+{
+ if (num < bucket_size)
+ return;
+
+ ilist->Split(this);
+ MWIndex<ObjType> * next = this->next;
+
+ this->SplitTo(ilist, bucket_size);
+ next->SplitTo(ilist, bucket_size);
+}
+
+/* Balance the current index with the next index, either split or merge,
+ * to make small buckets together, and cut large buckets into halves.
+ * Return ptr to new index (current when splitting or next when merging) */
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndex<ObjType>::BalanceNext(MWIndexList<ObjType>* ilist, int bucket_size)
+{
+ /* Need to split */
+ if (this->num > bucket_size) {
+ MWIndex<ObjType> * next = this->next;
+ this->SplitTo(ilist, bucket_size+1);
+ return next;
+ }
+
+ /* Already the end of index list */
+ if (this->next == ilist->dummy)
+ return this->next;
+
+ /* Need to merget */
+ MWIndex<ObjType>* next_ind = this->next;
+ if (this->num + next_ind->num < bucket_size+1) {
+ return ilist->Merge(this);
+ } else {
+ /* Nothing to be changed */
+ return this->next;
+ }
+}
+
+/** Implementation of MWIndexList<ObjType> **/
+template <class ObjType>
+MWIndexList<ObjType>::MWIndexList()
+{
+ dummy = new MWIndex<ObjType>();
+ if (dummy == NULL) {
+ MWprintf(10, "MWList::Can't initialize the list during object construction.\n");
+ return;
+ }
+ dummy->num = 0;
+ dummy->next = dummy;
+ dummy->prev = dummy;
+ dummy->lower = -DBL_MAX;
+ dummy->upper = DBL_MAX;
+ dummy->first = NULL;
+ dummy->last = NULL;
+
+ num = 0;
+}
+
+template <class ObjType>
+MWIndexList<ObjType>::~MWIndexList()
+{
+ MWIndex<ObjType>* ptr = dummy;
+
+ while (num !=0) {
+ ptr = ptr->next;
+ delete ptr;
+ num --;
+ }
+ delete dummy;
+
+ MWprintf(10, "MWIndexList destructed.\n");
+}
+
+/* Build index for the list, split index whose number >= bucket_size,
+ * and merge adjacent index whose number < 0.25 * bucket_size */
+template <class ObjType>
+void
+MWIndexList<ObjType>::BuildIndex(MWList<ObjType>* list, int bucket_size)
+{
+ MWprintf(10, "MWIndexList::BuildIndex()\n");
+
+ if (list->Number() < BUCKET_SIZE/2) {
+ MWprintf(10, "MWIndexList:: \
+ Will not build index when the list is still short.\n");
+ return;
+ }
+
+ if (num == 0) { /* create index */
+ list->Sort();
+
+ /* create the first index for the whole list */
+ MWIndex<ObjType> * ind = new MWIndex<ObjType>;
+ ind->num = list->Number();
+ ind->upper = DBL_MAX;
+ ind->lower = -DBL_MAX;
+ ind->first = list->dummy->next;
+ ind->last= list->dummy->prev;
+
+ /* Insert into index list */
+ dummy->next = ind;
+ ind->next = dummy;
+ dummy->prev = ind;
+ ind->prev = dummy;
+
+ num ++;
+
+ /* split into small enough buckets */
+ ind->SplitTo(this, bucket_size);
+
+ } else {
+ /* balance index items */
+ MWIndex<ObjType> * ind = dummy->next;
+
+ while ( (ind != this->dummy) && (ind != NULL) ) {
+ ind = ind->BalanceNext(this, bucket_size);
+ }
+ }
+}
+
+template <class ObjType>
+void
+MWIndexList<ObjType>::Split(MWIndex<ObjType>* index)
+{
+ MWIndex<ObjType> * another = index->Split();
+ index->next->prev = another;
+ another->next = index->next;
+ index->next = another;
+ another->prev = index;
+
+ num ++;
+}
+
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndexList<ObjType>::IndexFor(double key)
+{
+ MWIndex<ObjType> * ptr = dummy;
+ for (int i=0; i<num; i++) {
+ ptr = ptr->next;
+ if ( (ptr->upper >= key) && (ptr->lower <= key) )
+ return ptr;
+ }
+ return NULL;
+}
+
+/* Merge two index, and delete any empty index */
+template <class ObjType>
+MWIndex<ObjType>*
+MWIndexList<ObjType>::Merge(MWIndex<ObjType> * i1)
+{
+ if (num == 1) {/* Can't merge */
+ if (i1->num == 0) { /* Delete i1 then */
+ dummy->next = dummy->prev = dummy;
+ num = 0;
+ delete i1;
+ return NULL;
+ }
+ }
+
+ MWIndex<ObjType> * next_ind = i1->next;
+ while ((i1->next->num == 0) && (i1->next != dummy)) {
+ /* clear empty index until the first non empty index */
+ next_ind = i1->next;
+ i1->next = next_ind->next;
+ delete next_ind;
+ num --;
+ }
+
+ next_ind = i1->next;
+ if (i1->next != dummy) {
+ /* need to merge with it's next */
+ i1->num = i1->num + next_ind->num;
+ i1->last = next_ind->last;
+ i1->upper = next_ind->upper;
+
+ /* remove the item from the list */
+ next_ind->next->prev = i1;
+ i1->next = next_ind->next;
+ delete next_ind;
+ num --;
+ }
+
+ return i1;
+}
+
+/* Merge two index, and delete any empty index */
+template <class ObjType>
+bool
+MWIndexList<ObjType>::RemoveEmptyIndex(MWIndex<ObjType> * ind)
+{
+ if (num > 1) {
+ if (ind->next != dummy) {
+ /* Merge with ind->next */
+ ind->next->prev = ind->prev;
+ ind->prev->next = ind->next;
+ ind->next->lower = ind->lower;
+ } else if (ind->prev != dummy) {
+ /* Merge with ind->prev */
+ ind->prev->next = ind->next;
+ ind->next->prev = ind->prev;
+ ind->prev->upper = ind->upper;
+ }
+ num --;
+ return false;
+ } else {
+ num = 0;
+ return true; /* should ClearIndex() */
+ }
+}
+
+template <class ObjType>
+void
+MWIndexList<ObjType>::Display()
+{
+ MWIndex<ObjType> * ind = dummy;
+ int total = 0;
+ for (int i=0; i<num; i++) {
+ ind = ind->next;
+ if (ind == NULL) {
+ MWprintf(10, "MWList:: Bad problem, index list broken.\n");
+ }
+
+ total += ind->num;
+ if (ind->num > 0) {
+ if (ind->first == NULL)
+ MWprintf(10, "MWList:: Bad error, ind->first == NULL");
+ else if (ind->last == NULL)
+ MWprintf(10, "MWList:: Bad error, ind->last == NULL");
+ else MWprintf(10, "[%d] num=%4d lower=%12.2f\tupper=%12.2f\tfirst=%12.2f\tlast=%12.2f\n",
+ i, ind->num, ind->lower, ind->upper, ind->first->key, ind->last->key);
+ }
+ }
+ MWprintf(10, "Total num = %d.\n", total);
+}
+
+/** Implementation of MWList<ObjType> **/
+
+/* The empty list contains a dummy element which has a null ptr
+ * to an object. dummy->next will be the first obj, dummy->prev
+ * will be the last obj when the list is not empty. */
+template <class ObjType>
+MWList<ObjType>::MWList(char *name)
+{
+ dummy = new MWListElement<ObjType>(NULL, -DBL_MAX);
+ if (dummy == NULL) {
+ MWprintf(10, "MWList::Can't initialize the list during object construction.\n");
+ return;
+ }
+ dummy->next = dummy;
+ dummy->prev = dummy;
+
+ current = dummy;
+ num = 0;
+
+ /* Indexing */
+ sorted = false;
+ index = NULL;
+
+ this->name = (char*)malloc(strlen(name)+1);
+ if (this->name == NULL) {
+ MWprintf(10, "MWList::Can't initialize the list name during construction.\n");
+ return;
+ } else {
+ strcpy(this->name, name);
+ }
+}
+
+template <class ObjType>
+MWList<ObjType>::~MWList()
+{
+ if (num == 0)
+ return;
+ current = dummy->next;
+ while (RemoveCurrent() != NULL); // delete all the list elements
+ delete dummy;
+}
+
+template <class ObjType>
+bool
+MWList<ObjType>::IsEmpty()
+{
+ return (num == 0);
+}
+
+template <class ObjType>
+int
+MWList<ObjType>::Number()
+{
+ return num;
+}
+
+template <class ObjType>
+ObjType*
+MWList<ObjType>::First()
+{
+ if (num == 0)
+ return NULL;
+
+ current = dummy->next;
+ return current->obj;
+}
+
+template <class ObjType>
+ObjType*
+MWList<ObjType>::Last()
+{
+ if (num == 0)
+ return NULL;
+
+ current = dummy->prev;
+ return current->obj;
+}
+
+template <class ObjType>
+bool
+MWList<ObjType>::BeforeHead()
+{
+ return (current == dummy);
+}
+
+template <class ObjType>
+bool
+MWList<ObjType>::AfterEnd()
+{
+ return (current == dummy);
+}
+
+template <class ObjType>
+void
+MWList<ObjType>::ToHead()
+{
+ current = dummy->next;
+}
+
+template <class ObjType>
+void
+MWList<ObjType>::ToEnd()
+{
+ current = dummy->prev;
+}
+
+/* Return the current object, unless currently at head or end */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Current()
+{
+ if (num==0)
+ return NULL;
+
+ if (current == dummy)
+ return NULL;
+
+ return current->obj;
+}
+
+/* Return the position, can be used to remove a particular element */
+template <class ObjType>
+MWListElement<ObjType> *
+MWList<ObjType>::CurPosition()
+{
+ return current;
+}
+
+/* Advance the current ptr, and return the new obj that current pointed to */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Next()
+{
+ current = current->next;
+ if (current== dummy)
+ return NULL;
+ else return current->obj;
+}
+
+/* Retreat the current ptr, and return the new obj that current pointed to */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Prev()
+{
+ current = current->prev;
+ if (current->prev == dummy)
+ return NULL;
+ else return current->obj;
+}
+
+/* Remove an element from the list */
+template <class ObjType>
+void
+MWList<ObjType>::Remove(MWListElement<ObjType> * item)
+{
+ if ((item == dummy)||(num == 0)) {
+ MWprintf(10, "MWList::Can't remove the current element from empty list.\n");
+ return;
+ }
+
+ /* Update index */
+ if (index != NULL) {
+ MWIndex<ObjType> * ind = index->IndexFor(item->key);
+
+ if (ind->num > 1) {
+ if (item == ind->last)
+ ind->last = item->prev;
+ if (item == ind->first)
+ ind->first = item->next;
+ ind->num --;
+ } else {
+ /* ind will become empty after removal */
+ if (index->RemoveEmptyIndex(ind))
+ ClearIndex();
+ }
+ }
+
+ /* Remove the item */
+ if (item->key != 0.0)
+ MWprintf(70, "MWList remove %f.\n", item->key);
+
+ item->prev->next = item->next;
+ item->next->prev = item->prev;
+ delete item;
+ num --;
+}
+
+/* Remove the current element, and return the obj it points to.
+ * The current pointer will become the previous element, or if removing
+ * the first element, the dummy position */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::RemoveCurrent()
+{
+ if (num == 0) {
+ MWprintf(10, "MWList::Can't remove any element from empty list.\n");
+ return NULL;
+ }
+
+ ObjType * newObj = current->obj;
+ current = current->prev;
+ Remove(current->next);
+ return newObj;
+}
+
+/* Rewind to head position, remove the first element,
+ * and return the object it points to. - to keep compatible with the old API*/
+template <class ObjType>
+ObjType *
+MWList<ObjType>::Remove()
+{
+ if (num == 0) {
+ MWprintf(10, "MWList::Can't remove any element from empty list.\n");
+ return NULL;
+ }
+
+ ObjType * newObj = dummy->next->obj;
+ Remove(dummy->next);
+ current = dummy;
+ return newObj;
+}
+
+/* Pop the first element from the list */
+template <class ObjType>
+ObjType*
+MWList<ObjType>::Pop()
+{
+ return Remove();
+}
+
+/* Append an object at the end of the list */
+template <class ObjType>
+MWListElement<ObjType>*
+MWList<ObjType>::Append(ObjType *obj, double key)
+{
+ MWListElement<ObjType> * item = new MWListElement<ObjType>(obj, key);
+
+ if (item == NULL)
+ return NULL;
+
+ dummy->prev->next = item;
+ item->prev = dummy->prev;
+ dummy->prev = item;
+ item->next = dummy;
+ current = item;
+ num ++;
+
+ if (num == 1)
+ sorted = true;
+
+ if (sorted) { /* Update sorted */
+ if ( (num>1) && (dummy->prev->prev->key > key) ) {
+ sorted = false;
+ if (index != NULL)
+ ClearIndex();
+ } else if ( (index != NULL) && (index->num>0) ) {
+ /* Update index */
+ MWIndex<ObjType> * ind = index->dummy->prev;
+ /* ind is the last index entry */
+ ind->last = item;
+ ind->num ++;
+ }
+ }
+
+ return item;
+}
+
+/* Prepend an object at the head of the list */
+template <class ObjType>
+MWListElement<ObjType>*
+MWList<ObjType>::Prepend(ObjType *obj, double key)
+{
+ MWListElement<ObjType> * item = new MWListElement<ObjType>(obj, key);
+
+ if (item == NULL)
+ return NULL;
+
+ dummy->next->prev = item;
+ item->next = dummy->next;
+ dummy->next = item;
+ item->prev = dummy;
+ current = item;
+ num ++;
+
+ if (num == 1)
+ sorted = true;
+
+ if (sorted) { /* Update sorted */
+ if ( (num>1) && (dummy->next->next->key < key) ) {
+ sorted = false;
+ if (index != NULL)
+ ClearIndex();
+ } else if ( (index != NULL) && (index->num > 0) ) {
+ /* Update index */
+ MWIndex<ObjType> * ind = index->dummy->next;
+ /* ind is the first index entry */
+ ind->first = item;
+ ind->num ++;
+ }
+ }
+
+ return item;
+}
+
+template <class ObjType>
+void
+MWList<ObjType>::Display()
+{
+ MWprintf(80, "Number = %d\n", num);
+#if 0
+ MWListElement<ObjType> *p;
+
+ MWprintf(80, "<< -- \n");
+ p = dummy->next;
+ while (p!=dummy){
+ MWprintf(80, " %f\t", p->key);
+ p->obj->Display();
+ p = p->next;
+ }
+ MWprintf(80, "-- >>\n");
+#endif
+}
+
+/* Add an object into the list in a sorted order */
+template <class ObjType>
+void
+MWList<ObjType>::SortedInsert(ObjType *obj, double key)
+{
+ MWListElement<ObjType> * ptr;
+
+ if ( (sorted == false) && (num > 0) ) {
+ MWprintf(10, "MWList::SortedInsert into unsorted list.\n");
+ exit(1);
+ }
+
+ if (index != NULL) { /* indexed */
+ IndexedInsert(obj, key);
+ return;
+ }
+
+ /* If not indexed */
+ if (num == 0) {
+ MWListElement<ObjType>* ele = new MWListElement<ObjType>(obj, key);
+ dummy->next = dummy->prev = ele;
+ ele->next = ele->prev = dummy;
+ num ++;
+ sorted = true;
+ } else {
+ /* walk through the list to find a place to insert */
+ ptr = dummy->next;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ MWListElement<ObjType> * item =
+ new MWListElement<ObjType>(obj, key);
+
+ /* Insert before ptr */
+ // MWprintf(10, "MWList insert %f\n", item->key);
+ ptr->prev->next = item;
+ item->prev = ptr->prev;
+ item->next = ptr;
+ ptr->prev = item;
+ num ++;
+
+ /* Build index when there are already many elements */
+ if ( (num > BUCKET_SIZE) && (index == NULL) )
+ this->BuildIndex();
+ }
+}
+
+/* Delete the first item with given key from the sorted list */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::SortedRemove(double key)
+{
+ MWListElement<ObjType> * ptr;
+
+ if ( (sorted == false) && (num > 0) ) {
+ MWprintf(10, "MWList::SortedRemove from unsorted list.\n");
+ return NULL;
+ }
+
+ if (index != NULL) /* indexed */
+ return IndexedRemove(key);
+
+ /* If not indexed */
+ if (num == 0) {
+ return NULL;
+ } else {
+ /* walk through the list to find the element with given key */
+ ptr = dummy->next;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ if ( (key < ptr->key) || (ptr == dummy) ) /* not found */
+ return NULL;
+
+ /* delete ptr*/
+ ObjType * obj = ptr->obj;
+
+ ptr->prev->next = ptr->next;
+ ptr->next->prev = ptr->prev;
+ delete ptr;
+ num --;
+
+ return obj;
+ }
+}
+
+/* With the help of index, add an object into an ordered list */
+template <class ObjType>
+void
+MWList<ObjType>::IndexedInsert(ObjType *obj, double key)
+{
+ static int newly_inserted = 0;
+
+ MWIndex<ObjType> * ind = index->IndexFor(key);
+ if (ind == NULL) {
+ MWprintf(10, "MWList::IndexedInsert() can't find an index for key = %f.\n", key);
+ return;
+ }
+ /* walk through the list to find a place to insert */
+ MWListElement<ObjType>* ptr = ind->first;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ MWListElement<ObjType> * item =
+ new MWListElement<ObjType>(obj, key);
+
+ /* Insert before ptr */
+ // MWprintf(10, "MWList insert %f\n", item->key);
+ ptr->prev->next = item;
+ item->prev = ptr->prev;
+ item->next = ptr;
+ ptr->prev = item;
+ ind->num ++;
+ num ++;
+
+ /* Need to update the index */
+ if (ptr == ind->last->next)
+ ind->last = item;
+ if (ptr == ind->first)
+ ind->first = item;
+
+ /* Balance */
+ newly_inserted ++;
+
+ if (newly_inserted > BUCKET_SIZE) {
+ BuildIndex();
+ newly_inserted = 0;
+ }
+
+}
+
+/* With the help of index, add an object into an ordered list */
+template <class ObjType>
+ObjType *
+MWList<ObjType>::IndexedRemove(double key)
+{
+ static int newly_removed = 0;
+
+ if (num == 0)
+ return NULL;
+
+ MWIndex<ObjType> * ind = index->IndexFor(key);
+ if (ind == NULL) {
+ MWprintf(10, "MWList::IndexedRemove() can't find an index.\n");
+ return NULL;
+ }
+
+ /* walk through the list to find the element with given key */
+ MWListElement<ObjType> * ptr = ind->first;
+ while ( (ptr != dummy) && (key > ptr->key) )
+ ptr = ptr->next;
+
+ if ( (key < ptr->key) || (ptr == dummy) ) /* not found */
+ return NULL;
+
+ /* Need to update the index */
+ if (ind->num > 1) {
+ if (ptr == ind->last)
+ ind->last = ptr->prev;
+ if (ptr == ind->first)
+ ind->first = ptr->next;
+ ind->num --;
+ } else {
+ /* ind will become empty after removal */
+ if (index->RemoveEmptyIndex(ind))
+ ClearIndex();
+ }
+
+ /* delete ptr*/
+ ObjType * obj = ptr->obj;
+ // MWprintf(70, "MWList remove %f\n", ptr->key);
+ ptr->prev->next = ptr->next;
+ ptr->next->prev = ptr->prev;
+ delete ptr;
+ num --;
+
+ /* Balance */
+ if (index != NULL) {
+ newly_removed ++;
+ if (newly_removed > BUCKET_SIZE) {
+ BuildIndex();
+ newly_removed = 0;
+ }
+ }
+
+ return obj;
+}
+
+/* Sort the list */
+template <class ObjType>
+void
+MWList<ObjType>::Sort()
+{
+ if (sorted == true)
+ return;
+
+ MWList<ObjType> * list = new MWList<ObjType>;
+ ObjType * obj;
+ double key;
+
+ int inserted = 0;
+ while (num > 0) {
+ obj = dummy->next->obj;
+ key = dummy->next->key;
+ list->SortedInsert(obj, key);
+ Remove(dummy->next);
+ inserted ++;
+
+ /* Use index to accelerate insertion */
+ if ( (index == NULL)&&(inserted > BUCKET_SIZE/2) ) {
+ list->BuildIndex();
+ inserted = 0;
+ }
+ }
+
+ sorted = true;
+}
+
+/* Build index */
+template <class ObjType>
+void
+MWList<ObjType>::BuildIndex()
+{
+ if (num < BUCKET_SIZE/2) {
+ MWprintf(10, "MWIndexList:: Will not build index when the list is still short.\n");
+ return;
+ }
+
+ if (index == NULL)
+ index = new MWIndexList<ObjType>;
+
+ index->BuildIndex(this);
+ index->Display();
+}
+
+/* Build index */
+template <class ObjType>
+void
+MWList<ObjType>::ClearIndex()
+{
+ if (index == NULL)
+ return;
+
+ delete index;
+ index = NULL;
+}
+
+#endif // MWLIST_H
diff --git a/MW/src/MWMasterMain.C b/MW/src/MWMasterMain.C
new file mode 100644
index 0000000..56db4e6
--- /dev/null
+++ b/MW/src/MWMasterMain.C
@@ -0,0 +1,43 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/*
+ * This is the master's main function. The whole starts from this point
+ * This was done on 2/2/00 to make MW pure Object Oriented.
+ *
+ * Author:
+ * Sanjeev. R. Kulkarni
+ */
+
+
+
+#include <stdio.h>
+#include "MWDriver.h"
+
+extern MWDriver* gimme_the_master();
+
+int main ( int argc, char *argv[] )
+{
+ MWDriver *driver;
+ driver = gimme_the_master ( );
+ driver->go ( argc, argv );
+}
diff --git a/MW/src/MWStats.C b/MW/src/MWStats.C
new file mode 100644
index 0000000..0740bda
--- /dev/null
+++ b/MW/src/MWStats.C
@@ -0,0 +1,539 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* stats.C
+
+ Implementation of Statistics class
+*/
+
+#include "MWStats.h"
+#include "MWSystem.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+extern int num_completed_tasks;
+
+MWStatistics::MWStatistics() {
+
+ uptimes = new double[MW_MAX_WORKERS];
+ workingtimes = new double[MW_MAX_WORKERS];
+ susptimes = new double[MW_MAX_WORKERS];
+ cputimes = new double[MW_MAX_WORKERS];
+
+ workingtimesnorm = new double[MW_MAX_WORKERS];
+
+ sumbenchmark = new double[MW_MAX_WORKERS];
+ numbenchmark = new int[MW_MAX_WORKERS];
+
+ max_task_result = max_bench_result = 0.0;
+ min_task_result = min_bench_result = DBL_MAX;
+
+ for ( int i=0 ; i<MW_MAX_WORKERS ; i++ ) {
+ uptimes[i] = workingtimes[i] = susptimes[i] = cputimes[i] = 0.0;
+ workingtimesnorm[i] = sumbenchmark[i] = 0.0;
+ numbenchmark[i] = 0;
+ }
+
+ duration = 0;
+ // start in the constructor...
+ starttime = MWSystem::gettimeofday();
+ previoustime = 0.0;
+}
+
+
+MWStatistics::~MWStatistics() {
+
+ delete [] uptimes;
+ delete [] workingtimes;
+ delete [] susptimes;
+ delete [] cputimes;
+
+ delete [] sumbenchmark;
+ delete [] numbenchmark;
+ delete [] workingtimesnorm;
+}
+
+void MWStatistics::write_checkpoint( FILE *cfp, MWList<MWWorkerID> *worlist )
+{
+ /* write out stats for each worker Vid. This is a pain in
+ my ass. We have to find the maximum Vid in the system;
+ in both the old stats and the running workers. Then, for
+ each Vid, we have to sum the old stats + the new running
+ worker stats, and write them out one at a time.... */
+
+ MWWorkerID *wkr; // My eternal temporary workerID...
+ int sn_workers = get_max_vid(); // stats now says max is...
+ int run_workers=0;
+
+ wkr = worlist->First();
+ while ( worlist->AfterEnd() == false )
+ {
+ wkr = worlist->Current();
+ if ( wkr->get_vid() > run_workers )
+ {
+ run_workers = wkr->get_vid();
+ }
+ worlist->Next();
+ }
+ run_workers++; // there are this many running
+
+ int max = 0; // get the max of the two...
+ if ( run_workers > sn_workers ) {
+ max = run_workers;
+ } else {
+ max = sn_workers;
+ }
+
+ MWprintf ( 10, "In checkpointing -- sn: %d, run:%d, max:%d\n", sn_workers, run_workers, max );
+
+ double *u = new double[max];
+ double *w = new double[max];
+ double *s = new double[max];
+ double *c = new double[max];
+ double *wn = new double[max];
+ double *sb = new double[max];
+ int *nb = new int[max];
+
+ int i;
+ for ( i=0 ; i<max ; i++ ) {
+ u[i] = uptimes[i];
+ w[i] = workingtimes[i];
+ s[i] = susptimes[i];
+ c[i] = cputimes[i];
+ wn[i] = workingtimesnorm[i];
+ sb[i] = sumbenchmark[i];
+ nb[i] = numbenchmark[i];
+ }
+
+ double up, wo, su, cp, tn, sumb;
+ int numb;
+
+ wkr = worlist->First();
+ while ( worlist->AfterEnd() == false )
+ {
+ wkr = worlist->Current();
+ wkr->ckpt_stats( &up, &wo, &su, &cp, &tn, &sumb, &numb );
+ u[wkr->get_vid()] += up;
+ w[wkr->get_vid()] += wo;
+ s[wkr->get_vid()] += su;
+ c[wkr->get_vid()] += cp;
+ wn[wkr->get_vid()] += tn;
+ sb[wkr->get_vid()] += sumb;
+ nb[wkr->get_vid()] += numb;
+
+ worlist->Next();
+ }
+
+ double now = MWSystem::gettimeofday();
+
+ fprintf ( cfp, "%d %15.5f\n", max, ((now-starttime)+previoustime) );
+ for ( i=0 ; i<max ; i++ ) {
+ // MWprintf ( 10, "%15.5f %15.5f %15.5f %15.5f\n",
+ // u[i], w[i], s[i], c[i] );
+ fprintf ( cfp, "%15.5f %15.5f %15.5f %15.5f %15.5f %15.5f %d\n",
+ u[i], w[i], s[i], c[i] , wn[i], sb[i], nb[i]);
+ }
+
+ fprintf ( cfp, "%15.5f %15.5f\n", max_bench_result, min_bench_result);
+ fprintf ( cfp, "%15.5f %15.5f\n", max_task_result, min_task_result);
+
+ delete [] u;
+ delete [] w;
+ delete [] s;
+ delete [] c;
+ delete [] wn;
+ delete [] sb;
+ delete [] nb;;
+
+
+}
+
+
+//This is the good one
+void MWStatistics::read_checkpoint( FILE *cfp ) {
+
+ int n=0;
+ int i;
+ fscanf ( cfp, "%d %lf", &n, &previoustime );
+ MWprintf ( 10, "num stats to read: %d prev: %f\n", n, previoustime );
+ for ( i=0 ; i<n ; i++ ) {
+
+ fscanf ( cfp, "%lf %lf %lf %lf %lf %lf %d",
+ &uptimes[i],
+ &workingtimes[i],
+ &susptimes[i],
+ &cputimes[i],
+ &workingtimesnorm[i],
+ &sumbenchmark[i],
+ &numbenchmark[i]);
+
+ MWprintf ( 10, "%d %15.5f %15.5f %15.5f %15.5f %15.5f %15.5f %d\n",
+ i,
+ uptimes[i],
+ workingtimes[i],
+ susptimes[i],
+ cputimes[i],
+ workingtimesnorm[i],
+ sumbenchmark[i],
+ numbenchmark[i]);
+ }
+
+ fscanf ( cfp, "%lf %lf", &max_bench_result, &min_bench_result);
+ fscanf ( cfp, "%lf %lf", &max_task_result, &min_task_result);
+}
+
+
+
+
+void MWStatistics::gather( MWWorkerID *w )
+{
+ if ( w == NULL ) {
+ MWprintf ( 10, "Tried to gather NULL worker!\n" );
+ return;
+ }
+
+ // MWprintf ( 80, "Gathering: worker vid %d\n", w->get_vid() );
+
+ //JTL 8/25/00
+ // We need to update the total time to include this time,
+ // because now we can call gather() without calling ended()
+
+ // This is starting top get a bit kludgy, but the main
+ // sticking point is that we don't want the "kill workers"
+ // time in our efficiency numbers.
+
+ double now = MWSystem::gettimeofday();
+
+ if( w->start_time > 1.0 ) {
+ w->total_time = now - w->start_time;
+ }
+
+ uptimes[w->get_vid()] += w->total_time;
+ workingtimes[w->get_vid()] += w->total_working;
+ susptimes[w->get_vid()] += w->total_suspended;
+ cputimes[w->get_vid()] += w->cpu_while_working;
+
+ workingtimesnorm[w->get_vid()] += (w->normalized_cpu_working_time);
+
+ sumbenchmark[w->get_vid()] += (w->sum_benchmark);
+ numbenchmark[w->get_vid()] += (w->num_benchmark);
+
+
+ // Jeff resets all these to 0 -- so we can call gather
+ // more than once without affecting the stats validity
+
+ w->total_time = 0.0;
+ w->total_working = 0.0;
+ w->total_suspended = 0.0;
+ w->cpu_while_working = 0.0;
+ w->normalized_cpu_working_time = 0.0;
+ w->sum_benchmark = 0.0;
+ w->num_benchmark = 0;
+ w->start_time = now;
+
+
+ /* we don't delete w here. That's done in RMC->removeWorker() */
+}
+
+void MWStatistics::makestats() {
+ //jae - we don't want to print the stat out
+ return;
+
+ int i;
+ int numWorkers = get_max_vid();
+ double sumuptimes = 0.0;
+ double sumworking = 0.0;
+ double sumcpu = 0.0;
+ double sumsusp = 0.0;
+
+ double sumworknorm = 0.0;
+
+ double sum_sum_benchmark = 0.0;
+ int sum_num_benchmark = 0;
+
+ MWprintf ( 0, "**** Statistics ****\n" );
+
+ MWprintf ( 20, "Dumping raw stats:\n" );
+ MWprintf ( 20, "Vid Uptimes Working CpuUsage Susptime\n" );
+ for ( i=0 ; i<numWorkers ; i++ ) {
+ if ( uptimes[i] > 34560000 ) { /* 400 days! */
+ MWprintf ( 0, "Found odd uptime[%d] = %12.4f\n", i, uptimes[i] );
+ uptimes[i] = 0;
+ }
+
+ MWprintf ( 20, "%3d %10.4f %10.4f %10.4f %10.4f %10.4f %10.4f %d \n",
+ i,
+ uptimes[i],
+ workingtimes[i],
+ cputimes[i],
+ susptimes[i],
+ workingtimesnorm[i],
+ sumbenchmark[i],
+ numbenchmark[i] );
+
+
+ sumuptimes += uptimes[i];
+ sumworking += workingtimes[i];
+ sumcpu += cputimes[i];
+ sumsusp += susptimes[i];
+ sumworknorm += workingtimesnorm[i];
+ sum_sum_benchmark += sumbenchmark[i];
+ sum_num_benchmark += numbenchmark[i];
+
+ }
+
+ // find duration of this run (+= in case of checkpoint)
+ double now = MWSystem::gettimeofday();
+ duration = now - starttime;
+ duration += previoustime; // so it's sum over all checkpointed work
+
+ MWprintf ( 0, "\n" );
+ MWprintf ( 0, "Number of (different) workers: %d\n",
+ numWorkers);
+
+ MWprintf ( 0, "Number of completed tasks: %d\n",
+ num_completed_tasks);
+
+
+ MWprintf ( 0, "Wall clock time for this job: %10.4f\n",
+ duration );
+
+ MWprintf ( 0, "Total time workers were alive (up): %10.4f\n",
+ sumuptimes );
+ //JTL -- This is a confusing statistic -- should just use CPU time
+ //MWprintf ( 0, "Total wall clock time of workers: %10.4f\n",
+ //sumworking );
+ MWprintf ( 0, "Total cpu time used by all workers: %10.4f\n",
+ sumcpu );
+ MWprintf ( 0, "Total time workers were suspended: %10.4f\n",
+ sumsusp );
+
+ double average_bench = ( sum_sum_benchmark / sum_num_benchmark );
+ double equivalent_bench = ( sumworknorm / sumcpu );
+
+
+ MWprintf (0, "Average benchmark factor : %10.4f\n", average_bench);
+ MWprintf (0, "Equivalent benchmark factor : %10.4f\n", equivalent_bench);
+ MWprintf (0, "Minimum benchmark factor : %10.4f\n", min_bench_result);
+ MWprintf (0, "Maximum benchmark factor : %10.4f\n\n", max_bench_result);
+ MWprintf (0, "Minimum task cpu time : %10.4f\n", min_task_result);
+ MWprintf (0, "Maximum task cpu time : %10.4f\n\n", max_task_result);
+
+ double av_present_workers = ( sumuptimes / duration ) ;
+ double av_nonsusp_workers = ( ( sumuptimes - sumsusp) / duration ) ;
+ double av_active_workers = ( ( sumcpu ) / duration ) ;
+
+ MWprintf (0, "Average Number Present Workers : %10.4f\n", av_present_workers);
+ MWprintf (0, "Average Number NonSuspended Workers : %10.4f\n", av_nonsusp_workers);
+ MWprintf (0, "Average Number Active Workers : %10.4f\n", av_active_workers);
+
+ double equi_pool_performance = ( equivalent_bench * av_active_workers );
+ double equi_run_time = ( sumworknorm );
+ double parallel_performance = (( sumworking ) / ( sumuptimes - sumsusp)) ;
+
+ MWprintf (0, "Equivalent Pool Performance : %10.4f\n", equi_pool_performance);
+ MWprintf (0, "Equivalent Run Time : %10.4f\n\n", equi_run_time);
+
+ MWprintf (0, "Overall Parallel Performance : %10.4f\n", parallel_performance);
+ // JTL -- I don't know why we would print this...
+ //MWprintf (0, "Total Number of benchmark tasks : %10d\n\n", sum_num_benchmark);
+
+
+ double uptime_mean = mean( uptimes, numWorkers );
+ double uptime_var = var ( uptimes, numWorkers, uptime_mean );
+ double wktime_mean = mean( workingtimes, numWorkers );
+ double wktime_var = var ( workingtimes, numWorkers, wktime_mean );
+ double cputime_mean= mean( cputimes, numWorkers );
+ double cputime_var = var ( cputimes, numWorkers, cputime_mean );
+ double sptime_mean = mean( susptimes, numWorkers );
+ double sptime_var = var ( susptimes, numWorkers, sptime_mean );
+
+ MWprintf ( 0,"Mean & Var. uptime for the workers: %10.4f\t%10.4f\n",
+ uptime_mean, uptime_var );
+ MWprintf ( 0,"Mean & Var. working time for the worker: %10.4f\t%10.4f\n",
+ wktime_mean, wktime_var );
+ MWprintf ( 0,"Mean & Var. cpu time for the workers: %10.4f\t%10.4f\n",
+ cputime_mean, cputime_var );
+ MWprintf ( 0,"Mean & Var. susp. time for the workers: %10.4f\t%10.4f\n",
+ sptime_mean, sptime_var );
+
+}
+
+
+void MWStatistics::get_stats(double *average_bench,
+ double *equivalent_bench,
+ double *min_bench,
+ double *max_bench,
+ double *av_present_workers,
+ double *av_nonsusp_workers,
+ double *av_active_workers,
+ double *equi_pool_performance,
+ double *equi_run_time,
+ double *parallel_performance,
+ double *wall_time,
+ MWList<MWWorkerID> *wrlist
+ )
+{
+
+ int i;
+ int numWorkers = get_max_vid();
+ double sumuptimes = 0.0;
+ double sumworking = 0.0;
+ double sumcpu = 0.0;
+ double sumsusp = 0.0;
+ double sumworknorm = 0.0;
+
+ double sum_sum_benchmark = 0.0;
+ int sum_num_benchmark = 0;
+
+ for ( i=0 ; i<numWorkers ; i++ ) {
+ if ( uptimes[i] > 34560000 ) { /* 400 days! */
+ MWprintf ( 20, "Found odd uptime[%d] = %12.4f\n", i, uptimes[i] );
+ uptimes[i] = 0;
+ }
+
+ sumuptimes += uptimes[i];
+ sumworking += workingtimes[i];
+ sumsusp += susptimes[i];
+ sumcpu += cputimes[i];
+ sumworknorm += workingtimesnorm[i];
+ sum_sum_benchmark += sumbenchmark[i];
+ sum_num_benchmark += numbenchmark[i];
+
+ }
+
+ // find duration of this run (+= in case of checkpoint)
+ double now = MWSystem::gettimeofday();
+ duration = now - starttime;
+ duration += previoustime; // so it's sum over all checkpointed work
+
+ MWWorkerID *tempw = wrlist->First();
+ while( wrlist->AfterEnd() == false )
+ {
+ tempw = wrlist->Current();
+ if( tempw->start_time > 0.1 )
+ sumuptimes += now - tempw->start_time;
+
+ sumworking += tempw->total_working;
+ sumsusp += tempw->total_suspended;
+ sumcpu += tempw->cpu_while_working;
+
+ sumworknorm += (tempw->normalized_cpu_working_time);
+
+ sum_sum_benchmark += (tempw->sum_benchmark);
+ sum_num_benchmark += (tempw->num_benchmark);
+
+
+ MWprintf(10, "Stats, id: %d\t%lf, %lf, %lf, %lf, %lf, %lf, %d\n",
+ tempw->id1, sumuptimes, sumworking, sumsusp, sumcpu, sumworknorm,
+ sum_sum_benchmark, sum_num_benchmark );
+
+ wrlist->Next();
+ }
+
+ *wall_time = duration;
+
+ *average_bench = ( sum_sum_benchmark / sum_num_benchmark );
+ *equivalent_bench = ( sumworknorm / sumcpu );
+ *min_bench = min_bench_result;
+ *max_bench = max_bench_result;
+
+ *av_present_workers = ( sumuptimes / duration ) ;
+ *av_nonsusp_workers = ( ( sumuptimes - sumsusp ) / duration ) ;
+ *av_active_workers = ( ( sumcpu ) / duration ) ;
+
+ *equi_pool_performance = ( *equivalent_bench * *av_active_workers );
+ *equi_run_time = ( sumworknorm );
+ *parallel_performance = (( sumworking ) / ( sumuptimes - sumsusp)) ;
+
+ // Commented out so that no complain about unused variables.
+ /*
+ double uptime_mean = mean( uptimes, numWorkers );
+ double uptime_var = var ( uptimes, numWorkers, uptime_mean );
+ double wktime_mean = mean( workingtimes, numWorkers );
+ double wktime_var = var ( workingtimes, numWorkers, wktime_mean );
+ double cputime_mean= mean( cputimes, numWorkers );
+ double cputime_var = var ( cputimes, numWorkers, cputime_mean );
+ double sptime_mean = mean( susptimes, numWorkers );
+ double sptime_var = var ( susptimes, numWorkers, sptime_mean );
+ */
+}
+
+void MWStatistics::update_best_bench_results ( double bres ) {
+
+ MWprintf(10,"bench = %lf\n", bres);
+
+ if (bres > max_bench_result){
+ max_bench_result = bres;
+ }
+
+ if (bres < min_bench_result){
+ min_bench_result = bres;
+ }
+
+}
+
+void MWStatistics::update_best_task_results(double cpu_time) {
+ if (cpu_time > max_task_result){
+ max_task_result = cpu_time;
+ }
+
+ if ( cpu_time < min_task_result){
+ min_task_result = cpu_time;
+ }
+}
+
+
+double MWStatistics::mean( double *array, int length ) {
+ double sum=0;
+ for ( int i=0 ; i<length ; i++ ) {
+ sum += array[i];
+ }
+ sum /= length;
+ return sum;
+}
+
+double MWStatistics::var( double *array, int length, double mean ) {
+ double ret=0;
+ double diff=0;
+ for ( int i=0 ; i<length ; i++ ) {
+ diff = array[i] - mean;
+ ret += ( diff * diff );
+ }
+ if( length > 1 )
+ ret /= length-1;
+ return ret;
+}
+
+int MWStatistics::get_max_vid() {
+
+ int n = -1;
+ for ( int i=0 ; i<MW_MAX_WORKERS ; i++ ) {
+ if ( uptimes[i] > 0.0 ) {
+ n = i;
+ }
+ }
+ n++;
+ return n;
+}
diff --git a/MW/src/MWStats.h b/MW/src/MWStats.h
new file mode 100644
index 0000000..4cbd701
--- /dev/null
+++ b/MW/src/MWStats.h
@@ -0,0 +1,153 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* stats.h
+
+ Header file for statistics class.
+*/
+
+#ifndef STATISTICS_H
+#define STATISTICS_H
+
+#include "MWWorkerID.h"
+#include "MW.h"
+#include "MWList.h"
+
+/** This class serves as a holder for worker classes before they go to die.
+ It holds the workers until a makestats() call is made, at which
+ point it generates some statistics, given the workers.
+*/
+class MWStatistics {
+
+ public:
+ /// Default constructor
+ MWStatistics();
+ /// Destructor...
+ ~MWStatistics();
+
+ /** Literally, take the stats from this worker and store
+ them in the stats class. This is done when the worker
+ dies and during a checkpoint.
+ */
+ void gather ( MWWorkerID * );
+
+ /** This method is called at the end of a run. It prints out some
+ statistical information on that run.
+ */
+ void makestats();
+
+ /** This function is just like makestats(), except it return the relative
+ statistics information to the caller.
+ */
+ void get_stats(double *average_bench,
+ double *equivalent_bench,
+ double *min_bench,
+ double *max_bench,
+ double *av_present_workers,
+ double *av_nonsusp_workers,
+ double *av_active_workers,
+ double *equi_pool_performance,
+ double *equi_run_time,
+ double *parallel_performance,
+ double *wall_time,
+ MWList<MWWorkerID> *workerlist );
+
+ /** Everytime we get a new bench factor, we update the max and min ones if necessary */
+ void update_best_bench_results( double bres );
+
+ /** Each time a task finishes, we call this method, to record the
+ * best of times, the worst of times.
+ */
+ void update_best_task_results(double cpu_time);
+ /** We find that we should save stats across checkpoints. Here
+ we're given the ckpt FILE* and the list of running workers.
+ Basically, we write out the sum of the old stats we've got
+ plus the stats of the running workers. */
+ void write_checkpoint( FILE *cfp, MWList<MWWorkerID> *wlist );
+
+ /** Read in stats information across the checkpoint */
+ void read_checkpoint( FILE *cfp );
+
+ private:
+
+ double duration;
+ double starttime;
+ double previoustime; // the total run time of the checkpoints before...
+
+ /// Array of times that the workerIDs have been "up"
+ double *uptimes;
+ /// Array of times that the workerIDs have been working
+ double *workingtimes;
+ /// Array of times holding the CPU times of the workerIDs
+ double *cputimes;
+ /// Array of times that the workerIDs have been suspended
+ double *susptimes;
+
+ /**@name Normalized Statistics. MW computes "normalized" statistics
+ about the runs performance based on the relative speed of the machines
+ that the user obtained during the course of the run.
+ */
+
+
+ //@{
+
+ double *workingtimesnorm; // the total working time normalized by benchmark factor
+
+ /** Min benchmark result -- the "slowest" machine we ever had. */
+ double max_bench_result;
+
+ /** Max benchmark result -- the "faster" machine we ever had. */
+ double min_bench_result;
+
+ /** Min task result -- the "slowest" machine we ever had. */
+ double max_task_result;
+
+ /** Max benchmark result -- the "faster" machine we ever had. */
+ double min_task_result;
+
+ /// The sum of benchmark factors for this vid
+ double *sumbenchmark;
+ /// The number of benchmar factors for this vid
+ int *numbenchmark;
+
+ //@}
+
+ /// Computes the mean of an array of number.
+ double mean ( double *array, int length );
+
+ /** Computes the variance of an array of numbers (given the mean,
+ to avoid "double processing" the list -- which you don't need
+ to do anyway, but Mike wrote this function).
+ */
+ double var ( double *array, int length, double mean );
+
+ /** What is the maximum "virtuid ID" that we ever assigned to a worker.
+ This amounts to asking how many workers did we ever have in ALL states
+ at any one time during the course of the run.
+ */
+ int get_max_vid();
+
+};
+
+#endif
+
+
diff --git a/MW/src/MWSystem.h b/MW/src/MWSystem.h
new file mode 100644
index 0000000..312341d
--- /dev/null
+++ b/MW/src/MWSystem.h
@@ -0,0 +1,15 @@
+
+// This class implements all functionality outside of ANSI C/C++
+// All the ifdefery should be located here, and every class
+// above this should either call into MWSystem, or use
+// portable, ANSI code.
+
+class MWSystem {
+ public:
+ static int getpid();
+ static void gethostname(char *, int);
+ static double gettimeofday();
+ static double getcputime();
+ static void sleep(int);
+ static void mkdir(char *);
+};
diff --git a/MW/src/MWTask.C b/MW/src/MWTask.C
new file mode 100644
index 0000000..04a067c
--- /dev/null
+++ b/MW/src/MWTask.C
@@ -0,0 +1,129 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* MWTask.C
+
+ The implementation of the MWTask class
+
+*/
+
+#include "MWTask.h"
+#include "MWDriver.h"
+#include <stdio.h>
+
+extern int MWworkClasses;
+extern int *MWworkClassTasks;
+
+MWTask::MWTask() {
+ number = -1;
+ numsubtask = -1;
+ worker = NULL;
+ taskType = MWNORMAL;
+ group = new MWGroup ( MWworkClasses );
+}
+
+MWTask::~MWTask() {
+ if ( worker )
+ if ( worker->runningtask )
+ worker->runningtask = NULL;
+
+ delete group;
+}
+
+void MWTask::printself( int level )
+{
+ MWprintf ( level, " Task %d\n", number);
+}
+
+void
+MWTask::initGroups ( int num )
+{
+ // found LEAK_ASSIGN (group probably already allocated!)
+ // group = new MWGroup ( num );
+ if (group != NULL)
+ delete group;
+ group = new MWGroup( num );
+}
+
+void
+MWTask::addGroup ( int num )
+{
+ if ( doesBelong ( num ) )
+ return;
+ MWworkClassTasks[num]++;
+ group->join ( num );
+}
+
+void
+MWTask::deleteGroup ( int num )
+{
+ if ( !doesBelong ( num ) )
+ return;
+ MWworkClassTasks[num]--;
+ group->leave ( num );
+}
+
+bool
+MWTask::doesBelong ( int num )
+{
+ return group->belong ( num );
+}
+
+MWGroup*
+MWTask::getGroup ( )
+{
+ return group;
+}
+
+void
+MWTask::write_group_info ( FILE *fp )
+{
+ group->write_checkpoint ( fp );
+}
+
+void
+MWTask::read_group_info ( FILE *fp )
+{
+ // found LEAK_ASSIGN (group probably already allocated!)
+ // group = new MWGroup ( num );
+ if (group != NULL)
+ delete group;
+ group = new MWGroup ( MWworkClasses );
+ group->read_checkpoint ( fp );
+ for ( int i = 0; i < MWworkClasses; i++ )
+ {
+ if ( doesBelong ( i ) )
+ addGroup ( i );
+ }
+}
+
+void
+MWTask::completedTask(double wall_time, double cpu_time)
+{
+ worker->runningtask = NULL;
+ worker->completedtask( wall_time, cpu_time);
+ worker = NULL;
+
+ for ( int tempi = 0; tempi < MWworkClasses; tempi++ ) {
+ deleteGroup ( tempi );
+ }
+}
diff --git a/MW/src/MWTask.h b/MW/src/MWTask.h
new file mode 100644
index 0000000..2d093c9
--- /dev/null
+++ b/MW/src/MWTask.h
@@ -0,0 +1,191 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWTASK_H
+#define MWTASK_H
+
+#include "MW.h"
+#include "MWWorkerID.h"
+#include "MWGroup.h"
+#include <MWRMComm.h>
+#include <stdio.h>
+
+//I'm moving this into MW.h so that task container can compile
+//typedef enum { MWNORMAL, MWNWS, MWNUMTASKTYPES } MWTaskType;
+
+/**
+ This the class that represents a unit of work.
+
+ The task consits of two main components. The "work" to be done,
+ and the "result" of the completed task.
+ In order to create an application, the user must specify methods
+ for packing and unpacking both the "work" and "result" portions
+ of the task.
+ The user is not responsible for initializing the send
+ or for packing the task's number
+
+ When the task is being serviced by a worker, it contains a link
+ to the ID of that instance of the worker.
+
+
+ @see MWDriver
+ @see MWWorker
+ @author Mike Yoder, modified by Jeff Linderoth and Jean-Pierre Goux
+*/
+
+class MWTask
+{
+ public:
+
+ /// Default constructor
+ MWTask();
+
+ /// Default Destructor
+ virtual ~MWTask();
+
+ /// The task's number
+ int number;
+int randomstop;
+int numsubtask;
+ /// The task's type.
+ MWTaskType taskType;
+
+ /** @name Time and usage data */
+ //@{
+ /** The time (wall clock) that it takes to run the 'execute_task'
+ function on the worker's side. */
+ double working_time;
+ /** The amount of user+system time taken by this task, measured
+ from start to finish of the 'execute_task' function. */
+ double cpu_time;
+
+ //@}
+
+ /**@name Packing and Unpacking
+
+ The user must pack and unpack the contents of the class
+ so that it can be sent to the worker and back. These
+ functions will make RMC->pack() and RMC->unpack() calls.
+ */
+ //@{
+
+ /// Pack the work portion of the task
+ virtual void pack_work( void ) = 0;
+
+ /// Unpack the work portion of the task
+ virtual void unpack_work( void ) = 0;
+
+ /// Pack the result portion of the task
+ virtual void pack_results( void ) = 0;
+
+ /// Unpack the result portion of the task
+ virtual void unpack_results( void ) = 0;
+
+ /// Pack the subresult portion of the task
+ virtual void pack_subresults( int ) {}
+
+ /// Unpack the subresult portion of the task
+ virtual void unpack_subresults( int ) {}
+
+
+ /// Dump this task to the screen
+ virtual void printself( int level = 60 );
+
+ //@}
+
+ /**@name Checkpointing Utilities
+
+ These two functions are used when checkpointing. Simply put,
+ they write/read the state of the task to this file pointer
+ provided. */
+
+ //@{
+
+ /** Write the state of this task out to a FILE* */
+ virtual void write_ckpt_info( FILE *fp ) {};
+ /** Read the state of this task from a FILE* (overwriting
+ any existing state */
+ virtual void read_ckpt_info( FILE *fp ) {};
+
+ void write_group_info ( FILE *fp );
+
+ void read_group_info ( FILE *fp );
+
+
+ //@}
+
+ void initGroups ( int num );
+ /// add task to a workclass/group
+ void addGroup ( int num );
+ /// remove a task from a workclass/group
+ void deleteGroup ( int num );
+ bool doesBelong ( int num );
+ MWGroup *getGroup ( );
+
+
+ /**@name List management
+
+ The task also has pointers that aid for managing the list
+ of tasks to be done
+ */
+
+ //@{
+ /// A pointer to the worker ID executing this task (NULL if none)
+ MWWorkerID *worker;
+
+ /*
+ /// A pointer to the next task in the list (NULL if none)
+ MWTask *next;
+ */
+ //@}
+
+ MWGroup *group;
+
+ static MWRMComm * RMC;
+
+ //by jae
+ void completedTask(double wall_time, double cpu_time);
+
+#ifdef MEASURE
+public:
+ // double _measure_start_time; // the time called give_task
+ // double _measure_MP_master_time; // master send_data + recv_result
+ double _measure_MP_worker_time; // worker recv_data + send_result
+ double _measure_MP_worker_cpu_time; // CPU time (worker recv_data + send_result)
+ // double _measure_Exe_wall_time; // worker execute_task wall time = working_time
+ // double _measure_Exe_cpu_time; // worker execute_task CPU time = cpu_time
+ // double _measure_Life_time; // from creation to deletion
+#endif // MEASURE
+
+};
+
+#endif
+
+
+
+
+
+
+
+
+
+
diff --git a/MW/src/MWTaskContainer.C b/MW/src/MWTaskContainer.C
new file mode 100644
index 0000000..0c2d1a3
--- /dev/null
+++ b/MW/src/MWTaskContainer.C
@@ -0,0 +1,157 @@
+#include "MWTaskContainer.h"
+#include "MWDriver.h"
+MWDriver* gimme_the_master();
+// Constructor and Destructor
+MWTaskContainer::MWTaskContainer()
+{
+ taskType = MWNORMAL;
+ RMC = MWTask::RMC;
+ tasks = new MWList<MWTask>("");
+}
+
+MWTaskContainer::~MWTaskContainer()
+{
+ delete tasks;
+}
+
+// Task related
+void
+MWTaskContainer::pack_work()
+{
+// int numtasks = tasks->Number();
+
+// RMC->pack(&numtasks, 1, 1); //this is done in MWWorker.C
+//MWprintf(10,"MWTaskContainer::pack_work\n");
+ MWTask * t = tasks->First();
+ while ( tasks->AfterEnd() == false ) {
+ t = tasks->Current();
+ RMC->pack(&(t->number),1,1);
+ t->pack_work();
+ tasks->Next();
+ }
+}
+
+void
+MWTaskContainer::unpack_work()
+{
+//MWDriver *driver = gimme_the_master();
+//driver->gimme_a_task();
+//MWprintf(10,"MWTaskContainer::unpack_work");
+ MWTask * t = tasks->First();
+ while ( tasks->AfterEnd() == false ) {
+ t = tasks->Current();
+ RMC->unpack(&(t->number),1,1);
+ t->unpack_work();
+ tasks->Next();
+ }
+}
+
+void
+MWTaskContainer::pack_subresults(int tasknum)
+{
+}
+
+void
+MWTaskContainer::unpack_subresults(int tasknum)
+{
+}
+
+int
+MWTaskContainer::FirstNum()
+{
+ MWTask *t;
+
+ tasks->First();
+ t = tasks->Current();
+ return t->number;
+}
+
+int
+MWTaskContainer::LastNum()
+{
+ MWTask *t;
+
+ tasks->Last();
+ t = tasks->Current();
+ return t->number;
+}
+
+int
+MWTaskContainer::Number()
+{
+ return tasks->Number();
+}
+
+void
+MWTaskContainer::pack_results()
+{
+ //int results = tasks->Number();
+
+ //RMC->pack(&results, 1, 1);
+ MWTask * t = tasks->First();
+ while ( tasks->AfterEnd() == false ) {
+ t = tasks->Current();
+ t->pack_results();
+ tasks->Next();
+ }
+}
+
+void
+MWTaskContainer::unpack_results()
+{
+ //int results;
+
+ //RMC->unpack(&results, 1, 1);
+ MWTask * t = tasks->First();
+ while ( tasks->AfterEnd() == false ) {
+ t = tasks->Current();
+ t->unpack_results();
+ tasks->Next();
+ }
+}
+
+//List related
+void
+MWTaskContainer::addTask(MWTask *t)
+{
+ tasks->Append(t);
+
+}
+
+void
+MWTaskContainer::removeAll()
+{
+ while(tasks->Remove() != NULL){};
+}
+
+
+MWTask*
+MWTaskContainer::First()
+{
+ return tasks->First();
+}
+
+bool
+MWTaskContainer::AfterEnd()
+{
+ return tasks->AfterEnd();
+}
+
+MWTask*
+MWTaskContainer::Current()
+{
+ return tasks->Current();
+}
+
+MWTask*
+MWTaskContainer::Next()
+{
+ return tasks->Next();
+}
+
+void
+MWTaskContainer::printself( int level )
+{
+ MWprintf ( level, " Task container from task number %d to %d\n", FirstNum(), LastNum());
+}
+
diff --git a/MW/src/MWTaskContainer.h b/MW/src/MWTaskContainer.h
new file mode 100644
index 0000000..0974170
--- /dev/null
+++ b/MW/src/MWTaskContainer.h
@@ -0,0 +1,112 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWTASKCONTAINER_H
+#define MWTASKCONTAINER_H
+
+#include "MW.h"
+#include "MWList.h"
+#include "MWTask.h"
+//#include <MWRMComm.h> MWTask.h already had this header
+
+//forward declarations necessary for compilation
+class MWTask;
+class MWWorkerID;
+//enum MWTaskType;
+
+/**
+ MWTaskContainer allows MWDriver to send multiple tasks to a single worker.
+ The exact number of tasks is hardcoded in send_task_to_worker() in
+ MWDriver.C
+ The worker then works on each task and sends an update to MWDriver upon the
+ completion of each task; act_on_completed_subtask(MWTask*) is called.
+ When all tasks are done, the results of all the tasks are sent back to
+ MWDriver and act_on_completed_task(MWTask*) is called for each completed
+ task.
+ MWDriver then sends a new MWTaskContainer to the Worker.
+
+ The following functions in this class have to be defined in a derived class:
+ - pack_work()
+ - unpack_work()
+ - pack_subresults()
+ - unpack_subresults()
+ - pack_results()
+ - unpack_results()
+
+ The following functions in MWDriver.C have to be defined:
+ - MWDriver::act_on_completed_subtask(MWTask*)
+
+ Notes:
+ - None of the functions in MWTask are called directly by MW. They are now
+ called by MWTaskContainer.
+*/
+class MWTaskContainer
+{
+public:
+ MWTaskType taskType;
+ int number; // have to define numbering system for task containers, let's make it the number of the first task for now
+ MWList<MWTask> *tasks;
+ MWWorkerID *worker;
+ MWRMComm *RMC; //pointer to RMC instance in MWTask.h
+
+ MWTaskContainer();
+ virtual ~MWTaskContainer();
+ void addTask(MWTask *t);
+ void removeAll();
+ MWTask* First();
+ bool AfterEnd();
+ MWTask* Current();
+ MWTask* Next();
+
+ /// Pack all the tasks in this container
+ virtual void pack_work();
+
+ /// Unpack all the tasks in this container
+ virtual void unpack_work();
+
+ /// Pack all the results in this container
+ virtual void pack_results();
+
+ /// Unpack all the results in this container
+ virtual void unpack_results();
+
+ /// Called by MWWorker at the completion of each task(not task container). This could be left empty if we only want to let MWDriver know that a task was completed
+ virtual void pack_subresults(int tasknum);
+
+ /// Called by MWDriver at the completion of each task. @param tasknum number of the task that was completed
+ virtual void unpack_subresults(int tasknum);
+
+ virtual void printself(int level);
+
+ int FirstNum();
+
+ int LastNum();
+
+ /// Number of tasks in this task container
+ int Number();
+
+private:
+ double Side;
+};
+
+#endif
diff --git a/MW/src/MWUnixSystem.C b/MW/src/MWUnixSystem.C
new file mode 100644
index 0000000..ffd3098
--- /dev/null
+++ b/MW/src/MWUnixSystem.C
@@ -0,0 +1,52 @@
+
+#include "MWSystem.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <sys/resource.h> // getrusage
+#include <sys/time.h> // gettimeofday
+
+int
+MWSystem::getpid() {
+ return ::getpid();
+}
+
+void
+MWSystem::gethostname(char *h, int len) {
+ ::gethostname(h, len);
+}
+
+double
+timeval_to_double( struct timeval t )
+{
+ return (double) t.tv_sec + ( (double) t.tv_usec * (double) 1e-6 );
+}
+
+double
+MWSystem::gettimeofday() {
+ struct timeval t;
+ ::gettimeofday(&t, NULL);
+ return timeval_to_double(t);
+}
+
+double
+MWSystem::getcputime() {
+ struct rusage rt;
+ ::getrusage ( RUSAGE_SELF, &rt );
+ double d = timeval_to_double ( rt.ru_utime ) + timeval_to_double ( rt.ru_stime );
+ ::getrusage ( RUSAGE_CHILDREN, &rt );
+ return d + timeval_to_double ( rt.ru_utime ) + timeval_to_double ( rt.ru_stime );
+}
+
+void
+MWSystem::sleep(int t) {
+ ::sleep(t);
+}
+
+void
+MWSystem::mkdir(char *c) {
+ ::mkdir(c, 0755);
+}
diff --git a/MW/src/MWWinSystem.C b/MW/src/MWWinSystem.C
new file mode 100644
index 0000000..d69512f
--- /dev/null
+++ b/MW/src/MWWinSystem.C
@@ -0,0 +1,47 @@
+#include "MWSystem.h"
+
+#include <windows.h>
+#include <stdio.h>
+#include <direct.h>
+
+int
+MWSystem::getpid() {
+ return GetCurrentProcessId();
+}
+
+static bool initialized = false;
+
+void
+MWSystem::gethostname(char *h, int len) {
+ if (!initialized) {
+ WSAData wsaData;
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData) !=0) {
+ printf("Can't WSAStartup\n");
+ exit(-1);
+ };
+ initialized = true;
+ }
+
+ ::gethostname(h, len);
+ return;
+}
+
+double
+MWSystem::gettimeofday() {
+ return 0.0;
+}
+
+double
+MWSystem::getcputime() {
+ return 0.0;
+}
+
+void
+MWSystem::sleep(int time) {
+ ::Sleep(time * 1000);
+}
+
+void
+MWSystem::mkdir(char *filename) {
+ ::mkdir(filename);
+}
diff --git a/MW/src/MWWorker.C b/MW/src/MWWorker.C
new file mode 100644
index 0000000..7c97706
--- /dev/null
+++ b/MW/src/MWWorker.C
@@ -0,0 +1,541 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MW.h"
+#include "MWWorker.h"
+#include "MWSystem.h"
+#include "RMComm/MWRMComm.h"
+
+MWWorker::MWWorker()
+{
+ master = UNDEFINED;
+ workingTask = 0; // This must be initialized by subclass
+}
+
+MWWorker::~MWWorker()
+{
+}
+
+double
+MWWorker::benchmark(MWTask *t)
+{
+ if (!t) return 1.0;
+
+ double begTime = MWSystem::gettimeofday();
+ execute_task( t );
+ double endTime = MWSystem::gettimeofday();
+ return 1.0/(endTime-begTime);
+
+}
+
+void MWWorker::go( int argc, char *argv[] )
+{
+ MWprintf ( 10, "About to call setup\n");
+
+ if (workingTask == 0) {
+ MWprintf( 1, "Fatal Error - Worker did not set field workingTask to valid value\n");
+ exit(-1);
+ }
+
+ RMC->setup( argc, argv, &workerid, &master );
+ MWprintf ( 10, "Worker %x started.\n", workerid );
+
+ greet_master();
+#ifndef INDEPENDENT
+ worker_mainloop();
+#endif
+}
+
+MWReturn MWWorker::greet_master() {
+ MWSystem::gethostname ( mach_name, 64 );
+
+ MWprintf ( 10, "Worker started on machine %s.\npid = %d\n", mach_name, MWSystem::getpid() );
+
+ /* Pack and send to the master all these information
+ concerning the host and the worker specificities */
+ RMC->initsend();
+ RMC->pack( mach_name );
+ pack_worker_initinfo();
+
+ int status = RMC->send( master, INIT );
+ MWprintf ( 10, "Sent the master %x an INIT message.\n", master );
+
+ if ( status < 0 ) {
+ MWprintf ( 10, "Had a problem sending my name to master. Exiting.\n");
+ RMC->exit(1);
+ }
+
+
+#ifdef INDEPENDENT
+ return OK;
+#else
+ return do_benchmark_cmd();
+#endif
+}
+
+MWReturn MWWorker::do_benchmark_cmd ( )
+{
+ int status;
+ int len, tag, tid;
+
+ // wait for the setup info from the master
+ int buf_id = RMC->recv( master, -1 );
+ if( buf_id < 0 ) {
+ MWprintf ( 10, "Had a problem receiving INIT_REPLY. Exiting.\n" );
+ RMC->exit( INIT_REPLY_FAILURE );
+ }
+ status = RMC->bufinfo ( buf_id, &len, &tag, &tid );
+ MWprintf ( 10, "Got Something from the master in reply to INIT %d\n", tag);
+
+ MWReturn ustat = OK;
+ // unpack initial data to set up the worker state
+
+ switch ( tag )
+ {
+ case INIT_REPLY:
+ {
+
+ if ( RMC->unpack ( master_mach_name ) != 0 )
+ {
+ int err = -1;
+ MWprintf ( 10, "Error unpacking master hostname. \n");
+ RMC->initsend ( );
+ RMC->pack ( &err, 1 );
+ RMC->send ( master, BENCH_RESULTS );
+ return ustat;
+ }
+
+ if ( (ustat = unpack_init_data()) != OK ) {
+ int err = -1;
+ MWprintf ( 10, "Error unpacking initial data.\n" );
+ RMC->initsend();
+ RMC->pack( &err, 1 );
+ RMC->send( master, BENCH_RESULTS );
+ return ustat;
+ }
+
+ int bench_tf = FALSE;
+ RMC->unpack( &bench_tf, 1 );
+
+ if ( bench_tf ) {
+ MWprintf ( 10, "Recvd INIT_REPLY, now benchmarking.\n" );
+ workingTask->unpack_work();
+ double bench_result = benchmark( workingTask );
+
+ MWprintf ( 40, "Benchmark completed....%f\n", bench_result );
+ int zero = 0;
+ RMC->initsend();
+ RMC->pack( &zero, 1 ); // zero means that unpack_init_data is OK.
+ RMC->pack( &bench_result, 1 );
+ } else {
+ MWprintf ( 10, "Recvd INIT_REPLY, no benchmark.\n" );
+ double z = 0.0;
+ int zero = 0;
+ RMC->initsend();
+ RMC->pack( &zero, 1 ); // zero means that unpack_init_data is OK.
+ RMC->pack( &z, 1 );
+ }
+ MWprintf ( 10, "Worker Sending BENCH_RESULTS\n");
+ RMC->send( master, BENCH_RESULTS );
+
+ return ustat;
+ break;
+ }
+
+ case CHECKSUM_ERROR:
+ {
+ MWprintf ( 10, "Got a checksum error\n");
+ RMC->exit( CHECKSUM_ERROR_EXIT );
+ }
+ }
+ return OK;
+}
+
+
+void MWWorker::worker_mainloop() {
+
+ for (;;) {
+ worker_mainloop_oneshot();
+ }
+}
+
+MWReturn MWWorker::worker_mainloop_oneshot ()
+{
+ int status = 0, len = 0, tag = 0, tid = 0;
+ double wall_time = 0.0;
+ double cpu_time = 0.0;
+
+ int curSubTask = 0;
+
+#ifdef MEASURE
+ double _recv_start_time = _measure_cur_wall_time();
+ double _recv_start_cpu_time = _measure_cur_cpu_time();
+#endif // MEASURE
+
+ // get message from master. block if task done
+ int buf_id;
+ buf_id = RMC->recv ( master, -1 );
+ if( buf_id < 0 ) {
+ MWprintf( 10, "Could not receive message from master, ret = %d. Exiting\n", buf_id );
+ RMC->exit( buf_id );
+ }
+
+#ifdef MEASURE
+ double _task_recv_time = _measure_cur_wall_time() - _recv_start_time;
+ double _task_recv_cpu_time = _measure_cur_cpu_time() - _recv_start_cpu_time;
+#endif // MEASURE
+
+ status = -2; len = -2; tag = -2; tid = -2;
+ status = RMC->bufinfo ( buf_id, &len, &tag, &tid );
+
+ switch ( tag ) {
+
+ case RE_INIT: { /* This can happen: the lower level can tell us
+ that the master has gone down and come back
+ up, and we hve to re-initialize ourself. */
+ greet_master();
+ do_benchmark_cmd();
+ break;
+ }
+
+ case REFRESH:
+ {
+ unpack_init_data ( );
+ break;
+ }
+
+ case DO_THIS_WORK: {
+ MWprintf(51,"received DO_THIS_WORK signal\n");
+/*
+time_t now = time(0);
+while(time(0)-now<30){}
+*/
+ int num = UNDEFINED;
+ MWTaskType thisTaskType;
+ //moved out of switch statement
+ //double wall_time = 0.0;
+ //double cpu_time = 0.0;
+ int tstat;
+ int mytemp;
+
+ MWTask *curTask = NULL;
+
+ tstat = RMC->unpack ( &mytemp, 1, 1);
+
+ if ( tstat != 0 )
+ {
+ MWprintf ( 10, "Error: The receive buffer not unpacked on %d\n",
+ mach_name );
+ fflush ( stdout );
+ RMC->exit ( UNPACK_FAILURE );
+ }
+ thisTaskType = (MWTaskType)mytemp;
+
+ switch ( thisTaskType )
+ {
+ case MWNORMAL:
+ //curTask = workingTaskContainer->Current();
+ break;
+ case MWNWS:
+#ifndef NWSENABLED
+/*
+ MWprintf(31, "Got a MWNWS task. \n");
+ controlTask = getNWSTask ( );
+ curTask = controlTask;
+*/
+#endif
+ break;
+
+ default:
+ MWprintf(30, "MWWorker::worker_mainloop_ind() - other task type\n");
+ }
+ curTask = workingTask;
+
+ curTask->taskType = thisTaskType;
+ tstat = RMC->unpack( &num, 1, 1 );
+ if( tstat != 0 ) {
+ MWprintf( 10, "Error. The receive buffer not unpacked on %s\n",
+ mach_name );
+ fflush( stdout );
+ RMC->exit( UNPACK_FAILURE );
+ }
+ curTask->number = num;
+
+ unpack_driver_task_data();
+ curTask->unpack_work();
+
+ MWprintf(51,"Finished unpacking work, now executing...\n");
+ /* Set our stopwatch. :-) */
+ wall_time = - MWSystem::gettimeofday();
+ cpu_time = - MWSystem::getcputime();
+
+ /* do it! */
+ switch ( thisTaskType )
+ {
+ case MWNORMAL:
+ execute_task(curTask);
+ // Record times for it...
+ wall_time += MWSystem::gettimeofday();
+ cpu_time += MWSystem::getcputime();
+/*
+ RMC->initsend();
+ RMC->pack( &(curTask->number), 1, 1 );
+
+ // GGT Not sure what to do here..
+
+ RMC->pack(&curSubTask, 1, 1);
+ curTask->pack_subresults(curSubTask);
+
+ status = RMC->send(master, SUBRESULTS);
+ if ( status < 0 ){
+ MWprintf ( 10, "Bummer! Could not send SUBresults of task %d\n", num );
+ MWprintf( 10, "Exiting worker!" );
+ RMC->exit( FAIL_MASTER_SEND );
+ }
+*/
+ // if all subtasks done, do task and send RESULT message to master
+ // worker then goes back into blocking recv. This gets called if there is only 1 task in the container
+ {
+ // Record times for it...
+ //wall_time += MWSystem::getcputime();
+ //cpu_time += MWSystem::gettimeofday();
+
+ RMC->initsend();
+ RMC->pack( &num, 1, 1);
+#ifdef MEASURE
+ RMC->pack(&_task_recv_time, 1, 1);
+ RMC->pack(&_task_recv_cpu_time, 1, 1);
+#endif // END MEASURE
+ RMC->pack( &wall_time, 1, 1 );
+ RMC->pack( &cpu_time, 1, 1 );
+ curTask->pack_results();
+ status = RMC->send(master, RESULTS);
+ MWprintf(51,"sent result\n");
+ }
+
+ break;
+ case MWNWS:
+#ifndef NWSENABLED
+/*
+ curTask->printself ( 10 );
+ execute_nws ( curTask );
+ curTask->printself ( 10 );
+*/
+#endif
+ break;
+ default:
+ MWprintf ( 10, "Unidentified %d \n", thisTaskType);
+ exit(1);
+ }
+
+/*
+ if(curTask->numsubtask == -1) // partial results disabled
+ {
+ // Record times for it...
+ wall_time += _measure_cur_wall_time();
+ cpu_time += _measure_cur_cpu_time();
+
+ // Now send...
+ RMC->initsend();
+ //RMC->pack( &num, 1, 1 );
+#ifdef MEASURE
+ RMC->pack(&_task_recv_time, 1, 1);
+ RMC->pack(&_task_recv_cpu_time, 1, 1);
+#endif // END MEASURE
+ RMC->pack( &wall_time, 1, 1 );
+ RMC->pack( &cpu_time, 1, 1 );
+ curTask->pack_results();
+
+ status = RMC->send(master, RESULTS);
+
+ if ( status < 0 ){
+ MWprintf ( 10, "Bummer! Could not send results of task %d\n", num );
+ MWprintf( 10, "Exiting worker!" );
+ RMC->exit( FAIL_MASTER_SEND );
+ }
+
+
+ MWprintf ( 40, "%s sent results of job %d.\n",
+ mach_name, curTask->number );
+ }
+*/
+ switch ( thisTaskType )
+ {
+ case MWNORMAL:
+ break;
+ case MWNWS:
+#ifndef NWSENABLED
+ delete curTask;
+ controlTask = NULL;
+#endif
+ break;
+
+ default:
+ MWprintf(30, "MWWorker::worker_mainloop_ind() - other task type\n");
+ }
+ break;
+
+ }
+ case NO_MESSAGE:{
+ MWTask *curTask = workingTask;
+ int num = curTask->number;
+
+ /* Set our stopwatch. again :-) */
+ wall_time -= MWSystem::gettimeofday();
+ cpu_time -= MWSystem::getcputime();
+
+ execute_task(curTask);
+
+ // Record times for it...
+ wall_time += MWSystem::gettimeofday();
+ cpu_time += MWSystem::getcputime();
+
+ curSubTask++;
+
+ if(curSubTask==curTask->numsubtask)
+ { MWprintf(50,"sending result\n");
+ curSubTask = 0;
+ execute_task( curTask );
+ RMC->initsend();
+ RMC->pack( &num, 1, 1 );
+ #ifdef MEASURE
+ RMC->pack(&_task_recv_time, 1, 1);
+ RMC->pack(&_task_recv_cpu_time, 1, 1);
+ #endif // END MEASURE
+ RMC->pack( &wall_time, 1, 1 );
+ RMC->pack( &cpu_time, 1, 1 );
+ curTask->pack_results();
+ status = RMC->send(master, RESULTS);
+ MWprintf(50,"sent result\n");
+ }
+
+ break;
+ }
+ case UPDATE_FROM_DRIVER:
+ {
+ MWprintf(51,"Received update while not working on task\n");
+ break;
+ }
+ case STOP_WORK: {
+// GGT This shouldn't happen anymore -- ignore it
+
+// int tasknum;
+// RMC->unpack(&tasknum, 1, 1);
+// // stop our current task only if the signal is for current task (not a previous one) and task is still running
+// if(tasknum == curTask->number)
+// {
+// //curSubTask = 0;
+// //execute_task( workingTaskContainer );
+// RMC->initsend();
+// RMC->pack( &workingTaskContainer->number, 1, 1 );
+// #ifdef MEASURE
+// RMC->pack(&_task_recv_time, 1, 1);
+// RMC->pack(&_task_recv_cpu_time, 1, 1);
+// #endif // END MEASURE
+// RMC->pack( &wall_time, 1, 1 );
+// RMC->pack( &cpu_time, 1, 1 );
+// workingTaskContainer->pack_results();
+// status = RMC->send(master, RESULTS);
+// MWprintf(50,"sent result\n");
+// }
+
+ break;
+ }
+ case KILL_YOURSELF: {
+ suicide();
+ }
+ case CHECKSUM_ERROR:
+ {
+ MWprintf ( 10, "Got a checksum error\n");
+ RMC->exit( CHECKSUM_ERROR_EXIT );
+ }
+ default: {
+ MWprintf ( 10, "Received strange command %d.\n", tag );
+ RMC->exit( UNKNOWN_COMMAND );
+ }
+ } // switch
+
+ return OK;
+
+}
+
+/* We've received orders to kill ourself; we're not needed anymore.
+ Fall on own sword. */
+
+void MWWorker::suicide ()
+{
+ MWprintf ( 10, "\"Goodbye, cruel world...\" says %s\n", mach_name );
+
+ RMC->exit(0);
+}
+
+
+/* For steering */
+int
+MWWorker::send_update_message()
+{
+ return RMC->send(master, UPDATE_FROM_WORKER);
+}
+
+void
+MWWorker::check_update_message()
+{
+ int bid = 0 ;
+ int info, len, tag, sending_host;
+
+ RMC->nrecv(-1, UPDATE_FROM_DRIVER);
+ info = RMC->bufinfo(bid, &len, &tag, &sending_host);
+ if (tag == UPDATE_FROM_DRIVER)
+ {
+ unpack_update();
+ }
+ else if(tag != NO_MESSAGE)
+ MWprintf(10, "check_update_message: \
+ got a message which is not UPDATE_FROM_DRIVER.\n");
+/* moving recv_all functionality into recv
+ MWList<void> * recv_buf_list = RMC->recv_buffers();
+
+ RMC->recv_all(-1, UPDATE_FROM_DRIVER);
+ len = recv_buf_list->number();
+ recv_buf_list->First();
+ while (recv_buf_list->AfterEnd() == false) {
+ bid = (int*)recv_buf_list->Current();
+ info = RMC->bufinfo(*bid, &len, &tag, &sending_host);
+ if (tag != UPDATE_FROM_DRIVER) {
+ MWprintf(10, "check_update_message: \
+ got a message which is not UPDATE_FROM_DRIVER.\n");
+ recv_buf_list->Remove();
+ }
+ recv_buf_list->Next();
+ }
+ return RMC->recv_buffers()->number();
+*/
+}
+// Local Variables:
+// mode: c++
+// eval: (c-set-style "K&R")
+// eval: (setq fill-column 79)
+// eval: (setq c-basic-offset 2)
+// eval: (setq tab-width 4)
+// eval: (c-set-offset 'arglist-close 0)
+// eval: (setq indent-tabs-mode nil)
+// End:
diff --git a/MW/src/MWWorker.h b/MW/src/MWWorker.h
new file mode 100644
index 0000000..f4eab90
--- /dev/null
+++ b/MW/src/MWWorker.h
@@ -0,0 +1,190 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWWORKER_H
+#define MWWORKER_H
+
+#include <stdlib.h>
+#include <string.h>
+#include "MWTask.h"
+
+/** This is the worker class that performs the tasks in the
+ opportunistic condor environment. It is an oppressed worker class
+ in that in simply executes the tasks given to it and reports the
+ results back to the master. {\tt :-)}
+
+ Capitalist stooges who wish to create an application
+ must derive a class from this class, and implement the following
+ two methods
+
+ \begin{itemize}
+ \item unpack_init_data()
+ \item execute_task()
+ \end{itemize}
+
+ @see MWDriver
+ @see MWWorker
+ @author Mike Yoder, modified by Jeff Linderoth and Jean-Pierre Goux */
+
+class MWWorker
+{
+
+public:
+
+ /// Default constructor
+ MWWorker();
+
+ /// Default Destructor
+ virtual ~MWWorker();
+
+ /// Giddyap!
+ void go( int argc, char *argv[] );
+
+ MWReturn do_benchmark_cmd( );
+
+ MWReturn worker_mainloop_oneshot ();
+
+
+ /// Our RM / Comm class. Used here only for communication.
+ static MWRMComm * RMC;
+
+ protected:
+
+ /// The task ID of the master - used for sending messages.
+ int master;
+
+ /// The task instance that a worker will use for packing/unpacking
+ /// information from the master
+ MWTask *workingTask;
+ MWTask *controlTask;
+
+ /// The name of the machine the worker is running on.
+ char mach_name[64];
+
+ /// The name of the master machine.
+ char master_mach_name[64];
+
+ /**
+ Here we might in the future pack some useful information about
+ the specific machine on which we're running. Right now,
+ all workers are equal, and we pass only the hostname.
+
+ There must be a "matching" unpack_worker_initinfo() in
+ the MWDriver class.
+ */
+ virtual void pack_worker_initinfo() {};
+
+
+//virtual MWTask* gimme_a_task() { return ((MWTask *) 0xdeadbeef); }
+
+ /**
+ This unpacks the initial data that is sent to the worker
+ once the master knows that he has started.
+
+ There must be a "matching" pack_worker_init_data() in
+ the MWDriver class derived for your application.
+
+ */
+ virtual MWReturn unpack_init_data() = 0;
+
+ /** This function performs the actions that happen
+ once the Worker finds out there is a task to do.
+ You will need to cast the MWTask * to a pointer of the Task type
+ derived for your application. For example
+
+ \begin{verbatim}
+ Task_Fib *dt = dynamic_cast<Task_Fib *> ( t );
+ assert( dt );
+ \end{verbatim}
+
+ */
+ virtual void execute_task( MWTask * ) = 0;
+
+ /**
+ This function performs the action that happens once the worker
+ receives a subtask. Subtask id starts at 0 and ends at n-1 subtasks.
+
+ Deprecated - changing subtask model for container of tasks model
+ */
+ //virtual void execute_subtask(MWTask *, int) {}
+
+ /**
+ The number of subtasks per worker is defined here.
+ If this function is not implemented, then data streaming/subtasks
+ is turned off and Master-Worker executes normally.
+
+ Deprecated - changing subtask model for container of tasks model
+ */
+ //virtual void set_num_subtask(int *) {}
+
+ /** Run a benchmark, given an MWTASK. The default implementation
+ * is to call \begin{verbatim} execute_task(t) \end{verbatim}
+ * and return 1.0/(Task Time) as a benchmark of how fast the machine
+ * is
+ */
+ virtual double benchmark ( MWTask *t );
+
+ /**
+ If you have some driver data that you would like to use on the
+ worker in order to execute the task, you should unpack it here.
+ */
+ virtual void unpack_driver_task_data( void ) {};
+
+ /**
+ This is run before the worker_mainloop(). It prints a message
+ that the worker has been spawned, sends the master an INIT
+ message, and awaits a reply from the master, upon which
+ it calls unpack_init_data().
+
+ */
+ MWReturn greet_master();
+
+ /**
+ This sits in a loop in which it asks for work from the master
+ and does the work. Maybe we should name this class GradStudent.
+ {\tt :-)}
+ */
+ void worker_mainloop();
+
+ /// Die!!!!!!
+ void suicide();
+
+ private:
+
+public:
+ /* send a update message to the master, without stopping current execution
+ * assume that the user has already called RMC->initsend, and RMC->pack */
+ int send_update_message();
+
+ /* Non-blocking check for DRIVER_UPDATE message, calls unpack_update */
+ void check_update_message();
+
+ /* Unpack data sent by send_update in master. Defined by user and called by check_update_message */
+ virtual void unpack_update(){};
+
+ int workerid; // id of worker.
+
+};
+
+#endif
+
+
diff --git a/MW/src/MWWorkerID.C b/MW/src/MWWorkerID.C
new file mode 100644
index 0000000..353cabd
--- /dev/null
+++ b/MW/src/MWWorkerID.C
@@ -0,0 +1,659 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* MWWorkerID.C
+*/
+#include "MW.h"
+#include "MWWorkerID.h"
+#include "MWTask.h"
+#include "MWSystem.h"
+
+#include <memory.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+
+
+int *MWWorkerID::vids = new int[MW_MAX_WORKERS];
+int MWWorkerID::vids_inited = 0;
+
+char *MWWorkerID::ulv_filename = "/tmp/mw-ulv";
+FILE *MWWorkerID::lfp = NULL;
+extern int *MWworkClassWorkers;
+extern int MWworkClasses;
+
+/** This static array is used to hold strings that represent the
+ MWworker_states. They are handy for printing out a worker - now
+ you'll see "WORKING" instead of "2" in printself().
+ @see MWworker_states */
+
+const char *MWworker_statenames[] = {
+ "INITIALIZING",
+ "IDLE",
+ "BENCHMARKING/INITIAL DATA HANDLING",
+ "WORKING",
+ "SUSPENDED",
+ "EXITED"
+};
+
+
+void
+MWWorkerID::init_vids() {
+ if (vids_inited == 0) {
+ for ( int i = 0; i < MW_MAX_WORKERS; i++ )
+ vids[i] = 0;
+ vids_inited = 1;
+ }
+}
+
+MWWorkerID::MWWorkerID()
+{
+ init_vids();
+ memset ( mach_name, 0, 64 );
+
+ id1 = -1;
+ id2 = -1;
+ virtual_id = -1;
+ doomed = FALSE;
+ // We use a negative number to signify that no benchmark has been set
+ bench_result = -1.0;
+
+ runningtask = NULL;
+ /*
+ next = NULL;
+ */
+
+ state = INITIALIZING;
+ isBenchMark = FALSE;
+ isBenchMarkAvailable = FALSE;
+
+ total_suspended = 0.0;
+ total_working = 0.0;
+ start_time = 0.0;
+ total_time = 0.0;
+ last_event = 0.0;
+ cpu_while_working = 0.0;
+
+
+ normalized_cpu_working_time = 0.0;
+ sum_benchmark = 0.0;
+ num_benchmark = 0;
+
+
+ CondorLoadAvg = NO_VAL;
+ LoadAvg = NO_VAL;
+ Memory = NO_VAL;
+ Cpus = NO_VAL;
+ VirtualMemory = NO_VAL;
+ Disk = NO_VAL;
+ KFlops = NO_VAL;
+ Mips = NO_VAL;
+
+ memset(OpSys, 0, sizeof(OpSys));
+ memset(Arch, 0 , sizeof(Arch));
+
+ set_vid ( get_next_vid() );
+ double currentTime = MWSystem::gettimeofday();
+ networkLatency = 0.0;
+ networkLatency_lastMeasuredTime = currentTime;
+
+ group = NULL;
+ executable_name = NULL;
+}
+
+MWWorkerID::~MWWorkerID()
+{
+ delete group;
+}
+
+
+enum MWworker_states MWWorkerID::currentState()
+{
+ return state;
+}
+
+void MWWorkerID::printself( int level )
+{
+
+ MWprintf ( level, "id1: %d id2: %d, vid: %d, name: \"%s\"\n",
+ id1, id2, virtual_id, mach_name ? mach_name : "" );
+ MWprintf ( level, "Memory: %d, KFlops: %d, Mips: %d\n", Memory, KFlops, Mips );
+ MWprintf ( level, "arch: \"%d\" state: %s\n",
+ arch, MWworker_statenames[state] );
+
+ if ( runningtask != NULL ) {
+ MWprintf ( level, " -> Running task: " );
+ runningtask->printself( level );
+ }
+ else
+ MWprintf ( level, " -> There's no task on this worker.\n" );
+
+ /* Print Here other Worker specific Info */
+
+}
+
+void MWWorkerID::set_machine_name( char *name ) {
+ strncpy( mach_name, name, 64 );
+}
+
+char * MWWorkerID::machine_name() {
+ return mach_name;
+}
+
+void MWWorkerID::started() {
+ // this is called when a worker first starts up.
+ if( state != INITIALIZING && state != BENCHMARKING ) {
+ MWprintf( 10, "Danger Will Robinson! started() worker whose "
+ "state != INITIALIZING && state != BENCHMARKING\n" );
+ printself(10);
+ }
+
+ // The following line is commented out because the state should be INITIALIZING !? - jichuan
+ // state = IDLE;
+
+ //XXX Jeff's hack. To get parallel efficiency "right" on
+ // MWfiles (with worker timeouts), we don't want to count
+ // the machines that just sit there in INITIALIZING state
+ // until they time out. Thus, we do not start the counter here, but
+ // only when we send a benchmark.
+
+ lprintf ( virtual_id, start_time, "Started on host %s\n", mach_name );
+}
+
+
+void MWWorkerID::benchmark()
+{
+ // this is called when a worker is sent the benchmark task
+ if ( state != INITIALIZING )
+ {
+ MWprintf( 10, "Danger Will Robinson! benchmarking a worker "
+ "state != INITIALIZING\n" );
+ printself(10);
+ }
+ state = BENCHMARKING;
+ isBenchMark = TRUE;
+
+}
+
+void MWWorkerID::benchmarkOver()
+{
+ if ( state != BENCHMARKING )
+ {
+ MWprintf( 10, "Danger Will Robinson! benchmarking over of "
+ " a worker whose state != BENCHMARKING\n" );
+ printself(10);
+ }
+ isBenchMark = FALSE;
+
+ //XXX Jeff's hack. To get parallel efficiency "right" on
+ // MWfiles (with worker timeouts), we don't want to count
+ // the machines that just sit there in INITIALIZING state
+ // until they time out. Thus, we start the counter here
+
+ start_time = MWSystem::gettimeofday();
+ state = IDLE;
+
+}
+
+void MWWorkerID::gottask( int tasknum ) {
+ // called when we begin a task.
+ state = WORKING;
+ last_event = MWSystem::gettimeofday();
+
+ lprintf ( virtual_id, last_event, "Assigned task %d\n", tasknum );
+}
+
+void MWWorkerID::completedtask( double wall_time, double cpu_time ) {
+ // called when the master is told that we finished this task.
+ state = IDLE;
+ last_event = MWSystem::gettimeofday();
+
+ total_working += wall_time;
+ cpu_while_working += cpu_time;
+
+ if (isBenchMarkAvailable){
+ if ( (cpu_time * bench_result) < -1.0e-6 ) {
+ MWprintf ( 10, "PROBLEM !!! cpu_time = %lf ; bench = %lf\n", cpu_time, bench_result);
+ } else {
+ normalized_cpu_working_time += cpu_time * bench_result;
+ }
+ }
+
+ lprintf ( virtual_id, last_event, "Completed task. (tot: %12.4f)\n"
+ "\tWall time: %12.4f\n"
+ "\tCpu time: %12.4f\n",
+ total_working, wall_time, cpu_time );
+
+}
+
+void MWWorkerID::suspended() {
+ // Called when this worker has a task and gets suspended.
+ last_event = MWSystem::gettimeofday();
+ state = SUSPENDED;
+
+ lprintf ( virtual_id, last_event, "Suspend.\n" );
+}
+
+void MWWorkerID::resumed() {
+
+ double now = MWSystem::gettimeofday();
+
+ // called when we resume and have a task.
+ if ( state != SUSPENDED ) {
+ MWprintf ( 10, "Got resume while not suspended!\n" );
+ }
+ else
+ {
+ if ( runningtask ) {
+ total_suspended += now - last_event;
+ state = WORKING;
+ } else if ( isBenchMark == TRUE ) {
+ state = BENCHMARKING;
+ } else {
+ state = IDLE;
+ }
+
+ }
+ last_event = now;
+
+ lprintf ( virtual_id, now, "Resume.\n" );
+}
+
+void MWWorkerID::set_bench_result( double bres )
+{
+ if( bres < 1.0e-8 ) {
+ MWprintf( 10, "Benchmark result must be a *positive* number\nSetting to 0\n" );
+ bench_result = 0.0;
+ }
+ else {
+ bench_result = bres;
+ sum_benchmark += bres;
+ num_benchmark++;
+
+ isBenchMarkAvailable = TRUE;
+ }
+}
+
+void MWWorkerID::ended() {
+ // called when the master is aware of the worker's death.
+ double now = MWSystem::gettimeofday();
+
+ if ( state == WORKING ) {
+/* We don't want to do this! If we're here, it means that we're running
+ a task, but we're done - therefore whatever we were doing wasn't
+ important and we shouldn't count it towards our work. (It's not
+ part of "GoodPut", in other words.) */
+// total_working += now - last_event;
+ } else if ( state == SUSPENDED ) {
+/* But what the heck, we'll count suspended */
+ total_suspended += now - last_event;
+ }
+ state = EXITED;
+
+
+ if( start_time > 1.0 ) {
+ total_time = now - start_time;
+ }
+ else {
+ total_time = 0.0;
+ }
+
+ lprintf ( virtual_id, now, "Finished.\n" );
+
+ release_vid ( get_vid() );
+
+ if ( group )
+ {
+ for ( int i = 0; i < MWworkClasses; i++ )
+ if ( doesBelong ( i ) )
+ deleteGroup ( i );
+
+ }
+}
+
+void MWWorkerID::ckpt_stats( double *up,
+ double *working,
+ double *susp,
+ double *cpu,
+ double *norm,
+ double *s_bench,
+ int *n_bench ) {
+
+ // print duration, total_working, total_suspended
+
+ double now = MWSystem::gettimeofday();
+
+ if ( start_time > 1.0 ) {
+ *up = now - start_time;
+ } else {
+ *up = 0.0; // possible if not yet started().
+ }
+
+ *working = total_working;
+ *susp = total_suspended;
+ *cpu = cpu_while_working;
+ *norm = normalized_cpu_working_time;
+
+ *s_bench = sum_benchmark;
+ *n_bench = num_benchmark;
+
+/* Don't do any of this - only count goodput...
+ if ( state == WORKING ) {
+ *work += now - last_event;
+ *cpu += now - last_event; // punt...
+ } else if ( state == SUSPENDED ) {
+ *susp += now - last_event; // we can lose some cpu time here. Oops.
+ }
+*/
+}
+
+
+
+/* get the lowest vid from 'vids' */
+int
+MWWorkerID::get_next_vid() {
+ int i;
+ for ( i=0 ; i< MW_MAX_WORKERS ; i++ ) {
+ if ( MWWorkerID::vids[i] == 0 ) {
+ MWWorkerID::vids[i] = 1;
+ return i;
+ }
+ }
+ MWprintf ( 10, "ERROR: Ran out of virtual IDs in MWWorkerID!\n" );
+ return -1;
+}
+
+/* Set virtual id */
+void
+MWWorkerID::set_vid( int i ) {
+ virtual_id = i;
+}
+
+/* Returns a virtual id to the pool */
+void
+MWWorkerID::release_vid( int vid ) {
+ MWWorkerID::vids[vid] = 0;
+}
+
+void
+MWWorkerID::lprintf ( int vid, double now, char *fmt, ... ) {
+
+ /* let's return now so we don't inflict this code on others. */
+ return;
+
+ if ( !lfp ) {
+ if ( (lfp=fopen( ulv_filename, "w" )) == NULL ) {
+ MWprintf ( 10, "Failed to open %s in MWWorkerID::lprintf, "
+ "errno %d\n", ulv_filename, errno );
+ return;
+ } else {
+ fprintf ( lfp, "#MW\n" );
+ }
+ }
+
+ fprintf ( lfp, "(%03d) ", vid );
+
+ struct tm *tm;
+ time_t time = (time_t) now;
+ tm = localtime( (time_t *)&time );
+ fprintf( lfp, "%d/%d %02d:%02d:%02d.%03d ",
+ tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec,
+ ((int)(((double) ((double) now -((int) now ))) * 1000))
+ );
+
+ va_list ap;
+ va_start( ap, fmt );
+ vfprintf( lfp, fmt, ap );
+ va_end( ap );
+
+ if ( fmt[strlen(fmt)-1] == '\n' ) {
+ fprintf ( lfp, "...\n" );
+ } else {
+ fprintf ( lfp, "\n...\n" );
+ }
+
+ fflush ( lfp );
+}
+
+/* The following (until the end of the file) was written by one of
+ Jean-Pierre's students. It isn't exactly efficient, dumping
+ a condor_status output to a file and reading from that. I understand
+ that it does work, however. -MEY (8-18-99) */
+
+int MWWorkerID::check_for_int_val(char* name, char* key, char* value) {
+ if (strcmp(name, key) == 0)
+ return atoi(value);
+ else return NO_VAL;
+}
+
+double MWWorkerID::check_for_float_val(char* name, char* key, char* value) {
+ if (strcmp(name, key) == 0)
+ return atof(value);
+ else return NO_VAL;
+}
+
+int MWWorkerID::check_for_string_val(char* name, char* key, char* value) {
+ if (strcmp(name, key) == 0)
+ return 0;
+ else return NO_VAL;
+}
+
+void MWWorkerID::get_machine_info() {
+
+ FILE* inputfile;
+ char key[200];
+ char value[1300];
+ char raw_line[1500];
+ char* equal_pos;
+ int found;
+ char temp_str[256];
+
+ char zero_string[2];
+
+#ifdef INDEPENDENT
+ return;
+#endif
+
+ memset(zero_string, 0 , sizeof(zero_string));
+
+ memset(key, '\0', sizeof(key));
+ memset(value, '\0', sizeof(value));
+
+ // This is a terrible kludge, but I'd rather do this in a script.
+ // We're going to move this into the RMC class anyway, so it's
+ // not so bad to fake it for now.
+
+ const bool jeff_hack = false;;
+
+ if( jeff_hack ) {
+ // note to jeff_hack: change this script to output to stdout, not filename
+ sprintf( temp_str, "./create_condor_status_file %s", mach_name /*, filename */);
+ }
+ else {
+
+ memset(temp_str, '\0', sizeof(temp_str));
+ sprintf(temp_str, "%s/bin/condor_status -l %s",
+ CONDOR_DIR, mach_name);
+ }
+
+
+#ifdef WINDOWS
+ return;
+
+#else
+ if (( inputfile = popen(temp_str, "r")) == 0) {
+ MWprintf( 10, "Error occurred during attempt to get "
+ "condor_status for %s.\n", mach_name );
+ return;
+ }
+
+ while (fgets(raw_line, 1500, inputfile) != 0) {
+ found = 0;
+ equal_pos = strchr(raw_line, '=');
+
+ if (equal_pos != NULL) {
+ strncpy(key, raw_line, equal_pos - (raw_line+1));
+ strcpy(value, equal_pos+2);
+
+ if (CondorLoadAvg == NO_VAL && !found) {
+ CondorLoadAvg = check_for_float_val("CondorLoadAvg",
+ key, value);
+ if (CondorLoadAvg != NO_VAL)
+ found = 1;
+ }
+
+ if (LoadAvg == NO_VAL && !found) {
+ LoadAvg = check_for_float_val("LoadAvg", key, value);
+ if (LoadAvg != NO_VAL)
+ found = 1;
+ }
+
+ if (Memory == NO_VAL && !found) {
+ Memory = check_for_int_val("Memory", key, value);
+ if (Memory != NO_VAL)
+ found = 1;
+ }
+
+ if (Cpus == NO_VAL && !found) {
+ Cpus = check_for_int_val("Cpus", key, value);
+ if (Cpus != NO_VAL)
+ found = 1;
+ }
+
+ if (VirtualMemory == NO_VAL && !found) {
+ VirtualMemory = check_for_int_val("VirtualMemory", key, value);
+ if (VirtualMemory != NO_VAL)
+ found = 1;
+ }
+
+ if (Disk == NO_VAL && !found) {
+ Disk = check_for_int_val("Disk", key, value);
+ if (Disk != NO_VAL)
+ found = 1;
+ }
+
+ if (KFlops == NO_VAL && !found) {
+ KFlops = check_for_int_val("KFlops", key, value);
+ if (KFlops != NO_VAL)
+ found = 1;
+ }
+
+ if (Mips == NO_VAL && !found) {
+ Mips = check_for_int_val("Mips", key, value);
+ if (Mips != NO_VAL)
+ found = 1;
+ }
+
+ if ( (strncmp(Arch, zero_string, 1) == 0) && !found) {
+ if (check_for_string_val("Arch", key, value) == 0){
+ strncpy( Arch, value, strlen(value)-1 );
+ }
+
+ if (strncmp(Arch, zero_string, 1) != 0)
+ found = 1;
+ }
+
+ if ( (strncmp(OpSys, zero_string, 1) == 0) && !found) {
+ if (check_for_string_val("OpSys", key, value) == 0){
+ strncpy( OpSys, value, strlen(value)-1 );
+ }
+
+ if (strncmp(OpSys, zero_string, 1) != 0)
+ found = 1;
+ }
+
+ memset(key, '\0', sizeof(key));
+ memset(value, '\0', sizeof(value));
+
+ }
+
+ }
+
+ pclose ( inputfile);
+
+ MWprintf(90,"CURRENT MACHINE : %s \n", mach_name);
+ MWprintf(90,"Architecture : %s \n", Arch);
+ MWprintf(90,"Operating System : %s \n", OpSys);
+
+ MWprintf(90,"CondorLoadAvg : %f\n", CondorLoadAvg);
+ MWprintf(90,"LoadAvg : %f\n", LoadAvg);
+ MWprintf(90,"Memory : %d\n", Memory);
+ MWprintf(90,"Cpus : %d\n", Cpus);
+ MWprintf(90,"VirtualMemory : %d\n", VirtualMemory);
+ MWprintf(90,"Disk : %d\n", Disk);
+ MWprintf(90,"KFlops : %d\n", KFlops);
+ MWprintf(90,"Mips : %d\n", Mips);
+#endif
+}
+
+void
+MWWorkerID::setNetworkConnectivity ( double latency )
+{
+ networkLatency_lastMeasuredTime = MWSystem::gettimeofday();
+ networkLatency = latency;
+ MWprintf ( 10, "The network latency is %f\n", networkLatency);
+}
+
+double
+MWWorkerID::getNetworkConnectivity ( double &retVal )
+{
+ retVal = networkLatency_lastMeasuredTime;
+ return networkLatency;
+}
+
+void
+MWWorkerID::initGroups ( int num )
+{
+ group = new MWGroup ( num );
+}
+
+void
+MWWorkerID::addGroup ( int num )
+{
+ MWworkClassWorkers[num]++;
+ group->join ( num );
+ return;
+}
+
+void
+MWWorkerID::deleteGroup ( int num )
+{
+ MWworkClassWorkers[num]--;
+ group->leave ( num );
+ return;
+}
+
+bool
+MWWorkerID::doesBelong ( int num )
+{
+ return group->belong ( num );
+}
+
+MWGroup*
+MWWorkerID::getGroup ( )
+{
+ return group;
+}
diff --git a/MW/src/MWWorkerID.h b/MW/src/MWWorkerID.h
new file mode 100644
index 0000000..4795fc2
--- /dev/null
+++ b/MW/src/MWWorkerID.h
@@ -0,0 +1,395 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWWORKERID_H
+#define MWWORKERID_H
+#include "MW.h"
+#include "MWGroup.h"
+#include <string.h>
+
+#define NO_VAL -1
+
+/// A forward reference; needed to define the MWWorkerID class.
+class MWTask;
+
+/**
+ This is a list of the states in which a worker can be.
+ */
+enum MWworker_states {
+ /// Some initialization; not ready for work
+ INITIALIZING,
+ /// Waiting for the master to send work
+ IDLE,
+ /// Benchmarking, or doing application initialization on the initial data
+ BENCHMARKING,
+ /// Working actively on its task
+ WORKING,
+ /// The machine has been suspended
+ SUSPENDED,
+ /// This worker has finished life.
+ EXITED
+};
+
+/** This array is used to hold strings that represent the
+ MWworker_states. They are handy for printing out a worker - now
+ you'll see "WORKING" instead of "2" in printself().
+ @see MWworker_states */
+extern const char* MWworker_statenames[];
+
+
+/**
+ This class keeps an identification of the worker application
+ useful for the driver class. It also keeps statistical information
+ that is useful to the stats class. This information will be used at
+ the end of a run.
+ */
+class MWWorkerID {
+
+ // allow access to worker's data...makes my life easier.
+ friend class MWStatistics;
+
+public:
+
+ /// Default constructor
+ MWWorkerID();
+
+ /// Default destructor
+ virtual ~MWWorkerID();
+
+ /// Return primary id of this worker
+ int get_id1() { return id1; };
+
+ /// Return secondard id of this worker
+ int get_id2() { return id2; };
+
+ /** Return the virtual id. This is an int starting at zero and
+ increasing by one with each worker. When a worker dies, this
+ number can be reused by a worker that joins us. */
+ int get_vid() { return virtual_id; };
+
+ /// Set primary id
+ void set_id1( int i ) { id1 = i; };
+
+ /// Set secondary id
+ void set_id2( int i ) { id2 = i; };
+
+ /// Set the machine's name
+ void set_machine_name( char * );
+
+ /// Get the current machine information
+ void get_machine_info();
+
+ /// Returns a pointer to the machine's name
+ char *machine_name();
+
+ /// Set this worker's arch class
+ void set_arch ( int a ) { arch = a; };
+
+ /// Get this worker's arch class
+ int get_arch() { return arch; };
+
+ /// Sets the exec_class
+ void set_exec_class ( int num ) { exec_class = num; };
+
+ /// Gets the exec_class
+ int get_exec_class ( ) { return exec_class; };
+
+ /// Sets the executable
+ void set_executable ( char *exec ) { executable_name = exec; };
+
+ /// returns the executable name
+ char* get_executable ( ) { return executable_name; };
+
+ /// Mark this worker so that when the task completes it will exit
+ void mark_for_removal() { doomed = TRUE; };
+
+ /// returns TRUE if mark_for_removal was called previously
+ int is_doomed() { return doomed; };
+
+ ///
+ void set_bench_result( double bres );
+
+ ///
+ double get_bench_result() { return bench_result; };
+
+ ///
+ double getNetworkConnectivity ( double &t );
+ void setNetworkConnectivity ( double );
+
+
+ /// The task running on this worker. NULL if there isn't one.
+ MWTask *runningtask;
+
+ /*
+ /// The next worker ID in the list of available workers. NULL otherwise
+ MWWorkerID *next;
+ */
+
+ /// The state of the worker.
+ enum MWworker_states currentState();
+
+ /// Set the state of the worker
+ void setState ( MWworker_states st ) { state = st; };
+
+ /** Print out a description of this worker.
+ @param level The debug level to use */
+ virtual void printself( int level = 40 );
+
+ /**@name Statistics Collection Calls
+
+ These methods are called when events happen to workers.
+ */
+
+ //@{
+
+ /// Returns true if this worker is idle.
+ bool isIdle() { return (state==IDLE); }
+
+ /// Returns true if this worker is suspended.
+ bool isSusp() { return (state==SUSPENDED); }
+
+ /** This should be called when the master becomes aware of the
+ existence of this worker. */
+ void started();
+ /// Called when the worker is doing the benchmarking task
+ void benchmark();
+ /// Called when the worker has done the benchmarking task
+ void benchmarkOver();
+ /// Called when this worker gets a task.
+ void gottask( int tasknum );
+ /// Called when this worker just finished the task it was working on.
+ void completedtask( double wall_time = 0.0, double cpu_time = 0.0 );
+ /// Called when the worker becomes suspended
+ void suspended();
+ /// Called when the worker resumes.
+ void resumed();
+ /// Send flowers...this is called when the worker dies.
+ void ended();
+
+ //@}
+
+ void initGroups ( int num );
+ /// Add worker to a workclass/group
+ void addGroup ( int num );
+ /// Remove worker from a workclass/group
+ void deleteGroup ( int num );
+ bool doesBelong ( int num );
+ MWGroup *getGroup ( );
+
+ /**@name Checkpointing Call
+
+ Yes, each instance of a MWWorkerID needs to be able to checkpoint
+ itself. Why? It has to store statistics information on itself.
+ It never has to read them in, though, because stats that we write
+ out here wind up being read in by the stats class when we restart.
+ */
+
+ //@{
+
+ /// Return the relevant stats info for this worker.
+
+ void ckpt_stats( double *up,
+ double *working,
+ double *susp,
+ double *cpu,
+ double *norm,
+ double* s_bench,
+ int* n_bench );
+
+ //@}
+
+ /** @name Worker Information
+ This is now collected from condor_status. It's the work of
+ one of JP's students...
+
+ Note that this Arch is different from arch. This one is
+ what condor claims its arch is to the outside world.
+ */
+ //@{
+
+ ///
+ char Arch[64];
+
+ ///
+ char OpSys[64];
+
+ ///
+ double CondorLoadAvg;
+
+ ///
+ double LoadAvg;
+
+ ///
+ int Memory;
+
+ ///
+ int Cpus;
+
+ ///
+ int VirtualMemory;
+
+ ///
+ int Disk;
+
+ ///
+ int KFlops;
+
+ ///
+ int Mips;
+
+
+ ///
+ double get_total_time(){ return total_time;};
+ ///
+ double get_last_event(){return last_event;};
+ ///
+ double get_total_suspended(){return total_suspended;};
+ ///
+ double get_total_working(){return total_working;};
+
+ private:
+
+ int check_for_int_val(char* name, char* key, char* value);
+ double check_for_float_val(char* name, char* key, char* value);
+ int check_for_string_val(char* name, char* key, char* value);
+
+ //@}
+
+ /** @name Private Data... */
+ //@{
+
+ /// The machine name of the worker
+ char mach_name[64];
+
+ /// A "primary" identifier of this machine. (Was pvmd_tid)
+ int id1;
+
+ /// A "secondary" identifier of this machine. (Was user_tid)
+ int id2;
+
+ /** A "virtual" number for this worker. Assigned starting at
+ 0 and working upwards by one. Also, when a worker dies,
+ this number can get taken over by another worker */
+ int virtual_id;
+
+ /// This worker's arch class
+ int arch; // (should be just a 0, 1, 2, etc...)
+
+ /// This is the exec_class
+ int exec_class;
+
+ /// This is the executable_name
+ char *executable_name;
+
+ /// TRUE if marked for removal, FALSE otherwise
+ int doomed;
+
+ /// The results of the benchmarking process.
+ double bench_result;
+
+ /// The state of this worker.
+ enum MWworker_states state;
+
+ /** @name Time information
+ Note that all time information is really stored as a double.
+ We use gettimeofday() internally, and convert the result to
+ a double. That way, we don't have to mess around with the
+ struct timeval... */
+ //@{
+ /// The time that this worker started.
+ double start_time;
+
+ /// The total time that this worker ran for.
+ double total_time;
+
+ /// The time of the last 'event'.
+ double last_event;
+
+ /// The time spent in the suspended state
+ double total_suspended;
+
+ /// The time spent working
+ double total_working;
+
+ /// The cpu usage while working
+ double cpu_while_working;
+
+ /// The benchmarked (weighted) cpu working time
+ double benchmarked_cpu_working_time;
+
+ /// The benchmarked (normalized) cpu working time
+ double normalized_cpu_working_time;
+
+ /// The sum of the benchmark values for that vid
+ double sum_benchmark;
+
+ /// The number of the benchmark values for that vid
+ int num_benchmark;
+
+
+ //@}
+ //@}
+
+ bool isBenchMark;
+ bool isBenchMarkAvailable;
+
+ /** @name Virtual Id Helpers */
+ //@{
+ /// vids[i] is 1 if virtual id i is taken, 0 if not.
+ static int *vids;
+
+ // So here is the fix to MWStats bugs: I moved the vids[MW_MAX_WORKERS] init logic
+ // into the init_vids() function.
+ static int vids_inited;
+ void init_vids();
+
+ /// Set virtual id
+ void set_vid( int i );
+
+ /// Returns the lowest available virtual id; also sets it as used.
+ int get_next_vid();
+
+ /// Returns a virtual id to the pool
+ void release_vid( int vid );
+ //@}
+
+ /** @name A Special Printf
+ Used to make output for John Bent's ulv program... */
+
+ //@{
+ /** The log printf - use it to print ONE log event. It will
+ automagically add the "..." delimiter for you. */
+ void lprintf ( int vid, double now, char *fmt, ... );
+ /// The name of the ulv log file
+ static char *ulv_filename;
+ /// The log file fp.
+ static FILE *lfp;
+ //@}
+
+ /// Variables regarding the nw bandwidth.
+ double networkLatency;
+ double networkLatency_lastMeasuredTime;
+ MWGroup *group;
+};
+
+
+#endif
diff --git a/MW/src/MWWorkerMain.C b/MW/src/MWWorkerMain.C
new file mode 100644
index 0000000..b41a242
--- /dev/null
+++ b/MW/src/MWWorkerMain.C
@@ -0,0 +1,42 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/*
+ * This is the master's main function. The whole starts from this point
+ * This was done on 2/2/00 to make MW pure Object Oriented.
+ *
+ * Author:
+ * Sanjeev. R. Kulkarni
+ */
+
+
+
+#include <stdio.h>
+#include "MWWorker.h"
+extern MWWorker* gimme_a_worker();
+
+int main ( int argc, char *argv[] )
+{
+ MWWorker *worker;
+ worker = gimme_a_worker ( );
+ worker->go ( argc, argv );
+}
diff --git a/MW/src/MWprintf.C b/MW/src/MWprintf.C
new file mode 100644
index 0000000..fbc0d5a
--- /dev/null
+++ b/MW/src/MWprintf.C
@@ -0,0 +1,106 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* MWprintf.C - The place for the MWPrintf stuff. */
+
+#include "MW.h"
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef WINDOWS
+#include <sys/time.h>
+#endif
+
+int MWprintf_level = 50;
+static int fopen_count = 0;
+
+FILE* Open ( char *filename, char *mode )
+{
+ FILE *fp;
+
+ fp = fopen ( filename, mode );
+ if ( fp ) {
+ fopen_count++;
+ }
+ else{
+ //MWprintf ( 10, "Could not open file %s as errno is %d\n", filename, errno );
+ }
+ return fp;
+}
+
+void Close ( FILE *fp )
+{
+ int retval;
+ fflush(fp);
+ retval = fclose ( fp );
+ if ( retval != 0 )
+ MWprintf ( 10, "Could not close the file %x as errno is %d\n", fp, errno );
+ else
+ fopen_count--;
+}
+
+int
+get_MWprintf_level () {
+ return MWprintf_level;
+}
+
+
+int set_MWprintf_level ( int level ) {
+ int foo = MWprintf_level;
+ if ( (level<0) || (level>99) ) {
+ MWprintf( 10, "Bad arg \"%d\" in set_MWprintf_level().\n", level );
+ } else {
+ MWprintf_level = level;
+ }
+ return foo;
+}
+
+void MWprintf ( int level, char *fmt, ... ) {
+
+ static int printTime = TRUE;
+
+ if ( level > MWprintf_level ) {
+ return;
+ }
+
+#ifndef WINDOWS
+ if ( printTime ) {
+ struct timeval tv;
+ ::gettimeofday(&tv, NULL);
+ struct tm *t = localtime(&tv.tv_sec);
+ printf( "%d:%02d:%02d.%03d ", t->tm_hour, t->tm_min, t->tm_sec, (int) (tv.tv_usec / 1000));
+ }
+#endif
+
+ va_list ap;
+ va_start( ap, fmt );
+ vprintf( fmt, ap );
+ va_end( ap );
+ fflush( stdout );
+
+ if ( fmt[strlen(fmt)-1] == '\n' )
+ printTime = TRUE;
+ else
+ printTime = FALSE;
+}
diff --git a/MW/src/MWprintf.h b/MW/src/MWprintf.h
new file mode 100644
index 0000000..5e2cef7
--- /dev/null
+++ b/MW/src/MWprintf.h
@@ -0,0 +1,82 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/* MWprintf.h
+
+ A definition of the MWprintf functions
+
+*/
+
+#ifndef MWPRINTF_H
+#define MWPRINTF_H
+
+#include <stdio.h>
+
+ /** @name MWPrintf
+ This functions control the amount of printed information
+ in the MWDriver. This is controlled through "levels", where
+ a level of 0 is the most important and 99 is the least
+ important. You can set the debug level to only print
+ levels n and below.
+
+ Yes, this *is* a global function. However, everyone needs
+ to use it, and making it a static member of MWDriver would
+ mean that you'd have to type MWDriver::MWprintf(), which
+ would get downright annoying.
+
+ Other suggestions would be welcome.
+
+ Here's a proposed layout of how the numbers should work:
+ \begin{itemize}
+ \item 10 : Big errors, major events
+ \item 20 : Statistics at the end, user results
+ \item 30 : User-defined results, info, etc
+ \item 40 : Hosts up/down, other minor events
+ \item 50 : Checkpointing information
+ \item 60 : Sending/Receiving work
+ \item 70 : Misc messges...
+ \item 80 : Pointers!
+ \item 90 : Even more pointers, debugging info, etc
+ \end{itemize}
+
+ Remember, you've got 9 levels in between each of these, so
+ feel free to be creative....
+ */
+
+ //@{
+
+ /** A regular printf, with debugging level. */
+void MWprintf ( int level, char *fmt, ... );
+
+/** Get the debug level for the MWprintf function. */
+int get_MWprintf_level();
+
+ /** Set the debug level for the MWprintf function. The default
+ upon startup is 50.
+ @return The old level */
+int set_MWprintf_level( int level );
+ //@}
+
+FILE* Open ( char*, char* );
+void Close ( FILE* );
+
+#endif
diff --git a/MW/src/Makefile.in b/MW/src/Makefile.in
new file mode 100644
index 0000000..444b5ad
--- /dev/null
+++ b/MW/src/Makefile.in
@@ -0,0 +1,171 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+ENABLE_MWINDEPENDENT = @ENABLE_MWINDEPENDENT@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# Subdirectories
+SUBDIRS = RMComm MWControlTasks BlackBox
+
+### Libraries to be built, and dependent source files
+# If ENDABLE_INDEPENDENT is yes (you can do that by configure --with-independent).
+# It seems we must build two sets of object file/lib for the normal configuration and --with-independent (otherwise
+# the class definition included in different obj files are different (some are larget with independent - realized
+# this after PAINFUL debugging. Thanks for Peter's intuition!)
+# Here the safest way is to build libMW_indp.a and libMWutil_indp.a (although it currently doesn't include MWDriver.h
+# or MWWorker.h), also the libNWS_indp.a, libMWRMComm_lib.a and the libMWRC_indp.a (the actual RMC implementation).
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+LIBRARIES = libMW.a libMWutil.a libMW_indp.a libMWutil_indp.a
+else
+LIBRARIES = libMW.a libMWutil.a
+endif
+
+libMW_a_SOURCES = MW.C MWDriver.C MWTask.C MWTaskContainer.C MWWorkerID.C MWWorker.C MWStats.C MWprintf.C MWGroup.C MWUnixSystem.C
+libMW_a_OBJECTS = MW.o MWDriver.o MWTask.o MWTaskContainer.o MWWorkerID.o MWWorker.o MWStats.o MWprintf.o MWGroup.o MWUnixSystem.o
+libMWutil_a_SOURCES = MWList.C
+libMWutil_a_OBJECTS = MWList.o
+
+libMW_indp_a_OBJECTS = MWInd.o MWDriverInd.o MWWorkerInd.o MWWorkerIDInd.o MWTaskInd.o MWTaskContainerInd.o MWStatsInd.o MWprintfInd.o MWGroupInd.o MWUnixSystem.o
+libMWutil_indp_a_OBJECTS = MWListInd.o
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+INCLUDES = -I. -IRMComm -IMW-File -IMW-CondorPVM -IMW-Socket -IMWControlTasks $(MISC_DEFN) $(MEASURE_DEFN)
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+INDP_CXXCOMPILE = $(CXXCOMPILE) -DINDEPENDENT
+
+INCLUDEFILES = MW.h MWDriver.h\
+ MWGroup.h MWList.h MWStats.h MWSystem.h MWTask.h MWTaskContainer.h MWWorker.h MWWorkerID.h MWprintf.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+libMW.a: $(libMW_a_OBJECTS) $(libMW_a_DEPENDENCIES)
+ -rm -f libMW.a
+ $(AR) cru libMW.a $(libMW_a_OBJECTS) $(libMW_a_LIBADD)
+ $(RANLIB) libMW.a
+ cp libMW.a $(MW_LIBDIR)
+
+libMWutil.a: $(libMWutil_a_OBJECTS) $(libMWutil_a_DEPENDENCIES)
+ -rm -f libMWutil.a
+ $(AR) cru libMWutil.a $(libMWutil_a_OBJECTS) $(libMWutil_a_LIBADD)
+ $(RANLIB) libMWutil.a
+ cp libMWutil.a $(MW_LIBDIR)
+
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+libMW_indp.a: $(libMW_indp_a_OBJECTS)
+ -rm -f libMW_indp.a
+ $(AR) cru libMW_indp.a $(libMW_indp_a_OBJECTS)
+ $(RANLIB) libMW_indp.a
+ cp libMW_indp.a $(MW_LIBDIR)
+libMWutil_indp.a: $(libMWutil_indp_a_OBJECTS)
+ -rm -f libMWutil_indp.a
+ $(AR) cru libMWutil_indp.a $(libMWutil_indp_a_OBJECTS)
+ $(RANLIB) libMWutil_indp.a
+ cp libMWutil_indp.a $(MW_LIBDIR)
+MWInd.o:MW.C
+ $(INDP_CXXCOMPILE) -o MWInd.o -c MW.C
+MWDriverInd.o:MWDriver.C
+ $(INDP_CXXCOMPILE) -o MWDriverInd.o -c MWDriver.C
+MWWorkerInd.o:MWWorker.C
+ $(INDP_CXXCOMPILE) -o MWWorkerInd.o -c MWWorker.C
+MWTaskInd.o:MWTask.C
+ $(INDP_CXXCOMPILE) -o MWTaskInd.o -c MWTask.C
+MWTaskContainerInd.o:MWTaskContainer.C
+ $(INDP_CXXCOMPILE) -o MWTaskContainerInd.o -c MWTaskContainer.C
+MWWorkerIDInd.o:MWWorkerID.C
+ $(INDP_CXXCOMPILE) -o MWWorkerIDInd.o -c MWWorkerID.C
+MWStatsInd.o:MWStats.C
+ $(INDP_CXXCOMPILE) -o MWStatsInd.o -c MWStats.C
+MWprintfInd.o:MWprintf.C
+ $(INDP_CXXCOMPILE) -o MWprintfInd.o -c MWprintf.C
+MWGroupInd.o:MWGroup.C
+ $(INDP_CXXCOMPILE) -o MWGroupInd.o -c MWGroup.C
+MWListInd.o:MWList.C
+ $(INDP_CXXCOMPILE) -o MWListInd.o -c MWList.C
+endif
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+
+install: $(LIBRARIES) $(INCLUDEFILES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a *core
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a core
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
diff --git a/MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.C b/MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.C
new file mode 100644
index 0000000..b14c005
--- /dev/null
+++ b/MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.C
@@ -0,0 +1,1290 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWCondorPvmRC.h"
+#include <MW.h>
+#include <MWDriver.h>
+#include <MWTask.h>
+#include <MWWorker.h>
+
+#ifdef PVM_MASTER
+MWRMComm * MWDriver::RMC = new MWPvmRC;
+MWRMComm * MWTask::RMC = MWDriver::RMC;
+MWRMComm * MWWorker::RMC = NULL;
+#else
+MWRMComm * MWWorker::RMC = new MWPvmRC;
+MWRMComm * MWTask::RMC = MWWorker::RMC;
+MWRMComm * MWDriver::RMC = NULL;
+#endif
+
+extern int *MW_exec_class_num_workers;
+
+MWPvmRC::MWPvmRC ( )
+{
+ hostadd_reqs = NULL;
+ is_master = FALSE; // assume the worst...
+ submit_list = new MWList<void>;
+}
+
+MWPvmRC::~MWPvmRC ( )
+{
+ if ( hostadd_reqs )
+ {
+ for ( int i = 0; i < exec_classes; i++ )
+ delete [] hostadd_reqs[i];
+ delete [] hostadd_reqs;
+ }
+ if ( submit_list )
+ {
+ while ( submit_list->number() > 0 )
+ delete ((int *)submit_list->Remove());
+ delete submit_list;
+ }
+
+ if (recv_buf_list) {
+ while ( recv_buf_list->number() > 0 )
+ delete ((int *)recv_buf_list->Remove());
+ delete recv_buf_list;
+ }
+}
+
+/* Implementation of comm / rm class for pvm. */
+void
+MWPvmRC::exit( int exitval )
+{
+ MWprintf ( 50, "Before pvm_exit\n" );
+ pvm_catchout( 0 );
+ pvm_exit();
+ MWprintf ( 50, "After pvm_exit\n" );
+ ::exit(exitval);
+}
+
+int
+MWPvmRC::setup( int argc, char *argv[], int *id, int *master_id )
+{
+
+ MWprintf ( 10, "In MWPvmRC::setup()\n");
+
+ *id = pvm_mytid();
+ MWprintf(10, "MyPid is %d(%x)\n", *id, *id );
+
+ // BUFFER - init the recv_buf_list
+ recv_buf_list = new MWList<void>;
+
+ if ( ( *master_id = pvm_parent() ) == PvmNoParent ) {
+ MWprintf ( 40, "I have no parent, therefore I'm the master.\n" );
+ is_master = TRUE;
+ *master_id = 0;
+ } else {
+ is_master = FALSE;
+ return 0;
+ }
+
+ pvm_catchout( stderr );
+ /* We tell PVM to tell us when hosts are added. We will be sent
+ a message with tag HOSTADD. The -1 turns the notification on.
+ */
+ pvm_notify ( PvmHostAdd, HOSTADD, -1, NULL );
+
+ return 0;
+}
+
+int
+MWPvmRC::config( int *nhosts, int *narches, MWWorkerID ***workers )
+{
+ if ( !is_master ) {
+ MWprintf ( 10, "Slaves not allowed in this privaledged call!\n" );
+ return -1;
+ }
+
+ struct pvmhostinfo *hi= NULL;
+ int r;
+
+ MWprintf ( 70, "In MWPvmRC::config()\n" );
+
+ if ( *workers ) {
+ MWprintf ( 10, "workers should be NULL when called.\n" );
+ return -1;
+ }
+
+ if ( (r = pvm_config ( nhosts, narches, &hi ) ) < 0 ) {
+ MWprintf ( 10, "Return value of %d from pvm_config!\n", r );
+ return -1;
+ }
+
+ (*workers) = new MWWorkerID*[*nhosts];
+ for ( int i=0 ; i<*nhosts ; i++ ) {
+ (*workers)[i] = new MWWorkerID;
+ (*workers)[i]->set_arch ( atoi ( hi[i].hi_arch ) );
+ /* Do domething creative with speed later! */
+ }
+
+ return 0;
+}
+
+int
+MWPvmRC::start_worker ( MWWorkerID *w )
+{
+ struct condorpvm_submit_element *elem = NULL;
+ // int ex_cl;
+ int retval;
+
+ if ( !is_master )
+ {
+ MWprintf ( 10, "Slaves not allowed in this privaledged call!\n" );
+ return -1;
+ }
+
+ MWprintf ( 50, "In MWPvmRC::start_worker()\n" );
+ if ( !w )
+ {
+ MWprintf ( 10, "w cannot be NULL!\n" );
+ return -1;
+ }
+
+ /* First, we will unpack some goodies that pvm gave us: */
+ int val;
+ char name[64], arch[64];
+ int status, dsig;
+
+ /* The following is packed by the multishadow along with the
+ HOSTADD message. We unpack it here to put into the MWWorkerID */
+ unpack ( &val, 1, 1 );
+ unpack ( name );
+ unpack ( arch );
+ unpack ( &status, 1, 1 );
+ unpack ( &dsig, 1, 1 ); // new in 3.4.1
+ val &= PVM_MASK; // remove that annoying high bit
+ MWprintf ( 40, "Received a host: " );
+ MWprintf ( 40, "Host %x added (%s), arch: %s, status:%d\n",
+ val, name, arch, status );
+
+ w->set_arch( atoi(arch) );
+// w->set_machine_name( name );
+ elem = find_exec_class ( atoi(arch) );
+ if ( !elem )
+ {
+ MWprintf ( 10, "Strange!! No pending request found for arch %d\n", atoi(arch) );
+ w->set_id1(-1);
+ return -1;
+ }
+ else
+ {
+ w->set_exec_class ( elem->exec_class );
+ w->set_executable ( elem->exec );
+ retval = do_spawn( w );
+ }
+
+ /* We can do this now because the request will go down regardless
+ of whether or not the spawn succeeds... */
+ hostadd_reqs[elem->exec_class][w->get_arch()]--;
+ delete elem;
+ return retval;
+}
+
+int
+MWPvmRC::init_beginning_workers( int *nworkers, MWWorkerID ***workers )
+{
+ if ( !is_master )
+ {
+ MWprintf ( 10, "Slaves not allowed in this privaledged call!\n" );
+ return -1;
+ }
+
+ int i, j, narches;
+ MWprintf ( 50, "In MWPvmRC::init_beginning_workers\n" );
+
+ /* config allocates memory for workers */
+ if ( config( nworkers, &narches, workers ) < 0 )
+ {
+ return -1;
+ }
+
+ /* num_arches is a member of MWCommRC */
+ if ( (num_arches != -1) && (num_arches != narches) )
+ {
+ /* We were told by someone that we had the wrong number of
+ arch classes. Complain here. */
+ MWprintf ( 10, "num_arches was set to %d, pvm just told us %d!\n",
+ num_arches, narches );
+ return -1;
+ }
+ num_arches = narches;
+
+ MWprintf ( 40, "Number of hosts at start: %d.\n", *nworkers );
+ MWprintf ( 40, "Number of arch. classes: %d.\n", num_arches );
+
+ hostadd_reqs = new int*[exec_classes];
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ hostadd_reqs[i] = new int[num_arches];
+ for ( j = 0 ; j < num_arches ; j++ )
+ {
+ hostadd_reqs[i][j] = 0;
+ }
+ }
+
+ for ( i=0 ; i<(*nworkers) ; i++ )
+ {
+ do_spawn( (*workers)[i] );
+ }
+
+ return 0;
+}
+
+int
+MWPvmRC::restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg )
+{
+ return init_beginning_workers ( nworkers, workers );
+}
+
+int
+MWPvmRC::do_spawn ( MWWorkerID *w )
+{
+ int spawned_tid;
+ int exec_class;
+ char arch[4];
+ char *exec;
+ int archnum = w->get_arch();
+ sprintf ( arch, "%d", archnum );
+ int i;
+
+ if ( w->get_executable() == NULL )
+ {
+ int tempi[exec_classes];
+
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ tempi[i] = 0;
+ }
+
+ for ( i = 0; i < num_executables; i++ )
+ {
+ if ( worker_executables[i]->arch_class == w->get_arch() )
+ tempi[worker_executables[i]->exec_class] = 1;
+ }
+
+ exec_class = choose_exec_class ( tempi );
+ if ( exec_class < 0 )
+ {
+ MWprintf ( 10, "ERROR!! No suitable exec_class chosen for arch_class %d\n", w->get_arch() );
+ return -1;
+ }
+ exec = find_executable ( exec_class, w->get_arch() );
+ w->set_executable ( exec );
+ w->set_exec_class ( exec_class );
+ }
+ else
+ {
+ exec_class = w->get_exec_class();
+ exec = w->get_executable();
+ }
+
+ MWprintf ( 40, "About to call pvm_spawn (%s)...\n", exec );
+
+#if ! defined( STANDALONE )
+ int status = pvm_spawn( exec, NULL, 2, arch, 1, &spawned_tid );
+#else
+ int status = pvm_spawn( exec, NULL, 1, "wheel", 1, &spawned_tid );
+#endif
+
+ if ( status == 1 )
+ {
+ MWprintf ( 40, "Success spawning as tid %x.\n", spawned_tid );
+ w->set_id1( ( spawned_tid & PVM_MASK ) );
+ w->set_id2( ( pvm_tidtohost( spawned_tid ) & PVM_MASK ) );
+ setup_notifies ( spawned_tid );
+ return spawned_tid;
+ }
+ else
+ {
+ MWprintf ( 40, "Huh? Error: status:%d, tid:%d\n",
+ status, spawned_tid );
+ MWprintf ( 40, "There was a problem spawning on %x.\n", w->get_id1() );
+
+ /* We make sure that id2 is -1, signifying error! */
+ // w->set_id1( -1 ); // FIXME ??? Isn't it set_id2(-1) ?
+ w->set_id2(-1);
+ return -1;
+ }
+}
+
+int
+MWPvmRC::removeWorker ( MWWorkerID *w )
+{
+ char *machine = w->machine_name();
+ int info;
+ MWprintf ( 70, "Removing worker %s.\n", machine );
+ int retval = pvm_delhosts( &machine, 1, &info );
+ MWprintf(31, "pvm_delhosts returned %d and infos[0] = %d\n", retval, info);
+ if ( retval < 0 ) {
+ MWprintf ( 10, "pvm_delhosts returns an error of %d!\n", retval );
+ }
+ if ( info < 0 ) {
+ MWprintf ( 10, "pvm_delhosts of %s has error %d.\n", machine, info );
+ }
+ delete w;
+ return retval;
+}
+
+int
+MWPvmRC::hostaddlogic( int *num_workers )
+{
+ /* This awfully complex function determines the conditions
+ under which it being called, and then calls pvm_addhosts()
+ asking for the correct number of hosts.
+
+ - num_workers - an array of size num_arches that contains
+ the number of workers in each arch class.
+ - hostadd_reqs: The number of outstanding HOSTADDs out there
+ - target_num_workers: Set by the user...
+ */
+
+ /* If we're in STANDALONE mode, we never ask for hosts,
+ so we basically ignore this whole function: */
+#if !defined (STANDALONE)
+
+ if ( !hostadd_reqs ) {
+ /* if this doesn't exist yet, we won't do anything */
+ return 0;
+ }
+
+ /* number of hosts to ask for at a time. The idea is that we'll
+ have double this outstanding at a time - and this amounts
+ to 12 for 1, 2, or 3 arch classes. */
+
+ // Jeff changed this -- we always ask for six extra for each arch class...
+ int HOSTINC = hostinc_;
+
+
+ int i, j;
+ int *sorted_order = new int[exec_classes];
+ sort_exec_class_ratio ( sorted_order );
+ int *howmany = new int[num_arches]; // how many to ask for
+ int *current_reqs_arches = new int[num_arches];
+ int *current_reqs_execs = new int[num_arches];
+ int *num_execs = new int[exec_classes];
+ // int total_workers = 0;
+ // int total_reqs = 0;
+ // int total_howmany = 0;
+
+
+ // DEBUGGING
+ struct pvmhostinfo *hostp;
+ int info, k, nhost, narch;
+
+ MWprintf ( 60, "hal: target: %d.\n", target_num_workers );
+
+ for ( i = 0; i < num_arches; i++ )
+ {
+ current_reqs_arches[i] = 0;
+ howmany[i] = 0;
+ for ( j = 0; j < exec_classes; j++ )
+ {
+ current_reqs_arches[i] += hostadd_reqs[j][i];
+ }
+ }
+
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ current_reqs_execs[i] = 0;
+ num_execs[i] = 0;
+ for ( j = 0; j < num_arches; j++ )
+ {
+ current_reqs_execs[i] += hostadd_reqs[i][j];
+ }
+ }
+
+ for ( i = 0; i < num_executables; i++ )
+ {
+ num_execs[ worker_executables[i]->exec_class ]++;
+ }
+
+ for ( i = 0 ; i < exec_classes ; i++ )
+ {
+ MWprintf ( 60, "hal: %d workers in class %d\n", num_workers[i], i );
+ MWprintf ( 60, " -- outstanding reqs: %d\n", current_reqs_arches[i] );
+ int cur = sorted_order[i];
+ int req;
+
+ // DEBUGGING
+
+ info = pvm_config( &nhost, &narch, &hostp );
+ if (info!=0)
+ MWprintf(31, "DEBUG: pvm_config() failed, returns %d.\n", info);
+ else {
+ MWprintf(31, "DEBUG: pvm_config() returned, nhost = %d.\n", nhost);
+ if ( (exec_classes == 1) && (nhost > MW_exec_class_num_workers[cur]) ) {
+ MWprintf(81, "DEBUG: CondorPvm and MW thinks differently about the number of workers.\n");
+ MWprintf(81, "DEBUG: nhost(MW) = %d, nhost(CondorPvm) = %d. Below is the worker list: \n",
+ MW_exec_class_num_workers[cur], nhost);
+ for (k = 0; k < nhost; k++)
+ MWprintf(91, "HOST_NAME = %s\n", hostp[k].hi_name);
+ }
+ }
+
+
+ if ( MW_exec_class_num_workers[cur] + current_reqs_execs[cur] >= exec_class_target_num_workers[cur] ) continue;
+ if ( current_reqs_execs[cur] > num_execs[cur] * HOSTINC ) continue;
+ if ( exec_class_target_num_workers[cur] - ( MW_exec_class_num_workers[cur] + current_reqs_execs[cur] ) > 2 * HOSTINC )
+ req = 2 * HOSTINC;
+ else
+ req = exec_class_target_num_workers[cur] - ( MW_exec_class_num_workers[cur] + current_reqs_execs[cur] );
+
+ for ( j = 0; j < num_arches; j++ )
+ {
+ int given;
+ char *temp;
+ if ( !(temp = exists_executable ( cur, j )) ) continue;
+ if ( current_reqs_arches[j] > HOSTINC ) continue;
+ if ( current_reqs_arches[j] + req > 2 * HOSTINC )
+ {
+ given = 2 * HOSTINC - current_reqs_arches[j];
+ }
+ else
+ {
+ given = req;
+ }
+
+ req -= given;
+ current_reqs_execs[cur] += given;
+ hostadd_reqs[cur][j] += given;
+ current_reqs_arches[j] += given;
+ howmany[j] += given;
+
+ for ( int k = 0; k < given; k++ )
+ {
+ struct condorpvm_submit_element *news = new struct condorpvm_submit_element;
+ news->arch_class = j;
+ news->exec_class = cur;
+ news->exec = temp;
+ submit_list->Append ( (void *)news );
+ }
+ }
+ }
+
+ /* We're FINALLY ready to do the deed! */
+ for ( i = 0 ; i < num_arches ; i++ )
+ {
+ if ( howmany[i] > 0 )
+ ask_for_host( howmany[i], i );
+ }
+
+ delete [] howmany;
+ delete [] current_reqs_execs;
+ delete [] current_reqs_arches;
+ delete [] sorted_order;
+
+#endif /* ifndef STANDALONE */
+ return 0;
+}
+
+int
+MWPvmRC::setup_notifies ( int task_tid )
+{
+ /* Takes a *task* tid, and sets up all notifies at once. */
+
+ MWprintf ( 40, "Setting up notifies for tid %x.\n", task_tid );
+ int pvmd_tid = pvm_tidtohost( task_tid );
+
+ pvm_notify ( PvmHostDelete, HOSTDELETE, 1, &pvmd_tid );
+ pvm_notify ( PvmTaskExit, TASKEXIT, 1, &task_tid );
+#if !defined( STANDALONE )
+ pvm_notify ( PvmHostSuspend, HOSTSUSPEND, 1, &pvmd_tid );
+ pvm_notify ( PvmHostResume, HOSTRESUME, 1, &pvmd_tid );
+#endif
+
+ return 0;
+}
+
+int
+MWPvmRC::ask_for_host( int howmany, int arch )
+{
+ int status;
+ MWprintf ( 10, "Asking for %d host(s) with arch %d\n", howmany, arch );
+
+ char **arches = new char*[howmany];
+ for ( int i=0 ; i<howmany ; i++ ) {
+ arches[i] = new char[4];
+ sprintf( arches[i], "%d", arch );
+ }
+ int *infos = new int[howmany];
+
+ status = pvm_addhosts ( arches, howmany, infos );
+
+ for ( int j=0 ; j<howmany ; j++ ) {
+ delete [] arches[j];
+ }
+ delete [] arches;
+ delete [] infos;
+
+ if ( status < 0 ) {
+ MWprintf ( 10, "pvm_addhosts returns %d, may not be able to "
+ "aquire requested resources...\n", status );
+ } else {
+ MWprintf ( 90, "pvm_addhosts called with status = %d\n", status );
+ }
+
+ return status; // JGS
+}
+
+struct condorpvm_submit_element*
+MWPvmRC::find_exec_class ( int arch )
+{
+ struct condorpvm_submit_element *elem;
+
+ elem = (struct condorpvm_submit_element *)submit_list->First();
+ while ( submit_list->AfterEnd() == false )
+ {
+ elem = (struct condorpvm_submit_element *)submit_list->Current();
+ if ( elem->arch_class == arch ) {
+ submit_list->RemoveCurrent();
+ return elem;
+ }
+ else submit_list->Next ();
+ }
+ return NULL;
+}
+
+int
+MWPvmRC::choose_exec_class ( int *tempi )
+{
+ for ( int i = 0; i < exec_classes; i++ )
+ {
+ if ( tempi[i] == 1 )
+ return i;
+ }
+ return -1;
+}
+
+char*
+MWPvmRC::find_executable ( int ex_cl, int ar_cl )
+{
+ for ( int i = 0; i < num_executables; i++ )
+ {
+ if ( worker_executables[i]->arch_class == ar_cl &&
+ worker_executables[i]->exec_class == ex_cl )
+ return worker_executables[i]->executable_name;
+ }
+ return NULL;
+}
+
+void
+MWPvmRC::sort_exec_class_ratio ( int *temp )
+{
+ int i, j;
+ double ii, jj;
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ temp[i] = i;
+ }
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ for ( j = i + 1; j < exec_classes; j++ )
+ {
+ ii = ((double)MW_exec_class_num_workers[temp[i]]) / exec_class_target_num_workers[temp[i]];
+ jj = ((double)MW_exec_class_num_workers[temp[j]]) / exec_class_target_num_workers[temp[j]];
+ if ( jj > ii )
+ {
+ int temp = j;
+ j = i;
+ i = temp;
+ }
+ }
+ }
+ return;
+}
+
+char*
+MWPvmRC::exists_executable ( int ex_cl, int ar_cl )
+{
+ for ( int i = 0; i < num_executables; i++ )
+ {
+ if ( worker_executables[i]->arch_class == ar_cl &&
+ worker_executables[i]->exec_class == ex_cl )
+ return worker_executables[i]->executable_name;
+ }
+ return NULL;
+}
+
+void
+MWPvmRC::conf() {
+
+ int num_curr_hosts, num_curr_arch;
+
+ struct pvmhostinfo *hi;
+
+ // Foolish pvm_config allocs its own memory...
+ pvm_config ( &num_curr_hosts, &num_curr_arch, &hi );
+
+ MWprintf ( 40, "* Pvm says that there are %d machines and %d arches.\n",
+ num_curr_hosts, num_curr_arch );
+
+ MWprintf ( 40, "* These machines have the following configurations:\n" );
+ MWprintf ( 40, "* tid\t\tname\t\t\tarch\tspeed\n" );
+ MWprintf ( 40, "* ---\t\t----\t\t\t----\t-----\n" );
+
+ for ( int i=0 ; i<num_curr_hosts ; i++ ) {
+ MWprintf ( 40, "* %x\t%s\t%s\t%d\n", hi[i].hi_tid, hi[i].hi_name,
+ hi[i].hi_arch, hi[i].hi_speed );
+ }
+
+ MWprintf ( 40, "\n" );
+}
+
+int
+MWPvmRC::initsend ( int encoding )
+{
+ return pvm_initsend ( encoding );
+}
+
+
+int
+MWPvmRC::send ( int to_whom, int msgtag )
+{
+ return pvm_send ( to_whom, msgtag );
+}
+
+int
+MWPvmRC::nrecv( int from_whom, int msgtag)
+{
+ if ( (!is_master) )
+ return pvm_nrecv( from_whom, msgtag );
+
+ int *tmp;
+ int *buf_id = NULL;
+
+ if ( !(recv_buf_list->IsEmpty()) ) {
+ /* Assume that the first message in the list is already processed */
+ tmp = (int*) recv_buf_list->Remove();
+ MWprintf(91, "Deleted buffer %d\n", *tmp);
+ freebuf(*tmp);
+ }
+
+ if (recv_buf_list->IsEmpty()) {
+ buf_id = new int;
+ (*buf_id) = pvm_recv ( from_whom, msgtag );
+ if ( buf_id > 0 ) /* attach the buf_id */
+ recv_buf_list->Append((void*)buf_id);
+ } else {
+ buf_id = (int*)recv_buf_list->First();
+ }
+
+ return *buf_id;
+}
+
+/* old blocking recv() */
+int
+MWPvmRC::recv ( int from_whom, int msgtag )
+{
+ recv_all(-1, -1);
+ int *buf_id = NULL;
+
+ if (recv_buf_list == NULL || recv_buf_list->number()==0)
+ {
+ int *tmp;
+
+ if ( !(recv_buf_list->IsEmpty()) ) {
+ /* Assume that the first message in the list is already processed */
+ tmp = (int*) recv_buf_list->Remove();
+ MWprintf(91, "Deleted buffer %d\n", *tmp);
+ freebuf(*tmp);
+ }
+
+ if (recv_buf_list->IsEmpty()) {
+ buf_id = new int;
+ (*buf_id) = pvm_recv ( from_whom, msgtag );
+ if ( buf_id > 0 ) /* attach the buf_id */
+ recv_buf_list->Append((void*)buf_id);
+ } else {
+ buf_id = (int*)recv_buf_list->First();
+ }
+ }
+ else
+ {
+ int* bid = (int*) recv_buf_list->Remove();
+ buf_id = bid;
+ recv_buf_list->Prepend(bid);
+ }
+
+ return *buf_id;
+}
+
+/* BUFFER: returns the new buf_id if success, -1 otherwise. */
+int
+MWPvmRC::next_buf()
+{
+ int setr_ret;
+ int *bid1, *bid2;
+
+ MWprintf(91, "BUFFER: Entered MWPvmRC::next_buf()\n");
+
+ if ( recv_buf_list->number()<2 )
+ return -1;
+
+ bid1 = (int*) recv_buf_list->Remove();
+ bid2 = (int*) recv_buf_list->Remove();
+
+ if (bid2) {
+ setr_ret = pvm_setrbuf(*bid2);
+ while ( setr_ret == PvmBadParam || setr_ret == PvmNoSuchBuf ) {
+ MWprintf(91, "BUFFER: pvm_setrbuf() failed, can't move to the next buffer. Pvm returns %d.\n", setr_ret);
+
+ freebuf(*bid1);
+ delete bid1;
+ bid1 = bid2;
+ bid2 = (int*) recv_buf_list->Remove();
+
+ if (bid2)
+ setr_ret = pvm_setrbuf(*bid2);
+ else {
+ MWprintf(91, "BUFFER: In MWPvmRC::next_buf(), the next buffer points to NULL.\n");
+ return -1;
+ }
+ }
+
+ // Prepend the current active buffer
+ recv_buf_list->Prepend(bid2);
+ }
+
+ return (*bid2);
+}
+
+/* BUFFER: returns 1 if switched, returns 0 if no need to switch */
+int
+MWPvmRC::switch_buf_back()
+{
+ int *buf_id;
+
+ // if the newly received buffer is the only buffer in recv_buf_list, then return.
+ if (recv_buf_list->number()<1)
+ return 0;
+
+ // otherwise, need to set the active buffer back to the head buffer of recv_buf_list
+ buf_id = (int*) recv_buf_list->Remove();
+
+ int setr_ret = pvm_setrbuf(*buf_id);
+ if (setr_ret == PvmBadParam || setr_ret == PvmNoSuchBuf)
+ MWprintf(61, "BUFFER: Can't set active receive buffer to %d.\n", *buf_id);
+ else MWprintf(91, "BUFFER: Set active receive buffer back from %d to %d.\n", setr_ret, *buf_id);
+ recv_buf_list->Prepend(buf_id);
+
+ return 1;
+}
+
+/* BUFFER: receive from pvm and pack into the buffer list */
+int
+MWPvmRC::recv_all( int from_whom, int msgtag )
+{
+ int *buf_id = new int[1];
+ int *tmp, len = 0;
+
+ if ( !(recv_buf_list->IsEmpty()) ) {
+ /* Assume that the first message in the list is already processed */
+ tmp = (int*) recv_buf_list->Remove();
+ MWprintf(91, "Deleted buffer %d\n", *tmp);
+ freebuf(*tmp);
+ }
+
+ (*buf_id) = pvm_nrecv( from_whom, msgtag );
+
+ if ( *buf_id <= 0 ) {
+ MWprintf(91, "BUFFER: recv_all() got nothing, Pvm returns %d.\n", *buf_id);
+ if (recv_buf_list->number())
+ switch_buf_back();
+ return *buf_id;
+ }
+
+ while ( *buf_id > 0 ) {
+ MWprintf(91, "BUFFER: got a new buffer %d.\n", *buf_id);
+ recv_buf_list->Append(buf_id);
+ buf_id = new int [1];
+ len ++;
+
+ pvm_setrbuf(0);
+ (*buf_id) = pvm_nrecv( from_whom, msgtag );
+ }
+ delete buf_id;
+
+ MWprintf(31, "BUFFER: recv_all() got %d new messages, recv_buf_list length is %d.\n", len, recv_buf_list->number());
+
+ // Return the number of newly received buffers
+ return (switch_buf_back()) ? len : 1;
+}
+
+/* BUFFER: pvm_setrbuf wrapper */
+int
+MWPvmRC::setrbuf( int bid )
+{
+ return pvm_setrbuf( bid );
+}
+
+// BUFFER: pvm_freebuf wrapper */
+int
+MWPvmRC::freebuf( int bid )
+{
+ int ret = pvm_freebuf( bid );
+
+ if ( ret == PvmNoSuchBuf || ret == PvmBadParam )
+ MWprintf(61, "BUFFER: pvm_freebuf(%d) failed, returns %d.\n", bid, ret);
+
+ return ret;
+}
+
+/* BUFFER: pvm_bufinfo wrapper */
+int
+MWPvmRC::bufinfo ( int buf_id, int *len, int *tag, int *from )
+{
+ if ( buf_id == 0 ) // might want to check if 0 is a valid id
+ {
+ *tag = NO_MESSAGE;
+ return 0;
+ }
+
+ int retval = pvm_bufinfo ( buf_id, len, tag, from );
+ /* to clear out the annoying high bit! */
+ *from &= PVM_MASK;
+ return retval;
+}
+
+// BUFFER
+MWList<void>*
+MWPvmRC::recv_buffers()
+{
+ return recv_buf_list;
+}
+
+void
+MWPvmRC::who ( int *wh )
+{
+ unpack ( wh, 1, 1 );
+ *wh &= PVM_MASK;
+}
+
+int
+MWPvmRC::pack ( const char *bytes, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride;
+ return pvm_pkbyte ( const_cast<char *>(bytes), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const float *f, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(float);
+ return pvm_pkfloat ( const_cast<float *>(f), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const double *d, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(double);
+ return pvm_pkdouble ( const_cast<double *>(d), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const int *i, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(int);
+ return pvm_pkint ( const_cast<int *>(i), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const unsigned int *ui, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(unsigned int);
+ return pvm_pkuint ( const_cast<unsigned int *>(ui), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const short *sh, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(short);
+ return pvm_pkshort ( const_cast<short *>(sh), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const unsigned short *ush, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(unsigned short);
+ return pvm_pkushort ( const_cast<unsigned short *>(ush), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const long *l, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(long);
+ return pvm_pklong ( const_cast<long *>(l), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const unsigned long *ul, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(unsigned long);
+ return pvm_pkulong ( const_cast<unsigned long *>(ul), nitem, stride );
+}
+
+int
+MWPvmRC::pack ( const char *str )
+{
+ bytes_packed_ += strlen(str);
+ return pvm_pkstr ( const_cast<char *>(str) );
+}
+
+// BUFFER
+int
+MWPvmRC::unpack ( char *bytes, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkbyte ( bytes, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkbyte ( bytes, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(char);
+ return 0;
+ }
+ } else return setr_ret;
+
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( float *f, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkfloat ( f, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkfloat ( f, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(float);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( double *d, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkdouble ( d, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkdouble ( d, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(double);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( int *i, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkint ( i, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkint ( i, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(int);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( unsigned int *ui, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkuint( ui, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkuint ( ui, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned int);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( short *sh, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkshort ( sh, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkshort ( sh, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(short);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( unsigned short *ush, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkushort ( ush, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkushort ( ush, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned short);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( long *l, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upklong ( l, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upklong ( l, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(long);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( unsigned long *ul, int nitem, int stride )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkulong ( ul, nitem, stride );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkulong ( ul, nitem, stride );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned long);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::unpack ( char *str )
+{
+ int ret, setr_ret;
+
+ // receive from the current active buffer
+ ret = pvm_upkstr ( str );
+
+ if ( ret==0 ) // Success!
+ return 0;
+
+ if ( recv_buf_list == NULL )
+ return ret;
+
+ if ( ( ret == PvmNoData ) && (recv_buf_list->number()>=2) ) {
+ setr_ret = next_buf();
+
+ if (setr_ret!=-1) { // Switch to the next valid buffer succeeded!
+ ret = pvm_upkstr ( str );
+
+ if ( ret!=0 ) {
+ MWprintf(61, "BUFFER: The first two buffers returns PvmNoData, the second can't be unpacked %d.\n", ret);
+ return ret;
+ } else {
+ bytes_unpacked_ += strlen(str);
+ return 0;
+ }
+ } else return setr_ret;
+ } else return ret;
+}
+
+int
+MWPvmRC::read_RMstate ( FILE *fp = NULL )
+{
+ // No Pvm specific functions
+ return 0;
+}
+
+
+int
+MWPvmRC::write_RMstate ( FILE *fp = NULL )
+{
+ // No Pvm specific functions
+ return 0;
+}
+
+#ifdef NWSENABLED
+typedef int (*callBackFcnDefn)(void* arg, int status);
+void setRestartFunction (
+ callBackFcnDefn /*cbRestart*/,
+ void* /*cbRestartArg*/,
+ callBackFcnDefn /*cbCkpt*/,
+ void* /*cbCkptArg*/ )
+{
+}
+
+#endif
diff --git a/MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.h b/MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.h
new file mode 100644
index 0000000..91e8941
--- /dev/null
+++ b/MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.h
@@ -0,0 +1,287 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWPVMRC_H
+#define MWPVMRC_H
+
+#include "../MWRMComm.h"
+#include "MWList.h"
+extern "C" {
+#include "pvm3.h"
+}
+
+/// A mask for getting rid of that annoying high set bit.
+#define PVM_MASK 0x7fffffff
+
+struct condorpvm_submit_element
+{
+ int arch_class;
+ int exec_class;
+ char *exec;
+};
+
+/**
+ A Resource Management and Communication class that uses PVM
+ for underlying support of inter-process communication and
+ resource management.
+
+ We *could* do cool things here...like keep track of amount of
+ data sent, to whom, etc. We could also MWprintf ( 99, "..." )
+ everything that gets sent for heaps and heaps of debugging.
+
+*/
+
+class MWPvmRC : public MWRMComm
+{
+
+ public:
+
+ /// Constructor...
+ MWPvmRC();
+
+ /// Destructor...
+ ~MWPvmRC();
+
+ /** @name A. Resource Management Routines
+
+ Here we implement the pure virtual functions found in
+ ur parent class, MWRMComm.
+ */
+ //@{
+
+ /** Shut down. Calls pvm_exit(), then ::exit(exitval). */
+ void exit( int exitval );
+
+ /** Initialization. Does pvm_catchout(), pvm_parent(),
+ and pvm_notifies(). */
+ int setup( int argc, char *argv[], int *my_id, int *master_id );
+
+ /** Does a pvm_config, and stuffs the returned hostinfo
+ struct information into a lot of MWWorkerID's. See
+ the parent class for return details. */
+ int config( int *nhosts, int *narches, MWWorkerID ***workers );
+
+ /** Basically do a pvm_spawn. We also put some information
+ into w upon return.
+ @return The tid spawned. Negative number on error.
+ */
+ int start_worker ( MWWorkerID *w );
+
+ /** Start up the workers that are given to us at the beginning.
+ See base class comments for more details.
+ @param nworkers The number of workers at start
+ @param workers A pointer to an array of pointers to
+ MWWorkerID classes. This call will new() memory
+ for the MWWorkerIDs. Also, if (*w)[n]->id2 is
+ -1, that means that the spawn failed for
+ worker number n.
+ */
+ int init_beginning_workers ( int *nworkers, MWWorkerID ***workers );
+
+ /** Called at the time of restart */
+ int restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg );
+
+ /** Remove a worker. Basically, call pvm_delhosts(). */
+ int removeWorker( MWWorkerID *w );
+
+ /** Read some state. A null function */
+ int read_RMstate ( FILE *fp );
+
+ /** Write some state. A null function */
+ int write_RMstate ( FILE *fp );
+
+ //@}
+
+ private:
+ /** @name Other Functions to be implemented */
+
+ //@{
+
+ /** Figure out wether or not to ask for hosts, and how many...
+ @param num_workers An array of size num_arches that contains
+ the number of workers in each arch class.
+ */
+ int hostaddlogic( int *num_workers );
+
+ /** Do the pvm_spawn and associated stuff */
+ int do_spawn( MWWorkerID *w );
+
+ /** Set up the proper notifies for a task & host tid */
+ int setup_notifies ( int task_tid );
+
+ /** This function says to pvm: "I would like another machine,
+ please".
+ @param howmany The number of machines to request
+ @param archnum The arch class number to ask for. */
+ int ask_for_host( int howmany, int archnum );
+
+ /** Shows the pvm virtual machine according to pvm. Used
+ for debugging purposes; not normally called. */
+ void conf();
+
+ /** Helper for hostaddlogic(). Returns the index of the min
+ element in array, which is of length len */
+ int min ( int *array, int len );
+
+ /** The number of outstanding requests for a particular
+ arch. */
+ //int *hostadd_reqs;
+
+ /** The requests per exec_classes */
+ int **hostadd_reqs;
+
+ MWList<void> * submit_list;
+
+ //@}
+
+ /** Am I the master process or not? */
+ int is_master;
+
+ public:
+
+
+ /** @name C. Communication Routines
+
+ These are essentially thin wrappers of PVM calls.
+ */
+ //@{
+
+ ///
+ int initsend ( int encoding = PvmDataDefault);
+
+ ///
+ int send ( int to_whom, int msgtag );
+
+ ///
+ int recv ( int from_whom, int msgtag );
+
+ /// non-blocking version of receive
+ int nrecv (int fromWhom, int msgtag);
+
+ /** Provide info on the message just received */
+ int bufinfo ( int buf_id, int *len, int *tag, int *from );
+
+ /** Tells the affected party */
+ void who ( int *id );
+
+ /// Pack some bytes
+ int pack ( const char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int pack ( const float *f, int nitem, int stride = 1 );
+
+ /// double
+ int pack ( const double *d, int nitem, int stride = 1 );
+
+ /// int
+ int pack ( const int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int pack ( const unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int pack ( const short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int pack ( const unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int pack ( const long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int pack ( const unsigned long *ul, int nitem, int stride = 1 );
+
+ /// Pack a NULL-terminated string
+ int pack ( const char *str );
+
+ /// Unpack some bytes
+ int unpack ( char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int unpack ( float *f, int nitem, int stride = 1 );
+
+ /// double
+ int unpack ( double *d, int nitem, int stride = 1 );
+
+ /// int
+ int unpack ( int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int unpack ( unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int unpack ( short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int unpack ( unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int unpack ( long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int unpack ( unsigned long *ul, int nitem, int stride = 1 );
+
+ /// Unpack a NULL-terminated string
+ int unpack ( char *str );
+
+ //@}
+
+ private:
+ /** @name C. Some Misc Helper functions
+ */
+
+ //@{
+
+ /** Find a suitable executable_class for a particular arch_class.
+ This function is useful to pick up the executable */
+ struct condorpvm_submit_element* find_exec_class ( int arch );
+
+ /** In the beginning, find a exec_class to an already
+ acquired arch_class */
+ int choose_exec_class ( int *tempi );
+
+ /** Find the appropriate executable name that belongs to exec_class ex_cl and
+ arch_class ar_cl */
+ char* find_executable ( int ex_cl, int ar_cl );
+
+ /** Sort the array temp based on the ratio of current/desired
+ number of workers of each exec_class */
+ void sort_exec_class_ratio ( int *temp );
+
+ /** Find if there is an executable that belongs to exec_class ex_cl and
+ arch_class ar_cl and if it exists return the executable name */
+ char* exists_executable ( int ex_cl, int ar_cl );
+
+ /** The non-blocking recv functions */
+ public:
+ int recv_all( int from_whom, int msgtag ); // returns the number of new buffers
+ int setrbuf(int bid); // switch the active receive buffer
+ // return the old active buf_id
+ int freebuf(int bid); // free the receive buffer.
+ MWList<void>* recv_buffers(); // return the recv_buf_list
+ int next_buf(); // advance the active buffer to the next valid buffer
+ // in the recv_buf_list.
+ int switch_buf_back(); // Switch the active receive buffer to the buffer
+ // on the head of the recv_buf_list;
+};
+
+#endif
diff --git a/MW/src/RMComm/MW-CondorPVM/Makefile.in b/MW/src/RMComm/MW-CondorPVM/Makefile.in
new file mode 100644
index 0000000..4cd5d5d
--- /dev/null
+++ b/MW/src/RMComm/MW-CondorPVM/Makefile.in
@@ -0,0 +1,140 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(DEBUG_CHECKER) $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+
+# Subdirectories
+SUBDIRS =
+
+# Libraries to be built, and dependent source files
+LIBRARIES = libMWcondorpvmmaster.a libMWcondorpvmworker.a
+libNWcondorpvmmaster_a_SOURCES = MWCondorPvmRCM.ii
+libMWcondorpvmmaster_a_LIBADD = MWCondorPvmRCM.o
+libMWcondorpvmmaster_a_DEPENDENCIES = MWCondorPvmRCM.o
+libMWcondorpvmmaster_a_OBJECTS =
+
+libMWcondorpvmworker_a_SOURCES = MWCondorPvmRCW.o
+libMWcondorpvmworker_a_LIBADD = MWCondorPvmRCW.o
+libMWcondorpvmworker_a_DEPENDENCIES = MWCondorPvmRCW.o
+libMWcondorpvmworker_a_OBJECTS =
+
+INCLUDES = -I. -I.. -I../.. -I$(PVM_ROOT)/include $(MEASURE_DEFN)
+INCLUDEFILES = MWCondorPvmRC.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+
+libMWcondorpvmmaster.a: $(libMWcondorpvmmaster_a_OBJECTS) $(libMWcondorpvmmaster_a_DEPENDENCIES)
+ -rm -f libMWcondorpvmmaster.a
+ $(AR) cru libMWcondorpvmmaster.a $(libMWcondorpvmmaster_a_OBJECTS) $(libMWcondorpvmmaster_a_LIBADD)
+ $(RANLIB) libMWcondorpvmmaster.a
+ cp libMWcondorpvmmaster.a $(MW_LIBDIR)
+
+libMWcondorpvmworker.a: $(libMWcondorpvmworker_a_OBJECTS) $(libMWcondorpvmworker_a_DEPENDENCIES)
+ -rm -f libMWcondorpvmworker.a
+ $(AR) cru libMWcondorpvmworker.a $(libMWcondorpvmworker_a_OBJECTS) $(libMWcondorpvmworker_a_LIBADD)
+ $(RANLIB) libMWcondorpvmworker.a
+ cp libMWcondorpvmworker.a $(MW_LIBDIR)
+
+MWCondorPvmRCM.ii:MWCondorPvmRC.C
+ $(CXX) -E $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DPVM_MASTER MWCondorPvmRC.C > MWCondorPvmRCM.ii
+
+MWCondorPvmRCM.o:MWCondorPvmRCM.ii
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DPVM_MASTER MWCondorPvmRCM.ii
+
+MWCondorPvmRCW.ii:MWCondorPvmRC.C
+ $(CXX) -E $(DEFS) $(MISC_DEFN) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) MWCondorPvmRC.C > MWCondorPvmRCW.ii
+
+MWCondorPvmRCW.o:MWCondorPvmRCW.ii
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) MWCondorPvmRCW.ii
+
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
diff --git a/MW/src/RMComm/MW-File/MWFileError.h b/MW/src/RMComm/MW-File/MWFileError.h
new file mode 100644
index 0000000..e74a191
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileError.h
@@ -0,0 +1,35 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWFILEERROR_H
+#define MWFILEERROR_H
+
+#define HALF_WORK_WAIT_FILE 200
+
+#define HALF_MASTER_WAIT_FILE 201
+
+#define INIT_FILE_PROBLEM 202
+
+#define NEGNUMEXEC 203
+
+#endif
diff --git a/MW/src/RMComm/MW-File/MWFileRC.C b/MW/src/RMComm/MW-File/MWFileRC.C
new file mode 100644
index 0000000..8273bf1
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileRC.C
@@ -0,0 +1,2992 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWFileTypes.h"
+#include "MWFileSend.h"
+#include "MWFileRC.h"
+#include "MWFileRCSymbol.h"
+#include "MWFileError.h"
+
+#include <assert.h>
+#include <time.h>
+
+#ifdef FILE_MASTER
+#include <user_log.c++.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+
+#include <MWSystem.h>
+#include <MWDriver.h>
+#include <MWWorkerID.h>
+#include <MWTask.h>
+#include <MWWorker.h>
+
+#ifdef USE_CHIRP
+#include "chirp_client.h"
+#endif
+
+extern int *MW_exec_class_num_workers;
+
+// These static declarations are now necessary in the RMComm implementation
+#ifdef FILE_MASTER
+MWRMComm * MWDriver::RMC = new MWFileRC( TRUE, 0 );
+MWRMComm * MWTask::RMC = MWDriver::RMC;
+MWRMComm * MWWorker::RMC = NULL;
+#else
+MWRMComm * MWWorker::RMC = new MWFileRC ( FALSE, 0 );
+MWRMComm * MWTask::RMC = MWWorker::RMC;
+MWRMComm * MWDriver::RMC = NULL;
+#endif
+
+/// We need to do something better with this
+const int want_checkpointing = 0;
+
+/** If target_num_hosts is larger than this, we cut it back, since
+ we need to allocate arrays of reasonable size.
+*/
+const int REAL_TARGET_NUM_WORKERS = 2048;
+
+///
+const unsigned int SLEEP_DELAY = 5;
+
+int workerEvents[FileNumEvents] = { HOSTDELETE, HOSTADD, HOSTDELETE, HOSTSUSPEND, HOSTRESUME, CHECKSUM_ERROR };
+
+int min( int *arr, int len )
+{
+ // return index of min element in array of length len.
+ int min = 0;
+ for ( int i=1 ; i<len ; i++ )
+ {
+ if ( arr[i] < arr[min] )
+ {
+ min = i;
+ }
+ }
+ return min;
+}
+
+/* // To make gcc -Wall happy
+static void Truncate ( char *file )
+{
+ if ( truncate ( file, 0 ) != 0 );
+ //MWprintf ( 10, "Could not truncate file %s. Errno is %d\n", file, errno );
+}
+*/
+
+static void HardDeleteFile ( char *file )
+{
+ if ( !file ) return;
+ remove(file);
+}
+
+MWFileRC::MWFileRC ( bool val, int id )
+{
+ isMaster = val;
+ FileRCID = id;
+ sendList = NULL;
+ recvList = NULL;
+}
+
+void
+MWFileRC::exit ( int retval )
+{
+
+#ifndef FILE_MASTER
+ ::exit( retval );
+#else
+
+// struct stat statbuf;
+// char cmd[_POSIX_PATH_MAX];
+
+ for ( int i = 0; i < target_num_workers; i++ )
+ {
+ if ( &fileWorkers[i] && fileWorkers[i].state != FILE_FREE )
+ killWorker ( i );
+ }
+
+#if 1
+ // Jeff doesn't want to remove the directories for now...
+
+ /* We have to unlink the directories */
+ /*
+ if ( stat ( output_directory, &statbuf ) == 0 )
+ {
+ strcpy ( cmd, "/bin/rm -rf " );
+ strcat ( cmd, output_directory );
+ if ( system ( cmd ) < 0 )
+ MWprintf ( 10, "Cannot unlink %s directory\n", output_directory );
+ }
+
+ if ( stat ( input_directory, &statbuf ) == 0 )
+ {
+ strcpy ( cmd, "/bin/rm -rf " );
+ strcat ( cmd, input_directory );
+ if ( system ( cmd ) < 0 )
+ MWprintf ( 10, "Cannot unlink %s directory\n", input_directory );
+ }
+
+ if ( stat ( control_directory, &statbuf ) == 0 )
+ {
+ strcpy ( cmd, "/bin/rm -rf " );
+ strcat ( cmd, control_directory );
+ if ( system ( cmd ) < 0 )
+ MWprintf ( 10, "Cannot unlink %s directory\n", control_directory );
+ }
+*/
+#endif
+
+ ::exit( retval );
+#endif
+}
+
+
+int
+MWFileRC::setup( int argc, char *argv[], int *mytid, int *master_tid )
+{
+ SIMUL_SEND = 100;
+ worker_timeout = 80*60;
+
+ if ( isMaster == TRUE )
+ {
+
+ strcpy ( output_directory, "worker_output" );
+ strcpy ( input_directory, "worker_input" );
+ strcpy ( control_directory, "submit_files" );
+ strcpy ( moment_worker_file, "moment_worker_file" );
+ cyclePosition = 0;
+ turnNo = 0;
+ *mytid = FileRCID;
+ *master_tid = FileRCID;
+ CHECKLOG_FREQ = 100;
+ subId = 0;
+ hostadd_reqs = NULL;
+
+ MWSystem::mkdir ( output_directory);
+ MWSystem::mkdir ( input_directory);
+ MWSystem::mkdir ( control_directory);
+ }
+ else
+ {
+#ifdef USE_CHIRP
+ strcpy ( output_directory, "worker_output" );
+ strcpy ( input_directory, "worker_input" );
+ strcpy ( control_directory, "submit_files" );
+ strcpy ( moment_worker_file, "moment_worker_file" );
+
+ MWSystem::mkdir( output_directory);
+ MWSystem::mkdir( input_directory);
+ MWSystem::mkdir( control_directory);
+#endif
+
+ // Slave FileRC instance. Only now the argc and argv make any sense
+ FileRCID = atoi ( argv[1] );
+ expected_number = atoi ( argv[2] );
+ master_expected_number = atoi(argv[3] );
+ strcpy ( output_directory, argv[4] );
+ strcpy ( input_directory, argv[5] );
+ strcpy ( control_directory, "submit_files" );
+ *master_tid = atoi ( argv[6] );
+ *mytid = FileRCID;
+ }
+
+ sendList = recvList = NULL;
+ return 0;
+ }
+
+
+ //---------------------------------------------------------------------
+ // MWFileRC::init_beginning_workers():
+ // Called every time a master gets up either at the init time or
+ // aftermath a brutal crash. It is here that we do a resuscicate and
+ // fill our worker lists.
+ // We start off by generating all the needed workers.
+ //---------------------------------------------------------------------
+ int
+ MWFileRC::init_beginning_workers ( int *nworkers, MWWorkerID ***workers )
+ {
+ int j = 0;
+ int i;
+
+ *nworkers = j;
+
+ if ( !hostadd_reqs )
+ {
+ // It is not restarting from checkpoint
+ MWprintf ( 10, "In MWFileRC::init_beginning_workers()\n");
+ hostadd_reqs = new int[exec_classes];
+
+ for ( i = 0 ; i < exec_classes ; i++ )
+ {
+ hostadd_reqs[i] = 0;
+ }
+
+ fileWorkers = new struct FileWorker[target_num_workers];
+
+ if ( !fileWorkers )
+ {
+ MWprintf ( 10, "Cannot allocate memory\n");
+ return -1;
+ }
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ fileWorkers[i].state = FILE_FREE;
+ fileWorkers[i].served = -1;
+ fileWorkers[i].event_no = 0;
+ fileWorkers[i].id = -1;
+ fileWorkers[i].counter = 0;
+ fileWorkers[i].worker_counter = 0;
+ fileWorkers[i].arch = -1;
+ fileWorkers[i].condorID = -1;
+ fileWorkers[i].condorprocID = -1;
+ }
+ }
+
+ if ( j == 0 ) return 0;
+
+ return 0;
+ }
+
+int
+MWFileRC::restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg )
+{
+ int j = 0;
+ int i;
+ FILE *temp;
+ char worker_waitfile[_POSIX_PATH_MAX];
+ char master_waitfile[_POSIX_PATH_MAX];
+
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ if ( fileWorkers[i].state == FILE_RUNNING || fileWorkers[i].state == FILE_SUSPENDED ||
+ fileWorkers[i].state == FILE_RESUMED || fileWorkers[i].state == FILE_EXECUTE )
+ {
+ j++;
+ }
+ }
+
+ *nworkers = j;
+ if ( j == 0 ) return 0;
+
+ (*workers) = new MWWorkerID*[j];
+
+ j = 0;
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ if ( fileWorkers[i].state == FILE_RUNNING || fileWorkers[i].state == FILE_SUSPENDED ||
+ fileWorkers[i].state == FILE_RESUMED || fileWorkers[i].state == FILE_EXECUTE )
+ {
+ (*workers)[j] = new MWWorkerID;
+ (*workers)[j]->set_id1 ( fileWorkers[i].id );
+ (*workers)[j]->set_id2 ( fileWorkers[i].id );
+ (*workers)[j]->set_exec_class ( fileWorkers[i].exec_class );
+ j++;
+
+ sprintf ( worker_waitfile, "./%s/worker_waitfile.%d", input_directory, fileWorkers[i].id );
+ sprintf ( master_waitfile, "./%s/master_waitfile.%d", output_directory, fileWorkers[i].id );
+ temp = Open ( worker_waitfile, "a" );
+ if ( temp == NULL )
+ {
+ MWprintf ( 10, "Oops couldn't open the worker_waitfile for syncing\n");
+ continue;
+ }
+ fprintf( temp, "%c %d %c", SYNC, fileWorkers[i].worker_counter + SIMUL_SEND, ESYNC );
+ fileWorkers[i].worker_counter += SIMUL_SEND;
+ fflush( temp );
+ Close( temp );
+
+ initsend ( );
+ send ( i, msg );
+ fileWorkers[i].counter = 0;
+ fileWorkers[i].worker_counter = 0;
+ HardDeleteFile ( master_waitfile );
+ }
+ }
+ MWprintf (10, "Created in init %d workers\n", j );
+
+ return 0;
+}
+
+
+ //---------------------------------------------------------------------------
+ // MWFileRC::start_worker ()
+ // In responce to a HOSTADD message. You know in whomRecv who has started.
+ //---------------------------------------------------------------------------
+ int
+ MWFileRC::start_worker ( MWWorkerID *w )
+ {
+ if ( !w )
+ {
+ MWprintf ( 10, "WorkerID w cannot be null in start_worker\n");
+ return -1;
+ }
+
+ w->set_id1 ( fileWorkers[whomRecv].id );
+ w->set_id2 ( fileWorkers[whomRecv].id );
+ w->set_arch ( fileWorkers[whomRecv].arch );
+ w->set_exec_class ( fileWorkers[whomRecv].exec_class );
+
+ hostadd_reqs[fileWorkers[whomRecv].exec_class]--;
+ return 0;
+ }
+
+ int MWFileRC::removeWorker ( MWWorkerID *w )
+ {
+ if ( !w )
+ {
+ MWprintf (10, "Worker ID cannot be NULL in removeWorker\n" );
+ return -1;
+ }
+
+ char buf[_POSIX_PATH_MAX];
+
+ int condorID = fileWorkers[w->get_id1()].condorID;
+ int procID = fileWorkers[w->get_id1()].condorprocID;
+ MWprintf ( 10, "Removing workers %d.%d of %d\n", condorID, procID, w->get_id1() );
+ sprintf ( buf, "%s/bin/condor_rm %d.%d", CONDOR_DIR, condorID, procID );
+
+ if ( system ( buf ) < 0 )
+ {
+ MWprintf ( 10, "Could not condor_rm the worker\n" );
+ }
+
+ if ( fileWorkers[w->get_id1()].state == FILE_SUBMITTED )
+ {
+ // submitted_num_workers--;
+
+ hostadd_reqs[w->get_exec_class()]--;
+ /*
+ //XXX HOSTADDDEBUG
+ MWprintf( 20, "Subtracting from %d hostadd_reqs. Value %d\n", w->get_arch(),
+ hostadd_reqs[w->get_arch()] );
+ for ( int i = 0; i < 2 * HOSTINC; i++ )
+ if ( hostaddind_reqs[w->get_arch()][i] == w->get_id1() ) hostaddind_reqs[w->get_arch()][i] = -1;
+ */
+ }
+ /*
+ else
+ current_num_workers--;
+ */
+ fileWorkers[w->get_id1()].state = FILE_FREE;
+ write_RMstate ( NULL );
+ return 0;
+ }
+
+
+//---------------------------------------------------------------------
+// MWFileRC::do_spawn( int workerid ):
+// Spawns the worker.
+//---------------------------------------------------------------------
+int
+MWFileRC::do_spawn ( int nWorkers, int ex_cl )
+{
+ int cID = -1;
+ int i;
+ int ids[nWorkers];
+ char sub_file[_POSIX_PATH_MAX];
+ char exe[_POSIX_PATH_MAX];
+ char logfile[_POSIX_PATH_MAX];
+ char master_waitfile[_POSIX_PATH_MAX], worker_waitfile[_POSIX_PATH_MAX];
+ FILE *ptr;
+ char temp[_POSIX_PATH_MAX];
+ char requirements[num_executables * _POSIX_PATH_MAX];
+
+ if ( nWorkers <= 0 ) return 0;
+
+ sprintf( sub_file, "%s/submit_file.%d", control_directory, subId++ );
+ sprintf( exe, "%s/bin/condor_submit %s", CONDOR_DIR, sub_file );
+
+ FILE *f = Open( sub_file, "w" );
+ if ( f == NULL )
+ {
+ MWprintf ( 10, "Couldn't open the submitfile for writing\n");
+ return -1;
+ }
+
+ int index = 0;
+ for ( i = 0; i < target_num_workers && index < nWorkers; i++ )
+ {
+ if ( fileWorkers[i].state == FILE_FREE )
+ {
+ ids[index++] = i;
+ }
+ }
+
+ if ( index < nWorkers )
+ {
+ MWprintf ( 10, "In MW-File hostaddlogic asking for more workers than target_num_workers\n");
+ MWprintf ( 10, "Had asked %d workers but I am adding only %d\n", nWorkers, index );
+ nWorkers = index;
+ }
+
+#ifdef USE_CHIRP
+ fprintf ( f, "Universe = Vanilla\n");
+ fprintf( f, "+WantIOProxy=True\n");
+ fprintf( f, "should_transfer_files = Yes\n"); // These two just needed to move to the execute dir
+ fprintf( f, "when_to_transfer_output = ON_EXIT\n");
+#else
+ fprintf ( f, "Universe = Standard\n");
+#endif
+ fprintf( f, "Executable = mw_exec%d.$$(Opsys).$$(Arch)\n", ex_cl );
+
+ bool tempfirst = TRUE;
+ for ( i = 0; i < num_executables; i++ )
+ {
+ if ( worker_executables[i]->exec_class == ex_cl )
+ {
+ if ( tempfirst == TRUE )
+ {
+ sprintf ( requirements, "( ( %s ) ", arch_class_attributes[worker_executables[i]->arch_class] );
+ tempfirst = FALSE;
+ }
+ else
+ {
+ sprintf ( requirements, "%s || ( %s ) ", requirements, arch_class_attributes[worker_executables[i]->arch_class] );
+ }
+ }
+ }
+ strcat ( requirements, " )" );
+ for ( i = 0; i < nWorkers; i++ )
+ {
+ sprintf( logfile, "%s/log_file.%d", control_directory, ids[i] );
+ sprintf( master_waitfile, "./%s/master_waitfile.%d",
+ output_directory, ids[i] );
+ sprintf( worker_waitfile, "./%s/worker_waitfile.%d",
+ input_directory, ids[i] );
+
+ fprintf( f, "arguments = %d %d %d %s %s -1\n", ids[i], 0, 0,
+ output_directory, input_directory );
+ fprintf( f, "log = %s/log_file.%d\n", control_directory, ids[i] );
+
+ fprintf( f, "Output = %s/output_file.%d.$(Cluster).$(Process)\n", control_directory, ids[i] );
+ fprintf( f, "Error = %s/error_file.%d.$(Cluster).$(Process)\n", control_directory, ids[i] );
+
+ fprintf( f, "Requirements = %s\n ", requirements );
+ fprintf ( f, "getenv = True\n" );
+
+ // Jeff changed this
+
+ FILE *userf = Open( "worker_attributes", "r" );
+ if( userf == NULL )
+ {
+ MWprintf( 10, "No worker_attributes file, assuming Condor defaults\n" );
+ }
+ else
+ {
+ int c;
+ while( ( c = getc( userf ) ) != EOF )
+ {
+ putc( c, f );
+ }
+ Close( userf );
+ }
+
+ fprintf( f, "Queue\n" );
+
+ HardDeleteFile( logfile );
+ HardDeleteFile( master_waitfile );
+ HardDeleteFile( worker_waitfile );
+
+ }
+ Close( f );
+
+ MWprintf (10, "About to call condor_submit %s\n", exe);
+ if ( (ptr = popen(exe, "r") ) != NULL )
+ {
+ while ( fscanf(ptr, "%s", temp ) >= 0 )
+ {
+
+ if ( strcmp ( temp, "cluster" ) == 0 )
+ {
+
+ // This is for Jeff's debugging with JP
+ //MWprintf( 10, "Got cluster\n" );
+
+ fscanf( ptr, "%s", temp );
+
+ // This is for Jeff's debugging with JP
+ //MWprintf( 10, "Read %s from the pipe.\n", temp );
+
+ cID = atoi ( temp );
+ pclose(ptr);
+ ptr = NULL;
+ MWprintf ( 10, "Spawned to cluster %d\n", cID );
+ break;
+ }
+ }
+ if ( ptr ) pclose ( ptr );
+ for ( i = 0; i < nWorkers; i++ )
+ {
+ int tempp = ids[i];
+ fileWorkers[tempp].condorID = cID;
+ fileWorkers[tempp].condorprocID = i;
+ fileWorkers[tempp].arch = -1;
+ fileWorkers[tempp].counter = 0;
+ fileWorkers[tempp].worker_counter = 0;
+ fileWorkers[tempp].id = tempp;
+ fileWorkers[tempp].state = FILE_SUBMITTED;
+ fileWorkers[tempp].event_no = 1;
+ fileWorkers[tempp].exec_class = ex_cl;
+/*
+ for ( int j = 0; j < 2 * HOSTINC; j++ ) {
+ if ( hostaddind_reqs[archid][j] == -1 ) {
+ hostaddind_reqs[archid][j] = tempp;
+ break;
+ }
+ }
+*/
+ }
+ }
+ else
+ {
+ MWprintf ( 10, "Couldn't popen in FileRC\n");
+ return -1;
+ }
+
+ write_RMstate ( NULL );
+ return nWorkers;
+}
+
+int
+MWFileRC::initsend ( int useless )
+{
+ /* This prepares for a series of packs before we do the actual send */
+ if ( !sendList )
+ sendList = new MWList<void> ;
+
+ while ( sendList->number() > 0 )
+ {
+ struct FileSendBuffer *buf = (struct FileSendBuffer *)sendList->Remove();
+ delete buf;
+ }
+
+ checksum = 0;
+ return 0;
+}
+
+void
+MWFileRC::who ( int *wh )
+{
+ unpack ( wh, 1, 1 );
+}
+
+
+//---------------------------------------------------------------------------
+//
+//
+//---------------------------------------------------------------------------
+int
+MWFileRC::send ( int to_whom, int msgtag )
+{
+ char filename[_POSIX_PATH_MAX];
+ char control_file[_POSIX_PATH_MAX];
+ FILE *fp;
+ if ( isMaster == TRUE )
+ {
+ // In the master mode
+ sprintf ( filename, "%s/worker_input.%d.%d", input_directory, to_whom,
+ fileWorkers[to_whom].worker_counter );
+ sprintf ( control_file, "%s/worker_waitfile.%d", input_directory,
+ to_whom );
+ }
+ else
+ {
+ // We are sending something to the master. So to_whom actually has
+ // no meaning.
+ sprintf ( filename, "%s/worker_output.%d.%d", output_directory,
+ FileRCID, master_expected_number );
+ sprintf ( control_file, "%s/master_waitfile.%d", output_directory,
+ FileRCID );
+ }
+
+ fp = Open ( filename, "w" );
+ if ( fp == NULL )
+ {
+ MWprintf ( 10, "Couldn't open file %s for writing work. Bailing out!\n", filename );
+
+ assert( filename && 0 );
+ return -1;
+ }
+
+ fprintf ( fp, "%d %lld ", msgtag, checksum );
+
+ while ( sendList->IsEmpty() != TRUE )
+ {
+ struct FileSendBuffer *buf = ( struct FileSendBuffer *)sendList->Remove();
+ switch ( buf->type )
+ {
+ case INT:
+ fprintf ( fp, "%d %d ", INT, *(int *)buf->data );
+ break;
+ case CHAR:
+ fprintf ( fp, "%d %c ", CHAR, *(char *)buf->data );
+ break;
+ case LONG:
+ fprintf ( fp, "%d %ld ", LONG, *(long *)buf->data );
+ break;
+ case FLOAT:
+ fprintf ( fp, "%d %f ", FLOAT, *(float *)buf->data );
+ break;
+ case DOUBLE:
+ fprintf ( fp, "%d %f ", DOUBLE, *(double*)buf->data );
+ break;
+ case UNSIGNED_INT:
+ fprintf ( fp, "%d %o ", UNSIGNED_INT, *(unsigned int *)buf->data );
+ break;
+ case SHORT:
+ fprintf ( fp, "%d %hd ", SHORT, *(short *)buf->data );
+ break;
+ case UNSIGNED_SHORT:
+ fprintf ( fp, "%d %ho ", UNSIGNED_SHORT, *(unsigned short *)buf->data );
+ break;
+ case UNSIGNED_LONG:
+ fprintf ( fp, "%d %lo ", UNSIGNED_LONG, *(unsigned long *)buf->data );
+ break;
+ case STRING:
+ fprintf ( fp, "%d %d %s ", STRING, buf->size - 1,
+ (char *)buf->data );
+ break;
+ default:
+ MWprintf ( 10, "Couldnot decipher a data type while sending\n");
+ MWprintf ( 10, "Got %d\n", buf->type );
+ Close ( fp );
+ return -1;
+ }
+
+ delete buf;
+ }
+
+ fflush ( fp );
+ Close ( fp );
+
+ if ( isMaster || ( !isMaster && master_expected_number == 0 ) )
+ {
+ fp = Open ( control_file, "a" );
+ }
+ else
+ {
+ // You are a slave and expected_number is not zero.
+ fp = Open ( control_file, "a" );
+ if (fp == NULL)
+ {
+ MWprintf ( 10, "In slave my %s doesn't exist\n");
+ HardDeleteFile ( filename );
+ return 0;
+ }
+ }
+ if ( fp == NULL )
+ {
+ MWprintf ( 10, "Could not open the waitfile %s. Send will fail!\n", control_file );
+
+ assert( control_file && 0 );
+ return -1;
+ }
+
+ if ( isMaster == TRUE )
+ {
+ fprintf ( fp, "%d %c", fileWorkers[to_whom].worker_counter, OK );
+ fileWorkers[to_whom].worker_counter++;
+ }
+ else
+ {
+ fprintf ( fp, "%d %c", master_expected_number, OK );
+ master_expected_number++;
+ }
+ fflush ( fp );
+ Close ( fp );
+
+#ifdef USE_CHIRP
+ if (!isMaster) {
+ sendFileToMaster(filename);
+ sendFileToMaster(control_file);
+ }
+#endif
+ return 0;
+}
+
+
+int
+MWFileRC::recv ( int from_whom, int msgtag )
+{
+ if ( !recvList )
+ recvList = new MWList<void> ;
+ while ( recvList->number() > 0 )
+ {
+ struct FileSendBuffer *buf = (struct FileSendBuffer *)recvList->Remove();
+ delete buf;
+ }
+
+ if ( isMaster == TRUE )
+ return master_recv ( from_whom, msgtag );
+ else
+ return worker_recv ( from_whom, msgtag );
+}
+
+int
+MWFileRC::nrecv ( int from_whom, int msgtag )
+{
+ if ( !recvList )
+ recvList = new MWList<void> ;
+
+ while ( recvList->number() > 0 )
+ {
+ struct FileSendBuffer *buf = (struct FileSendBuffer *)recvList->Remove();
+ delete buf;
+ }
+
+ //from_whom has no meaning as it is invariably from the master.
+ static time_t last_comm = time(0);
+ int calculated_number = 0;
+ char c;
+ char filename[_POSIX_PATH_MAX];
+ FILE *op = NULL;
+ bool toFlush = FALSE;
+ time_t starttime;
+ time_t waitedtime;
+ starttime = waitedtime = time(0);
+
+ sprintf ( filename, "%s/worker_waitfile.%d", input_directory, FileRCID );
+ op = Open ( filename, "r" );
+ while ( 1 )
+ {
+ waitedtime = time(0);
+ /*
+ if(waitedtime - starttime > SLEEP_DELAY*2)
+ {
+ Close(op);
+ msgTag = NO_MESSAGE;
+ return 0;
+ }
+ */
+ if ( worker_timeout > 0 && last_comm + worker_timeout < time(0) )
+ {
+ MWprintf ( 10, "Worker Timed out\n");
+ if ( op ) Close ( op );
+ return WORKER_TIMEOUT;
+ }
+ if ( !op )
+ {
+ MWSystem::sleep( SLEEP_DELAY );
+ op = Open ( filename, "r" );
+ //MWprintf(10,"Cannot open file, try again\n");
+ continue;
+ }
+ if ( fscanf( op, "%c", &c ) < 0 )
+ {// end of file, return from non-blocking receive
+ Close(op);
+ msgTag = NO_MESSAGE;
+ return 0;
+ /*
+ Close( op );
+ sleep( SLEEP_DELAY );
+ op = Open ( filename, "r" );
+ MWprintf(10,"opened file no data, try again\n"); // wenhan
+ continue;
+ */
+ }
+ if ( c == OK )
+ {
+ if ( calculated_number != expected_number )
+ {
+ if ( calculated_number > expected_number )
+ {
+ MWprintf(10, "Fault in master resuscicate logic,exiting\n");
+ Close ( op );
+ return UNABLE_TO_WAKE;
+ }
+ calculated_number = 0;
+ continue;
+ }
+ else
+ {
+ MWprintf ( 10, "Got the work in slave %d\n", expected_number );
+ expected_number++;
+ Close(op);
+ whomRecv = 0;
+ last_comm = time(0);
+ int hh = handle_work( msgtag );
+ if ( toFlush )
+ {
+ expected_number = 0;
+ master_expected_number = 0;
+ HardDeleteFile ( filename );
+ toFlush = FALSE;
+ }
+ return hh;
+ }
+ }
+ else if ( c == ' ' )
+ {
+ }
+ else if ( c == SYNC)
+ {
+ // Master wants it to ignore some things.
+ calculated_number = 0;
+ }
+ else if ( c == ESYNC )
+ {
+ expected_number = calculated_number;
+ calculated_number = 0;
+ toFlush = TRUE;
+ }
+ else if ( isdigit ( c ) )
+ {
+ calculated_number = calculated_number * 10 + c - '0';
+ }
+ else
+ {
+ Close ( op );
+ return WAITFILE_PROTOCOL_ERROR;
+ }
+ }
+}
+
+
+int MWFileRC::master_recv ( int from_whom, int msgtag )
+{
+ // msgtag has no meaning as we have to recv all sorts of control info.
+ int i;
+ bool change = FALSE;
+ while ( 1 )
+ {
+ if ( turnNo == CHECKLOG_FREQ )
+ {
+ CheckLogFilesRunning();
+ turnNo = 0;
+ }
+ for ( i = cyclePosition; i < target_num_workers; i++ )
+ {
+ cyclePosition++;
+ switch ( fileWorkers[i].state )
+ {
+ case FILE_RUNNING:
+ change = IsComplete ( i );
+ if ( change == TRUE )
+ {
+ MWprintf ( 10, "Master received something from worker %d\n", i );
+ return handle_finished_worker ( i );
+ }
+ break;
+
+ case FILE_EXECUTE:
+ if ( fileWorkers[i].served != FILE_RUNNING )
+ {
+ MWprintf ( 10, "Master found that worker is Started %d\n", i );
+ return handle_executing_worker (i );
+ }
+ break;
+
+ case FILE_KILLED:
+ if ( fileWorkers[i].served != FILE_KILLED )
+ {
+ MWprintf ( 10, "Master found that worker was Killed %d\n", i);
+ return handle_killed_worker(i);
+ }
+ break;
+
+ case FILE_SUSPENDED:
+ if ( fileWorkers[i].served != FILE_SUSPENDED )
+ {
+ MWprintf ( 10, "Master found that worker was Suspended %d \n", i);
+ return handle_suspended_worker(i);
+ }
+ break;
+
+ case FILE_RESUMED:
+ if ( fileWorkers[i].served != FILE_RESUMED )
+ {
+ MWprintf ( 10, "Master found that worker was Resumed %d\n", i);
+ return handle_resumed_worker(i);
+ }
+ break;
+
+ case FILE_TRANSIT:
+ if ( fileWorkers[i].served != FILE_TRANSIT )
+ {
+ MWprintf ( 10, "Master found that worker transited %d \n", i );
+ return handle_transited_worker(i);
+ }
+
+ default:
+ break;
+ }
+
+ }
+
+ cyclePosition = 0;
+ turnNo++;
+ }
+}
+
+
+int
+MWFileRC::worker_recv ( int from_whom, int msgtag )
+{
+ //from_whom has no meaning as it is invariably from the master.
+ static time_t last_comm = time(0);
+ int calculated_number = 0;
+ char c;
+ char filename[_POSIX_PATH_MAX];
+ FILE *op = NULL;
+ bool toFlush = FALSE;
+
+
+ sprintf ( filename, "%s/worker_waitfile.%d", input_directory, FileRCID );
+#ifdef USE_CHIRP
+ getFileFromMaster(filename);
+#endif
+ op = Open ( filename, "r" );
+ while ( 1 )
+ {
+ if ( worker_timeout > 0 && last_comm + worker_timeout < time(0) )
+ {
+ MWprintf ( 10, "Worker Timed out\n");
+ if ( op ) Close ( op );
+ return WORKER_TIMEOUT;
+ }
+ if ( !op )
+ {
+ MWSystem::sleep( SLEEP_DELAY );
+#ifdef USE_CHIRP
+ getFileFromMaster(filename);
+#endif
+ op = Open ( filename, "r" );
+ continue;
+ }
+ if ( fscanf( op, "%c", &c ) < 0 )
+ {
+ Close( op );
+ MWSystem::sleep( SLEEP_DELAY );
+#ifdef USE_CHIRP
+ getFileFromMaster(filename);
+#endif
+ op = Open ( filename, "r" );
+ continue;
+ }
+ if ( c == OK )
+ {
+ if ( calculated_number != expected_number )
+ {
+ if ( calculated_number > expected_number )
+ {
+ MWprintf(10, "Fault in master resuscicate logic,exiting\n");
+ Close ( op );
+ return UNABLE_TO_WAKE;
+ }
+ calculated_number = 0;
+ continue;
+ }
+ else
+ {
+ MWprintf ( 10, "Got the work in slave %d\n", expected_number );
+ expected_number++;
+ Close(op);
+ whomRecv = 0;
+ last_comm = time(0);
+ int hh = handle_work( msgtag );
+ if ( toFlush )
+ {
+ expected_number = 0;
+ master_expected_number = 0;
+ HardDeleteFile ( filename );
+ toFlush = FALSE;
+ }
+ return hh;
+ }
+ }
+ else if ( c == ' ' )
+ {
+ }
+ else if ( c == SYNC)
+ {
+ // Master wants it to ignore some things.
+ calculated_number = 0;
+ }
+ else if ( c == ESYNC )
+ {
+ expected_number = calculated_number;
+ calculated_number = 0;
+ toFlush = TRUE;
+ }
+ else if ( isdigit ( c ) )
+ {
+ calculated_number = calculated_number * 10 + c - '0';
+ }
+ else
+ {
+ Close ( op );
+ return WAITFILE_PROTOCOL_ERROR;
+ }
+ }
+}
+
+
+int
+MWFileRC::pack ( const char *bytes, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&bytes[i * stride], CHAR, sizeof(char) );
+ sendList->Append ( (void *)buf );
+ checksum += CHAR;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const float *f, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(f[i * stride]), FLOAT, sizeof(float));
+ sendList->Append ( (void *)buf );
+ checksum += FLOAT;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const double *d, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(d[i * stride]), DOUBLE, sizeof(double) );
+ sendList->Append ( (void *)buf );
+ checksum += DOUBLE;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const int *j, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(j[i * stride]), INT, sizeof(int) );
+ sendList->Append ( (void *)buf );
+ checksum += INT;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const unsigned int *ui, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf = new FileSendBuffer ( (void *)&(ui[i * stride]), UNSIGNED_INT, sizeof(unsigned int) );
+ sendList->Append ( (void *)buf );
+ checksum += UNSIGNED_INT;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const short *sh, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(sh[i * stride]), SHORT, sizeof(short) );
+ sendList->Append ( (void *)buf );
+ checksum += SHORT;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const unsigned short *ush, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(ush[i * stride]), UNSIGNED_SHORT,
+ sizeof(unsigned short) );
+ sendList->Append ( (void *)buf );
+ checksum += UNSIGNED_SHORT;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const long *l, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(l[i * stride]), LONG, sizeof(long) );
+ sendList->Append ( (void *)buf );
+ checksum += LONG;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const unsigned long *ul, int nitem, int stride )
+{
+ int i;
+
+ if ( nitem < 0 ) return -1;
+ if ( nitem == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ for ( i = 0; i < nitem; i++ )
+ {
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)&(ul[i * stride]), UNSIGNED_LONG,
+ sizeof(unsigned long) );
+ sendList->Append ( (void *)buf );
+ checksum += UNSIGNED_LONG;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::pack ( const char *str )
+{
+ if ( str == NULL ) return -1;
+ if ( strlen(str) == 0 ) return 0;
+
+ if ( sendList == NULL )
+ {
+ MWprintf ( 10, "Didn't do an init send before packing something\n");
+ return -1;
+ }
+
+ FileSendBuffer *buf =
+ new FileSendBuffer ( (void *)str, STRING,
+ strlen(str) + 1 );
+ sendList->Append ( (void *)buf );
+ checksum += STRING;
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( char *bytes, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return 0;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != CHAR )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &bytes[i * stride], buf->data, sizeof(char) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( float *f, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != FLOAT )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &f[i * stride], buf->data, sizeof(float) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( double *d, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != DOUBLE )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &d[i * stride], buf->data, sizeof(double) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( int *j, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != INT )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+ memcpy ( &j[i * stride], buf->data, sizeof(int) );
+ delete buf;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( unsigned int *ui, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != UNSIGNED_INT )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &ui[i * stride], buf->data, sizeof(unsigned int) );
+
+ delete buf;
+ }
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( short *sh, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != SHORT )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &sh[i * stride], buf->data, sizeof(short) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+int
+MWFileRC::unpack ( unsigned short *ush, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != UNSIGNED_SHORT )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &ush[i * stride], buf->data, sizeof(unsigned short) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( long *l, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != LONG )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &l[i * stride], buf->data, sizeof(long) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( unsigned long *ul, int nitems, int stride )
+{
+ int i;
+
+ if ( nitems <= 0 ) return -1;
+
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ for ( i = 0; i < nitems; i++ )
+ {
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != UNSIGNED_LONG )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else \n");
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( &ul[i * stride], buf->data, sizeof(unsigned long) );
+
+ delete buf;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::unpack ( char *str )
+{
+ if ( recvList == NULL || recvList->IsEmpty ( ) == TRUE )
+ {
+ MWprintf ( 10, "Trying to unpack before receiving \n" );
+ return -1;
+ }
+
+ FileSendBuffer *buf = (FileSendBuffer *)recvList->Remove();
+ if ( buf == NULL || buf->type != STRING )
+ {
+ MWprintf ( 20, "Recieve buffer contained something else %d\n", buf->type);
+ recvList->Prepend ( (void *)buf );
+ return -1;
+ }
+
+ memcpy ( str, buf->data, sizeof(char) * buf->size );
+
+ delete buf;
+
+ return 0;
+}
+
+
+bool
+MWFileRC::IsComplete ( int i )
+{
+ char c;
+ char f_name[_POSIX_PATH_MAX];
+
+ int number_calculated = 0;
+ int num = fileWorkers[i].counter;
+
+ sprintf( f_name, "./%s/master_waitfile.%d", output_directory, i );
+
+ FILE *fp = Open ( f_name, "r" );
+ if ( fp == NULL )
+ {
+ return FALSE;
+ }
+
+ while ( fscanf(fp, "%c", &c ) > 0 )
+ {
+ if ( c == OK )
+ {
+ if ( number_calculated == num )
+ {
+ Close(fp);
+ return TRUE;
+ }
+ else
+ number_calculated = 0;
+ }
+ else if ( c == WRONGINITFILE )
+ {
+ // The process found a wrong init file.
+ // It probably has killed itself. Thus do nothing.
+ }
+ else if ( c == SYNC )
+ {
+ number_calculated = 0;
+ }
+ else if ( isdigit(c) > 0 )
+ {
+ number_calculated = number_calculated * 10 + c - '0';
+ }
+ }
+
+ Close(fp);
+ return FALSE;
+}
+
+
+int
+MWFileRC::handle_finished_worker ( int i )
+{
+ FILE *fp;
+ char filename[_POSIX_PATH_MAX];
+ int typeno;
+
+ fileWorkers[i].served = FILE_RUNNING;
+ sprintf ( filename, "%s/worker_output.%d.%d", output_directory, fileWorkers[i].id, fileWorkers[i].counter );
+ fp = Open ( filename, "r" );
+ if ( fp == NULL )
+ {
+ MWprintf ( 10, "Couldn't open the worker output file %s for reading: Errno is %d\n", filename, errno );
+ return -1;
+ }
+ fscanf ( fp, "%d %lld ", &msgTag, &checksum );
+
+ while ( fscanf ( fp, "%d ", &typeno ) >= 0 )
+ {
+ FileSendBuffer *buf;
+
+ switch ( typeno )
+ {
+ case INT:
+ int it1;
+ fscanf ( fp, "%d ", &it1 );
+ buf = new FileSendBuffer ( (void *)&it1, INT, sizeof(int) );
+ if (buf == NULL)
+ MWprintf(30, "MWDEBUG: FileSendBuffer construction failed\n");
+ recvList->Append ( (void *)buf );
+ checksum -= INT;
+ break;
+
+ case CHAR:
+ char it2;
+ fscanf ( fp, "%c ", &it2 );
+ buf = new FileSendBuffer ( (void *)&it2, CHAR, sizeof(char) );
+ recvList->Append ( (void *)buf );
+ checksum -= CHAR;
+ break;
+
+ case LONG:
+ long it3;
+ fscanf ( fp, "%ld ", &it3 );
+ buf = new FileSendBuffer ( (void *)&it3, LONG, sizeof(long) );
+ recvList->Append ( (void *)buf );
+ checksum -= LONG;
+ break;
+
+ case FLOAT:
+ float it4;
+ fscanf ( fp, "%f ", &it4 );
+ buf = new FileSendBuffer ( (void *)&it4, FLOAT, sizeof(float) );
+ recvList->Append ( (void *)buf );
+ checksum -= FLOAT;
+ break;
+
+ case DOUBLE:
+ double it5;
+ fscanf ( fp, "%lf ", &it5 );
+ buf = new FileSendBuffer ( (void *)&it5, DOUBLE, sizeof(double));
+ if (buf == NULL)
+ MWprintf(30, "MWDEBUG: FileSendBuffer construction failed\n");
+ recvList->Append ( (void *)buf );
+ checksum -= DOUBLE;
+ break;
+
+ case UNSIGNED_INT:
+ unsigned int it6;
+ fscanf ( fp, "%o ", &it6 );
+ buf = new FileSendBuffer ( (void *)&it6, UNSIGNED_INT,
+ sizeof(unsigned int));
+ recvList->Append ( (void *)buf );
+ checksum -= UNSIGNED_INT;
+ break;
+
+ case SHORT:
+ short it7;
+ fscanf ( fp, "%hd ", &it7 );
+ buf = new FileSendBuffer ( (void *)&it7, SHORT, sizeof(short));
+ recvList->Append ( (void *)buf );
+ checksum -= SHORT;
+ break;
+
+ case UNSIGNED_SHORT:
+ unsigned short it8;
+ fscanf ( fp, "%ho ", &it8 );
+ buf = new FileSendBuffer ( (void *)&it8, UNSIGNED_SHORT,
+ sizeof(unsigned short));
+ recvList->Append ( (void *)buf );
+ checksum -= UNSIGNED_SHORT;
+ break;
+
+ case UNSIGNED_LONG:
+ unsigned long it9;
+ fscanf ( fp, "%lo ", &it9 );
+ buf = new FileSendBuffer ( (void *)&it9, UNSIGNED_LONG,
+ sizeof(unsigned long));
+ recvList->Append ( (void *)buf );
+ checksum -= UNSIGNED_LONG;
+ break;
+
+ case STRING:
+ {
+ int sz, z;
+ fscanf ( fp, "%d ", &sz );
+ char *it10 = new char[sz+1];
+ for ( z = 0; z < sz; z++ )
+ fscanf ( fp, "%c", &it10[z] );
+ it10[z] = '\0';
+ buf = new FileSendBuffer ( (void *)it10, STRING,
+ strlen(it10) + 1);
+ recvList->Append ( (void *)buf );
+ delete []it10;
+ checksum -= STRING;
+ break;
+ }
+
+ default:
+ MWprintf (10, "Couldn't decipher the data type in receiving\n");
+ MWprintf (10, "Got %d\n", typeno );
+ Close ( fp );
+ return -1;
+ break;
+ }
+ }
+ if ( checksum != 0 )
+ {
+ // Problem
+ MWprintf ( 10, "The checksum is not zero in recv\n");
+ while ( recvList->IsEmpty() != TRUE )
+ {
+ FileSendBuffer *buff = (FileSendBuffer *)recvList->Remove();
+ delete buff;
+ }
+
+ FileSendBuffer *newbuf = new FileSendBuffer ( &fileWorkers[i].id, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)newbuf );
+
+ msgTag = workerEvents[FileChecksumError];
+ }
+
+ whomRecv = i;
+ Close ( fp );
+ fileWorkers[i].counter++;
+ HardDeleteFile ( filename );
+ return 0;
+}
+
+
+int
+MWFileRC::bufinfo ( int buf_id, int *len, int *tag, int *sending_host )
+{
+ *sending_host = whomRecv;
+ *tag = msgTag;
+ *sending_host = whomRecv;
+ return 0;
+}
+
+int
+MWFileRC::handle_killed_worker ( int i )
+{
+ // We got the info that a worker has been killed.
+ // Inform the upper layer that the worker has disappeared.
+ fileWorkers[i].served = FILE_KILLED;
+
+ FileSendBuffer *buf = new FileSendBuffer ( &fileWorkers[i].id, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)buf );
+
+ whomRecv = i;
+ msgTag = workerEvents[FileTaskExit];
+
+ // Jeff debugging
+ MWprintf( 10, "State of killed worker was %d\n", fileWorkers[i].state );
+
+ if ( fileWorkers[i].state == FILE_SUBMITTED )
+ {
+
+ //XXX HOSTADDDEBUG
+
+ hostadd_reqs[fileWorkers[i].exec_class]--;
+/*
+ MWprintf( 20, "Substracting from %d hostadd_reqs. Value %d\n", fileWorkers[i].arch,
+ hostadd_reqs[fileWorkers[i].arch] );
+
+ submitted_num_workers--;
+ for ( int j = 0; j < 2 * HOSTINC; j++ )
+ if ( hostaddind_reqs[fileWorkers[i].arch][j] == i ) hostaddind_reqs[fileWorkers[i].arch][j] = -1;
+*/
+ }
+/*
+ else
+ current_num_workers--;
+*/
+
+ fileWorkers[i].state = FILE_FREE;
+ return 0;
+}
+
+int
+MWFileRC::handle_transited_worker ( int i )
+{
+ // int j;
+
+ MWprintf( 10, "Transit event was from worker %d, whose previous state was %d\n",
+ i, fileWorkers[whomRecv].served );
+
+ fileWorkers[i].served = FILE_TRANSIT;
+ FileSendBuffer *buf = new FileSendBuffer ( &fileWorkers[i].id, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)buf );
+
+ whomRecv = i;
+ msgTag = workerEvents[FileTaskExit];
+
+ if ( fileWorkers[i].state == FILE_SUBMITTED )
+ {
+ MWprintf ( 10, "How can a transit event happen when I am in submit state\n");
+ hostadd_reqs[fileWorkers[i].exec_class]--;
+ }
+
+ char exe[_POSIX_PATH_MAX];
+ sprintf ( exe, "%s/bin/condor_rm %d.%d", CONDOR_DIR, fileWorkers[i].condorID, fileWorkers[i].condorprocID );
+ system ( exe );
+ fileWorkers[i].state = FILE_FREE;
+
+ return 0;
+}
+
+
+int
+MWFileRC::handle_suspended_worker ( int i )
+{
+ // We got the info from the log file that the worker has been suspended.
+ // Inform the upper layer that this is the case.
+ // No need to change the state of fileWorkers as that has been
+ // modified by the CheckLogFiles.
+
+ fileWorkers[i].served = FILE_SUSPENDED;
+ FileSendBuffer *buf = new FileSendBuffer ( &fileWorkers[i].id, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)buf );
+
+ whomRecv = i;
+ msgTag = workerEvents[FileTaskSuspend];
+
+ return 0;
+}
+
+
+
+int
+MWFileRC::handle_resumed_worker ( int i )
+{
+ // We got the info from the log file that the worker has been resumed.
+ // Inform the upper layer that this is the case.
+ // No need to change the state of fileWorkers as that has been
+ // modified by the CheckLogFiles.
+
+ fileWorkers[i].state = FILE_RUNNING;
+ fileWorkers[i].served = FILE_RESUMED;
+ FileSendBuffer *buf = new FileSendBuffer ( &fileWorkers[i].id, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)buf );
+
+ whomRecv = i;
+ msgTag = workerEvents[FileTaskResume];
+
+ return 0;
+}
+
+int
+MWFileRC::handle_executing_worker ( int i )
+{
+ // We got the info that the worker i started executin.
+
+ if ( !(&fileWorkers[i]) )
+ {
+ MWprintf( 10, "How can the corresponding entry in execute worker be null\n");
+ return -1;
+ }
+
+ fileWorkers[i].served = FILE_EXECUTE;
+ fileWorkers[i].state = FILE_RUNNING;
+ FileSendBuffer *buf = new FileSendBuffer ( &fileWorkers[i].id, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)buf );
+
+ whomRecv = fileWorkers[i].id;
+ msgTag = workerEvents[FileHostAdd];
+
+ return 0;
+}
+
+
+int
+MWFileRC::handle_work ( int msgtag )
+{
+ // Called by the worker recv.
+ // Read the worker_input file and prepare the recvList.
+ FILE *fp;
+ char filename[_POSIX_PATH_MAX];
+ int typeno;
+
+ sprintf ( filename, "%s/worker_input.%d.%d", input_directory, FileRCID,
+ expected_number - 1 );
+#ifdef USE_CHIRP
+ getFileFromMaster(filename);
+#endif
+ fp = Open ( filename, "r" );
+ if ( fp == NULL )
+ {
+ MWprintf ( 10, "Couldn't open the worker input file %s for reading: errno = %d\n", filename, errno );
+ return CANNOT_OPEN_INPUT_FILE;
+ }
+
+ if ( fscanf ( fp, "%d %lld ", &msgTag, &checksum ) <= 0 )
+ {
+ Close ( fp );
+ return SCANF_ERROR_ON_INPUT_FILE;
+ }
+
+ if ( msgtag != -1 && msgTag != msgtag )
+ {
+ MWprintf( 10, "FileRC wrong message sequence got %d \n", msgTag);
+ Close ( fp );
+ return MESSAGE_SEQUENCE_ERROR;
+ }
+
+ while ( fscanf ( fp, "%d ", &typeno ) > 0 )
+ {
+ FileSendBuffer *buf;
+
+ switch ( typeno )
+ {
+ case INT:
+ int it1;
+ fscanf ( fp, "%d ", &it1 );
+ buf = new FileSendBuffer ( (void *)&it1, INT, sizeof(int) );
+ recvList->Append ( (void *)buf );
+ checksum -= INT;
+ break;
+
+ case CHAR:
+ char it2;
+ fscanf ( fp, "%c ", &it2 );
+ buf = new FileSendBuffer ( (void *)&it2, CHAR, sizeof(char) );
+ recvList->Append ( (void *)buf );
+ checksum -= CHAR;
+ break;
+
+ case LONG:
+ long it3;
+ fscanf ( fp, "%ld ", &it3 );
+ buf = new FileSendBuffer ( (void *)&it3, LONG, sizeof(long) );
+ recvList->Append ( (void *)buf );
+ checksum -= LONG;
+ break;
+
+ case FLOAT:
+ float it4;
+ fscanf ( fp, "%f ", &it4 );
+ buf = new FileSendBuffer ( (void *)&it4, FLOAT, sizeof(float) );
+ recvList->Append ( (void *)buf );
+ checksum -= FLOAT;
+ break;
+
+ case DOUBLE:
+ double it5;
+ fscanf ( fp, "%lf ", &it5 );
+ buf = new FileSendBuffer ( (void *)&it5, DOUBLE, sizeof(double));
+ recvList->Append ( (void *)buf );
+ checksum -= DOUBLE;
+ break;
+
+ case UNSIGNED_INT:
+ unsigned int it6;
+ fscanf ( fp, "%o ", &it6 );
+ buf = new FileSendBuffer ( (void *)&it6, UNSIGNED_INT,
+ sizeof(unsigned int));
+ recvList->Append ( (void *)buf );
+ checksum -= UNSIGNED_INT;
+ break;
+
+ case SHORT:
+ short it7;
+ fscanf ( fp, "%hd ", &it7 );
+ buf = new FileSendBuffer ( (void *)&it7, SHORT, sizeof(short));
+ recvList->Append ( (void *)buf );
+ checksum -= SHORT;
+ break;
+
+ case UNSIGNED_SHORT:
+ unsigned short it8;
+ fscanf ( fp, "%ho ", &it8 );
+ buf = new FileSendBuffer ( (void *)&it8, UNSIGNED_SHORT,
+ sizeof(unsigned short));
+ recvList->Append ( (void *)buf );
+ checksum -= UNSIGNED_SHORT;
+ break;
+
+ case UNSIGNED_LONG:
+ unsigned long it9;
+ fscanf ( fp, "%lo ", &it9 );
+ buf = new FileSendBuffer ( (void *)&it9, UNSIGNED_LONG,
+ sizeof(unsigned long));
+ recvList->Append ( (void *)buf );
+ checksum -= UNSIGNED_LONG;
+ break;
+
+ case STRING:
+ {
+ int sz;
+ fscanf ( fp, "%d ", &sz );
+ char *it10 = new char[sz + 1];
+ it10[sz] = '\0';
+ for ( int z = 0; z < sz; z++ )
+ fscanf ( fp, "%c", &it10[z] );
+ buf = new FileSendBuffer ( (void *)it10, STRING,
+ strlen(it10) + 1);
+ recvList->Append ( (void *)buf );
+ delete []it10;
+ checksum -= STRING;
+ break;
+ }
+
+ default:
+ MWprintf (10, "Couldn't decipher the data type in receiving\n");
+ MWprintf (10, "Got %d\n", typeno );
+ Close ( fp );
+ return UNKNOWN_DATA_TYPE;
+ }
+ }
+ if ( checksum != 0 )
+ {
+ // Problem
+ MWprintf ( 10, "The checksum is not zero in recv\n");
+ while ( recvList->IsEmpty() != TRUE )
+ {
+ FileSendBuffer *buff = (FileSendBuffer *)recvList->Remove();
+ delete buff;
+ }
+
+ FileSendBuffer *newbuf = new FileSendBuffer ( &FileRCID, INT,
+ sizeof(int) );
+ recvList->Append ( (void *)newbuf );
+
+ msgTag = CHECKSUM_ERROR;
+ }
+
+ Close ( fp );
+ HardDeleteFile ( filename );
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------
+// MWFileRC::CheckLogFiles():
+// Sophisticated check log function which never fails to detect any event
+// in the log.
+//---------------------------------------------------------------------------
+void
+MWFileRC::CheckLogFilesRunning ( )
+{
+#ifdef FILE_MASTER
+ int i;
+ char f_name[_POSIX_PATH_MAX];
+
+ for ( i = 0; i < target_num_workers; i++ ) {
+ //Discuss about this thing.
+ if ( fileWorkers[i].state == FILE_FREE ) continue;
+ int num_event = 0;
+
+ ReadUserLog log;
+ ULogEvent *event;
+ ULogEventOutcome outcome;
+
+ sprintf( f_name, "%s/log_file.%d", control_directory, i );
+
+ FILE *f;
+ if ( (f = fopen( f_name, "r" )) == NULL )
+ {
+ fileWorkers[i].state = FILE_IDLE;
+ fileWorkers[i].event_no = 0;
+ continue;
+ }
+ fclose(f);
+
+ log.initialize ( f_name );
+
+ // Skip over events we've seen before.
+ while( (outcome = log.readEvent(event)) == ULOG_OK) {
+ num_event++;
+ if ( num_event >= fileWorkers[i].event_no) {
+ break;
+ }
+ delete event;
+ }
+
+ // If we hit EOF in this userlog, no new events
+ if (outcome != ULOG_OK) {
+ delete event;
+ continue;
+ }
+
+ // Make sure this event belongs to this job
+ while ( event->cluster != fileWorkers[i].condorID || event->proc != fileWorkers[i].condorprocID ) {
+ MWprintf ( 10, "How can an event belonging to a different cluster be printed here\n");
+ num_event++;
+ fileWorkers[i].event_no++;
+ delete event;
+ outcome = log.readEvent(event);
+ if (outcome != ULOG_OK) {
+ break;
+ }
+ }
+
+ if (outcome != ULOG_OK) {
+ delete event;
+ continue;
+ }
+
+ switch (event->eventNumber) {
+
+ case ULOG_JOB_ABORTED:
+ case ULOG_JOB_TERMINATED:
+ case ULOG_EXECUTABLE_ERROR:
+ {
+ fileWorkers[i].state = FILE_KILLED;
+ break;
+ }
+
+ case ULOG_SHADOW_EXCEPTION:
+ {
+ fileWorkers[i].state = FILE_TRANSIT;
+ break;
+ }
+ case ULOG_CHECKPOINTED:
+ {
+ //fileWorkers[i].state = FILE_SUSPENDED;
+ break;
+ }
+ case ULOG_SUBMIT:
+ {
+ MWprintf ( 10, "Got a submit event\n");
+ fileWorkers[i].state = FILE_SUBMITTED;
+ break;
+ }
+ case ULOG_JOB_EVICTED:
+ {
+ if ( want_checkpointing == 1 )
+ {
+ JobEvictedEvent *evictEvent = (JobEvictedEvent *)event;
+
+ if ( evictEvent->checkpointed == TRUE )
+ {
+ fileWorkers[i].state = FILE_SUSPENDED;
+ MWprintf ( 10, "Got an evict with checkpoint event from %d\n",i );
+ }
+ else
+ {
+ fileWorkers[i].state = FILE_TRANSIT;
+ }
+ }
+ else
+ {
+ fileWorkers[i].state = FILE_TRANSIT;
+ }
+
+ break;
+ }
+ case ULOG_EXECUTE:
+ {
+ if ( fileWorkers[i].state == FILE_SUSPENDED )
+ {
+ MWprintf (10,"In LogFiles gotResumed after suspend %d\n",i);
+ fileWorkers[i].state = FILE_RESUMED;
+ }
+ else if ( fileWorkers[i].state == FILE_SUBMITTED )
+ fileWorkers[i].state = FILE_EXECUTE;
+ else {
+ MWprintf ( 10, "Unexpected state transition to execute from %d in submitfile %s\n", fileWorkers[i].state, f_name );
+ MWprintf ( 10, "Forcing this worker to TRANSIT state\n");
+ fileWorkers[i].state = FILE_TRANSIT;
+ }
+ break;
+ }
+
+ default:
+ {
+ fileWorkers[i].event_no++;
+ break;
+ }
+ }
+ fileWorkers[i].event_no++;
+ delete event;
+ }
+#endif
+}
+
+
+//---------------------------------------------------------------------------
+// MWFileRC::CheckFilesResuscicate ():
+// Called when recovering from a crash.
+//---------------------------------------------------------------------------
+void
+MWFileRC::CheckLogFilesResuscicate ( char *f_name, struct FileWorker &fw )
+{
+#ifdef FILE_MASTER
+
+ ReadUserLog log;
+ ULogEvent *event;
+ ULogEventOutcome outcome;
+
+ FILE *f;
+ if ( (f = fopen ( f_name, "r" )) == NULL )
+ {
+ fw.state = FILE_FREE;
+ fw.event_no = 0;
+ return;
+ }
+ fclose(f);
+
+ log.initialize ( f_name );
+
+ outcome = log.readEvent( event );
+ for ( ; outcome == ULOG_OK ;outcome = log.readEvent( event ) )
+ {
+ if ( event->eventNumber == ULOG_JOB_ABORTED )
+ {
+ fw.state = FILE_KILLED;
+ fw.event_no++;
+ delete event;
+ return;
+ }
+ else if ( event->eventNumber == ULOG_SHADOW_EXCEPTION )
+ {
+ char exe[128];
+ sprintf ( exe, "%s/bin/condor_rm %d.%d", CONDOR_DIR, fw.condorID, fw.condorprocID);
+ system ( exe );
+ fw.state = FILE_KILLED;
+ fw.event_no++;
+ delete event;
+ return;
+ }
+ else if ( event->eventNumber == ULOG_JOB_TERMINATED )
+ {
+ fw.state = FILE_KILLED;
+ fw.event_no++;
+ delete event;
+ return;
+ }
+ else if ( event->eventNumber == ULOG_EXECUTABLE_ERROR )
+ {
+ fw.state = FILE_KILLED;
+ fw.event_no++;
+ delete event;
+ return;
+ }
+ else if ( event->eventNumber == ULOG_CHECKPOINTED )
+ {
+ fw.event_no++;
+ delete event;
+ }
+ else if ( event->eventNumber == ULOG_SUBMIT )
+ {
+ fw.state = FILE_SUBMITTED;
+ fw.event_no++;
+ delete event;
+ }
+ else if ( event->eventNumber == ULOG_JOB_EVICTED )
+ {
+ if ( want_checkpointing == 1 )
+ {
+ JobEvictedEvent *evictEvent = (JobEvictedEvent *)event;
+ if ( evictEvent->checkpointed == TRUE )
+ {
+ fw.state = FILE_SUSPENDED;
+ fw.event_no++;
+ delete event;
+ }
+ else
+ {
+ char exe[128];
+ sprintf ( exe, "%s/bin/condor_rm %d.%d", CONDOR_DIR, fw.condorID,
+ fw.condorprocID);
+ system ( exe );
+ fw.state = FILE_KILLED;
+ delete event;
+ break;
+ }
+ }
+ else
+ {
+ char exe[128];
+ sprintf ( exe, "%s/bin/condor_rm %d.%d", CONDOR_DIR, fw.condorID,
+ fw.condorprocID);
+ system ( exe );
+ fw.state = FILE_KILLED;
+ fw.event_no++;
+ delete event;
+ }
+ }
+ else if ( event->eventNumber == ULOG_EXECUTE )
+ {
+ fw.state = FILE_RUNNING;
+ fw.event_no++;
+ delete event;
+ }
+ else
+ {
+ fw.event_no++;
+ delete event;
+ }
+ }
+
+ if ( fw.state == FILE_KILLED )
+ {
+ fw.state = FILE_FREE;
+ }
+
+#endif
+}
+
+
+//---------------------------------------------------------------------------
+// MWFileRC::resuscicate ( )
+// Sanjeev : This is THE function of the whole program. It is this routine that
+// gives MWFileRC that robustness that one can only dream right now.
+// The real Sanjeev : Robustness? You must be Just kidding!!
+//---------------------------------------------------------------------------
+void
+MWFileRC::resuscicate ()
+{
+ int i;
+ char c[2]; c[1] = '\0';
+ char worker_state_file[_POSIX_PATH_MAX];
+ char master_waitfile[_POSIX_PATH_MAX], worker_waitfile[_POSIX_PATH_MAX];
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ if ( fileWorkers[i].id < 0 ) continue;
+
+ sprintf ( worker_state_file, "%s/log_file.%d", control_directory, fileWorkers[i].id );
+ sprintf ( master_waitfile, "./%s/master_waitfile.%d", output_directory, fileWorkers[i].id );
+ sprintf ( worker_waitfile, "./%s/worker_waitfile.%d", input_directory, fileWorkers[i].id );
+
+ fileWorkers[i].worker_counter = GetWorkerCounter ( worker_waitfile );
+ fileWorkers[i].counter = GetCounter ( master_waitfile );
+ MWprintf ( 10, "The counters of %d are %d and %d and %d\n", i, fileWorkers[i].counter,
+ fileWorkers[i].worker_counter, fileWorkers[i].condorID );
+
+ CheckLogFilesResuscicate( worker_state_file, fileWorkers[i] );
+ }
+}
+
+//---------------------------------------------------------------------------
+//Master::GetCondorId():
+// Read the open log file and get the condor cluster of the log file.
+//---------------------------------------------------------------------------
+void
+MWFileRC::GetCondorId ( char *lgfile, int *cID, int *pID )
+{
+#ifdef FILE_MASTER
+
+ ReadUserLog log;
+ ULogEvent *event;
+ ULogEventOutcome outcome;
+
+ log.initialize ( lgfile );
+ outcome = log.readEvent( event );
+ while ( outcome == ULOG_OK && event->eventNumber != ULOG_SUBMIT )
+ {
+ outcome = log.readEvent ( event );
+ }
+
+ if ( outcome != ULOG_OK )
+ {
+ *cID = -1;
+ *pID = -1;
+ return;
+ }
+
+ *cID = event->cluster;
+ *pID = event->proc;
+ return;
+#endif
+ return;
+}
+
+
+void
+MWFileRC::sort_exec_class_ratio ( int *temp )
+{
+ int i, j;
+ double ii, jj;
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ temp[i] = i;
+ }
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ for ( j = i + 1; j < exec_classes; j++ )
+ {
+ ii = ((double)MW_exec_class_num_workers[temp[i]]) / exec_class_target_num_workers[temp[i]];
+ jj = ((double)MW_exec_class_num_workers[temp[j]]) / exec_class_target_num_workers[temp[j]];
+ if ( jj > ii )
+ {
+ int temp = j;
+ j = i;
+ i = temp;
+ }
+ }
+ }
+ return;
+}
+
+//---------------------------------------------------------------------------
+// hostaddlogic():
+// If the number of workers are less than the target number of workers
+// just spawns the remaining. current_num_workers holds the information about the
+// the current number of workers.
+//---------------------------------------------------------------------------
+int
+MWFileRC::hostaddlogic ( int *num_workers )
+{
+ /* This awfully complex function determines the conditions
+ under which it being called, and then calls condor_submit
+ asking for the correct number of hosts.
+
+ - num_workers - an array of size exec_classes that contains
+ the number of workers in each arch class.
+ - hostadd_reqs: The number of outstanding HOSTADDs out there
+ - target_num_workers: Set by the user...
+ */
+
+ MWprintf ( 10, "In hostaddlogic \n" );
+ if ( !hostadd_reqs )
+ {
+ /* if this doesn't exist yet, we won't do anything */
+ return 0;
+ }
+
+ /* number of hosts to ask for at a time. The idea is that we'll
+ have double this outstanding at a time - and this amounts
+ to 12 for 1, 2, or 3 arch classes. */
+ int i;
+ int *sorted_order = new int [exec_classes];
+ int *num_execs = new int[exec_classes];
+ int cur;
+ int req;
+ sort_exec_class_ratio ( sorted_order );
+ int status;
+
+ MWprintf ( 60, "hal: target: %d.\n", target_num_workers );
+
+ int HOSTINC = hostinc_;
+
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ cur = sorted_order[i];
+ if ( MW_exec_class_num_workers[cur] + hostadd_reqs[cur] >= exec_class_target_num_workers[cur] ) continue;
+ if ( hostadd_reqs[cur] > 0 ) continue;
+ if ( exec_class_target_num_workers[cur] - ( MW_exec_class_num_workers[cur] + hostadd_reqs[cur] ) > HOSTINC )
+ req = HOSTINC;
+ else
+ req = exec_class_target_num_workers[cur] - ( MW_exec_class_num_workers[cur] + hostadd_reqs[cur] );
+ status = do_spawn ( req, cur );
+ if ( status > 0 )
+ {
+ MWprintf ( 10, "Added %d workers of exec_class %d\n", req, i );
+ hostadd_reqs[cur] += status;
+ }
+ else
+ {
+ MWprintf ( 10, "ERROR!! Failed to submit workers of exec_class %d\n", i );
+ }
+ }
+
+ write_RMstate ( );
+
+ delete [] sorted_order;
+ delete [] num_execs;
+ return 0;
+}
+
+
+//---------------------------------------------------------------------------
+// GetWorkerCounter ():
+// Gets the next message to be sent to the worker.
+//---------------------------------------------------------------------------
+int
+MWFileRC::GetWorkerCounter ( char *file )
+{
+ int cal = 0;
+ int task_num = 0;
+ char c[2]; c[1] = '\0';
+ bool end = FALSE;
+ bool first = TRUE;
+
+ if ( !file ) return 0;
+
+ FILE *fp = Open ( file, "r" );
+ if ( fp == NULL ) return 0;
+
+ while ( fscanf(fp, "%c", &c[0] ) >= 0 )
+ {
+ if ( isdigit ( c[0] ) > 0 )
+ {
+ cal = cal * 10 + atoi(c);
+ end = FALSE;
+ }
+ else if ( isspace(c[0]) > 0 )
+ {
+ }
+ else if ( c[0] == OK )
+ {
+ task_num = cal;
+ cal = 0;
+ end = TRUE;
+ first = FALSE;
+ }
+ else if ( c[0] == SYNC || c[0] == ESYNC )
+ {
+ cal = 0;
+ end = TRUE;
+ }
+ }
+ Close ( fp );
+ if ( first == TRUE ) return 0;
+ if ( end == TRUE )
+ {
+ return task_num + 1;
+ }
+ else
+ {
+ return task_num;
+ }
+}
+
+
+
+//---------------------------------------------------------------------------
+// GetCounter ():
+// Gets the next message to be received from the worker.
+//---------------------------------------------------------------------------
+int
+MWFileRC::GetCounter ( char *file )
+{
+
+ char c[2]; c[1] = '\0';
+ int num_cal = 0;
+ int task_num = 0;
+ bool end = TRUE;
+
+ FILE *fp = Open ( file, "r" );
+ if ( !fp ) return 0;
+
+ while ( fscanf(fp, "%c", &c[0] ) >= 0 )
+ {
+ if ( isdigit ( c[0] ) > 0 )
+ {
+ num_cal = num_cal * 10 + atoi(c);
+ end = FALSE;
+ }
+ else if ( c[0] == OK )
+ {
+ task_num = num_cal;
+ num_cal = 0;
+ end = TRUE;
+ }
+ }
+ Close ( fp );
+
+ if ( end ) return task_num + 1;
+ else return task_num;
+}
+
+
+void
+MWFileRC::killWorker ( int i )
+{
+ char exe[_POSIX_PATH_MAX];
+ MWprintf ( 10, "Killing condor job %d.%d\n", fileWorkers[i].condorID,
+ fileWorkers[i].condorprocID );
+ sprintf ( exe, "%s/bin/condor_rm %d.%d", CONDOR_DIR, fileWorkers[i].condorID,
+ fileWorkers[i].condorprocID);
+ system ( exe );
+}
+
+
+void
+MWFileRC::InitStructures ( )
+{
+ int i;
+
+ fileWorkers = new struct FileWorker[target_num_workers];
+
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ fileWorkers[i].state = FILE_FREE;
+ fileWorkers[i].served = -1;
+ fileWorkers[i].event_no = 0;
+ fileWorkers[i].id = -1;
+ }
+
+ hostadd_reqs = new int[exec_classes];
+ for ( i = 0; i < exec_classes; i++ )
+ hostadd_reqs[i] = 0;
+}
+
+
+// Here you have to resuscicate and fill in the appropriate structures
+// By This time target_num_workers has been filled up.
+// We should not touch target_num_workers. All things go into current_num_workers.
+int
+MWFileRC::read_RMstate ( FILE *fp )
+{
+ int i, temp;
+ int temp1, temp2, temp3, temp4;
+ char target_file[_POSIX_PATH_MAX];
+
+ sprintf ( target_file, "%s/%s", control_directory, moment_worker_file );
+
+
+ FILE *numwf = Open ( target_file, "r" );
+ if ( numwf == NULL )
+ {
+ MWprintf ( 10, "Coudn't open the moment_worker_file for reading\n");
+ InitStructures ( );
+ return 0;
+ }
+
+ if ( fscanf ( numwf, "%d %d", &temp, &subId ) < 0 )
+ {
+ MWprintf (10, "Was unable to read the moment worker file\n");
+ InitStructures ( );
+ Close ( numwf );
+ return 0;
+ }
+
+ if ( temp != target_num_workers )
+ {
+ MWprintf ( 10, "Something wrong with the target_num_workers\n");
+ if ( temp > target_num_workers )
+ target_num_workers = temp;
+ }
+
+ InitStructures ( );
+
+ while ( fscanf ( numwf, "%d %d %d %d ", &temp1, &temp2, &temp3, &temp4 ) > 0 )
+ {
+ if ( temp1 > target_num_workers )
+ {
+ MWprintf ( 10, "ERROR!! Some Big Time Screwup, how can id be greater than target_num_workers\n");
+ ::exit(1);
+ }
+ fileWorkers[temp1].id = temp1;
+ fileWorkers[temp1].condorID = temp2;
+ fileWorkers[temp1].condorprocID = temp3;
+ fileWorkers[temp1].exec_class = temp4;
+ }
+
+ Close ( numwf );
+
+ resuscicate();
+
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ if ( fileWorkers[i].state == FILE_SUBMITTED )
+ hostadd_reqs[fileWorkers[i].exec_class]++;
+ }
+
+ return 0;
+}
+
+
+int
+MWFileRC::write_RMstate ( FILE *filp )
+{
+ int i;
+ FILE *fp;
+ char target_file[_POSIX_PATH_MAX];
+ char cmd[4 * _POSIX_PATH_MAX];
+
+ sprintf ( target_file, "%s/%s", control_directory, moment_worker_file );
+
+ fp = Open ( "temp_File", "w" );
+ if ( fp == NULL )
+ {
+ MWprintf ( 10, "Cannot open the file temp_File for writing\n");
+ return -1;
+ }
+
+// fprintf ( fp, "%d %d ", max_num_workers, subId );
+ fprintf ( fp, "%d %d ", target_num_workers, subId );
+
+ for ( i = 0; i < exec_classes; i++ )
+ {
+// fprintf ( fp, "%d ", hostadd_reqs[i] );
+ for ( int j = 0; j < target_num_workers; j++ )
+ {
+ if ( fileWorkers[j].state != FILE_FREE && fileWorkers[j].exec_class == i )
+ fprintf ( fp, "%d %d %d %d ", j, fileWorkers[j].condorID, fileWorkers[j].condorprocID, fileWorkers[j].exec_class );
+ }
+/*
+ for ( int j = 0; j < 2 * HOSTINC; j++ )
+ if ( hostaddind_reqs[i][j] != -1 )
+ fprintf ( fp, "%d ", hostaddind_reqs[i][j] );
+*/
+ }
+
+ Close ( fp );
+
+ sprintf ( cmd, "mv temp_File %s", target_file );
+// if ( rename ( "temp_File", target_file ) < 0 )
+ if ( system ( cmd ) < 0 )
+ {
+ MWprintf (10, "Could not move the new RM_status file %d\n", errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+char*
+MWFileRC::process_executable_name ( char *exec, int ex_cl, int ar_cl )
+{
+ int i;
+ char newstring[_POSIX_PATH_MAX];
+ char arch[100], opsys[100];
+ char *index;
+ char *req = arch_class_attributes[ar_cl];
+ char *newexec = new char[_POSIX_PATH_MAX];
+ char exe[4 * _POSIX_PATH_MAX];
+ strcpy ( newstring, req );
+ sprintf ( newexec, "mw_exec%d", ex_cl );
+
+ for ( unsigned i = 0; i < strlen ( newstring ); i++ )
+ {
+ int k = newstring[i];
+ if( ! ( ( k == 'u' || k == 'x' ) && newstring[i-1] == '4' ) )
+ {
+ k = toupper(k);
+ }
+ newstring[i] = k;
+ }
+
+ i = 0;
+ index = strstr ( newstring, "OPSYS" );
+ index += 5;
+ while ( *index == ' ' || *index == '=' || *index == '"' || *index == '\\' ) index++;
+ while ( *index != ')' && *index != '"' && *index != '\\' ) opsys[i++] = *index++;
+ opsys[i] = '\0';
+
+ i = 0;
+ index = strstr ( newstring, "ARCH" );
+ index += 4;
+ while ( *index == ' ' || *index == '=' || *index == '"' || *index == '\\' ) index++;
+ while ( *index != ')' && *index != '"' && *index != '\\' ) arch[i++] = *index++;
+ arch[i] = '\0';
+
+ sprintf ( newexec, "%s.%s.%s", newexec, opsys, arch );
+ remove ( newexec );
+
+ MWprintf ( 10, "Making a link from %s to %s\n", exec, newexec );
+#ifdef WINDOWS
+ sprintf ( exe, "copy %s %s", exec, newexec );
+#else
+ sprintf ( exe, "ln -s %s %s", exec, newexec );
+#endif
+ system ( exe );
+
+ return newexec;
+}
+
+//BUFFER
+int
+MWFileRC::recv_all( int from_whom, int msgtag )
+{
+ MWprintf(91, "Not implemented yet for MW-File.\n");
+ return 0;
+}
+
+int
+MWFileRC::setrbuf( int bid )
+{
+ MWprintf(91, "Not implemented yet for MW-File.\n");
+ return -1;
+}
+
+int
+MWFileRC::freebuf( int bid )
+{
+ MWprintf(91, "Not implemented yet for MW-File.\n");
+ return -1;
+}
+
+MWList<void> *
+MWFileRC::recv_buffers()
+{
+ MWprintf(91, "Not implemented yet for MW-File.\n");
+ return NULL;
+}
+
+int
+MWFileRC::next_buf()
+{
+ MWprintf(91, "Not implemented yet for MW-File.\n");
+ return -1;
+}
+
+
+
+int
+MWFileRC::sendFileToMaster(char *filename) {
+#ifdef USE_CHIRP
+#ifndef FILE_MASTER
+ struct chirp_client *client;
+
+ // We connect each time, so that we don't have thousands
+ // of idle connections hanging around the master
+ MWprintf(60, "Sending %s to master\n", filename);
+ client = chirp_client_connect_default();
+ if (!client) {
+ MWprintf(10, "MWFileRC:sendFileToMaster cannot chirp_connect to master, exitting\n");
+ exit(-1);
+ }
+
+ FILE *rfd = ::fopen(filename, "r");
+ if (rfd == NULL) {
+ chirp_client_disconnect(client);
+ MWprintf(10, "MWFileRC:sendFileToMaster can't open filename %s:%s\n", filename, strerror(errno));
+ return -1;
+ }
+
+ int wfd = chirp_client_open(client, filename, "cwat", 0777);
+ if (wfd < 0) {
+ ::fclose(rfd);
+ chirp_client_disconnect(client);
+ MWprintf(10, "MWFfileRC:sendFileToMaster can't chirp_client_open %s:%d\n", filename, wfd);
+ return -1;
+ }
+
+ char buf[1024];
+
+ int num_read = 0;
+ do {
+ num_read = ::fread(buf, 1, 1024, rfd);
+ if (num_read < 0) {
+ fclose(rfd);
+ chirp_client_close(client, wfd);
+ chirp_client_disconnect(client);
+ MWprintf(10, "MWFileRC:sendFileToMaster local read error on %s\n", filename);
+ return -1;
+ }
+ int num_written = chirp_client_write(client, wfd, buf, num_read);
+ if (num_written != num_read) {
+ fclose(rfd);
+ chirp_client_close(client, wfd);
+ chirp_client_disconnect(client);
+ MWprintf(10, "MWFileRC:sendFileToMaster couldn't chirp_write as much as we read\n");
+ return -1;
+ }
+
+ } while (num_read == 1024);
+
+ ::fclose(rfd);
+ chirp_client_close(client, wfd);
+ chirp_client_disconnect(client);
+
+#endif
+#endif
+ return 0;
+}
+
+int
+MWFileRC::getFileFromMaster(char *filename) {
+#ifdef USE_CHIRP
+#ifndef FILE_MASTER
+ struct chirp_client *client = 0;
+
+ MWprintf(60, "Fetching %s from master\n", filename);
+
+ // We connect each time, so that we don't have thousands
+ // of idle connections hanging around the master
+
+ client = chirp_client_connect_default();
+ if (!client) {
+ MWprintf(10, "MWFileRC:getFileFromMaster cannot chirp_connect to master, waiting\n");
+ return -1;
+ }
+
+ int rfd = chirp_client_open(client, filename, "r", 0);
+ if (rfd < 0) {
+ MWprintf(10, "MWFileRC:getFileFromMaster can't chirp_client_open %s:%d\n", filename, rfd);
+ chirp_client_disconnect(client);
+ return -1;
+ }
+
+ FILE *wfd = ::fopen(filename, "w+");
+ if (wfd == NULL) {
+ MWprintf(10, "MWFileRC:getFileFromMaster can't open filename %s: %s\n", filename, strerror(errno));
+ chirp_client_close(client, rfd);
+ chirp_client_disconnect(client);
+ return -1;
+ }
+
+
+ char buf[1024];
+
+ int num_read = 0;
+ do {
+ num_read = chirp_client_read(client, rfd, buf, 1024);
+ if (num_read < 0) {
+ MWprintf(10, "MWFileRC:getFileFromMaster couldn't chirp_read\n");
+ ::fclose(wfd);
+ chirp_client_close(client, rfd);
+ chirp_client_disconnect(client);
+ return -1;
+ }
+
+ int num_written = fwrite(buf, 1, num_read, wfd);
+ if (num_written < 0) {
+ MWprintf(10, "MWFileRC:GetFileFromMaster local read error on %s\n", filename);
+ ::fclose(wfd);
+ chirp_client_close(client, rfd);
+ chirp_client_disconnect(client);
+ return -1;
+ }
+
+ } while (num_read == 1024);
+
+ ::fclose(wfd);
+ chirp_client_close(client, rfd);
+ chirp_client_disconnect(client);
+ return 0;
+#endif
+#endif
+ return 0;
+
+}
+
diff --git a/MW/src/RMComm/MW-File/MWFileRC.h b/MW/src/RMComm/MW-File/MWFileRC.h
new file mode 100644
index 0000000..c69df89
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileRC.h
@@ -0,0 +1,397 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWFILERC_H
+#define MWFILERC_H
+
+#include "../MWRMComm.h"
+#include "MWFileWorker.h"
+#include "MWList.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ A Resource Management and Communication class that uses Condor
+ for underlying support of resource managament. Some crude inter-process
+ communication is provided using the userlog feature of Condor.
+ resource management.
+*/
+
+
+enum FileRCEvents
+{
+ FileHostDelete, /* Not yet implemented */
+ FileHostAdd, /* Host gets added */
+ FileTaskExit, /* Task has exited */
+ FileTaskSuspend, /* Task has been suspended */
+ FileTaskResume, /* Task resumed */
+ FileChecksumError, /* Checksum error */
+ FileNumEvents /* Number of events */
+};
+
+class MWFileRC : public MWRMComm
+{
+
+ public:
+
+ /// Constructor
+ MWFileRC( bool val, int id );
+
+ /// Destructor
+ ~MWFileRC() {};
+
+ /** A function that inits some internal structures */
+ void InitStructures ( );
+
+ /** @name A. Resource Management Routines
+
+ Here we implement the pure virtual functions found in
+ ur parent class, MWRMComm.
+ */
+ //@{
+
+ /** Initialises. Depending on whether it is master or worker instance
+ it initializes all the internal variables. */
+ int setup ( int argc, char *argv[], int *mytid, int *mastertid );
+
+ /** Shutdown. Kills all the workers if it is master */
+ void exit ( int exitval );
+
+ /** Initialize workers if already some have started up */
+ int init_beginning_workers ( int *nworkers, MWWorkerID ***workers );
+
+ /** Restart function */
+ int restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg );
+
+ /** This function is actually a misonomer. It DOES NOT spawn a new
+ worker. Rather it just inits the structure that is passed on to
+ it */
+ int start_worker ( MWWorkerID *w );
+
+ /** This function removes a existing worker */
+ int removeWorker ( MWWorkerID *w );
+
+ /** Figure out whether or not to generate a new worker depending on
+ whether new requests have been made */
+ int hostaddlogic ( int *w );
+
+ /** A routine for reading in the MW-File state at the time
+ * of checkpointing.
+ */
+ int read_RMstate ( FILE *fp = NULL );
+
+ /** A routine for writing in the MW-File state at the time
+ * of checkpointing.
+ */
+ int write_RMstate ( FILE *fp = NULL );
+
+ char* process_executable_name ( char *execut, int, int );
+
+ //@}
+
+ /** @name B. Communication Routines
+
+ Unlike MWPvmRC, the communication routines are non-trivial
+ because Condor provides no inter-process comminucation.
+ Thus we use files for communication. So a send is essentially
+ a file write operation and a recv is a file-read operation.
+ We maintain 2 lists:- The sendList and recvList for taking
+ care of what is to be written/read to/from the files. As in
+ pvm a user beings by calling initsend which creates a new list.
+ Calls to pack insert into the list what is being packed. And
+ finally a send writes the entire thing into a file
+ identified by the destination. Corresponding things happpen
+ in recv.
+ */
+ //@{
+
+ /** A Function called to know which worker had an exception event */
+ void who ( int *wh );
+
+ /** Initialize the send buffer */
+ int initsend ( int useless = 0 );
+
+ /** Send function */
+ int send ( int toWhom, int msgtag );
+
+ /** Recv function */
+ int recv ( int fromWhom, int msgtag );
+
+ /** Non-blocking version of Recv */
+ int nrecv (int fromWhom, int msgtag);
+
+ /** Get some info about the recv buffer */
+ int bufinfo ( int buf_id, int *len, int *tag, int *sending_host );
+
+ /// pack some bytes
+ int pack ( const char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int pack ( const float *f, int nitem, int stride = 1 );
+
+ /// double
+ int pack ( const double *d, int nitem, int stride = 1 );
+
+ /// int
+ int pack ( const int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int pack ( const unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int pack ( const short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int pack ( const unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int pack ( const long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int pack ( const unsigned long *ul, int nitem, int stride = 1 );
+
+ /// string
+ int pack ( const char *str );
+
+ /// Unpack some bytes
+ int unpack ( char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int unpack ( float *f, int nitem, int stride = 1 );
+
+ ///double
+ int unpack ( double *d, int nitem, int stride = 1 );
+
+ /// int
+ int unpack ( int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int unpack ( unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int unpack ( short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int unpack ( unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int unpack ( long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int unpack ( unsigned long *ul, int nitem, int stride = 1 );
+
+ /// string
+ int unpack ( char *str );
+
+ //@}
+
+ private:
+
+ /** @name Internal event processing functions */
+
+ //@{
+
+ /** Handle a message from the worker */
+ int handle_finished_worker ( int i );
+
+ /** Is Called when a host is resumed */
+ int handle_resumed_worker ( int i );
+
+ /** Is Called when a host is suspended */
+ int handle_suspended_worker ( int i );
+
+ /** Is Called when a task is dead */
+ int handle_killed_worker ( int i );
+
+ /** Called when the worker starts executing first */
+ int handle_executing_worker( int i );
+
+ /** Called in no_checkpoint mode */
+ int handle_transited_worker( int i );
+
+ /** Is called when the worker detects that the master has
+ * come up
+ */
+ int handle_master_executing ();
+
+ /** Is Called when a message is received by the worker. */
+ int handle_work ( int msgtag );
+
+ //@}
+
+ /** @name Checkpoint Files processing functions. */
+
+ //@{
+
+ /** Always get the last result */
+ void CheckLogFilesRunning ( );
+
+ /** Determine whether worker i has sent a message */
+ bool IsComplete ( int i );
+
+ /** Is Called when we are recovering from a crash */
+ void CheckLogFilesResuscicate ( char *, struct FileWorker& );
+
+ //@}
+
+ /** @name Functions used upon restart */
+
+ //@{
+
+ /** The main resuscicate function */
+ void resuscicate ( );
+
+ /** The helping routine for resuscicate */
+ int GetWorkerCounter ( char *file );
+
+ /** Another helping routine */
+ int GetCounter ( char *file1 );
+
+ /** Find the condor_ID of the worker with this log file */
+ void GetCondorId ( char *lgfile, int *cId, int *pId );
+
+ //@}
+
+ /** @name Internal worker management functions */
+
+ //@{
+
+ /** Create workers, basically do a condor_submit */
+ int do_spawn ( int numworkers, int arch );
+
+ /** Kill a worker */
+ void killWorker ( int i );
+
+ //@}
+
+
+ /** if using CHIRP IO, send a file */
+ int sendFileToMaster( char *filename);
+
+ /** if using CHIRP IO, get a file */
+ int getFileFromMaster( char *filename);
+
+ /** Master receive */
+ int master_recv ( int fromWhom, int msgtag );
+
+ /** Worker receive */
+ int worker_recv ( int fromWhom, int msgtag );
+
+ void sort_exec_class_ratio ( int *);
+
+
+ /** The bool indicates the mode of the RC instance
+ * a true value means that it is a master and a false means that
+ * it is a worker.
+ * We need to make it a tristate as somtimes an RC can be both
+ * a master and a worker.
+ */
+ bool isMaster;
+
+ /** The value is the id that the worker gets. For master it is
+ * of no use.
+ */
+ int FileRCID;
+
+ /** The expected number of the next message */
+ int expected_number;
+
+ /** The expected_number of the next message that the master is
+ * expecting
+ */
+ int master_expected_number;
+
+ /** The directory where all the workers have to send their output */
+ char output_directory[256];
+
+ /** The directory where the master has to send the work */
+ char input_directory[256];
+
+ /** The control directory the master reads for all resource
+ * management functions.
+ */
+ char control_directory[256];
+
+ /** The file in the control directory that will contain the momentary
+ * number of workers.
+ */
+ char moment_worker_file[256];
+
+ /** An array of the number of workers */
+ struct FileWorker *fileWorkers;
+
+ /** A list of all the items that are sent in a send after a series of
+ * packs.
+ */
+ MWList<void> *sendList;
+
+ /** A list of all the items that are received */
+ MWList<void> *recvList;
+
+ /** This is a variable that keeps the cycle in effect. The receive
+ * of ours goes in cycles to ensure fairness to the messages from all
+ * the slaves.
+ */
+ int cyclePosition;
+
+ /** This determines with what frequency should we check the log files
+ */
+ int CHECKLOG_FREQ;
+
+ /** This keeps the track of how many cycles were made.
+ */
+ int turnNo;
+
+ /** The tag of the message that just came in */
+ int msgTag;
+
+ /** The message came from whom */
+ int whomRecv;
+
+ int SIMUL_SEND;
+
+ /** A variable to keep track of submit files */
+ int subId;
+
+ /** A variable array keeping track of how many have been requested */
+ int *hostadd_reqs;
+
+ /** The checksum calculated */
+ long long checksum;
+
+ /** The worker timeout in minutes */
+ long worker_timeout;
+
+ /** The non-blocking recv() functions */
+ public:
+ int recv_all( int from_whom, int msgtag ); // returns the number of new buffers
+ int setrbuf(int bid); // switch the active receive buffer
+ // return the old active buf_id
+ int freebuf(int bid); // free the receive buffer.
+ MWList<void> * recv_buffers(); // return the recv_buf_list
+ int next_buf(); // advance the active buffer to the next valid buffer
+ // in the recv_buf_list.
+
+};
+#endif
+
diff --git a/MW/src/RMComm/MW-File/MWFileRCSymbol.h b/MW/src/RMComm/MW-File/MWFileRCSymbol.h
new file mode 100644
index 0000000..1d7cd57
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileRCSymbol.h
@@ -0,0 +1,37 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWFILERCSYMBOL_H
+#define MWFILERCSYMBOL_H
+
+// This file lists all the symbols that have been used in the wait files.
+
+#define OK '$'
+
+#define WRONGINITFILE '@'
+
+#define SYNC '^'
+
+#define ESYNC '!'
+
+#endif
diff --git a/MW/src/RMComm/MW-File/MWFileSend.h b/MW/src/RMComm/MW-File/MWFileSend.h
new file mode 100644
index 0000000..5fad478
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileSend.h
@@ -0,0 +1,58 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWFILESEND_H
+#define MWFILESEND_H
+
+#include "MWFileTypes.h"
+#include <stdlib.h>
+#include <string.h>
+
+class FileSendBuffer
+{
+ public:
+ FileType type;
+ void *data;
+ int size;
+
+ FileSendBuffer ( void *dt, FileType tp, int sz )
+ {
+ int siz;
+ if ( tp == STRING )
+ siz = sizeof(char) * sz;
+ else
+ siz = sz;
+
+ data = (void *) malloc ( siz );
+ memcpy ( data, dt, siz );
+ type = tp;
+ size = sz;
+ }
+
+ ~FileSendBuffer ( )
+ {
+ if ( data != NULL ) free(data);
+ }
+};
+#endif
+
diff --git a/MW/src/RMComm/MW-File/MWFileTypes.h b/MW/src/RMComm/MW-File/MWFileTypes.h
new file mode 100644
index 0000000..eab83ba
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileTypes.h
@@ -0,0 +1,42 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWFILETYPES_H
+#define MWFILETYPES_H
+
+enum FileType
+{
+ INT,
+ CHAR,
+ LONG,
+ FLOAT,
+ DOUBLE,
+ UNSIGNED_INT,
+ SHORT,
+ UNSIGNED_SHORT,
+ UNSIGNED_LONG,
+ STRING,
+ NUM_FILE_TYPES
+};
+#endif
+
diff --git a/MW/src/RMComm/MW-File/MWFileWorker.h b/MW/src/RMComm/MW-File/MWFileWorker.h
new file mode 100644
index 0000000..9d4b42c
--- /dev/null
+++ b/MW/src/RMComm/MW-File/MWFileWorker.h
@@ -0,0 +1,68 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWFILEWORKER_H
+#define MWFILEWORKER_H
+
+enum FileWorkerState
+{
+ FILE_FREE,
+ FILE_SUBMITTED,
+ FILE_EXECUTE, // Started executing for the first time.
+ FILE_RUNNING,
+ FILE_KILLED,
+ FILE_SUSPENDED,
+ FILE_RESUMED,
+ FILE_IDLE,
+ FILE_TRANSIT,
+};
+
+
+struct FileWorker
+{
+ int id;
+
+ // What is the message number that I have to look next for.
+ int counter;
+
+ // What is the message that the worker is looking for.
+ int worker_counter;
+
+ // What is the condor_id of the worker.
+ int condorID;
+
+ // What is the proc id.
+ int condorprocID;
+
+ FileWorkerState state;
+
+ int arch;
+
+ int event_no;
+
+ /** What was last served */
+ int served;
+
+ int exec_class;
+};
+
+#endif
diff --git a/MW/src/RMComm/MW-File/Makefile.in b/MW/src/RMComm/MW-File/Makefile.in
new file mode 100644
index 0000000..65c2a5e
--- /dev/null
+++ b/MW/src/RMComm/MW-File/Makefile.in
@@ -0,0 +1,143 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(DEBUG_CHECKER) $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+
+# Subdirectories
+SUBDIRS =
+
+# Libraries to be built, and dependent source files
+LIBRARIES = libMWfileworker.a libMWfilemaster.a
+libMWfilemaster_a_SOURCES = MWFileRCM.ii
+libMWfilemaster_a_LIBADD = MWFileRCM.o
+libMWfilemaster_a_DEPENDENCIES = MWFileRCM.o
+libMWfilemaster_a_OBJECTS =
+
+libMWfileworker_a_SOURCES = MWFileRCW.ii chirp_client.c
+libMWfileworker_a_LIBADD = MWFileRCW.o chirp_client.o
+libMWfileworker_a_DEPENDENCIES = MWFileRCW.o chirp_client.o
+libMWfileworker_a_OBJECTS =
+
+INCLUDES = -I. -I.. -I../.. -I$(CONDOR_DIR)/include $(MEASURE_DEFN)
+INCLUDEFILES = MWFileRC.h MWFileSend.h MWFileTypes.h MWFileWorker.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+
+libMWfilemaster.a: $(libMWfilemaster_a_OBJECTS) $(libMWfilemaster_a_DEPENDENCIES)
+ -rm -f libMWfilemaster.a
+ $(AR) cru libMWfilemaster.a $(libMWfilemaster_a_OBJECTS) $(libMWfilemaster_a_LIBADD)
+ $(RANLIB) libMWfilemaster.a
+ cp libMWfilemaster.a $(MW_LIBDIR)
+
+libMWfileworker.a: $(libMWfileworker_a_OBJECTS) $(libMWfileworker_a_DEPENDENCIES)
+ -rm -f libMWfileworker.a
+ $(AR) cru libMWfileworker.a $(libMWfileworker_a_OBJECTS) $(libMWfileworker_a_LIBADD)
+ $(RANLIB) libMWfileworker.a
+ cp libMWfileworker.a $(MW_LIBDIR)
+
+MWFileRCM.ii:MWFileRC.C
+ $(CXX) -E $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DFILE_MASTER MWFileRC.C > MWFileRCM.ii
+
+MWFileRCM.o:MWFileRCM.ii
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DFILE_MASTER MWFileRCM.ii
+
+MWFileRCW.ii:MWFileRC.C
+ $(CXX) -E $(DEFS) $(MISC_DEFN) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) MWFileRC.C > MWFileRCW.ii
+
+MWFileRCW.o:MWFileRCW.ii
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) MWFileRCW.ii
+
+chirp_client.o: chirp_client.c
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) chirp_client.c
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.ii *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.ii *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
+
diff --git a/MW/src/RMComm/MW-File/chirp_client.c b/MW/src/RMComm/MW-File/chirp_client.c
new file mode 100644
index 0000000..a219976
--- /dev/null
+++ b/MW/src/RMComm/MW-File/chirp_client.c
@@ -0,0 +1,623 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/*
+Chirp C Client
+
+This public domain software is provided "as is". See the Chirp License
+for details.
+*/
+
+#include "chirp_protocol.h"
+#include "chirp_client.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+static int tcp_connect( const char *host, int port );
+static void chirp_fatal_request( const char *name );
+static void chirp_fatal_response();
+static int get_result( FILE *s );
+static int convert_result( int response );
+static int simple_command(struct chirp_client *c,char const *fmt,...);
+static void vsprintf_chirp(char *command,char const *fmt,va_list args);
+static char const *read_url_param(char const *url,char *buffer,size_t length);
+
+
+struct chirp_client {
+ FILE *stream;
+};
+
+/*
+ chirp_client_connect_url()
+
+ Sets path_part to the position of the start of the path information
+ in the URL and connects to the specified Chirp server.
+
+ URL format:
+ chirp:host.name:port/path (absolute path)
+ chirp:host.name:port./path (relative path)
+ chirp:/path (absolute path)
+ chirp:./path (relative path)
+ chirp:path (sloppy relative path)
+
+ Note that the initial part of a sloppy relative path can be confused
+ for a host:port specification if it happens to look like one. Example:
+ 'chirp:strange:1/file'. For this reason, it is better to use one of
+ the non-sloppy formats.
+
+ In all of the above URL formats, any number of extra connection
+ parameters may be inserted before the path part (including the leading
+ '/' or '.'). These are of the form ";parameter=value" where parameter
+ and value are encoded using the standard Mime type
+ application/x-www-form-url encoded, just like the parameters in a typical
+ HTTP GET CGI request, but using ';' instead of '&' as the delimiter.
+
+ At this time, no connection parameters are defined, and any that
+ are supplied are simply ignored.
+
+*/
+
+struct chirp_client *
+chirp_client_connect_url( const char *url, const char **path_part)
+{
+ struct chirp_client *client;
+ char const *str;
+ char *host = NULL;
+ int port = 0;
+
+ if(strncmp(url,"chirp:",6)) {
+ //bare file name
+ *path_part = url;
+ return chirp_client_connect_default();
+ }
+
+ url += 6; // "chirp:"
+
+ if(*url != '/' && *url != '\\' && *url != ';' && *url != '.' \
+ && (str = strchr(url,':')))
+ {
+ char *end;
+ port = strtol(str+1,&end,10);
+ if(port && end > str+1 &&
+ (*end == '\0' || *end == '/' || *end == '\\' ||
+ *end == '.' || *end == ';'))
+ {
+ //URL form chirp:host.name:port...
+ //Note that we try to avoid getting here on a "sloppy"
+ //relative path that happens to contain a ':' but
+ //which is not followed by a valid port/path.
+
+ host = (char *)malloc(str-url+1);
+ strncpy(host,url,str-url);
+ host[str-url] = '\0';
+
+ url = end;
+ }
+ }
+
+ while(*url == ';') { //parse connection parameters
+ char param[CHIRP_LINE_MAX];
+ char value[CHIRP_LINE_MAX];
+
+ url = read_url_param(++url,param,sizeof(param));
+ if(!url) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if(*url == '=') {
+ url = read_url_param(++url,value,sizeof(value));
+ if(!url) {
+ errno = EINVAL;
+ return NULL;
+ }
+ }
+ else *value = '\0';
+
+ //No connection parameters are defined at this time!
+ //Handle them here when they are defined.
+ }
+
+ *path_part = url;
+
+ if(!host) { //URL must be in form 'chirp:path'
+ client = chirp_client_connect_default();
+ }
+ else {
+ client = chirp_client_connect(host,port);
+ }
+
+ free(host);
+ return client;
+}
+
+struct chirp_client *
+chirp_client_connect_default()
+{
+ FILE *file;
+ int fields;
+ int save_errno;
+ struct chirp_client *client;
+ char host[CHIRP_LINE_MAX];
+ char cookie[CHIRP_LINE_MAX];
+ int port;
+ int result;
+
+ file = fopen("chirp.config","r");
+ if(!file) return 0;
+
+ fields = fscanf(file,"%s %d %s",host,&port,cookie);
+ fclose(file);
+
+ if(fields!=3) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ client = chirp_client_connect(host,port);
+ if(!client) return 0;
+
+ result = chirp_client_cookie(client,cookie);
+ if(result!=0) {
+ save_errno = errno;
+ chirp_client_disconnect(client);
+ errno = save_errno;
+ return 0;
+ }
+
+ return client;
+}
+
+struct chirp_client *
+chirp_client_connect( const char *host, int port )
+{
+ struct chirp_client *c;
+ int save_errno;
+ int fd;
+
+ c = (chirp_client *) malloc(sizeof(*c));
+ if(!c) return 0;
+
+ fd = tcp_connect(host,port);
+ if(fd<0) {
+ save_errno = errno;
+ free(c);
+ errno = save_errno;
+ return 0;
+ }
+
+ c->stream = fdopen(fd,"w+");
+ if(!c->stream) {
+ save_errno = errno;
+ close(fd);
+ free(c);
+ errno = save_errno;
+ return 0;
+ }
+
+ return c;
+}
+
+void
+chirp_client_disconnect( struct chirp_client *c )
+{
+ fclose(c->stream);
+ free(c);
+}
+
+int
+chirp_client_cookie( struct chirp_client *c, const char *cookie )
+{
+ return simple_command(c,"cookie %s\n",cookie);
+}
+
+int
+chirp_client_login( struct chirp_client *c, const char *name, const char *password )
+{
+ return simple_command(c,"login %s %s\n",name,password);
+}
+
+int
+chirp_client_lookup( struct chirp_client *c, const char *logical_name, char **url )
+{
+ int result;
+ int actual;
+
+ result = simple_command(c,"lookup %s\n",logical_name);
+ if(result>0) {
+ *url = (char *)malloc(result);
+ if(*url) {
+ actual = fread(*url,1,result,c->stream);
+ if(actual!=result) chirp_fatal_request("lookup");
+ } else {
+ chirp_fatal_request("lookup");
+ }
+ }
+
+ return result;
+}
+
+int
+chirp_client_constrain( struct chirp_client *c, const char *expr)
+{
+ return simple_command(c,"constrain %s\n",expr);
+}
+
+int
+chirp_client_get_job_attr( struct chirp_client *c, const char *name, char **expr )
+{
+ int result;
+ int actual;
+
+ result = simple_command(c,"get_job_attr %s\n",name);
+ if(result>0) {
+ *expr = (char *)malloc(result);
+ if(*expr) {
+ actual = fread(*expr,1,result,c->stream);
+ if(actual!=result) chirp_fatal_request("get_job_attr");
+ } else {
+ chirp_fatal_request("get_job_attr");
+ }
+ }
+
+ return result;
+}
+
+int
+chirp_client_set_job_attr( struct chirp_client *c, const char *name, const char *expr )
+{
+ return simple_command(c,"set_job_attr %s %s\n",name,expr);
+}
+
+int
+chirp_client_open( struct chirp_client *c, const char *path, const char *flags, int mode )
+{
+ return simple_command(c,"open %s %s %d\n",path,flags,mode);
+}
+
+int
+chirp_client_close( struct chirp_client *c, int fd )
+{
+ return simple_command(c,"close %d\n",fd);
+}
+
+int
+chirp_client_read( struct chirp_client *c, int fd, void *buffer, int length )
+{
+ int result;
+ int actual;
+
+ result = simple_command(c,"read %d %d\n",fd,length);
+
+ if( result>0 ) {
+ actual = fread(buffer,1,result,c->stream);
+ if(actual!=result) chirp_fatal_request("read");
+ }
+
+ return result;
+}
+
+int
+chirp_client_write( struct chirp_client *c, int fd, const void *buffer, int length )
+{
+ int actual;
+ int result;
+
+ result = fprintf(c->stream,"write %d %d\n",fd,length);
+ if(result<0) chirp_fatal_request("write");
+
+ result = fflush(c->stream);
+ if(result<0) chirp_fatal_request("write");
+
+ actual = fwrite(buffer,1,length,c->stream);
+ if(actual!=length) chirp_fatal_request("write");
+
+ return convert_result(get_result(c->stream));
+}
+
+int
+chirp_client_unlink( struct chirp_client *c, const char *path )
+{
+ return simple_command(c,"unlink %s\n",path);
+}
+
+int
+chirp_client_rename( struct chirp_client *c, const char *oldpath, const char *newpath )
+{
+ return simple_command(c,"rename %s %s\n",oldpath,newpath);
+}
+int
+chirp_client_fsync( struct chirp_client *c, int fd )
+{
+ return simple_command(c,"fsync %d\n",fd);
+}
+
+int
+chirp_client_lseek( struct chirp_client *c, int fd, int offset, int whence )
+{
+ return simple_command(c,"lseek %d %d %d\n",fd,offset,whence);
+}
+
+int
+chirp_client_mkdir( struct chirp_client *c, char const *name, int mode )
+{
+ return simple_command(c,"mkdir %s %d\n",name,mode);
+}
+
+int
+chirp_client_rmdir( struct chirp_client *c, char const *name )
+{
+ return simple_command(c,"rmdir %s\n",name);
+}
+
+
+static int
+convert_result( int result )
+{
+ if(result>=0) {
+ return result;
+ } else {
+ switch(result) {
+ case CHIRP_ERROR_NOT_AUTHENTICATED:
+ case CHIRP_ERROR_NOT_AUTHORIZED:
+ errno = EACCES;
+ break;
+ case CHIRP_ERROR_DOESNT_EXIST:
+ errno = ENOENT;
+ break;
+ case CHIRP_ERROR_ALREADY_EXISTS:
+ errno = EEXIST;
+ break;
+ case CHIRP_ERROR_TOO_BIG:
+ errno = EFBIG;
+ break;
+ case CHIRP_ERROR_NO_SPACE:
+ errno = ENOSPC;
+ break;
+ case CHIRP_ERROR_NO_MEMORY:
+ errno = ENOMEM;
+ break;
+ case CHIRP_ERROR_INVALID_REQUEST:
+ errno = EINVAL;
+ break;
+ case CHIRP_ERROR_TOO_MANY_OPEN:
+ errno = EMFILE;
+ break;
+ case CHIRP_ERROR_BUSY:
+ errno = EBUSY;
+ break;
+ case CHIRP_ERROR_TRY_AGAIN:
+ errno = EAGAIN;
+ break;
+ case CHIRP_ERROR_UNKNOWN:
+ chirp_fatal_response();
+ break;
+ }
+ return -1;
+ }
+}
+
+static int
+get_result( FILE *s )
+{
+ char line[CHIRP_LINE_MAX];
+ char *c;
+ int result;
+ int fields;
+
+ c = fgets(line,CHIRP_LINE_MAX,s);
+ if(!c) chirp_fatal_response();
+
+ fields = sscanf(line,"%d",&result);
+ if(fields!=1) chirp_fatal_response();
+
+#ifdef CHIRP_DEBUG
+ fprintf(stderr,"chirp received: %s\n",line);
+#endif
+
+ return result;
+}
+
+static void
+chirp_fatal_request( const char *name )
+{
+ fprintf(stderr,"chirp: couldn't %s: %s\n",name,strerror(errno));
+ abort();
+}
+
+static
+void chirp_fatal_response()
+{
+ fprintf(stderr,"chirp: couldn't get response from server: %s\n",strerror(errno));
+ abort();
+}
+
+static int
+tcp_connect( const char *host, int port )
+{
+ struct hostent *h;
+ struct sockaddr_in address;
+ int success;
+ int fd;
+
+ h = gethostbyname(host);
+ if(!h) return -1;
+
+ address.sin_port = htons(port);
+ address.sin_family = h->h_addrtype;
+ memcpy(&address.sin_addr.s_addr,h->h_addr_list[0],sizeof(address.sin_addr.s_addr));
+
+ fd = socket( AF_INET, SOCK_STREAM, 0 );
+ if(fd<0) return -1;
+
+ success = connect( fd, (struct sockaddr *) &address, sizeof(address) );
+ if(success<0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+/*
+ vsprintf_chirp -- simple sprintf capabilities with character escaping
+
+ The following format characters are interpreted:
+
+ %d -- decimal
+ %s -- word (whitespace is escaped)
+ %% -- output %
+*/
+
+void
+vsprintf_chirp(char *command,char const *fmt,va_list args)
+{
+ char *c;
+ char const *f;
+
+ c = command;
+ f = fmt;
+ while(*f) {
+ if(*f == '%') {
+ switch(*(++f)) {
+ case 'd':
+ f++;
+ sprintf(c,"%d",va_arg(args,int));
+ c += strlen(c);
+ break;
+ case 's': {
+ char const *w = va_arg(args,char const *);
+ f++;
+ while(*w) {
+ switch(*w) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\\':
+ *(c++) = '\\';
+ /*fall through*/
+ default:
+ *(c++) = *(w++);
+ }
+ }
+ break;
+ }
+ case '%':
+ *(c++) = *(f++);
+ break;
+ default:
+ chirp_fatal_request(f);
+ }
+ } else {
+ *(c++) = *(f++);
+ }
+ }
+ *(c++) = '\0';
+}
+
+int
+simple_command(struct chirp_client *c,char const *fmt,...)
+{
+ int result;
+ char command[CHIRP_LINE_MAX];
+ va_list args;
+
+ va_start(args,fmt);
+ vsprintf_chirp(command,fmt,args);
+ va_end(args);
+
+#ifdef DEBUG_CHIRP
+ fprintf(stderr,"chirp sending: %s",command);
+#endif
+
+ result = fputs(command,c->stream);
+
+
+
+ if(result < 0) chirp_fatal_request(fmt);
+
+ result = fflush(c->stream);
+ if(result < 0) chirp_fatal_request(fmt);
+
+ return convert_result(get_result(c->stream));
+}
+
+char const *
+read_url_param(char const *url,char *buffer,size_t length)
+{
+ size_t bufpos = 0;
+
+ while(*url != '\0' && *url != '.' && *url != '/'
+ && *url != '=' && *url != ';' && *url != '\\')
+ {
+ if(bufpos >= length) return NULL;
+
+ switch(*url) {
+ case '+':
+ buffer[bufpos++] = ' ';
+ break;
+ case '%': { //form-url-encoded escape sequence
+ //following two characters are hex digits
+ char d = tolower(*(++url));
+
+ if(d >= '0' && d <= '9') d -= '0';
+ else if(d >= 'a' && d <= 'f') d = d - 'a' + 0xA;
+ else return NULL; //invalid hex digit
+
+ buffer[bufpos] = d<<4;
+
+ d = tolower(*(++url));
+
+ if(d >= '0' && d <= '9') d -= '0';
+ else if(d >= 'a' && d <= 'f') d = d - 'a' + 0xA;
+ else return NULL; //invalid hex digit
+
+ buffer[bufpos++] |= d;
+
+ break;
+ }
+ default:
+ buffer[bufpos++] = *url;
+ break;
+ }
+
+ url++;
+ }
+
+ if(bufpos >= length) return NULL;
+ buffer[bufpos] = '\0';
+
+ return url;
+}
diff --git a/MW/src/RMComm/MW-File/chirp_client.h b/MW/src/RMComm/MW-File/chirp_client.h
new file mode 100644
index 0000000..419d5a4
--- /dev/null
+++ b/MW/src/RMComm/MW-File/chirp_client.h
@@ -0,0 +1,202 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/*
+Chirp C Client
+
+This public domain software is provided "as is". See the Chirp License
+for details.
+*/
+
+#ifndef CHIRP_CLIENT_H
+#define CHIRP_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+Error codes:
+
+-1 NOT_AUTHENTICATED The client has not authenticated its identity.
+-2 NOT_AUTHORIZED The client is not authorized to perform that action.
+-3 DOESNT_EXIST There is no object by that name.
+-4 ALREADY_EXISTS There is already an object by that name.
+-5 TOO_BIG That request is too big to execute.
+-6 NO_SPACE There is not enough space to store that.
+-7 NO_MEMORY The server is out of memory.
+-8 INVALID_REQUEST The form of the request is invalid.
+-9 TOO_MANY_OPEN There are too many resources in use.
+-10 BUSY That object is in use by someone else.
+-11 TRY_AGAIN A temporary condition prevented the request.
+-12 UNKNOWN An unknown error occurred.
+*/
+
+struct chirp_client * chirp_client_connect_default();
+/*chirp_client_connect_default()
+ Opens connection to the default chirp server. The default connection
+ information is determined by reading ./chirp.config. Under Condor,
+ the starter can automatically create this file if you specify
+ +WantIOProxy=True in the submit file.
+*/
+struct chirp_client * chirp_client_connect( const char *host, int port );
+/*chirp_client_connect()
+ Connect to a chirp server at the specified address.
+ */
+
+struct chirp_client * chirp_client_connect_url( const char *url, const char **path_part);
+/*
+ chirp_client_connect_url()
+
+ Sets path_part to the position of the start of the path information
+ in the URL and connects to the specified Chirp server.
+
+ URL format:
+ chirp:host.name:port/path (absolute path)
+ chirp:host.name:port./path (relative path)
+ chirp:/path (absolute path)
+ chirp:./path (relative path)
+ chirp:path (sloppy relative path)
+
+ Note that the initial part of a sloppy relative path can be confused
+ for a host:port specification if it happens to look like one. Example:
+ 'chirp:strange:1/file'. For this reason, it is better to use one of
+ the non-sloppy formats.
+
+ In all of the above URL formats, any number of extra connection
+ parameters may be inserted before the path part (including the leading
+ '/' or '.'). These are of the form ";parameter=value" where parameter
+ and value are encoded using the standard Mime type
+ application/x-www-form-url encoded, just like the parameters in a typical
+ HTTP GET CGI request, but using ';' instead of '&' as the delimiter.
+
+ At this time, no connection parameters are defined, and any that
+ are supplied are simply ignored.
+
+*/
+
+void chirp_client_disconnect( struct chirp_client *c );
+/*chirp_client_disconnect()
+ Closes the connection to a chirp server.
+*/
+
+int chirp_client_cookie( struct chirp_client *c, const char *cookie );
+/*chirp_client_cookie
+ Authenticate with the server using the specified cookie.
+ */
+
+int chirp_client_lookup( struct chirp_client *c, const char *logical_name, char **url );
+/*chirp_client_lookup()
+ Ask the chirp server to translate the filename "logical_name". This is
+ done internally on any filename presented to chirp_client_open(). Under
+ Condor, the shadow may translate the path using the same mechanisms
+ available to redirect paths in Standard Universe.
+*/
+
+int chirp_client_constrain( struct chirp_client *c, const char *expr );
+/*chirp_client_constrain()
+ When running under Condor, set the job's requirement expression.
+*/
+
+int chirp_client_get_job_attr( struct chirp_client *c, const char *name, char **expr );
+/*chirp_client_get_job_attr()
+ When running under Condor, obtain the value of a job ClassAd attribute.
+*/
+
+int chirp_client_set_job_attr( struct chirp_client *c, const char *name, const char *expr );
+/*chirp_client_set_job_attr()
+ When running under Condor, set the value of a job ClassAd attribute.
+*/
+
+int chirp_client_open( struct chirp_client *c, const char *path, const char *flags, int mode );
+/*chirp_client_open()
+ Open a file through the chirp server. Note that if you want to create a
+ new file, you _must_ include "c" or "x" in the flags. The mode is the same
+ as in the POSIX open() call.
+
+ Flags:
+ r - open for reading
+ w - open for writing
+ a - force all writes to append
+ t - truncate before use
+ c - create if it doesn't exist
+ x - fail if 'c' is given and the file already exists
+
+ Returns an integer file handle to be used in future chirp_client() functions.
+ On error, returns a value less than 0.
+*/
+
+int chirp_client_close( struct chirp_client *c, int fd );
+/*chirp_client_close()
+ Closes a file opened via chirp_client_open().
+*/
+
+int chirp_client_read( struct chirp_client *c, int fd, void *buffer, int length );
+/*chirp_client_read()
+ Reads from a file and puts the result in a buffer. The number of bytes
+ actually read is returned.
+*/
+
+int chirp_client_write( struct chirp_client *c, int fd, const void *buffer, int length );
+/*chirp_client_write()
+ Writes from a buffer into a file. On success, returns the number of
+ bytes written, which will always be the number of bytes requested.
+ On error, returns a negative error code.
+*/
+
+int chirp_client_unlink( struct chirp_client *c, const char *path );
+/*chirp_client_unlink()
+ Removes a file.
+*/
+
+int chirp_client_rename( struct chirp_client *c, const char *oldpath, const char *newpath );
+/*chirp_client_rename()
+ Renames a file.
+*/
+
+int chirp_client_fsync( struct chirp_client *c, int fd );
+/*chirp_client_fsync()
+ Flushes any buffered data to disk.
+*/
+
+int chirp_client_lseek( struct chirp_client *c, int fd, int offset, int whence );
+/*chirp_client_lseek()
+ Changes the read/write file offset. The values for whence are the same
+ as for the POSIX lseek() call.
+*/
+
+int chirp_client_mkdir( struct chirp_client *c, char const *name, int mode );
+/*chirp_client_mkdir()
+ Create a directory with the specified mode.
+*/
+
+int chirp_client_rmdir( struct chirp_client *c, char const *name );
+/*chirp_client_rmdir()
+ Removes an empty directory.
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/MW/src/RMComm/MW-File/chirp_protocol.h b/MW/src/RMComm/MW-File/chirp_protocol.h
new file mode 100644
index 0000000..5ba0232
--- /dev/null
+++ b/MW/src/RMComm/MW-File/chirp_protocol.h
@@ -0,0 +1,50 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+/*
+Chirp C Client
+
+This public domain software is provided "as is". See the Chirp License
+for details.
+*/
+
+#ifndef CHIRP_PROTOCOL_H
+#define CHIRP_PROTOCOL_H
+
+#define CHIRP_LINE_MAX 1024
+#define CHIRP_VERSION 2
+
+#define CHIRP_ERROR_NOT_AUTHENTICATED -1
+#define CHIRP_ERROR_NOT_AUTHORIZED -2
+#define CHIRP_ERROR_DOESNT_EXIST -3
+#define CHIRP_ERROR_ALREADY_EXISTS -4
+#define CHIRP_ERROR_TOO_BIG -5
+#define CHIRP_ERROR_NO_SPACE -6
+#define CHIRP_ERROR_NO_MEMORY -7
+#define CHIRP_ERROR_INVALID_REQUEST -8
+#define CHIRP_ERROR_TOO_MANY_OPEN -9
+#define CHIRP_ERROR_BUSY -10
+#define CHIRP_ERROR_TRY_AGAIN -11
+#define CHIRP_ERROR_UNKNOWN -127
+
+#endif
+
diff --git a/MW/src/RMComm/MW-Independent/MWIndRC.C b/MW/src/RMComm/MW-Independent/MWIndRC.C
new file mode 100644
index 0000000..14bfc0e
--- /dev/null
+++ b/MW/src/RMComm/MW-Independent/MWIndRC.C
@@ -0,0 +1,500 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWIndRC.h"
+#include <MW.h>
+#include <MWDriver.h>
+#include <MWTask.h>
+#include <MWWorker.h>
+
+MWRMComm * GlobalRMComm = new MWIndRC ( );
+MWRMComm * MWTask::RMC = GlobalRMComm;
+MWRMComm * MWDriver::RMC = GlobalRMComm;
+MWRMComm * MWWorker::RMC = GlobalRMComm;
+
+MWIndRC::MWIndRC()
+{
+ target_num_workers = -1;
+ num_arches = -1;
+ // memset ( worker_requirements, 0, (16 * 1024 ));
+ // num_arches = 1;
+}
+ /// Destructor...
+MWIndRC::~MWIndRC()
+{
+ /// Nothing to delete
+}
+
+void
+MWIndRC::hostadd ( )
+{
+ last_tag = HOSTADD;
+ return;
+}
+
+void
+MWIndRC::exit( int exitval )
+{
+ // ::exit ( exitval );
+}
+
+int
+MWIndRC::setup ( int argc, char *argv[], int *my_id, int *master_id )
+{
+ *my_id = 2;
+ *master_id = 0;
+ return 0;
+};
+
+
+int
+MWIndRC::config( int *nhosts, int *narches, MWWorkerID ***w )
+{
+ // Nothing to configure either
+ return 0;
+}
+
+int
+MWIndRC::start_worker ( MWWorkerID *w )
+{
+ if (!w) return -1;
+ w->set_id1 ( 2 );
+ w->set_arch ( 0 );
+ w->set_exec_class(0); // XXX should have done this!
+ return 0;
+};
+
+int
+MWIndRC::init_beginning_workers ( int *nworkers, MWWorkerID ***workers )
+{
+ return 0;
+};
+
+int
+MWIndRC::restart_beginning_workers( int *nworkers, MWWorkerID ***workers, MWmessages msg ){
+ return init_beginning_workers( nworkers, workers);
+}
+
+int
+MWIndRC::removeWorker( MWWorkerID *w )
+{
+ return 0;
+};
+
+int
+MWIndRC::read_RMstate( FILE *fp )
+{
+ return 0;
+}
+
+int
+MWIndRC::write_RMstate ( FILE *fp )
+{
+ return 0;
+}
+
+int
+MWIndRC::hostaddlogic( int *num_workers )
+{
+ return 0;
+}
+
+int
+MWIndRC::initsend ( int encoding )
+{
+ ind_sendbuf.num_sent = 0;
+ return 0;
+}
+
+int
+MWIndRC::send ( int to_whom, int msgtag )
+{
+ last_tag = msgtag;
+ sent_data = true;
+ return 0;
+}
+
+int
+MWIndRC::recv ( int from_whom, int msgtag )
+{
+ memcpy ( &ind_recvbuf.buf, &ind_sendbuf.buf, INDP_BUF_SIZE * sizeof(char) );
+ ind_recvbuf.num_sent = 0;
+ sent_data = false;
+ return 0;
+}
+
+int
+MWIndRC::nrecv ( int from_whom, int msgtag )
+{
+ if ( !sent_data )
+ {
+ last_tag = NO_MESSAGE;
+ sent_data = false;
+ return 0;
+ }
+ else
+ {
+ recv ( from_whom, msgtag );
+ }
+ return 0;
+}
+
+int
+MWIndRC::bufinfo ( int buf_id, int *len, int *tag, int *from )
+{
+ *tag = last_tag;
+ return 0;
+}
+
+void
+MWIndRC::who ( int *wh )
+{
+ unpack ( wh, 1, 1 );
+}
+
+
+int
+MWIndRC::pack ( const char *bytes, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( char ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &bytes[ i * stride ], sizeof(char) );
+ ind_sendbuf.num_sent += sizeof(char);
+ num_sent += sizeof(char);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const float *f, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( float ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &f[ i * stride ], sizeof(float) );
+ ind_sendbuf.num_sent += sizeof(float);
+ num_sent += sizeof(float);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const double *d, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( double ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &d[ i * stride ], sizeof(double) );
+ ind_sendbuf.num_sent += sizeof(double);
+ num_sent += sizeof(double);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const int *in, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( int ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &in[ i * stride ], sizeof(int) );
+ ind_sendbuf.num_sent += sizeof(int);
+ num_sent += sizeof(int);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const unsigned int *ui, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( unsigned int ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &ui[ i * stride ], sizeof(unsigned int) );
+ ind_sendbuf.num_sent += sizeof(unsigned int);
+ num_sent += sizeof(unsigned int);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const short *sh, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( short ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &sh[ i * stride ], sizeof(short) );
+ ind_sendbuf.num_sent += sizeof(short);
+ num_sent += sizeof(short);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const unsigned short *ush, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( unsigned short ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &ush[ i * stride ], sizeof(unsigned short) );
+ ind_sendbuf.num_sent += sizeof(unsigned short);
+ num_sent += sizeof(unsigned short);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const long *l, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( long ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &l[ i * stride ], sizeof(long) );
+ ind_sendbuf.num_sent += sizeof(long);
+ num_sent += sizeof(long);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const unsigned long *ul, int nitem, int stride )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ // ASSERT ( num_sent + sizeof ( unsigned long ) <= 1024 * 64 );
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &ul[ i * stride ], sizeof(unsigned long) );
+ ind_sendbuf.num_sent += sizeof(unsigned long);
+ num_sent += sizeof(unsigned long);
+ }
+ return 0;
+}
+
+int
+MWIndRC::pack ( const char *string )
+{
+ int num_sent = ind_sendbuf.num_sent;
+ // ASSERT ( num_sent + sizeof(int) + sizeof( char ) * strlen (string) <= 1024 * 64 );
+ int len = strlen(string);
+ memcpy ( &(ind_sendbuf.buf[num_sent]), &len, sizeof(int) );
+ ind_sendbuf.num_sent += sizeof(int);
+ num_sent += sizeof(int);
+ memcpy ( &(ind_sendbuf.buf[num_sent]), string, len * sizeof(char) );
+ ind_sendbuf.num_sent += sizeof(char) * len;
+ num_sent += sizeof(char) * len;
+ return 0;
+}
+
+int
+MWIndRC::unpack ( char *bytes, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ char temp;
+ memcpy ( &temp,&(ind_recvbuf.buf[num_sent]), sizeof(char) );
+ ind_recvbuf.num_sent += sizeof(char);
+ num_sent += sizeof(char);
+ bytes[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( float *f, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ float temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(float) );
+ ind_recvbuf.num_sent += sizeof(float);
+ num_sent += sizeof(float);
+ f[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( double *d, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ double temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(double) );
+ ind_recvbuf.num_sent += sizeof(double);
+ num_sent += sizeof(double);
+ d[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( int *i, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int ii = 0; ii < nitem; ii++ )
+ {
+ int temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(int) );
+ ind_recvbuf.num_sent += sizeof(int);
+ num_sent += sizeof(int);
+ i[ii * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( unsigned int *ui, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ unsigned int temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(unsigned int) );
+ ind_recvbuf.num_sent += sizeof(unsigned int);
+ num_sent += sizeof(unsigned int);
+ ui[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( short *sh, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ short temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(short) );
+ ind_recvbuf.num_sent += sizeof(short);
+ num_sent += sizeof(short);
+ sh[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( unsigned short *ush, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ unsigned short temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(unsigned short) );
+ ind_recvbuf.num_sent += sizeof(unsigned short);
+ num_sent += sizeof(unsigned short);
+ ush[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( long *l, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ long temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(long) );
+ ind_recvbuf.num_sent += sizeof(long);
+ num_sent += sizeof(long);
+ l[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( unsigned long *ul, int nitem, int stride )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ unsigned long temp;
+ memcpy ( &temp, &(ind_recvbuf.buf[num_sent]), sizeof(unsigned long) );
+ ind_recvbuf.num_sent += sizeof(unsigned long);
+ num_sent += sizeof(unsigned long);
+ ul[i * stride] = temp;
+ }
+ return 0;
+}
+
+int
+MWIndRC::unpack ( char *string )
+{
+ int num_sent = ind_recvbuf.num_sent;
+ int len;
+ memcpy ( &len, &(ind_recvbuf.buf[num_sent]), sizeof(int) );
+ ind_recvbuf.num_sent += sizeof(int);
+ num_sent += sizeof(int);
+ memcpy ( string, &(ind_recvbuf.buf[num_sent]), len * sizeof(char) );
+ ind_recvbuf.num_sent += sizeof(char) * len;
+ num_sent += sizeof(char) * len;
+ string[len] = '\0';
+ return 0;
+}
+//BUFFER
+int
+MWIndRC::recv_all( int from_whom, int msgtag )
+{
+ MWprintf(91, "Not implemented yet for MW-Ind.\n");
+ return 0;
+}
+
+int
+MWIndRC::setrbuf( int bid )
+{
+ MWprintf(91, "Not implemented yet for MW-Ind.\n");
+ return -1;
+}
+
+int
+MWIndRC::freebuf( int bid )
+{
+ MWprintf(91, "Not implemented yet for MW-Ind.\n");
+ return -1;
+}
+
+MWList<void> *
+MWIndRC::recv_buffers()
+{
+ MWprintf(91, "Not implemented yet for MW-Ind.\n");
+ return NULL;
+}
+
+int
+MWIndRC::next_buf()
+{
+ MWprintf(91, "Not implemented yet for MW-Ind.\n");
+ return -1;
+}
+
diff --git a/MW/src/RMComm/MW-Independent/MWIndRC.h b/MW/src/RMComm/MW-Independent/MWIndRC.h
new file mode 100644
index 0000000..824f62e
--- /dev/null
+++ b/MW/src/RMComm/MW-Independent/MWIndRC.h
@@ -0,0 +1,230 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWINDRC_H
+#define MWINDRC_H
+#include "../MWRMComm.h"
+
+/** This class is an derived from the Resource Management (RM) and
+ Communication (Comm) layer. In MW-Ind, there is just one worker and one master
+ and both are on the same machine. And not just that both are same process!!
+ Send and Recv are merely memcpy. This class I deem is useful for debugging purposes.
+ The api etc all will remain the same when using this layer. All the user has to do
+ is to compile it with the INDEPENDENT flag and use this as the RMComm layer. See into
+ the fibonacci example for more details on the makefile. And then just launch the
+ application as a process. That's it.
+*/
+
+class MWIndRC : public MWRMComm
+{
+ public:
+ /** Constructor. Sets data to -1's. */
+ MWIndRC();
+ /// Destructor...
+ ~MWIndRC();
+
+ void hostadd ( );
+
+ /** @name A. Resource Management Functions
+
+ Here are all the methods you could want to have for managing
+ a set of machines. See each method for details...
+ */
+ //@{
+
+ /** System shutdown. Does not return.
+ @param exitval The value to call ::exit() with
+ */
+ void exit( int exitval );
+
+ /** Initialization of the master process. This will be called
+ one time only when the master starts up.
+ @return 0 on success, -1 on failure
+ */
+ int setup( int argc, char* argv[], int *my_id, int *master_id);
+
+ /** What is there to configure? Nothing.
+ */
+ int config( int *nhosts, int *narches, MWWorkerID ***w );
+
+ /** Just init the workerID to a worker. This is an idempotent function.
+ */
+ int start_worker( MWWorkerID *w );
+
+ /** This routine is used to start up multiple workers at
+ the beginning of a run. In MW-Ind there is no initial worker.
+ Simply return 0.
+ */
+ int init_beginning_workers( int *nworkers, MWWorkerID ***workers );
+
+ /** Called at the time of restart */
+ int restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg );
+
+
+ /** Remove a worker from the virtual machine. MW-Ind has
+ no concept of host management. Hence all are null.
+ */
+ int removeWorker( MWWorkerID *w );
+ //@}
+
+ /** @name B. Checkpointing Functions */
+ //@{
+
+ /** Do nothing */
+ int read_RMstate( FILE *fp );
+
+ int write_RMstate ( FILE *fp );
+ //@}
+
+ protected:
+
+ /** @name D. Host Management Members */
+ //@{
+ /** This will figure out if we need to ask for more hosts
+ or remove hosts. In MW-Ind version there is just one worker.
+ So this function is NULL.
+ */
+ int hostaddlogic( int *num_workers );
+
+ //@}
+
+#define INDP_BUF_SIZE 1024*1024*64
+
+ struct SendBuf {
+ int num_sent;
+ char buf[INDP_BUF_SIZE];
+ };
+ struct SendBuf ind_sendbuf, ind_recvbuf;
+ int last_tag;
+ bool sent_data;
+
+ public:
+
+ /** @name The Communication Routines
+ These communication primitives use memcpy as the communication
+ mechanism for the transfer of data.
+
+ */
+
+ //@{
+
+ /** A Function called to know which worker had an exception event */
+ void who ( int *wh );
+
+ /** Initialize a buffer for sending some data.
+ @param encoding Defined by each application. 0 = default */
+ int initsend ( int encoding = 0 );
+ /** Send the data that has been packed.
+ @param to_whom An identifier for the recipient
+ @param msgtag A 'tag' to identify that type of message */
+ int send ( int to_whom, int msgtag );
+
+ /** Receive some data that has been packed. Just a memcpy
+ @param from_whom From a specific source; -1 is from all
+ @param msgtag With a certain tag; -1 is all. */
+ int recv ( int from_whom, int msgtag );
+
+ int nrecv ( int from_whom, int msgtag );
+
+ /** Provide info on the message just received */
+ int bufinfo ( int buf_id, int *len, int *tag, int *from );
+
+ /** @name Pack Functions
+
+ In the following pack() functions, there are some common themes.
+ First, each stuffs some data into a buffer to be sent. The
+ nitem parameter is just a count of the number of items. The
+ stride parameter specifies *which* items to pack. 1 implies
+ all, 2 would be every 2nd item, 3 is every 3rd item, etc.
+
+ The return value is user defined. It should be standardized,
+ but I'll do that later.
+ */
+ //@{
+
+ /// Pack some bytes
+ int pack ( const char *bytes, int nitem, int stride = 1 );
+ /// float
+ int pack ( const float *f, int nitem, int stride = 1 );
+ /// double
+ int pack ( const double *d, int nitem, int stride = 1 );
+ /// int
+ int pack ( const int *i, int nitem, int stride = 1 );
+ /// unsigned int
+ int pack ( const unsigned int *ui, int nitem, int stride = 1 );
+ /// short
+ int pack ( const short *sh, int nitem, int stride = 1 );
+ /// unsigned short
+ int pack ( const unsigned short *ush, int nitem, int stride = 1 );
+ /// long
+ int pack ( const long *l, int nitem, int stride = 1 );
+ /// unsigned long
+ int pack ( const unsigned long *ul, int nitem, int stride = 1 );
+ /// Pack a NULL-terminated string
+ int pack ( const char *string );
+
+ //@}
+
+ /** @name Unpack Functions
+
+ These unpack functions unpack data packed with the pack()
+ functions. See the pack() functions for more details.
+
+ */
+ //@{
+
+ /// Unpack some bytes
+ int unpack ( char *bytes, int nitem, int stride = 1 );
+ /// float
+ int unpack ( float *f, int nitem, int stride = 1 );
+ /// double
+ int unpack ( double *d, int nitem, int stride = 1 );
+ /// int
+ int unpack ( int *i, int nitem, int stride = 1 );
+ /// unsigned int
+ int unpack ( unsigned int *ui, int nitem, int stride = 1 );
+ /// short
+ int unpack ( short *sh, int nitem, int stride = 1 );
+ /// unsigned short
+ int unpack ( unsigned short *ush, int nitem, int stride = 1 );
+ /// long
+ int unpack ( long *l, int nitem, int stride = 1 );
+ /// unsigned long
+ int unpack ( unsigned long *ul, int nitem, int stride = 1 );
+ /// Unpack a NULL-terminated string
+ int unpack ( char *string );
+ //@}
+ //@}
+
+ /** The non-blocking recv() functions */
+ public:
+ int recv_all( int from_whom, int msgtag ); // returns the number of new buffers
+ int setrbuf(int bid); // switch the active receive buffer
+ // return the old active buf_id
+ int freebuf(int bid); // free the receive buffer.
+ MWList<void> * recv_buffers(); // return the recv_buf_list
+ int next_buf(); // advance the active buffer to the next valid buffer
+ // in the recv_buf_list.
+
+};
+#endif
+
diff --git a/MW/src/RMComm/MW-Independent/Makefile.in b/MW/src/RMComm/MW-Independent/Makefile.in
new file mode 100644
index 0000000..6c28e83
--- /dev/null
+++ b/MW/src/RMComm/MW-Independent/Makefile.in
@@ -0,0 +1,122 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+ENABLE_MWINDEPENDENT= @ENABLE_MWINDEPENDENT@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(DEBUG_CHECKER) $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+
+# Subdirectories
+SUBDIRS =
+
+# Libraries to be built, and dependent source files
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+LIBRARIES = libMWRC_indp.a
+else
+LIBRARIES =
+endif
+libMWRC_indp_a_SOURCES = MWIndRC.C
+libMWRC_indp_a_LIBADD = MWIndRC.o
+libMWRC_indp_a_DEPENDENCIES = MWIndRC.o
+libMWRC_indp_a_OBJECTS =
+
+INCLUDES = -g -I. -I.. -I../.. -I$(CONDOR_DIR)/include $(MEASURE_DEFN)
+INCLUDEFILES = MWIndRC.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+
+libMWRC_indp.a: $(libMWRC_indp_a_OBJECTS) $(libMWRC_indp_a_DEPENDENCIES)
+ -rm -f libMWRC_indp.a
+ $(AR) cru libMWRC_indp.a $(libMWRC_indp_a_OBJECTS) $(libMWRC_indp_a_LIBADD)
+ $(RANLIB) libMWRC_indp.a
+ cp libMWRC_indp.a $(MW_LIBDIR)
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
+
diff --git a/MW/src/RMComm/MW-Socket/MWSocketRC.C b/MW/src/RMComm/MW-Socket/MWSocketRC.C
new file mode 100644
index 0000000..308b777
--- /dev/null
+++ b/MW/src/RMComm/MW-Socket/MWSocketRC.C
@@ -0,0 +1,2114 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifdef WINDOWS
+
+#define FD_SETSIZE 1024
+#include <winsock2.h>
+#define close closesocket
+#define popen _popen
+#define pclose _pclose
+#define sleep _sleep
+#define EINTR WSAEINTR
+#define errno WSAGetLastError()
+#else
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+#include <netinet/in.h>
+
+#endif
+
+#include <ctype.h>
+
+#ifdef __svr4__
+#include <strings.h>
+#endif
+
+#include "MWSocketRC.h"
+#include <MWDriver.h>
+#include <MWWorkerID.h>
+#include <MWTask.h>
+#include <MWWorker.h>
+#include <MWSystem.h>
+
+#define MAX_TCP_BUFFER (64*1024)
+
+#ifdef SOCKET_MASTER
+MWRMComm * MWDriver::RMC = new MWSocketRC( TRUE, 0 );
+MWRMComm * MWTask::RMC = MWDriver::RMC;
+MWRMComm * MWWorker::RMC = NULL;
+#else
+MWRMComm * MWWorker::RMC = new MWSocketRC ( FALSE, 0 );
+MWRMComm * MWTask::RMC = MWWorker::RMC;
+MWRMComm * MWDriver::RMC = NULL;
+#endif
+
+extern int *MW_exec_class_num_workers;
+
+#ifdef USE_POLL
+#include <sys/poll.h>
+#endif
+
+/*
+ * Instead of ifdef'ing this for platforms that don't have it
+ * we have our own, so that we are always compiling it, and
+ * always know that it is correct.
+ */
+
+char *mw_inet_ntop( int family, const void *addrptr, char *strptr, size_t len)
+{
+ const u_char *p = ( const u_char *) addrptr;
+
+ if ( family == AF_INET )
+ {
+ char temp[16];
+ sprintf( temp, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ strcpy( strptr, temp);
+ return(strptr);
+ }
+ return( NULL);
+}
+
+int cyclePosition = 0;
+bool toBlock = TRUE;
+static bool timedOut;
+static int timeOutSocket = -1;
+
+#ifndef WINDOWS
+void alarmed(int signo) {
+ timedOut = true;
+ close(timeOutSocket);
+ write(1, "Alarm timed out\n", 17);
+}
+
+void brokenPipeHandler ( int sig )
+{
+ MWprintf ( 10, "Got the signal %d\n", sig );
+ signal ( SIGPIPE, brokenPipeHandler );
+ return;
+}
+#endif
+
+MWSocketRC::MWSocketRC ( bool master, int id )
+{
+ isMaster = master;
+ if ( isMaster )
+ socketId = 8997;
+ else
+ socketId = id;
+ strcpy ( control_directory, "submit_files" );
+ strcpy ( worker_number_file, "worker_number_file" );
+
+#ifdef WINDOWS
+ WORD version = MAKEWORD(2,2);
+ WSADATA d;
+ WSAStartup(version, &d);
+#endif
+
+ //by jae
+ pre_send_done = false;
+ m_poll_timeout = 5; // Default value is 5 sec
+}
+
+MWSocketRC::~MWSocketRC ( )
+{
+ delete []hostadd_reqs;
+ delete []socketWorkers;
+}
+
+int
+MWSocketRC::setup ( int argc, char *argv[], int *mytid, int *mastertid )
+{
+ struct hostent *hptr;
+
+ char **ptr;
+ char str[16];
+
+ subId = 0;
+
+ if ( isMaster == TRUE )
+ {
+ turnNo = 0;
+ *mytid = socketId;
+ *mastertid = socketId;
+ hostadd_reqs = NULL;
+ masterId = socketId;
+ masterSocket = 8997;
+
+ char myname[256];
+ MWSystem::gethostname(myname, 256);
+
+ if ( (hptr = gethostbyname(myname)) == NULL)
+ {
+ MWprintf ( 10, "Cannot do a gethostbyname: errno %d\n", errno );
+ ::exit(1);
+ }
+
+ ptr = hptr->h_addr_list;
+ strcpy ( masterAddress, ((char *)mw_inet_ntop(hptr->h_addrtype, *ptr, str, sizeof(str))) );
+
+ socketComm = creatAndBind ( masterSocket );
+
+ if ( listen( socketComm, 50 ) < 0 )
+ {
+ MWprintf ( 10, "Listen failed: errno %d\n", errno );
+ close ( socketComm );
+ ::exit(1);
+ }
+
+ FD_ZERO ( &rfds );
+ FD_SET ( socketComm, &rfds );
+
+ for ( int i = 0; i < 4096; i++ )
+ {
+ reverseMap[i] = -1;
+ }
+
+ // If the directory doesn't exist make it, ignoring the error
+ // if it does exist
+
+ char buf[256];
+ sprintf(buf, "mkdir %s", control_directory);
+ system(buf);
+
+ // Windows doesn't raise signals on broken pipe writes
+#ifndef WINDOWS
+ signal ( SIGPIPE, brokenPipeHandler );
+#endif
+ }
+ else
+ {
+ struct sockaddr_in myAddr;
+
+ *mastertid = atoi ( argv[2] );
+ socketId = atoi ( argv[1] );
+ masterSocket = atoi ( argv[3] );
+ *mytid = socketId;
+ strcpy ( masterAddress, argv[4] );
+ socketComm = creatAndBind ( 0 );
+
+ memset(&myAddr, 0, sizeof(myAddr));
+ myAddr.sin_family = AF_INET;
+ (myAddr.sin_addr).s_addr = inet_addr(masterAddress);
+ myAddr.sin_port = htons(masterSocket);
+
+ int retryCount = 0;
+
+tryAgain:
+ if ( connect ( socketComm, (struct sockaddr *)&myAddr, sizeof(myAddr) ) < 0 )
+ {
+ MWprintf ( 10, "Connect failed with the master: errno %d\n", errno );
+ if (retryCount++ < 24) {
+ sleep(5);
+ goto tryAgain;
+ }
+ ::exit(1);
+ }
+ MWprintf ( 10, "Connect succeeded\n");
+
+ char buf[sizeof(int)];
+ marshall_int ( socketId, buf );
+ if ( finalSend ( socketComm, buf, sizeof(int), 0 ) < 0 )
+ {
+ MWprintf ( 10, "Initial Send failed to the master: errno %d\n", errno );
+ ::exit(1);
+ }
+ }
+
+ return 0;
+}
+
+void
+MWSocketRC::exit ( int retval )
+{
+ if ( isMaster )
+ {
+ killWorkers ( );
+ closeSockets ( );
+ }else {
+ // by jae
+ ::exit ( retval );
+ }
+}
+
+int
+MWSocketRC::init_beginning_workers ( int *nworkers, MWWorkerID ***workers )
+{
+ int i;
+
+ MWprintf ( 10, "In MWSocketRC::init_beginning_workers()\n");
+ hostadd_reqs = new int[num_arches];
+
+ for ( i = 0; i < num_arches; i++ )
+ {
+ hostadd_reqs[i] = 0;
+ }
+
+
+ socketWorkers = new SocketWorker[target_num_workers];
+ for ( i = 0; i < target_num_workers; i++ )
+ {
+ socketWorkers[i].state = MWSocket_FREE;
+ socketWorkers[i].socket = -1;
+ }
+ *nworkers = 0;
+
+ return 0;
+}
+
+int
+MWSocketRC::restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg )
+{
+ return init_beginning_workers ( nworkers, workers );
+}
+
+void
+MWSocketRC::who ( int *wh )
+{
+ unpack ( wh, 1, 1 );
+}
+
+int
+MWSocketRC::start_worker ( MWWorkerID *w )
+{
+ w->set_id1 ( whomRecv );
+ w->set_id2 ( whomRecv );
+ w->set_arch ( socketWorkers[whomRecv].arch );
+ w->set_exec_class ( socketWorkers[whomRecv].exec_class );
+
+ hostadd_reqs[socketWorkers[whomRecv].exec_class]--;
+
+ return 0;
+}
+
+int
+MWSocketRC::removeWorker ( MWWorkerID *w )
+{
+ // char buf[_POSIX_PATH_MAX];
+
+ if ( !w )
+ {
+ MWprintf (10, "Worker ID cannot be NULL in removeWorker\n" );
+ return -1;
+ }
+
+ return killWorker ( w->get_id1() );
+}
+
+int
+MWSocketRC::hostaddlogic ( int *numworkers )
+{
+ /* This awfully complex function determines the conditions
+ under which it being called, and then calls condor_submit
+ asking for the correct number of hosts.
+
+ - num_workers - an array of size exec_classes that contains
+ the number of workers in each arch class.
+ - hostadd_reqs: The number of outstanding HOSTADDs out there
+ - target_num_workers: Set by the user...
+ */
+
+ MWprintf ( 10, "In hostaddlogic \n" );
+ if ( !hostadd_reqs )
+ {
+ /* if this doesn't exist yet, we won't do anything */
+ return 0;
+ }
+
+ /* number of hosts to ask for at a time. The idea is that we'll
+ have double this outstanding at a time - and this amounts
+ to 12 for 1, 2, or 3 arch classes. */
+ int i;
+ int *sorted_order = new int [exec_classes];
+ int cur;
+ int req;
+ sort_exec_class_ratio ( sorted_order );
+ int status;
+
+ MWprintf ( 60, "hal: target: %d\n", target_num_workers );
+
+ int HOSTINC = hostinc_;
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ cur = sorted_order[i];
+ MWprintf(60, "hal: cur: %d, num_workers: %d, hostadd_reqs: %d, target: %d\n", cur,
+ MW_exec_class_num_workers[cur], hostadd_reqs[cur],
+ exec_class_target_num_workers[cur]);
+ if ( MW_exec_class_num_workers[cur] + hostadd_reqs[cur] >= exec_class_target_num_workers[cur] ) continue;
+ if ( hostadd_reqs[cur] > 0 ) continue;
+ if ( exec_class_target_num_workers[cur] - ( MW_exec_class_num_workers[cur] + hostadd_reqs[cur] ) > HOSTINC )
+ req = HOSTINC;
+ else
+ req = exec_class_target_num_workers[cur] - ( MW_exec_class_num_workers[cur] + hostadd_reqs[cur] );
+ status = do_spawn ( req, cur );
+ if ( status > 0 )
+ {
+ MWprintf ( 10, "Added %d workers of exec_class %d\n", req, i );
+ hostadd_reqs[cur] += status;
+ }
+ else
+ {
+ MWprintf ( 10, "ERROR!! Failed to submit workers of exec_class %d\n", i );
+ }
+ }
+
+ delete [] sorted_order;
+ return 0;
+}
+
+void
+MWSocketRC::sort_exec_class_ratio ( int *temp )
+{
+ int i, j;
+ double ii, jj;
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ temp[i] = i;
+ }
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ for ( j = i + 1; j < exec_classes; j++ )
+ {
+ ii = ((double)MW_exec_class_num_workers[temp[i]]) / exec_class_target_num_workers[temp[i]];
+ jj = ((double)MW_exec_class_num_workers[temp[j]]) / exec_class_target_num_workers[temp[j]];
+ if ( jj > ii )
+ {
+ int temp = j;
+ j = i;
+ i = temp;
+ }
+ }
+ }
+ return;
+}
+
+
+int
+MWSocketRC::read_RMstate ( FILE *myfp )
+{
+ char temp[_POSIX_PATH_MAX];
+ int cluster, subcluster;
+ FILE *fp;
+
+ sprintf ( temp, "%s/%s", control_directory, worker_number_file );
+ fp = fopen ( temp, "r" );
+ if ( fp )
+ {
+ while ( fscanf ( fp, "%d %d", &cluster, &subcluster ) > 0 )
+ {
+ char condor_cmd[ 3 * _POSIX_PATH_MAX];
+ sprintf ( condor_cmd, "condor_rm %d.%d", cluster, subcluster );
+ if ( system ( condor_cmd ) < 0 )
+ {
+ MWprintf ( 10, "Couldn't remove the job %d.%d\n", cluster, subcluster );
+ }
+ }
+ fclose ( fp );
+ }
+ return 0;
+}
+
+int
+MWSocketRC::write_RMstate ( FILE *myfp )
+{
+ FILE *fp;
+ char temp[_POSIX_PATH_MAX];
+ char cmd[3 * _POSIX_PATH_MAX];
+
+ sprintf ( temp, "%s/%s", control_directory, worker_number_file );
+#ifdef WINDOWS
+ sprintf ( cmd, "copy temp %s\\%s", control_directory, worker_number_file );
+ printf("Before rename cmd is %s\n", cmd);
+#else
+ sprintf ( cmd, "/bin/mv temp %s/%s", control_directory, worker_number_file );
+#endif
+ fp = fopen ( "temp", "w" );
+ if ( !fp )
+ {
+ MWprintf ( 10, "DANGER!!, MW was not able to write into file temp\n" );
+ return -1;
+ }
+
+ for ( int i = 0; i < target_num_workers; i++ )
+ {
+ if ( socketWorkers[i].state == MWSocket_FREE )
+ continue;
+
+ fprintf ( fp, "%d %d\n", socketWorkers[i].cId, socketWorkers[i].subcId );
+ }
+
+ fclose ( fp );
+
+ if ( system ( cmd ) < 0 )
+ {
+ MWprintf ( 10, "Couldn't mv file temp into the actual file\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+char*
+MWSocketRC::process_executable_name ( char *exec, int ex_cl, int ar_cl )
+{
+ int i;
+ char newstring[_POSIX_PATH_MAX];
+ char arch[100], opsys[100];
+ char *index;
+ char *req = arch_class_attributes[ar_cl];
+ char *newexec = new char[_POSIX_PATH_MAX];
+ char exe[4 * _POSIX_PATH_MAX];
+ strcpy ( newstring, req );
+ sprintf ( newexec, "mw_exec%d", ex_cl );
+
+
+ MWprintf(20, "MWSocketRC::process_executable_name %s %d %d\n", exec, ex_cl, ar_cl);
+ // Use unsigned int to make gcc -Wall happy
+
+ // Change everything to capitals, except in cases...
+ // 1) u, x newstring[i-1] == '4' ?
+ // 2) k == 'u' || k == 'x' and newstring[i+1] == '8' (handles arch==x86_64)
+ for ( unsigned ii = 0; ii < strlen ( newstring ); ii++ )
+ {
+ int k = newstring[ii];
+ if( ! ( ( k == 'u' || k == 'x' ) &&
+ ( (newstring[ii-1] == '4') || (newstring[ii+1] == '8') ) ) )
+ {
+ k = toupper(k);
+ }
+ newstring[ii] = k;
+ }
+
+ i = 0;
+ index = strstr ( newstring, "OPSYS" );
+
+ if (index == NULL) {
+ MWprintf(10, "ERROR: OPSYS not specified in add_executable requirements string\n");
+ MWprintf(10, "newstring is %s\n", newstring);
+ exit(-1);
+ }
+
+ index += 5;
+ while ( *index == ' ' || *index == '=' || *index == '"' || *index == '\\' ) index++;
+ while ( *index && *index != ')' && *index != '"' && *index != '\\' ) opsys[i++] = *index++;
+ opsys[i] = '\0';
+
+ i = 0;
+ index = strstr ( newstring, "ARCH" );
+ if (index == NULL) {
+ MWprintf(10, "ERROR: ARCH not specified in add_executable requirements string\n");
+ exit(-1);
+ }
+ index += 4;
+ while ( *index == ' ' || *index == '=' || *index == '"' || *index == '\\' ) index++;
+ while ( *index && *index != ')' && *index != '"' && *index != '\\' ) arch[i++] = *index++;
+ arch[i] = '\0';
+
+ sprintf ( newexec, "%s.%s.%s.exe", newexec, opsys, arch );
+ unlink ( newexec );
+
+ MWprintf ( 10, "Making a link from %s to %s\n", exec, newexec );
+#if defined(WINDOWS) || defined(CYGWIN)
+ sprintf ( exe, "copy %s %s", exec, newexec );
+#else
+ sprintf ( exe, "ln -s %s %s", exec, newexec );
+#endif
+ system ( exe );
+
+ return newexec;
+}
+
+int
+MWSocketRC::initsend ( int useless )
+{
+ messageSize = 0;
+ pre_send_done = false;
+ return 0;
+}
+
+int
+MWSocketRC::send ( int toWhom, int msgtag )
+{
+ char buffer[3*sizeof(int)];
+ int retVal;
+ int sendingSocket;
+
+ if ( isMaster )
+ sendingSocket = socketWorkers[toWhom].socket;
+ else {
+ // by jae
+ // Worker
+ if( pre_send_done ) {
+ return 0;
+ }
+ sendingSocket = socketComm;
+ }
+
+ marshall_int ( msgtag, buffer );
+ marshall_int ( messageSize, buffer + sizeof(msgtag) );
+ marshall_int ( socketId, buffer + sizeof(msgtag) + sizeof(messageSize) );
+
+ retVal = finalSend ( sendingSocket, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 )
+ return retVal;
+ retVal = finalSend ( sendingSocket, sendBuffer, messageSize, 0 );
+
+ return retVal;
+}
+
+//by jae
+int
+MWSocketRC::pre_send (int msgtag )
+{
+ if( pre_send_done ) {
+ return 0;
+ }
+
+ if ( isMaster ) {
+ MWprintf ( 10, "ERROR: pre_send is not implemented for Master\n");
+ return -1;
+ }
+
+ int retVal = send(0, msgtag);
+ pre_send_done = true;
+
+ return retVal;
+}
+
+int
+MWSocketRC::finalSend ( int s, char *buf, size_t len, int flags )
+{
+#ifdef __svr4__
+ ssize_t retVal;
+#else
+ int retVal;
+#endif
+
+
+ do
+ {
+ retVal = ::send ( s, buf, len, flags );
+ } while ( (retVal == -1) && (errno == EINTR ));
+
+ if (retVal == -1) {
+ MWprintf(10, "FinalSend::send returned -1 errno %d\n", errno);
+ return -1;
+ }
+
+ if ( retVal < (int)len ) // Make gcc -Wall happy
+ {
+ return finalSend(s, buf + retVal, len - retVal, flags);
+ }
+
+ return retVal;
+}
+
+int
+MWSocketRC::recv ( int fromWhom, int msgtag )
+{
+ recvPointer = 0;
+ if ( isMaster )
+ return masterrecv ( fromWhom, msgtag );
+ else
+ return workerrecv ( fromWhom, msgtag );
+}
+
+int
+MWSocketRC::masterrecv ( int fromWhom, int msgtag )
+{
+ char buffer[ 3 * sizeof(int) ];
+
+ // if fromWhom == -1, receive from anyone
+ if ( fromWhom <= 0 ) {
+ return masterrecvany();
+ }
+
+ // Otherwise, from one particular someone
+ {
+ // to recv from someone.
+ int retVal = finalRecv ( socketWorkers[fromWhom].socket, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 )
+ return retVal;
+
+ while ( msgtag > 0 && unmarshall_int ( buffer ) != msgtag )
+ {
+ retVal = finalRecv ( socketWorkers[fromWhom].socket, recvBuffer,
+ unmarshall_int ( &buffer[sizeof(int)] ), 0 );
+ if ( retVal < 0 )
+ return retVal;
+
+ retVal = finalRecv ( socketWorkers[fromWhom].socket, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 )
+ return retVal;
+ }
+
+ retVal = finalRecv ( socketWorkers[fromWhom].socket, recvBuffer,
+ unmarshall_int ( &buffer[sizeof(int)] ), 0 );
+
+ recvSize = retVal;
+ msgTag = unmarshall_int ( buffer );
+ whomRecv = fromWhom;
+ return retVal;
+ }
+}
+
+#ifdef USE_POLL
+
+int
+MWSocketRC::masterrecvany()
+{
+ struct pollfd pollfds[target_num_workers + 1];
+
+ int index = 0;
+ for (int i = 0; i < target_num_workers; i++) {
+ if (socketWorkers[i].socket > 0) {
+ if( socketWorkers[i].state == MWSocket_THREAD ) {
+ // skip sockets attacehd to threads
+ continue;
+ }
+ pollfds[index].fd = socketWorkers[i].socket;
+ pollfds[index].events = POLLIN;
+ index++;
+ }
+ }
+
+ pollfds[index].fd = socketComm;
+ pollfds[index].events = POLLIN;
+
+ index++;
+
+ int r;
+ do {
+ errno = 0;
+ //jae
+ //r = poll(pollfds, index, -1);
+ r = poll(pollfds, index, m_poll_timeout*1000);
+ } while (errno == EINTR);
+
+ if (r == -1) {
+ MWprintf(10, "poll returned -1, errno = %d\n", errno);
+ return -1;
+ }
+
+ //by jae
+ if( r == 0 ) {
+ // timeout
+ MWprintf(10, "poll timeout\n");
+ return -1;
+ }
+
+ // For all the non-accept'ing sockets
+ for (int j = 0; j < index - 1; j++) {
+ if (pollfds[j].revents & POLLHUP) {
+ // It doesn't look like linux returns this on a socket, but
+ // just in case it does...
+ return handle_killed_worker(reverseMap[pollfds[j].fd]);
+ }
+ if (pollfds[j].revents & POLLIN) {
+ return handle_finished_worker(reverseMap[pollfds[j].fd]);
+ }
+
+ if (pollfds[j].revents != 0) {
+ MWprintf(10, "Unexpected return from poll for fd %d: %x\n", pollfds[j].fd, pollfds[j].revents);
+ }
+ }
+
+ if (pollfds[index - 1].revents) {
+ return handle_starting_worker();
+ }
+
+
+ MWprintf(10, "USE_POLL::masterrecvany shouldn't get here\n");
+ return -1;
+
+}
+#endif
+
+#ifndef USE_POLL
+int
+MWSocketRC::masterrecvany()
+{
+
+ int retVal;
+ int i;
+ FD_ZERO ( &rfds );
+ FD_SET ( socketComm, &rfds );
+
+ for ( i = 0; i < FD_SETSIZE; i++ )
+ {
+ int worker_id = reverseMap[i];
+ if ( worker_id >= 0 )
+ {
+ if( socketWorkers[worker_id].state == MWSocket_THREAD ) {
+ // skip sockets attacehd to threads
+ continue;
+ }
+ FD_SET ( i, &rfds );
+ }
+ }
+
+
+ struct timeval timeout;
+ timeout.tv_usec = 0;
+ timeout.tv_sec = m_poll_timeout;
+
+ do
+ {
+ retVal = select ( FD_SETSIZE, &rfds, NULL, NULL, &timeout );
+ } while ((retVal == -1) && ( errno == EINTR ));
+
+ //by jae
+ if( retVal == 0 ) {
+ // timeout
+ MWprintf(10, "select timeout\n");
+ return -1;
+ }
+
+ if ( retVal < 0 )
+ {
+ MWprintf ( 10, "Select returned -1, errno = %d\n", errno );
+ //exit(1);
+ // don't need to exit if select returns zero, just remove the worker that went down
+ fd_set temprfds;
+ FD_ZERO ( &rfds );
+ for ( i = 0; i < FD_SETSIZE; i++ )
+ {
+ int worker_id = reverseMap[i];
+ if ( worker_id >= 0 )
+ {
+ if( socketWorkers[worker_id].state == MWSocket_THREAD ) {
+ // skip sockets attacehd to threads
+ continue;
+ }
+
+ struct timeval zero;
+ zero.tv_sec=0;
+ zero.tv_usec=0;
+ FD_ZERO ( &temprfds );
+ FD_SET ( i, &temprfds );
+ int selRet;
+ do
+ {
+ selRet = select ( FD_SETSIZE, &temprfds, NULL, NULL, &zero );
+ } while ( errno == EINTR );
+ if( selRet < 0 )
+ {
+ int len = handle_killed_worker ( reverseMap[i] );
+ reverseMap[i] = -1;
+ return len;
+ }
+ }
+ }
+ }
+ if ( retVal == 0 )
+ {
+ MWprintf ( 10, "Unexpected 0 return from select, exitting\n" );
+ exit(1);
+ }
+
+ return checkSockets ( );
+}
+
+#endif
+int
+MWSocketRC::workerrecv ( int fromWhom, int msgtag )
+{
+ // int temp;
+ int retVal;
+ char buffer [ 3 * sizeof(int) ];
+
+ retVal = finalRecv ( socketComm, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 )
+ return retVal;
+
+ while ( msgtag > 0 && unmarshall_int( buffer ) != msgtag )
+ {
+ retVal = finalRecv ( socketComm, recvBuffer, unmarshall_int ( &buffer[sizeof(int)] ), 0 );
+ if ( retVal < 0 )
+ return retVal;
+
+ retVal = finalRecv ( socketComm, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 )
+ return retVal;
+ }
+
+ retVal = finalRecv ( socketComm, recvBuffer, unmarshall_int( &buffer[sizeof(int)] ), 0 );
+
+ recvSize = retVal;
+ msgTag = unmarshall_int ( buffer );
+ whomRecv = fromWhom;
+ return retVal;
+}
+
+int
+MWSocketRC::nrecv ( int fromWhom, int msgtag )
+{
+ recvPointer = 0;
+ if( isMaster )
+ {
+ MWprintf(10, "Master should not call this\n");
+ exit(-1);
+ }
+ int retVal;
+ char buffer [ 3 * sizeof(int) ];
+
+ retVal = nfinalRecv ( socketComm, buffer, 3 * sizeof(int), 0 );
+ if ( retVal == -2 ) // nothing in the socket, return from call
+ {
+ recvSize = 0;//retVal;
+ msgTag = NO_MESSAGE;
+ whomRecv = fromWhom;
+ return 0;
+ }
+ while ( msgtag > 0 && unmarshall_int( buffer ) != msgtag )
+ {
+ retVal = finalRecv ( socketComm, recvBuffer, unmarshall_int ( &buffer[sizeof(int)] ), 0 );
+ if ( retVal < 0 )
+ return retVal;
+
+ retVal = finalRecv ( socketComm, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 )
+ return retVal;
+ }
+ retVal = finalRecv ( socketComm, recvBuffer, unmarshall_int( &buffer[sizeof(int)] ), 0 );
+ recvSize = retVal;
+ msgTag = unmarshall_int ( buffer );
+ whomRecv = fromWhom;
+ return retVal;
+}
+
+int
+MWSocketRC::nfinalRecv ( int s, void *buf, size_t len, int flags )
+{
+ int retVal;
+
+ fd_set sfd;
+ FD_ZERO( &sfd );
+ FD_SET( s, &sfd );
+ struct timeval zero;
+ zero.tv_sec=0; zero.tv_usec=0;
+ int selRet = select(s+1, &sfd, NULL, NULL, &zero);
+ if( selRet == 0 )
+ return -2;
+
+ do
+ {
+ retVal = ::recv ( s, (char *)buf, len, MSG_PEEK );
+/*
+if(retVal == -1 && errno == EAGAIN){
+ fcntl(s, F_SETFL, fdflags);
+ MWprintf(51,"Nothing in socket, returning\n");
+ return -1;
+ }
+*/
+ } while ( errno == EINTR || retVal < (int)len ); // Make -Wall happy
+
+ do
+ {
+ retVal = ::recv ( s, (char *)buf, len, flags );
+ } while ((retVal == -1) && ( errno == EINTR ));
+
+ if ( retVal < (int)len ) // Make gcc -Wall happy
+ {
+ MWprintf ( 10, "Couldn't properly do a recv from socket %d: retVal = %d, errno = %d\n", s, retVal, errno );
+ return -1;
+ }
+
+ return retVal;
+}
+
+int
+MWSocketRC::finalRecv ( int s, char *b, size_t len, int flags )
+{
+ int retVal;
+
+ char *buf = (char *) b;
+
+ int total = 0;
+ retVal = 0;
+
+ timedOut = false;
+ timeOutSocket = s;
+
+ do
+ {
+
+ // First time through, these are no-ops
+ len -= retVal;
+ buf += retVal;
+
+ retVal = ::recv ( s, buf, len, flags );
+
+ if( (timedOut == true) || (retVal < 0 && errno != EINTR)) {
+ MWprintf(10, "recv returned -1: errno is %d\n", errno);
+ return -1;
+ }
+
+ if ( retVal == 0 ) return 0; // Socket closed
+
+ if (errno == EINTR) {
+ retVal = 0;
+ }
+ total += retVal;
+
+ } while (( errno == EINTR ) || (retVal < (int)len)) ;
+
+ if ( retVal < (int)len ) // Make gcc -Wall happy
+ {
+ return 0;
+ }
+
+ return total;
+}
+
+int
+MWSocketRC::creatAndBind ( int port )
+{
+ int retVal;
+ int bufSize = MAX_TCP_BUFFER;
+ struct sockaddr_in myAddr;
+
+ retVal = socket ( AF_INET, SOCK_STREAM, 0 );
+ if ( retVal < 0 )
+ {
+ MWprintf ( 10, "Couldn't open a socket errno %d\n", errno );
+ ::exit(1);
+ }
+ if ( setsockopt( retVal, SOL_SOCKET, SO_SNDBUF, (char *)&bufSize, sizeof(int)) != 0)
+ {
+ MWprintf ( 10, "Couldn't set the send buffer size: errno %d\n", errno );
+ close ( retVal );
+ ::exit(1);
+ }
+ if ( setsockopt( retVal, SOL_SOCKET, SO_RCVBUF, (char *)&bufSize, sizeof(int)) != 0)
+ {
+ MWprintf ( 10, "Couldn't set the recv buffer size: errno %d\n", errno );
+ close ( retVal );
+ ::exit(1);
+ }
+ memset(&myAddr, 0, sizeof(myAddr));
+ myAddr.sin_family = AF_INET;
+ (myAddr.sin_addr).s_addr = htonl(INADDR_ANY);
+ myAddr.sin_port = htons(port);
+
+ int range = 50; // range of ports to scan
+ int range_counter = 0;
+ while( bind( retVal, (struct sockaddr *) &myAddr, sizeof(myAddr) ) < 0 && range_counter < range)
+ {
+ //MWprintf ( 10, "Couldn't bind the socket to port: errno %d\n", errno );
+ port++;
+ myAddr.sin_port = htons(port);
+ range_counter++;
+ //close ( retVal );
+ //::exit(1);
+ }
+ if ( range_counter >= range )
+ {
+ MWprintf ( 10, "Couldn't bind the socket to port: errno %d\n", errno );
+ close ( retVal );
+ ::exit(1);
+ }
+ else
+ MWprintf ( 10, "Socket bound to port: %d\n", port );
+ if ( isMaster == TRUE )
+ masterSocket = port;
+
+ return retVal;
+}
+
+int
+MWSocketRC::checkSockets ( )
+{
+ char buf;
+ int len = 1;
+ // First we check the read list
+ for ( int i = 0; i < FD_SETSIZE; i++ )
+ {
+ if ( i == socketComm )
+ continue;
+
+ if ( FD_ISSET ( i, &rfds ) )
+ {
+ cyclePosition = i;
+ toBlock = FALSE;
+ FD_CLR ( i, &rfds );
+
+ //by jae
+ int worker_id = reverseMap[i];
+ if( worker_id >= 0 ) {
+ if( socketWorkers[worker_id].state == MWSocket_THREAD ) {
+ continue;
+ }
+ }
+
+ int retVal;
+ do
+ {
+ retVal = ::recv ( i, &buf, len, MSG_PEEK );
+ } while ( (retVal < 0) && (errno == EINTR ));
+ if ( errno != 0 )
+ {
+ len = handle_killed_worker ( reverseMap[i] );
+ reverseMap[i] = -1;
+ return len;
+ }
+ else if ( retVal <= 0 )
+ {
+ len = handle_killed_worker ( reverseMap[i] );
+ reverseMap[i] = -1;
+ return len;
+ }
+ else
+ {
+ return handle_finished_worker ( reverseMap[i] );
+ }
+ }
+ }
+
+ // Finally let us examine the socketComm.
+ if ( FD_ISSET ( socketComm, &rfds ) )
+ {
+ // someone is trying to connect to us.
+ FD_CLR ( socketComm, &rfds );
+ return handle_starting_worker ( );
+ }
+ cyclePosition = 0;
+ toBlock = TRUE;
+ return -1;
+}
+
+int
+MWSocketRC::handle_starting_worker ( )
+{
+ int temp;
+ int remote;
+ char buf[sizeof(int)];
+
+ temp = accept ( socketComm, 0, 0 );
+ if ( temp < 0 )
+ {
+ MWprintf ( 10, "Accept failed: errno %d\n", errno );
+ return -1;
+ }
+
+#ifndef WINDOWS
+ signal(SIGALRM, alarmed);
+ alarm(5);
+#endif
+ if ( finalRecv ( temp, buf, sizeof(int), 0 ) < 0 )
+ {
+ MWprintf ( 10, "First recv from the new guy failed: errno %d\n", errno );
+#ifndef WINDOWS
+ alarm(0);
+#endif
+ close ( temp );
+ return -1;
+ }
+#ifndef WINDOWS
+ alarm(0);
+#endif
+ remote = unmarshall_int ( buf );
+
+ if ( !&socketWorkers[remote] )
+ {
+ MWprintf ( 10, "How can the socket worker structure be null from a worker that is starting\n");
+ return -1;
+ }
+
+ if ( socketWorkers[remote].socket != -1 )
+ {
+ close(temp);
+
+ // What's happened here is that the worker has died and been restarted by
+ // Condor, but the socket connection hasn't gone away. This can happen!
+ // Since we don't have user-level keep-alives, if a machine's kernel panics,
+ // or loses power, it is possible for Condor to realize the machine has gone
+ // away before we do. Since we can only return one value to the higher level,
+ // we close the new socket (which will make the new worker restart again),
+ // and mark the old worker dead to the upper level.
+
+ int len = handle_killed_worker ( remote );
+ if ( reverseMap[socketWorkers[remote].socket] == remote ) // if mapping of socket to worker not already taken by another worker, invalidate
+ reverseMap[socketWorkers[remote].socket] = -1;
+ MWprintf(10, "worker %d tried to come back from eviction, killed it\n",remote);
+ return len;
+ }
+
+ socketWorkers[remote].state = MWSocket_EXECUTING;
+ socketWorkers[remote].socket = temp;
+ if ( socketWorkers[remote].socket < 0 )
+ {
+ MWprintf ( 10, "Accept failed: errno %d\n", errno );
+ return -1;
+ }
+ FD_SET ( socketWorkers[remote].socket, &rfds );
+ reverseMap[socketWorkers[remote].socket] = remote;
+
+ whomRecv = remote;
+ msgTag = MWSocketMessageTags[MWSocketHostAdd];
+ recvSize = 0;
+ return 0;
+}
+
+int
+MWSocketRC::handle_finished_worker ( int i )
+{
+ // int temp;
+ int retVal;
+ char buffer [ 3 * sizeof(int) ];
+
+ //by jae
+ if( i < 0 ) {
+ return -1;
+ }
+
+ if ( !&socketWorkers[i] )
+ {
+ MWprintf ( 10, "How can the socket worker structure be null from a worker that is executing\n");
+ return -1;
+ }
+
+ //by jae
+ if( socketWorkers[i].state == MWSocket_THREAD ) {
+ return -1;
+ }
+
+#ifndef WINDOWS
+ signal(SIGALRM, alarmed);
+ alarm(5);
+#endif
+ retVal = finalRecv ( socketWorkers[i].socket, buffer, 3 * sizeof(int), 0 );
+ if ( retVal < 0 ) {
+#ifndef WINDOWS
+ alarm(0);
+#endif
+ return retVal;
+ }
+#ifndef WINDOWS
+ alarm(0);
+#endif
+
+ if (retVal == 0) {
+ MWprintf(10, "read from worker returned 0, killing off disconnected worker\n");
+ return handle_killed_worker(i);
+ }
+ retVal = finalRecv ( socketWorkers[i].socket, recvBuffer, unmarshall_int ( &buffer[sizeof(int)] ), 0 );
+
+ recvSize = retVal;
+ msgTag = unmarshall_int ( buffer ) ;
+ whomRecv = i;
+ return retVal;
+}
+
+int
+MWSocketRC::handle_killed_worker ( int i )
+{
+ MWprintf ( 10, "A worker is killed %d\n", i );
+ //by jae
+ if( i < 0 ) {
+ return -1;
+ }
+ if ( !&socketWorkers[i] )
+ {
+ MWprintf ( 10, "How can the socket worker structure be null from a worker that is executing\n");
+ return -1;
+ }
+
+ marshall_int ( i, recvBuffer );
+ recvSize = sizeof(int);
+ msgTag = MWSocketMessageTags[MWSocketTaskExit];
+ whomRecv = i;
+
+ killWorker(i);
+ return 0;
+}
+
+int
+MWSocketRC::bufinfo ( int buf_id, int *len, int *tag, int *sending_host )
+{
+ *sending_host = whomRecv;
+ *tag = msgTag;
+ *len = recvSize;
+ return 0;
+}
+
+int
+MWSocketRC::do_spawn ( int nWorkers, int ex_cl )
+{
+ int cID = -1;
+ int i;
+
+ char sub_file[_POSIX_PATH_MAX];
+ char sub_file1[_POSIX_PATH_MAX];
+ char temp[65536];
+ char exe[_POSIX_PATH_MAX];
+ FILE *ptr;
+ char requirements[10 * _POSIX_PATH_MAX]; // 10 is max num executables
+
+ if ( nWorkers <= 0 ) return 0;
+
+ int *ids = new int[nWorkers];
+
+ sprintf( sub_file1, "submit_file.%d", subId );
+ sprintf( sub_file, "./%s/submit_file.%d", control_directory, subId++ );
+ sprintf( exe, "condor_submit ./%s/%s", control_directory, sub_file1 );
+
+
+ FILE *f = Open( sub_file, "w" );
+ if ( f == NULL )
+ {
+ MWprintf ( 10, "Couldn't open the submitfile for writing\n");
+ return -1;
+ }
+
+ int index = 0;
+ for ( i = 0; i < target_num_workers && index < nWorkers; i++ )
+ {
+ if ( socketWorkers[i].state == MWSocket_FREE )
+ {
+ ids[index++] = i;
+ }
+ }
+
+ if ( index < nWorkers )
+ {
+ MWprintf ( 10, "In MW-File hostaddlogic asking for more workers than target_num_workers\n");
+ MWprintf ( 10, "Had asked %d workers but I am adding only %d\n", nWorkers, index );
+ nWorkers = index;
+ }
+
+ fprintf ( f, "Universe = Vanilla\n");
+ fprintf( f, "Executable = mw_exec%d.$$(Opsys).$$(Arch).exe\n", ex_cl );
+
+ bool tempfirst = TRUE;
+ for ( i = 0; i < num_executables; i++ )
+ {
+ if ( worker_executables[i]->exec_class == ex_cl )
+ {
+ if ( tempfirst == TRUE )
+ {
+ sprintf ( requirements, "( ( %s ) ", arch_class_attributes[worker_executables[i]->arch_class] );
+ tempfirst = FALSE;
+ }
+ else
+ {
+ sprintf ( requirements, "%s || ( %s ) ", requirements, arch_class_attributes[worker_executables[i]->arch_class] );
+ }
+ }
+ }
+ //strcat ( requirements, "&& (Machine==\"quasar-16.biostat.wisc.edu\")");
+ strcat ( requirements, " )" );
+ for ( i = 0; i < nWorkers; i++ )
+ {
+ fprintf( f, "arguments = %d %d %d %s\n", ids[i], masterId, masterSocket, masterAddress );
+ fprintf( f, "log = %s/log_file\n", control_directory );
+
+ fprintf( f, "Output = output_file.%d\n", ids[i] );
+ fprintf( f, "Error = error_file.%d\n", ids[i] );
+
+ fprintf( f, "Requirements = %s\n ", requirements );
+
+ fprintf( f, "should_transfer_files = Yes\n");
+ fprintf( f, "when_to_transfer_output = ON_EXIT\n");
+
+ FILE *userf = Open( "worker_attributes", "r" );
+ if( userf == NULL )
+ {
+ MWprintf( 10, "No worker_attributes file, assuming Condor defaults\n" );
+ }
+ else
+ {
+ int c;
+ while( ( c = getc( userf ) ) != EOF )
+ {
+ putc( c, f );
+ }
+ Close( userf );
+ }
+
+
+ // send worker MWprintf back immediately, don't wait
+ // for worker exit. May want to turn this off for
+ // better performance, but this is really handy for debugging
+
+ // This causes windows clients to hang, so leave off by default
+ //fprintf( f, "stream_output = true\n");
+ //fprintf( f, "stream_error = true\n");
+
+ // Have Condor give us workers sorted by MIPS
+ fprintf( f, "rank = Mips\n");
+
+ // If a job starts, then exits before connecting to the
+ // socket master, we want condor to restart the job.
+ // otherwise, the master doen't know the job has left
+ // the queue, and will wait indefinitely for it to start
+ // only need this for Socket
+ fprintf( f, "on_exit_remove = false\n");
+ fprintf( f, "Queue\n" );
+ }
+ fclose( f );
+
+ MWprintf (10, "About to call condor_submit %s\n", exe);
+ ptr = popen ( exe, "r" );
+ if ( ptr != NULL )
+ {
+ while ( fscanf(ptr, "%s", temp ) >= 0 )
+ {
+
+ if ( strcmp ( temp, "cluster" ) == 0 )
+ {
+
+ fscanf( ptr, "%s", temp );
+ cID = atoi ( temp );
+ MWprintf ( 10, "Spawned to cluster %d\n", cID );
+ break;
+ }
+ }
+ if ( ptr ) pclose ( ptr );
+ for ( i = 0; i < nWorkers; i++ )
+ {
+ int tempp = ids[i];
+ socketWorkers[tempp].state = MWSocket_SUBMITTED;
+ socketWorkers[tempp].cId = cID;
+ socketWorkers[tempp].subcId = i;
+ socketWorkers[tempp].arch = -1;
+ socketWorkers[tempp].socket = -1;
+ socketWorkers[tempp].exec_class = ex_cl;
+ }
+ }
+ else
+ {
+ MWprintf ( 10, "Couldn't popen in FileRC\n");
+ return -1;
+ }
+
+ delete []ids;
+ write_RMstate ( NULL );
+ return nWorkers;
+}
+
+int
+MWSocketRC::pack ( const char *bytes, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(char) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(char), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride;
+ for ( int i = 0; i < nitem; i++ )
+ {
+ memcpy ( &sendBuffer[messageSize], &(bytes [ i * stride ]), sizeof(char) );
+ messageSize += sizeof(char);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const float *f, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(float) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(float), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(float);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_float ( f[ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(float);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const double *d, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(double) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(double), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(double);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_double ( d [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(double);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const int *ii, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(int) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(int), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(int);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_int ( ii [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(int);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const unsigned int *ui, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(unsigned int) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(unsigned int), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+
+ bytes_packed_ += nitem / stride * sizeof(unsigned int);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_uint ( ui [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(unsigned int);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const short *sh, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(short) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(short), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(short);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_short ( sh [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(short);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const unsigned short *us, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(unsigned short) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(unsigned short), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(unsigned short);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_ushort ( us [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(unsigned short);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const long *l, int nitem, int stride )
+{
+
+ if ( messageSize + nitem * sizeof(long) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(long), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(long);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_long ( l [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(long);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const unsigned long *ul, int nitem, int stride )
+{
+ if ( messageSize + nitem * sizeof(unsigned long) > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + nitem * sizeof(unsigned long), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += nitem / stride * sizeof(unsigned long);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ marshall_ulong ( ul [ i * stride ], &sendBuffer[messageSize] );
+ messageSize += sizeof(unsigned long);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::pack ( const char *str )
+{
+ int len = strlen ( str );
+
+ if ( messageSize + sizeof(int) * len > MWSOCKET_MAX_MSG_SIZE )
+ {
+ MWprintf ( 10, "ERROR: Maximum Message size exceeded, (%d > %d), cannot pack\n",
+ messageSize + len * sizeof(int), MWSOCKET_MAX_MSG_SIZE);
+ return -1;
+ }
+
+ bytes_packed_ += strlen(str);
+ marshall_int ( len, &sendBuffer[messageSize] );
+ messageSize += sizeof(int);
+ memcpy ( &sendBuffer[messageSize], str, len );
+ messageSize += len;
+
+ return 0;
+}
+
+// by jae
+// Send raw data directly
+int MWSocketRC::raw_pack( char* buf, int len )
+{
+ // Currently, this function works only for Worker
+ if( isMaster ) {
+ MWprintf ( 10, "ERROR: raw_pack is not implemented for Master\n");
+ return -1;
+ }
+
+ return finalSend ( socketComm, buf, len, 0 );
+}
+
+void MWSocketRC::thread_start(int worker_id)
+{
+ socketWorkers[worker_id].state = MWSocket_THREAD;
+}
+
+void MWSocketRC::thread_stop(int worker_id)
+{
+ if( socketWorkers[worker_id].state == MWSocket_THREAD ) {
+ socketWorkers[worker_id].state = MWSocket_EXECUTING;
+ }
+}
+
+/// Read raw data from Worker ID
+int MWSocketRC::raw_unpack( int from_whom, char* buf, int len )
+{
+ if( !isMaster ) {
+ MWprintf ( 10, "ERROR: raw_unpack is not implemented for Worker\n");
+ return -1;
+ }
+ if ( from_whom < 0 ) {
+ MWprintf ( 10, "ERROR: raw_unpack has invalid Worker ID\n");
+ return -1;
+ }
+
+ return finalRecv ( socketWorkers[from_whom].socket, buf, len, 0 );
+}
+
+int
+MWSocketRC::unpack ( char *bytes, int nitem, int stride )
+{
+ if ( int(recvPointer + nitem * sizeof(char)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(char);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ memcpy ( &(bytes [ i * stride ]), &recvBuffer[recvPointer], sizeof(char) );
+ recvPointer += sizeof(char);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( float *f, int nitem, int stride )
+{
+ if ( int(recvPointer + nitem * sizeof(float)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(float);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ f [ i * stride ] = unmarshall_float ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(float);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( double *d, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(double)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(double);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ d [ i * stride ] = unmarshall_double ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(double);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( int *ii, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(int)) > recvSize ) // Make gcc -Wall happy
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(int);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ ii [ i * stride ] = unmarshall_int ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(int);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( unsigned int *ui, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(unsigned int)) > recvSize ) // Make gcc -Wall happy
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned int);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ ui [ i * stride ] = unmarshall_uint ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(unsigned int);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( short *sh, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(short)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(short);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ sh [ i * stride ] = unmarshall_short ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(short);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( unsigned short *us, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(unsigned short)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned short);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ us [ i * stride ] = unmarshall_ushort ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(unsigned short);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( long *l, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(long)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(long);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ l [ i * stride ] = unmarshall_long ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(long);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( unsigned long *ul, int nitem, int stride )
+{
+ if ( int (recvPointer + nitem * sizeof(unsigned long)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned long);
+ for ( int i = 0; i < nitem; i++ )
+ {
+ ul [ i * stride ] = unmarshall_ulong ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(unsigned long);
+ }
+
+ return 0;
+}
+
+int
+MWSocketRC::unpack ( char *str )
+{
+ int len;
+
+ if ( int (recvPointer + sizeof(int)) > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ len = unmarshall_int ( &recvBuffer[recvPointer] );
+ recvPointer += sizeof(int);
+
+ if ( recvPointer + len > recvSize )
+ {
+ MWprintf ( 10, "ERROR: You can't unpack more than what's received\n");
+ return -1;
+ }
+
+ memcpy ( str, &recvBuffer[recvPointer], len );
+ str[len] = '\0';
+ recvPointer += len;
+
+ bytes_unpacked_ += strlen(str);
+
+ return 0;
+}
+
+int
+MWSocketRC::killWorkers ( )
+{
+ for ( int i = 0; i < target_num_workers; i++ )
+ {
+ if ( socketWorkers[i].state == MWSocket_SUBMITTED || socketWorkers[i].state == MWSocket_EXECUTING || socketWorkers[i].state == MWSocket_THREAD)
+ {
+ char exe[ 8 * _POSIX_PATH_MAX];
+
+ sprintf ( exe, "condor_rm %d.%d", socketWorkers[i].cId, socketWorkers[i].subcId );
+ if ( system ( exe ) < 0 )
+ {
+ MWprintf ( 10, "ERROR: Couldnt kill the worker %d, condor job %d.%d\n", i, socketWorkers[i].cId, socketWorkers[i].subcId );
+ }
+ }
+ }
+
+ return 0;
+}
+
+void
+MWSocketRC::closeSockets ( )
+{
+ close ( socketComm );
+ return;
+}
+
+int
+MWSocketRC::killWorker ( int i )
+{
+ //by jae
+ if( i < 0 ) {
+ return -1;
+ }
+
+ close ( socketWorkers[i].socket );
+ hostadd_reqs[socketWorkers[i].exec_class]++;
+
+ socketWorkers[i].state = MWSocket_SUBMITTED;
+ socketWorkers[i].socket = -1;
+ write_RMstate ( NULL );
+ return 0;
+}
+
+inline void
+MWSocketRC::marshall_int ( int n, char *buf )
+{
+ unsigned int k = htonl ( n );
+ memcpy ( buf, &k, sizeof(int) );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_uint ( unsigned int n, char *buf )
+{
+ unsigned int k = htonl ( n );
+ memcpy ( buf, &k, sizeof(unsigned int) );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_short ( short n, char *buf )
+{
+ unsigned short k = htons ( n );
+ memcpy ( buf, &k, sizeof(short) );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_ushort ( unsigned short n, char *buf )
+{
+ unsigned short k = htons ( n );
+ memcpy ( buf, &k, sizeof(unsigned short) );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_long ( long n, char *buf )
+{
+ long k = htonl ( n );
+ memcpy ( buf, &k, sizeof(long) );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_ulong ( unsigned long n, char *buf )
+{
+ unsigned long k = htonl ( n );
+ memcpy ( buf, &k, sizeof(unsigned long) );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_float ( float n, char *buf )
+{
+ int k = *(int *)&n;
+ marshall_int ( k, buf );
+ return;
+}
+
+inline void
+MWSocketRC::marshall_double ( double n, char *buf )
+{
+
+ // Union utopia is the best flavor of babcock ice cream
+ union utopia {
+ double d;
+ struct {
+ int low;
+ int high;
+ } ints;
+ char bytes[8];
+ };
+
+ union utopia u;
+ u.d = n;
+
+
+ if ( htonl ( 3 ) == 3 )
+ {
+ marshall_int ( u.ints.low, buf );
+ marshall_int ( u.ints.high, buf + sizeof(int) );
+ }
+ else
+ {
+ marshall_int ( u.ints.high, buf );
+ marshall_int ( u.ints.low, buf + sizeof(int) );
+ }
+ return;
+}
+
+inline int
+MWSocketRC::unmarshall_int ( char *buf )
+{
+ int k;
+ memcpy ( &k, buf, sizeof(int) );
+ return ntohl ( k );
+}
+
+inline unsigned int
+MWSocketRC::unmarshall_uint ( char *buf )
+{
+ unsigned int k;
+ memcpy ( &k, buf, sizeof(unsigned int) );
+ return ntohl ( k );
+}
+
+inline short
+MWSocketRC::unmarshall_short ( char *buf )
+{
+ short k;
+ memcpy ( &k, buf, sizeof(short) );
+ return ntohs ( k );
+}
+
+inline unsigned short
+MWSocketRC::unmarshall_ushort ( char *buf )
+{
+ unsigned short k;
+ memcpy ( &k, buf, sizeof(unsigned short) );
+ return ntohs ( k );
+}
+
+inline long
+MWSocketRC::unmarshall_long ( char *buf )
+{
+ long k;
+ memcpy ( &k, buf, sizeof(long) );
+ return ntohl ( k );
+}
+
+inline unsigned long
+MWSocketRC::unmarshall_ulong ( char *buf )
+{
+ unsigned long k;
+ memcpy ( &k, buf, sizeof(unsigned long) );
+ return ntohl ( k );
+}
+
+inline float
+MWSocketRC::unmarshall_float ( char *buf )
+{
+ int k = unmarshall_int ( buf );
+ float f = *(float *)&k;
+ return f;
+}
+
+inline double
+MWSocketRC::unmarshall_double ( char *buf )
+{
+ double d;
+ int f,s;
+
+ f = unmarshall_int ( buf );
+ s = unmarshall_int ( buf + sizeof(int) );
+ if ( ntohl ( 3 ) == 3 )
+ {
+ memcpy ( &d, &f, sizeof(int) );
+ memcpy ( ((char *)&d) + sizeof(int), &s, sizeof(int) );
+ }
+ else
+ {
+ memcpy ( &d, &s, sizeof(int) );
+ memcpy ( ((char *)&d) + sizeof(int), &f, sizeof(int) );
+ }
+ return d;
+}
+
+#ifdef NWSENABLED
+typedef int (*callBackFcnDefn)(void* arg, int status);
+void setRestartFunction (
+ callBackFcnDefn /*cbRestart*/,
+ void* /*cbRestartArg*/,
+ callBackFcnDefn /*cbCkpt*/,
+ void* /*cbCkptArg*/ )
+{
+}
+
+#endif
+//BUFFER
+int
+MWSocketRC::recv_all( int from_whom, int msgtag )
+{
+ MWprintf(91, "Not implemented yet for MW-Socket.\n");
+ return 0;
+}
+
+int
+MWSocketRC::setrbuf( int bid )
+{
+ MWprintf(91, "Not implemented yet for MW-Socket.\n");
+ return -1;
+}
+
+int
+MWSocketRC::freebuf( int bid )
+{
+ MWprintf(91, "Not implemented yet for MW-Socket.\n");
+ return -1;
+}
+
+MWList<void>*
+MWSocketRC::recv_buffers()
+{
+ MWprintf(91, "Not implemented yet for MW-Socket.\n");
+ return NULL;
+}
+
+int
+MWSocketRC::next_buf()
+{
+ MWprintf(91, "Not implemented yet for MW-Socket.\n");
+ return -1;
+}
diff --git a/MW/src/RMComm/MW-Socket/MWSocketRC.h b/MW/src/RMComm/MW-Socket/MWSocketRC.h
new file mode 100644
index 0000000..27c6373
--- /dev/null
+++ b/MW/src/RMComm/MW-Socket/MWSocketRC.h
@@ -0,0 +1,434 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+
+#ifndef MWSOCKETRC_H
+#define MWSOCKETRC_H
+
+#include "../MWRMComm.h"
+#include <stdio.h>
+
+#ifdef WINDOWS
+#define _POSIX_PATH_MAX 1024
+#endif
+
+typedef enum { MWSocket_FREE, MWSocket_SUBMITTED, MWSocket_EXECUTING, MWSocket_THREAD } SocketWorkerState;
+#define MWSOCKET_MAX_MSG_SIZE (16 * 1024 * 1024)
+
+#define MWSocketHostAdd 0
+#define MWSocketHostDelete 1
+#define MWSocketTaskExit 2
+#define MWSocketTaskSuspend 3
+#define MWSocketTaskResume 4
+#define MWSocketChecksumError 5
+
+static int MWSocketMessageTags[] =
+ { HOSTADD,
+ HOSTDELETE,
+ HOSTDELETE,
+ HOSTSUSPEND,
+ HOSTRESUME,
+ CHECKSUM_ERROR
+ };
+
+typedef struct
+{
+ SocketWorkerState state;
+ int arch;
+ int cId;
+ int subcId;
+ int socket;
+ int exec_class;
+}SocketWorker;
+
+/**
+ A Resource Management and Communication class that uses Condor
+ for underlying support of resource managament. Some crude inter-process
+ communication is provided using the userlog feature of Condor.
+ resource management.
+
+*/
+
+class MWSocketRC : public MWRMComm
+{
+
+ public:
+
+ /// Constructor
+ MWSocketRC( bool maste, int id );
+
+ /// Destructor
+ ~MWSocketRC();
+
+ /** @name A. Resource Management Routines
+
+ Here we implement the pure virtual functions found in
+ ur parent class, MWRMComm.
+ */
+ //@{
+
+ /** Initialises. Depending on whether it is master or worker instance
+ it initializes all the internal variables. */
+ int setup ( int argc, char *argv[], int *mytid, int *mastertid );
+
+ /** Shutdown. Kills all the workers if it is master */
+ void exit ( int exitval );
+
+ /** Initialize workers if already some have started up */
+ int init_beginning_workers ( int *nworkers, MWWorkerID ***workers );
+
+ /** Restart function */
+ int restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg );
+
+ /** This function is actually a misonomer. It DOES NOT spawn a new
+ worker. Rather it just inits the structure that is passed on to
+ it */
+ int start_worker ( MWWorkerID *w );
+
+ /** This function removes a existing worker */
+ int removeWorker ( MWWorkerID *w );
+
+ /** Figure out whether or not to generate a new worker depending on
+ whether new requests have been made */
+ int hostaddlogic ( int *w );
+
+ /** A routine for reading in the MW-File state at the time
+ * of checkpointing.
+ */
+ int read_RMstate ( FILE *fp = NULL );
+
+ /** A routine for writing in the MW-File state at the time
+ * of checkpointing.
+ */
+ int write_RMstate ( FILE *fp = NULL );
+
+ char* process_executable_name ( char *execut, int, int );
+
+ //@}
+
+ /** @name B. Communication Routines
+
+ Unlike MWPvmRC, the communication routines are non-trivial
+ because Condor provides no inter-process comminucation.
+ Thus we use files for communication. So a send is essentially
+ a file write operation and a recv is a file-read operation.
+ We maintain 2 lists:- The sendList and recvList for taking
+ care of what is to be written/read to/from the files. As in
+ pvm a user beings by calling initsend which creates a new list.
+ Calls to pack insert into the list what is being packed. And
+ finally a send writes the entire thing into a file
+ identified by the destination. Corresponding things happpen
+ in recv.
+ */
+ //@{
+
+ /** A Function called to know which worker had an exception event */
+ void who ( int *wh );
+
+ /** Initialize the send buffer */
+ int initsend ( int useless = 0 );
+
+ /** Send function */
+ int send ( int toWhom, int msgtag );
+
+ // by jae
+ /** Send function for Jae */
+ int pre_send ( int msgtag );
+ void setPollTimeOut(int secs) { m_poll_timeout = secs; }
+
+ /** Recv function */
+ int recv ( int fromWhom, int msgtag );
+
+ /** Non-blocking version of recv */
+ int nrecv (int fromWhom, int msgtag);
+
+ /** Get some info about the recv buffer */
+ int bufinfo ( int buf_id, int *len, int *tag, int *sending_host );
+
+ /// pack some bytes
+ int pack ( const char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int pack ( const float *f, int nitem, int stride = 1 );
+
+ /// double
+ int pack ( const double *d, int nitem, int stride = 1 );
+
+ /// int
+ int pack ( const int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int pack ( const unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int pack ( const short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int pack ( const unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int pack ( const long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int pack ( const unsigned long *ul, int nitem, int stride = 1 );
+
+ /// string
+ int pack ( const char *str );
+
+ /// by jae
+ /***************************/
+ void thread_start(int worker_id);
+ void thread_stop(int worker_id);
+
+ /// Send raw data directly
+ int raw_pack( char* buf, int len );
+
+ /// Read raw data from Worker ID
+ int raw_unpack( int from_whom, char* buf, int len );
+ /***************************/
+
+ /// Unpack some bytes
+ int unpack ( char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int unpack ( float *f, int nitem, int stride = 1 );
+
+ ///double
+ int unpack ( double *d, int nitem, int stride = 1 );
+
+ /// int
+ int unpack ( int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int unpack ( unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int unpack ( short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int unpack ( unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int unpack ( long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int unpack ( unsigned long *ul, int nitem, int stride = 1 );
+
+ /// string
+ int unpack ( char *str );
+
+ //@}
+ private:
+
+ /** Some private functions */
+ /** Some marshalling functions */
+ /// int
+ inline void marshall_int ( int n, char *buf );
+
+ /// unsigned int
+ inline void marshall_uint ( unsigned int n, char *buf );
+
+ /// short
+ inline void marshall_short ( short n, char *buf );
+
+ /// unsigned short
+ inline void marshall_ushort ( unsigned short n, char *buf );
+
+ /// long
+ inline void marshall_long ( long n, char *buf );
+
+ /// unsigned long
+ inline void marshall_ulong ( unsigned long n, char *buf );
+
+ /// float
+ inline void marshall_float ( float n, char *buf );
+
+ /// double
+ inline void marshall_double ( double n, char *buf );
+
+ /** Some unmarhsalling routines */
+ /// int
+ inline int unmarshall_int ( char *buf );
+
+ /// unsigned int
+ inline unsigned int unmarshall_uint ( char *buf );
+
+ /// short
+ inline short unmarshall_short ( char *buf );
+
+ /// unsigned short
+ inline unsigned short unmarshall_ushort ( char *buf );
+
+ /// long
+ inline long unmarshall_long ( char *buf );
+
+ /// unsigned long
+ inline unsigned long unmarshall_ulong ( char *buf );
+
+ /// float
+ inline float unmarshall_float ( char *buf );
+
+ /// double
+ inline double unmarshall_double ( char *buf );
+
+ /** Handle a message from the worker */
+ int handle_finished_worker ( int i );
+
+ /** Is Called when a task is dead */
+ int handle_killed_worker ( int i );
+
+ /** Called when the worker starts executing first */
+ int handle_starting_worker( );
+
+ /** Create a worker */
+ int do_spawn ( int numworkers, int arch );
+
+ /** Kill all the workers */
+ int killWorkers ( );
+
+ /** Kill a worker */
+ int killWorker ( int i );
+
+ /** Final closing of sockets */
+ void closeSockets ( );
+
+ /** A primitive Send function */
+ int finalSend ( int s, char *buf, size_t len, int flags );
+
+ /** A primitive Recv function */
+ int finalRecv ( int s, char *buf, size_t len, int flags );
+
+ int nfinalRecv ( int s, void *buf, size_t len, int flags );
+
+ /** Master receive */
+ int masterrecv ( int fromWhom, int msgtag );
+
+ /** Worker receive */
+ int workerrecv ( int fromWhom, int msgtag );
+
+ /** Master recive from anyone */
+ int masterrecvany();
+
+ /** A generic function to create and bind a socket to a address */
+ int creatAndBind ( int port );
+
+ /** The function that checks the sockets */
+ int checkSockets ( );
+
+ /** A function to sort the exec_classes */
+ void sort_exec_class_ratio ( int *temp );
+
+ /** The bool indicates the mode of the RC instance
+ * a true value means that it is a master and a false means that
+ * it is a worker.
+ * We need to make it a tristate as somtimes an RC can be both
+ * a master and a worker.
+ */
+ bool isMaster;
+
+ /** The value is the id that the worker gets. For master it is
+ * of no use.
+ */
+ int socketId;
+
+ /** The id of the master */
+ int masterId;
+
+ /** The address of the master */
+ char masterAddress[_POSIX_PATH_MAX];
+ /** The value of the master Socket */
+ int masterSocket;
+
+ /** The actual Socket */
+ int socketComm;
+
+ char control_directory[_POSIX_PATH_MAX];
+
+ char worker_number_file[_POSIX_PATH_MAX];
+
+ /** The number of workers that were present. This is an internal
+ * variable that will be used for copying the entire thing when
+ * the target number changes. This is the number that will be maintained close to
+ * target_num_workers.
+ */
+ int current_num_workers;
+
+ /** The number of submitted workers */
+ int submitted_num_workers;
+
+ /** An array of the number of workers */
+ SocketWorker *socketWorkers;
+
+ /** A reverse map in the master from socket to socketWorkers */
+ int reverseMap[4096];
+
+ /** This keeps the track of how many cycles were made.
+ */
+ int turnNo;
+
+ /** The tag of the message that just came in */
+ int msgTag;
+
+ /** The message came from whom */
+ int whomRecv;
+
+ /** A variable to keep track of submit files */
+ int subId;
+
+ /** A variable array keeping track of how many have been requested */
+ int *hostadd_reqs;
+
+ /** A variable array keeping track of how many workers of each arch */
+ int *num_workers;
+
+ /** The worker timeout in minutes */
+ long worker_timeout;
+
+ /** For the sake of transmission */
+ char sendBuffer[MWSOCKET_MAX_MSG_SIZE];
+ /** The current message size */
+ int messageSize;
+
+ /** For the sake of reception */
+ char recvBuffer[MWSOCKET_MAX_MSG_SIZE];
+ /** The received message size */
+ int recvSize;
+ int recvPointer;
+ fd_set rfds;
+
+ //by jae
+ bool pre_send_done;
+ int m_poll_timeout;
+
+ /** The non-blocking recv() functions */
+ public:
+ int recv_all( int from_whom, int msgtag ); // returns the number of new buffers
+ int setrbuf(int bid); // switch the active receive buffer
+ // return the old active buf_id
+ int freebuf(int bid); // free the receive buffer.
+ MWList<void> * recv_buffers(); // return the recv_buf_list
+ int next_buf(); // advance the active buffer to the next valid buffer
+ // in the recv_buf_list.
+
+};
+#endif
+
diff --git a/MW/src/RMComm/MW-Socket/Makefile.in b/MW/src/RMComm/MW-Socket/Makefile.in
new file mode 100644
index 0000000..ec25881
--- /dev/null
+++ b/MW/src/RMComm/MW-Socket/Makefile.in
@@ -0,0 +1,139 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(DEBUG_CHECKER) $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+
+# Subdirectories
+SUBDIRS =
+
+# Libraries to be built, and dependent source files
+LIBRARIES = libMWsocketworker.a libMWsocketmaster.a
+libMWsocketmaster_a_SOURCES = MWSocketRCM.ii
+libMWsocketmaster_a_LIBADD = MWSocketRCM.o
+libMWsocketmaster_a_DEPENDENCIES = MWSocketRCM.o
+libMWsocketmaster_a_OBJECTS =
+
+libMWsocketworker_a_SOURCES = MWSocketRCW.ii
+libMWsocketworker_a_LIBADD = MWSocketRCW.o
+libMWsocketworker_a_DEPENDENCIES = MWSocketRCW.o
+libMWsocketworker_a_OBJECTS =
+
+INCLUDES = -g -I. -I.. -I../.. -I$(CONDOR_DIR)/include $(MEASURE_DEFN)
+INCLUDEFILES = MWSocketRC.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+
+libMWsocketmaster.a: $(libMWsocketmaster_a_OBJECTS) $(libMWsocketmaster_a_DEPENDENCIES)
+ -rm -f libMWsocketmaster.a
+ $(AR) cru libMWsocketmaster.a $(libMWsocketmaster_a_OBJECTS) $(libMWsocketmaster_a_LIBADD)
+ $(RANLIB) libMWsocketmaster.a
+ cp libMWsocketmaster.a $(MW_LIBDIR)
+
+libMWsocketworker.a: $(libMWsocketworker_a_OBJECTS) $(libMWsocketworker_a_DEPENDENCIES)
+ -rm -f libMWsocketworker.a
+ $(AR) cru libMWsocketworker.a $(libMWsocketworker_a_OBJECTS) $(libMWsocketworker_a_LIBADD)
+ $(RANLIB) libMWsocketworker.a
+ cp libMWsocketworker.a $(MW_LIBDIR)
+
+MWSocketRCM.ii:MWSocketRC.C
+ $(CXX) -E $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DSOCKET_MASTER MWSocketRC.C > MWSocketRCM.ii
+
+MWSocketRCM.o:MWSocketRCM.ii
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DSOCKET_MASTER MWSocketRCM.ii
+
+MWSocketRCW.ii:MWSocketRC.C
+ $(CXX) -E $(DEFS) $(MISC_DEFN) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) MWSocketRC.C > MWSocketRCW.ii
+
+MWSocketRCW.o:MWSocketRCW.ii
+ $(CXX) -c $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) MWSocketRCW.ii
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
diff --git a/MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.C b/MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.C
new file mode 100644
index 0000000..fa4a1f0
--- /dev/null
+++ b/MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.C
@@ -0,0 +1,754 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWStaticMPIRC.h"
+#include <MW.h>
+#include <MWDriver.h>
+#include <MWTask.h>
+#include <MWWorker.h>
+#include <stdio.h>
+
+MWStaticMPIRC * MWGlobalMPIRMComm = new MWStaticMPIRC();
+MWRMComm * MWDriver::RMC = MWGlobalMPIRMComm;
+MWRMComm * MWTask::RMC = MWGlobalMPIRMComm;
+MWRMComm * MWWorker::RMC = MWGlobalMPIRMComm;
+
+extern int *MW_exec_class_num_workers;
+//#define S_PRINT
+
+MWStaticMPIRC::MWStaticMPIRC ( )
+{
+
+ is_master = FALSE;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** In MWStaticMPIRC -- constructor ****\n");
+#endif
+}
+
+MWStaticMPIRC::~MWStaticMPIRC ( )
+{
+
+}
+
+void MWStaticMPIRC::init_env(int argc, char* argv[])
+{
+
+ MPI_Init(&argc, &argv);
+#ifdef S_PRINT
+ MWprintf(10, "**** In MWStaticMPIRC -- init_env ****\n");
+#endif
+}
+
+bool MWStaticMPIRC::is_master_proc()
+{
+ int myId;
+ MPI_Comm_rank(MPI_COMM_WORLD, &myId);
+#ifdef S_PRINT
+ MWprintf(10, "****PID = %d In MWStaticMPIRC -- is_master_proc ****\n", myId);
+#endif
+ if (myId == 0)
+ return true;
+ else
+ return false;
+}
+/* Implementation of comm / rm class for mpi_finalize. */
+void MWStaticMPIRC::exit( int exitval )
+{
+ MWprintf ( 50, "Before MPI_Finalize\n" );
+ MPI_Finalize();
+ MWprintf ( 50, "After MPI_Finalize\n" );
+ ::exit(exitval);
+
+}
+
+
+int
+MWStaticMPIRC::setup( int argc, char *argv[], int *id, int *master_id )
+{
+ MWprintf ( 10, "In MWStaticMPIRC::setup()\n");
+ //Check the process id
+ MPI_Comm_rank(MPI_COMM_WORLD, id);
+#ifdef S_PRINT
+ MWprintf(10, "**** PID = %d In MWStaticMPIRC -- setup ****\n", id);
+#endif
+
+ sendBuffer = new Msg_buf();
+ recvBuffer = new Msg_buf();
+ //In MPI the master has pid=0
+
+ *master_id = 0;
+
+ if ( *id == 0 ) {
+ MWprintf ( 40, "I have no parent, therefore I'm the master.\n" );
+ is_master = TRUE;
+ *master_id = 0;
+ return 0;
+ } else {
+ is_master = FALSE;
+ return 0;
+
+ }
+
+
+}
+
+int
+MWStaticMPIRC::config( int *nhosts, int *narches, MWWorkerID ***workers )
+{
+ if ( !is_master ) {
+ MWprintf ( 10, "Slaves not allowed in this privaledged call!\n" );
+ return -1;
+ }
+
+ *narches = 1;
+ MWprintf ( 70, "In MWStaticMPIRC::config()\n" );
+#ifdef S_PRINT
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MWprintf(10, "**** PID = %d In MWStaticMPIRC -- config() ****\n", id);
+#endif
+
+ if ( *workers ) {
+ MWprintf ( 10, "workers should be NULL when called.\n" );
+ return -1;
+ }
+ //Numero di processi compreso il master
+ int numProc;
+ MPI_Comm_size(MPI_COMM_WORLD, &numProc);
+ *nhosts = numProc - 1;
+ MWprintf ( 70, "In MWStaticMPIRC::config(). Number of processes are %d \n", *nhosts );
+
+
+ //The number of workers is number of processes-master (nhost -1 )
+ (*workers) = new MWWorkerID*[*nhosts];
+ for ( int i=0 ; i<*nhosts ; i++ ) {
+ (*workers)[i] = new MWWorkerID;
+ (*workers)[i]->set_arch ( 0 );
+ /* Do domething creative with speed later! */
+ }
+
+ return 0;
+}
+
+int
+MWStaticMPIRC::start_worker ( MWWorkerID *w )
+{
+
+ if ( !is_master )
+ {
+ MWprintf ( 10, "Slaves not allowed in this privaledged call!\n" );
+ return -1;
+ }
+#ifdef S_PRINT
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MWprintf(10, "**** PID = %d In MWStaticMPIRC -- start_worker ****\n", id);
+#endif
+
+ MWprintf ( 50, "In MWStaticMPIRC::start_worker()\n" );
+ if ( !w )
+ {
+ MWprintf ( 10, "w cannot be NULL!\n" );
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+MWStaticMPIRC::init_beginning_workers( int *nworkers, MWWorkerID ***workers )
+{
+ if ( !is_master )
+ {
+ MWprintf ( 10, "Slaves not allowed in this privaledged call!\n" );
+ return -1;
+ }
+#ifdef S_PRINT
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MWprintf(10, "**** PID = %d In MWStaticMPIRC -- init_beginning workers() ****\n", id);
+#endif
+
+ int i, j, narches;
+ MWprintf ( 50, "In MWStaticMPIRC::init_beginning_workers\n" );
+
+ /* config allocates memory for workers */
+ if ( config( nworkers, &narches, workers ) < 0 )
+ {
+ return -1;
+ }
+
+ num_arches = narches;
+
+ MWprintf ( 40, "Number of hosts at start: %d.\n", *nworkers );
+ MWprintf ( 40, "Number of arch. classes: %d.\n", num_arches );
+
+ hostadd_reqs = new int*[exec_classes];
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ hostadd_reqs[i] = new int[num_arches];
+ for ( j = 0 ; j < num_arches ; j++ )
+ {
+ hostadd_reqs[i][j] = 0;
+ }
+ }
+
+ for ( i=0 ; i<(*nworkers) ; i++ )
+ {
+ //do_spawn( (*workers)[i] );
+ (*workers)[i]->set_id1(i+1);
+ (*workers)[i]->set_id2(0);
+ (*workers)[i]->set_exec_class(0);
+ (*workers)[i]->set_executable(0);
+ (*workers)[i]->set_arch(0);
+ }
+
+ return 0;
+}
+
+
+int
+MWStaticMPIRC::restart_beginning_workers ( int *nworkers, MWWorkerID ***workers, MWmessages msg )
+{
+#ifdef S_PRINT
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MWprintf(10, "**** PID = %d In MWStaticMPIRC -- restart_beginning_workers ****\n", id);
+#endif
+ return init_beginning_workers ( nworkers, workers );
+}
+
+
+int
+MWStaticMPIRC::initsend ( int encoding )
+{
+#ifdef S_PRINT
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MWprintf(10, "**** PID = %d In MWStaticMPIRC -- initsend ****\n", id);
+#endif
+ sendBuffer->reset();
+ sendPosition = 0;
+ return 0;
+}
+
+
+int
+MWStaticMPIRC::send ( int to_whom, int msgtag )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+#ifdef S_PRINT
+ MWprintf(10, "***** PID %d : Send to %d mstgag %d size = %d ***** \n", id, to_whom, msgtag, sendBuffer->size);
+#endif
+ return MPI_Send(sendBuffer->data, sendBuffer->size, MPI_PACKED, to_whom, msgtag, MPI_COMM_WORLD);
+
+}
+
+int
+MWStaticMPIRC::nrecv( int from_whom, int msgtag)
+{
+ recvPosition = 0;
+ if (is_master)
+ return masterrecv(from_whom, msgtag);
+ else
+ return iworkerrecv(from_whom, msgtag);
+}
+
+
+
+int MWStaticMPIRC::iworkerrecv(int from_whom, int msgtag)
+{
+ int flag, bytes;
+ MPI_Status status;
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : iworkerrecv from = %d msgtag = %d ****\n", id, from_whom, msgtag);
+#endif
+ MPI_Iprobe(from_whom, msgtag, MPI_COMM_WORLD, &flag, &status);
+ if (flag <= 0) {
+ return flag;
+ }
+ else {
+ recvBuffer->reset();
+ MPI_Get_count( &status, MPI_PACKED, &bytes );
+ recvBuffer->resize(bytes);
+ recvBuffer->sender = status.MPI_SOURCE;
+ recvBuffer->tag = status.MPI_TAG;
+ recvBuffer->size = bytes;
+ return MPI_Recv(recvBuffer->data, recvBuffer->size, MPI_PACKED, recvBuffer->sender, recvBuffer->tag, MPI_COMM_WORLD,&status);
+
+ }
+
+
+
+}
+
+int MWStaticMPIRC::masterrecv (int from_whom, int msgtag) {
+
+
+ int *buf_id = NULL;
+ int bytes;
+ MPI_Status status;
+ buf_id = new int;
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : imasterrecv from = %d msgtag = %d ****\n", id, from_whom, msgtag);
+#endif
+ (*buf_id) = MPI_Probe(from_whom, msgtag, MPI_COMM_WORLD,&status);
+ if (buf_id > 0) {
+ MPI_Get_count( &status, MPI_PACKED, &bytes );
+ recvBuffer->reset();
+ recvBuffer->resize(bytes);
+ recvBuffer->sender = status.MPI_SOURCE;
+ recvBuffer->tag = status.MPI_TAG;
+ recvBuffer->size = bytes;
+ MPI_Recv(recvBuffer->data, recvBuffer->size, MPI_PACKED, recvBuffer->sender, recvBuffer->tag, MPI_COMM_WORLD,&status);
+ return *buf_id;
+ }
+ else
+ return 0;
+
+}
+
+ int
+MWStaticMPIRC::recv( int from_whom, int msgtag)
+{
+ recvPosition = 0;
+ if (from_whom == -1)
+ from_whom = MPI_ANY_SOURCE;
+ if (msgtag == -1)
+ msgtag = MPI_ANY_TAG;
+
+ int *buf_id = new int;
+ int retVal;
+ MPI_Status status;
+ int bytes, myId;
+ MPI_Comm_rank(MPI_COMM_WORLD, &myId);
+#ifdef S_PRINT
+
+ MWprintf(40, "**** PID %d : MPI_Probe in recv myId = %d from_whom = %d and tag = % d ****\n", myId, myId, from_whom, msgtag);
+#endif
+ retVal = MPI_Probe(from_whom, msgtag, MPI_COMM_WORLD,&status);
+ if (retVal >= 0)
+ {
+ MPI_Get_count( &status, MPI_PACKED, &bytes );
+ recvBuffer->reset();
+ recvBuffer->resize(bytes);
+ recvBuffer->sender = status.MPI_SOURCE;
+ recvBuffer->tag = status.MPI_TAG;
+ recvBuffer->size = bytes;
+ MPI_Recv(recvBuffer->data, recvBuffer->size, MPI_PACKED, recvBuffer->sender, recvBuffer->tag, MPI_COMM_WORLD,&status);
+ *buf_id = 1;
+ }
+ else
+ {
+ *buf_id = 0;
+ }
+
+ return *buf_id;
+
+}
+
+int MWStaticMPIRC::bufinfo ( int buf_id, int *len, int *tag, int *from )
+{
+
+ *len = recvBuffer->size;
+ *tag = recvBuffer->tag;
+ *from = recvBuffer->sender;
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+#ifdef S_PRINT
+
+ MWprintf(40, "**** PID %d : MWStaticMPIRC::bufinfo: len %d tag %d from %d ****\n",id, *len, *tag, *from);
+#endif
+ return 0;
+
+}
+int
+MWStaticMPIRC::recv_all( int from_whom, int msgtag )
+{
+
+ MWprintf(91, "Not implemented yet recv_all for MW-StaticMPI.\n");
+ return 0;
+}
+
+
+
+int
+MWStaticMPIRC::setrbuf( int bid )
+{
+ MWprintf(91, "Not implemented yet setrbuf for MW-StaticMPI.\n");
+ return -1;
+}
+
+int
+MWStaticMPIRC::freebuf( int bid )
+{
+ MWprintf(91, "Not implemented yet freebuf for MW-StaticMPI.\n");
+ return -1;
+}
+
+MWList<void>*
+MWStaticMPIRC::recv_buffers()
+{
+ MWprintf(91, "Not implemented yet recv_buffers for MW-StaticMPI.\n");
+ return NULL;
+}
+
+int
+MWStaticMPIRC::next_buf()
+{
+ MWprintf(91, "Not implemented yet next_buf for MW-StaticMPI.\n");
+ return -1;
+}
+
+int
+MWStaticMPIRC::pack (const char *bytes, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride;
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof bytes);
+ MPI_Pack(const_cast<char *> (bytes), (nitem*stride), MPI_CHAR,
+ sendBuffer->data, sendBuffer->max_size,
+ &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Pack char bytes = %s nitem = %d sendPosition = %d stride = %d ****\n", id, bytes, nitem, sendPosition, stride);
+#endif
+ return 0;
+}
+
+int
+MWStaticMPIRC::pack (const float *f, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(float);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof f);
+ MPI_Pack(const_cast<float *> (f), (nitem*stride), MPI_FLOAT,
+ sendBuffer->data, sendBuffer->max_size,
+ &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack float data = %f nitem = %d sendPosition = %d stride = %d ****\n", id, *f, nitem, sendPosition, stride);
+#endif
+
+ return 0;
+}
+
+
+int
+MWStaticMPIRC::pack(const double *d, int nitem, int stride)
+{
+ bytes_packed_ += nitem / stride * sizeof(double);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof d);
+ MPI_Pack(const_cast<double *> (d), (nitem*stride), MPI_DOUBLE, sendBuffer->data, sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack double sendPosition = %d nitem*stride = %d size = %d stride = %d ****\n", id, sendPosition, nitem*stride, sendBuffer->size, stride);
+#endif
+ return 0;
+}
+
+
+int
+MWStaticMPIRC::pack(const int *i, int nitem, int stride)
+{
+ bytes_packed_ += nitem / stride * sizeof(int);
+ int id, dim;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof i);
+ MPI_Pack(const_cast<int *> (i), (nitem*stride), MPI_INT, sendBuffer->data,
+ sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack int data = %d nitem = %d sendPosition = %d stride = %d ****\n", id, *i, nitem, sendPosition, stride);
+#endif
+
+ return 0;
+}
+
+
+int
+MWStaticMPIRC::pack(const unsigned int *ui, int nitem, int stride)
+{
+ bytes_packed_ += nitem / stride * sizeof(unsigned int);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Pack(const_cast<unsigned int *> (ui), (nitem*stride), MPI_UNSIGNED,
+ sendBuffer->data, sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Pack ui data = %ui nitem = %d sendPosition = %d stride = %d ****\n", id, *ui, nitem, sendPosition, stride);
+#endif
+ return 0;
+};
+
+int
+MWStaticMPIRC::pack(const short *sh, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(short);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof sh);
+ MPI_Pack(const_cast<short *> (sh), (nitem*stride), MPI_SHORT,
+ sendBuffer->data, sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack sh data = %sh nitem = %d sendPosition = %d stride = %d ****\n", id, *sh, nitem, sendPosition, stride);
+#endif
+ return 0;
+};
+
+int
+MWStaticMPIRC::pack (const unsigned short *ush, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(unsigned short);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof ush);
+ MPI_Pack(const_cast<unsigned short *> (ush), (nitem*stride), MPI_UNSIGNED_SHORT,
+ sendBuffer->data, sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack ush data = %ush nitem = %d sendPosition = %d stride = %d ****\n", id, *ush, nitem, sendPosition, stride );
+#endif
+ return 0;
+};
+
+int
+MWStaticMPIRC::pack(const long *l, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(long);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof l);
+ MPI_Pack(const_cast<long *> (l), (nitem*stride), MPI_LONG, sendBuffer->data,
+ sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Pack l data = %l nitem = %d sendPosition = %d stride = %d ****\n", id, *l, nitem, sendPosition, stride);
+#endif
+ return 0;
+};
+
+
+int
+MWStaticMPIRC::pack(const unsigned long *ul, int nitem, int stride )
+{
+ bytes_packed_ += nitem / stride * sizeof(unsigned long);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem*sizeof ul);
+ MPI_Pack(const_cast<unsigned long *> (ul), (nitem*stride), MPI_UNSIGNED_LONG,
+ sendBuffer->data, sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack ul data = %ul nitem = %d sendPosition = %d ****\n", id, *ul, nitem, sendPosition);
+#endif
+ return 0;
+};
+
+int MWStaticMPIRC::pack(const char *str)
+{
+ bytes_packed_ += strlen(str);
+ int nitem = strlen(str);
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ sendBuffer->resize(nitem);
+
+ MPI_Pack(&nitem, 1, MPI_INT, sendBuffer->data, sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ MPI_Pack(const_cast<char *> (str), nitem, MPI_CHAR, sendBuffer->data,
+ sendBuffer->max_size, &sendPosition, MPI_COMM_WORLD);
+ sendBuffer->size = sendPosition;
+
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Pack str data = %s nitem = %d sendPosition = %d ****\n", id, str, nitem, sendPosition);
+#endif
+ return 0;
+};
+
+int MWStaticMPIRC::unpack( char *bytes, int nitem, int stride )
+{
+
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition, bytes, nitem, MPI_CHAR, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack bytes data = %s nitem = %d recvPosition = %d ****\n", id, bytes, (nitem*stride), recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(char);
+ return 0;
+};
+
+ /// float
+int MWStaticMPIRC::unpack( float *f, int nitem, int stride )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition , &f, (nitem*stride), MPI_FLOAT, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack float data = %f nitem = %d recvPosition = %d ****\n", id, *f, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(float);
+ return 0;
+};
+
+ /// double
+int MWStaticMPIRC::unpack( double *d, int nitem, int stride )
+{
+ int id, dim;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ dim = (sizeof d)*nitem;
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition , d, (nitem*stride), MPI_DOUBLE, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack double recvPosition = %d ****\n", id, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(double);
+ return 0;
+};
+
+ /// int
+int MWStaticMPIRC::unpack( int *i, int nitem, int stride )
+{
+ int id, dim = (sizeof i)*nitem;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition ,i , (nitem*stride), MPI_INT, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack int data = %i nitem = %d recvPosition = %d ****\n", id, *i, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(int);
+ return 0;
+};
+
+ /// unsigned int
+int MWStaticMPIRC::unpack( unsigned int *ui, int nitem, int stride )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition, &ui, (nitem*stride), MPI_UNSIGNED, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack ui data = %ui nitem = %d recvPosition = %d ****\n", id, *ui, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned int);
+ return 0;
+};
+
+ /// short
+int MWStaticMPIRC::unpack( short *sh, int nitem, int stride )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition , &sh, (nitem*stride), MPI_SHORT, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack sh data = %sh nitem = %d recvPosition = %d ****\n", id, *sh, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(short);
+ return 0;
+};
+
+ /// unsigned short
+int MWStaticMPIRC::unpack( unsigned short *ush, int nitem, int stride )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition, &ush , (nitem*stride), MPI_UNSIGNED_SHORT, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack ush data = %ush nitem = %d recvPosition = %d ****\n", id, *ush, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned short);
+ return 0;
+};
+
+ /// long
+int MWStaticMPIRC::unpack( long *l, int nitem, int stride )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition, &l , (nitem*stride), MPI_LONG, MPI_COMM_WORLD);
+#ifdef S_PRINT
+
+ MWprintf(10, "**** PID %d : Unpack l data = %l nitem = %d recvPosition = %d ****\n", id, *l, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(long);
+ return 0;
+};
+
+ /// unsigned long
+int MWStaticMPIRC::unpack( unsigned long *ul, int nitem, int stride )
+{
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition, &ul, (nitem*stride), MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Unpack ul data = %ul nitem = %d recvPosition = %d ****\n", id, *ul, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += nitem / stride * sizeof(unsigned long);
+ return 0;
+};
+
+ /// Unpack a NULL-terminated string
+int MWStaticMPIRC::unpack( char *str )
+{
+ char* data, nitem;
+ int id;
+ MPI_Comm_rank(MPI_COMM_WORLD, &id);
+ //Spacchetto prima la dimensione della stringa e poi la stringa stessa
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition , &nitem , 1 ,MPI_INT, MPI_COMM_WORLD);
+ MPI_Unpack(recvBuffer->data, recvBuffer->size, &recvPosition ,str , nitem ,MPI_CHAR, MPI_COMM_WORLD);
+ str[nitem] = '\0';
+#ifdef S_PRINT
+ MWprintf(10, "**** PID %d : Unpack str data = %s nitem = %d recvPosition = %d ****\n", id, str, nitem, recvPosition);
+#endif
+ bytes_unpacked_ += strlen(str);
+ return 0;
+};
+
+int
+MWStaticMPIRC::write_RMstate ( FILE *fp = NULL )
+{
+ // No MPI specific functions
+ return 0;
+}
diff --git a/MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.h b/MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.h
new file mode 100644
index 0000000..bd7bd70
--- /dev/null
+++ b/MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.h
@@ -0,0 +1,371 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWSTATICMPIRC_H
+#define MWSTATICMPIRC_H
+
+#define MPICH_SKIP_MPICXX
+#define KB64 1048576
+
+#include "MWRMComm.h"
+#include "MWList.h"
+
+extern "C" {
+#include "mpi.h"
+}
+//#include "/usr/local/mpich-g2/include/mpi.h"
+
+class Msg_buf
+{
+public:
+ Msg_buf(int max_size = KB64)
+ {
+ data = new char[max_size];
+ size = 0;
+ pos = 0;
+ tag = 0;
+ };
+
+
+ /// Destructor
+ virtual ~Msg_buf( ) { delete[] data; };
+
+ /// Set everything to default
+ void reset(int max_size = KB64)
+ {
+ tag = 0;
+ max_size = max_size;
+ size = 0;
+ pos = 0;
+ id = -1;
+ delete[] data;
+ data = new char[max_size];
+ }
+ //@}
+
+ /// Resize the buffer if it is not ehough place to add <code> add_size </code>.
+ void resize(int add_size)
+ {
+ if( size + add_size <= max_size)
+ return;
+ max_size = size + add_size + KB64;
+ char* tmp = new char[max_size];
+ memcpy(tmp, data, size);
+ delete[] data;
+ data = tmp;
+ }
+
+ /// Message tag.
+ int tag;
+
+ /// Pointer to the data
+ char* data;
+
+
+ /// Allocated size.
+ int max_size;
+
+ /// Current message size
+ int size;
+
+ /// Current position in the buffer to read from the buffer
+ int pos;
+
+ /// ID of the buffer
+ int id;
+
+ /// Sender pid.
+ int sender;
+};
+
+
+
+
+class MWStaticMPIRC: public MWRMComm
+{
+
+
+
+public:
+
+ /** Constructor. Sets data to -1's. */
+ MWStaticMPIRC();
+
+ /// Destructor...
+ ~MWStaticMPIRC();
+
+ /** @name A. Resource Management Functions
+
+ Here are all the methods you could want to have for managing
+ a set of machines. See each method for details...
+ */
+ //@{
+
+ /** System shutdown. Does not return.
+ @param exitval The value to call ::exit() with
+ */
+ void exit( int exitval );
+
+ /** Initialization of the master process. This will be called
+ one time only when the master starts up.
+ @return 0 on success, -1 on failure
+ */
+ int setup( int argc, char* argv[], int *my_id, int *master_id ) ;
+
+ void init_env(int argc, char* argv[]);
+ bool is_master_proc();
+
+ /** This returns the state of the "virtual machine" - aka the
+ set of workers under the master's control.
+ @param nhosts The number of hosts
+ @param narches The number of architechture classes
+ @param w A pointer to a pointer to an array of pointers.
+ This should be NULL when called; config() will allocate
+ the memory using new and return it to you. Don't forget
+ to delete not only the elements in that array, but
+ also the array itself. The array will have nhosts
+ elements, and they will each represent a worker
+ machine.
+ @return 0 on success, -1 on error.
+ */
+ int config( int *nhosts, int *narches, MWWorkerID ***w ) ;
+
+ /** Start a worker on a machine that has been given to you.
+ This is really only important if the process of starting
+ a worker is two-stage. For instance, in pvm, you
+ first get a machine. THEN you have to spawn an
+ executable on that machine. For something like MW-files,
+ once you get a worker it already has the executable
+ started on it. In that case this will basically be
+ a no-op.
+ @param w A pointer to a MWWorkerID. This must point
+ to allocated memory. It is filled with info like the
+ machine name, id2, and the arch.
+ @return id2 on success, -1 on failure
+ */
+ int start_worker( MWWorkerID *w ) ;
+
+
+
+ /** Start up the workers that are given to us at the beginning.
+ See base class comments for more details.
+ @param nworkers The number of workers at start
+ @param workers A pointer to an array of pointers to
+ MWWorkerID classes. This call will new() memory
+ for the MWWorkerIDs. Also, if (*w)[n]->id2 is
+ -1, that means that the spawn failed for
+ worker number n.
+ */
+ int init_beginning_workers ( int *nworkers, MWWorkerID ***workers );
+
+ /** Called at the time of restart */
+ int restart_beginning_workers ( int *nworkers, MWWorkerID ***worker, MWmessages msg );
+
+ /** Remove a worker. Basically, call pvm_delhosts(). */
+ int removeWorker( MWWorkerID *w ){ return 0; };
+
+ /** Read some state. A null function */
+ int read_RMstate ( FILE *fp ){ return 0; };
+
+ /** Write some state. A null function */
+ int write_RMstate ( FILE *fp );
+
+
+ //@}
+
+ private:
+ /** @name Other Functions to be implemented */
+
+ //@{
+
+ /** Figure out wether or not to ask for hosts, and how many...
+ @param num_workers An array of size num_arches that contains
+ the number of workers in each arch class.
+ */
+ int hostaddlogic( int *num_workers ){ return 0; };
+
+ /** Do the pvm_spawn and associated stuff */
+ int do_spawn( MWWorkerID *w ){ return 0; };
+
+ /** Set up the proper notifies for a task & host tid */
+ int setup_notifies ( int task_tid ){ return 0; };
+
+ /** This function says to pvm: "I would like another machine,
+ please".
+ @param howmany The number of machines to request
+ @param archnum The arch class number to ask for. */
+ int ask_for_host( int howmany, int archnum ){ return 0; };
+
+ /** Shows the pvm virtual machine according to pvm. Used
+ for debugging purposes{ return 0; }; not normally called. */
+ void conf(){ };
+
+ /** Helper for hostaddlogic(). Returns the index of the min
+ element in array, which is of length len */
+ int min ( int *array, int len ){ return 0; };
+
+ /** Funzioni di ricezione del worker e del master */
+
+ int iworkerrecv(int from_whom, int msgtag);
+ int masterrecv(int from_whom, int msgtag);
+
+ /** The number of outstanding requests for a particular
+ arch. */
+ //int *hostadd_reqs{ return 0; };
+
+ /** The requests per exec_classes */
+ int **hostadd_reqs;
+
+ MWList<void> * submit_list;
+
+ //@}
+
+ /** Am I the master process or not? */
+ int is_master;
+
+ public:
+
+
+ /** @name C. Communication Routines
+
+ These are essentially thin wrappers of PVM calls.
+ */
+ //@{
+
+ ///
+ int initsend ( int encoding = 0);
+
+ ///
+ int send ( int to_whom, int msgtag );
+
+ ///
+ int recv ( int from_whom, int msgtag );
+
+ /// non-blocking version of receive
+ int nrecv (int fromWhom, int msgtag);
+
+ /** Provide info on the message just received */
+ int bufinfo ( int buf_id, int *len, int *tag, int *from );
+
+ /** Tells the affected party */
+ void who ( int *id ){ };
+
+ /// Pack some bytes
+ int pack ( const char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int pack ( const float *f, int nitem, int stride = 1 );
+
+ /// double
+ int pack ( const double *d, int nitem, int stride = 1 );
+
+ /// int
+ int pack ( const int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int pack ( const unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int pack ( const short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int pack ( const unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int pack ( const long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int pack ( const unsigned long *ul, int nitem, int stride = 1 );
+
+ /// Pack a NULL-terminated string
+ int pack ( const char *str );
+
+ /// Unpack some bytes
+ int unpack ( char *bytes, int nitem, int stride = 1 );
+
+ /// float
+ int unpack ( float *f, int nitem, int stride = 1 );
+
+ /// double
+ int unpack ( double *d, int nitem, int stride = 1 );
+
+ /// int
+ int unpack ( int *i, int nitem, int stride = 1 );
+
+ /// unsigned int
+ int unpack ( unsigned int *ui, int nitem, int stride = 1 );
+
+ /// short
+ int unpack ( short *sh, int nitem, int stride = 1 );
+
+ /// unsigned short
+ int unpack ( unsigned short *ush, int nitem, int stride = 1 );
+
+ /// long
+ int unpack ( long *l, int nitem, int stride = 1 );
+
+ /// unsigned long
+ int unpack ( unsigned long *ul, int nitem, int stride = 1 );
+
+ /// Unpack a NULL-terminated string
+ int unpack ( char *str );
+
+
+ //@}
+
+ private:
+ /** @name C. Some Misc Helper functions
+ */
+
+ //@{
+
+ /** Number of sent messages */
+ int num_send_msgs;
+
+ /** Number of received messages */
+ int num_recv_msgs;
+
+
+ /** The current message to send */
+ Msg_buf *sendBuffer;
+
+ /** For the sake of transmission */
+ Msg_buf *recvBuffer;
+
+ int sendPosition;
+ int recvPosition;
+ //@}
+ /** The non-blocking recv functions */
+ public:
+ int recv_all( int from_whom, int msgtag ); // returns the number of new buffers
+ int setrbuf(int bid); // switch the active receive buffer
+ // return the old active buf_id
+ int freebuf(int bid); // free the receive buffer.
+ MWList<void>* recv_buffers(); // return the recv_buf_list
+ int next_buf(); // advance the active buffer to the next valid buffer
+ // in the recv_buf_list.
+ int switch_buf_back(); // Switch the active receive buffer to the buffer
+ // on the head of the recv_buf_list;
+};
+
+extern MWStaticMPIRC *MWGlobalMPIRMComm;
+#endif
diff --git a/MW/src/RMComm/MW-StaticMPI/Makefile.in b/MW/src/RMComm/MW-StaticMPI/Makefile.in
new file mode 100644
index 0000000..bbf3e8b
--- /dev/null
+++ b/MW/src/RMComm/MW-StaticMPI/Makefile.in
@@ -0,0 +1,120 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MPICXX = @MPICXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+ENABLE_MWINDEPENDENT= @ENABLE_MWINDEPENDENT@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+
+CXXCOMPILE = $(DEBUG_CHECKER) $(MPICXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+
+# Subdirectories
+SUBDIRS =
+
+# Libraries to be built, and dependent source files
+LIBRARIES = libMWRC_mpi.a
+libMWRC_mpi_a_SOURCES = MWStaticMPIRC.C
+libMWRC_mpi_a_LIBADD = MWStaticMPIRC.o
+libMWRC_mpi_a_DEPENDENCIES = MWStaticMPIRC.o
+libMWRC_mpi_a_OBJECTS =
+
+INCLUDES = -g -I. -I.. -I../.. $(MEASURE_DEFN)
+INCLUDEFILES = MWStaticMPIRC.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+
+libMWRC_mpi.a: $(libMWRC_mpi_a_OBJECTS) $(libMWRC_mpi_a_DEPENDENCIES)
+ -rm -f libMWRC_mpi.a
+ $(AR) cru libMWRC_mpi.a $(libMWRC_mpi_a_OBJECTS) $(libMWRC_mpi_a_LIBADD)
+ $(RANLIB) libMWRC_mpi.a
+ cp libMWRC_mpi.a $(MW_LIBDIR)
+
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Common
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
+
+
+
diff --git a/MW/src/RMComm/MWRMComm.C b/MW/src/RMComm/MWRMComm.C
new file mode 100644
index 0000000..406092a
--- /dev/null
+++ b/MW/src/RMComm/MWRMComm.C
@@ -0,0 +1,457 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#include "MWRMComm.h"
+
+#ifdef WINDOWS
+#define _POSIX_PATH_MAX 1024
+#endif
+
+MWRMComm::MWRMComm()
+{
+ exec_classes = 0;
+ num_arches = 0;
+ arch_class_attributes = NULL;
+ num_executables = tempnum_executables = 0;
+ hostinc_ = 6;
+
+ worker_executables = NULL;
+ worker_checkpointing = false;
+
+ target_num_workers = 0;
+ exec_class_target_num_workers = NULL;
+ MW_exec_class_num_workers = NULL;
+}
+
+
+MWRMComm::~MWRMComm()
+{
+ int i;
+
+ if ( arch_class_attributes )
+ {
+ for ( i = 0; i < num_arches; i++ )
+ if ( arch_class_attributes[i] )
+ delete [] arch_class_attributes[i];
+ }
+
+ if ( worker_executables )
+ {
+ for ( i = 0; i < num_executables; i++ )
+ if ( worker_executables[i] )
+ {
+ delete [] worker_executables[i]->executable;
+ delete [] worker_executables[i]->executable_name;
+ delete [] worker_executables[i]->attributes;
+ delete worker_executables[i];
+ }
+ }
+
+ if ( exec_class_target_num_workers )
+ delete [] exec_class_target_num_workers;
+
+ if ( MW_exec_class_num_workers )
+ delete [] MW_exec_class_num_workers;
+}
+
+void MWRMComm::exit( int exitval )
+{
+ ::exit ( exitval );
+}
+
+int MWRMComm::write_checkpoint( FILE *fp )
+{
+ int i;
+
+ MWprintf ( 80, "Writing checkpoint for MWPvmRC layer.\n" );
+
+ fprintf ( fp, "%d \n", exec_classes );
+ fprintf ( fp, "%d \n", num_arches );
+ for ( i = 0 ; i<num_arches ; i++ )
+ {
+ if ( arch_class_attributes && arch_class_attributes[i] )
+ fprintf ( fp, "1 %d %s\n", strlen(arch_class_attributes[i]), arch_class_attributes[i] );
+ else
+ fprintf ( fp, "0 " );
+ }
+
+ fprintf ( fp, "%d \n", num_executables );
+ for ( i = 0; i < num_executables; i++ )
+ {
+ fprintf ( fp, "%d %d %s %s\n", worker_executables[i]->arch_class,
+ worker_executables[i]->exec_class, worker_executables[i]->executable,
+ worker_executables[i]->executable_name );
+ if ( worker_executables[i]->attributes != NULL )
+ fprintf ( fp, "1 %d %s\n", strlen(worker_executables[i]->attributes),
+ worker_executables[i]->attributes );
+ else
+ fprintf ( fp, "0 " );
+ }
+
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ fprintf ( fp, "%d ", exec_class_target_num_workers[i] );
+ }
+ fprintf ( fp, "\n");
+
+ write_RMstate ( fp );
+ return 0;
+}
+
+int MWRMComm::read_checkpoint( FILE *fp )
+{
+ int temp;
+ int i;
+ MWprintf ( 50, "Reading checkpoint in MWPvmRC layer.\n" );
+ fscanf ( fp, "%d %d", &exec_classes, &num_arches );
+ MWprintf ( 50, "Target num workers: %d Num arches %d.\n",
+ target_num_workers, num_arches );
+ arch_class_attributes = new char*[num_arches];
+ target_num_workers = 0;
+ for ( i = 0; i < num_arches; i++ )
+ {
+ fscanf ( fp, "%d ", &temp );
+ if ( temp == 1 )
+ {
+ fscanf ( fp, "%d ", &temp );
+ arch_class_attributes[i] = new char[temp+1];
+ fgets ( arch_class_attributes[i], temp + 1, fp );
+ }
+ else
+ arch_class_attributes[i] = NULL;
+ }
+
+ fscanf ( fp, "%d ", &num_executables );
+ MWprintf ( 50, "%d Worker executables:\n", num_executables );
+ worker_executables = new struct RMC_executable*[num_executables];
+ for ( i = 0 ; i < num_executables; i++ )
+ {
+ worker_executables[i] = new struct RMC_executable;
+ worker_executables[i]->executable = new char[_POSIX_PATH_MAX];
+ worker_executables[i]->executable_name = new char[_POSIX_PATH_MAX];
+ fscanf ( fp, "%d %d %s %s", &worker_executables[i]->arch_class,
+ &worker_executables[i]->exec_class, worker_executables[i]->executable,
+ worker_executables[i]->executable_name );
+ fscanf ( fp, "%d ", &temp );
+ if ( temp == 1 )
+ {
+ fscanf ( fp, "%d ", &temp );
+ worker_executables[i]->attributes = new char[temp+1];
+ fgets ( worker_executables[i]->attributes, temp + 1, fp );
+ }
+ else
+ worker_executables[i]->attributes = NULL;
+ }
+
+ MW_exec_class_num_workers = new int[exec_classes];
+ exec_class_target_num_workers = new int[exec_classes];
+ for ( i = 0; i < exec_classes; i++ )
+ {
+ fscanf ( fp, "%d ", &exec_class_target_num_workers[i] );
+ target_num_workers += exec_class_target_num_workers[i];
+ MW_exec_class_num_workers[i] = 0;
+ }
+
+ read_RMstate ( fp );
+ return 0;
+}
+
+int MWRMComm::read_RMstate( FILE *fp )
+{
+ return 0;
+}
+
+int MWRMComm::write_RMstate( FILE *fp )
+{
+ return 0;
+}
+
+
+// An exec class is a partition of the total number
+// of running workers, and can be of Any architecture
+void
+MWRMComm::set_num_exec_classes ( int num )
+{
+ exec_classes = num;
+
+ if (exec_class_target_num_workers) {
+ delete [] exec_class_target_num_workers;
+ delete [] MW_exec_class_num_workers;
+ }
+
+ exec_class_target_num_workers = new int[num];
+ MW_exec_class_num_workers = new int[num];
+ for ( int i = 0; i < num; i++ )
+ {
+ exec_class_target_num_workers[i] = 0;
+ MW_exec_class_num_workers[i] = 0;
+ }
+
+}
+
+int
+MWRMComm::get_num_exec_classes ( )
+{
+ return exec_classes;
+}
+
+// arch_classes are the different opsys/arch combos
+// we will be running with
+void
+MWRMComm::set_num_arch_classes ( int num )
+{
+ char **tmp_arch_class_attributes = new char*[num];
+
+ MWprintf(80, "MWRMComm::set_num_arch_classes to %d\n", num);
+ for (int i = 0 ; i < num; i++) {
+ tmp_arch_class_attributes[i] = NULL;
+ }
+
+ if (arch_class_attributes) {
+ for (int i = 0; i < num_arches; i++) {
+ tmp_arch_class_attributes[i] = arch_class_attributes[i];
+ }
+ delete [] arch_class_attributes;
+ }
+
+ num_arches = num;
+ arch_class_attributes = tmp_arch_class_attributes;
+}
+
+void
+MWRMComm::set_arch_class_attributes ( int arch_class, const char *attr )
+{
+ MWprintf(80, "MWRMComm::set_arch_class_attributes for arch class %d to %s\n", arch_class, attr);
+ if ( arch_class >= num_arches ) {
+ MWprintf(10, "Warning: arch_class %d >= num_arches (%d)\n", arch_class, num_arches);
+ exit(-1);
+ return;
+ }
+ arch_class_attributes[arch_class] = new char[strlen(attr)+1];
+ strcpy ( arch_class_attributes[arch_class], attr );
+}
+
+int
+MWRMComm::get_num_arch_classes ( )
+{
+ return num_arches;
+}
+
+void
+MWRMComm::set_num_executables ( int num )
+{
+ int i = 0;
+
+ struct RMC_executable **tmp_executables = new RMC_executable*[num];
+
+ if (worker_executables != NULL) {
+ for ( i = 0; i < num_executables; i++ ) {
+ tmp_executables[i] = worker_executables[i];
+ //Jeff changed this.
+ worker_executables[i] = NULL;
+ }
+
+ delete [] worker_executables;
+ }
+
+ worker_executables = tmp_executables;
+ num_executables = num;
+}
+
+int
+MWRMComm::get_num_executables() {
+ return num_executables;
+}
+
+void MWRMComm::add_executable( int exec_class, int arch_class, char *exec_name,
+ char *requirements )
+{
+ if ( !exec_name )
+ return;
+
+ if( arch_class >= num_arches )
+ {
+ MWprintf( 10, "set_worker_attributes(): incrementing num_arches to %d\n",
+ arch_class + 1 );
+ num_arches = arch_class + 1;
+ }
+
+ MWprintf(31, "tempnum_executables = %d\n", tempnum_executables);
+ worker_executables[tempnum_executables] = new struct RMC_executable;
+ worker_executables[tempnum_executables]->arch_class = arch_class;
+ worker_executables[tempnum_executables]->exec_class = exec_class;
+ worker_executables[tempnum_executables]->executable = new char [ strlen(exec_name) + 1 ];
+ strcpy ( worker_executables[tempnum_executables]->executable, exec_name );
+ worker_executables[tempnum_executables]->executable_name =
+ process_executable_name ( worker_executables[tempnum_executables]->executable,
+ exec_class, arch_class );
+ if ( !requirements )
+ {
+ worker_executables[tempnum_executables]->attributes = NULL;
+ }
+ else
+ {
+ worker_executables[tempnum_executables]->attributes = new char [ strlen(requirements) + 1 ];
+ strcpy ( worker_executables[tempnum_executables]->attributes, requirements );
+ }
+ tempnum_executables++;
+}
+
+// This is the new, easy way to add executables. No more worrying about getting
+// calling order right, or setting up the wrong number of arrays.
+// We assume that this will be called a couple of times at startup, so
+// efficiency isn't a big concern.
+
+void
+MWRMComm::add_executable(const char *exec_name, const char *requirements)
+{
+ verify_file_exists(exec_name);
+ // exec class is the notion that you want to partition
+ // the number of executables into two or more groups, and
+ // try to maintain a different number in each group.
+
+ // Most codes don't need this, so always force it to one,
+ // no matter how many executables we have
+ set_num_exec_classes(1);
+
+ // make a new arch_class, and give it this requirements
+ int num_arches = get_num_arch_classes();
+ if (num_arches == -1) {
+ num_arches = 0;
+ }
+ set_num_arch_classes(1 + num_arches);
+ set_arch_class_attributes(get_num_arch_classes() - 1, requirements);
+
+ // make a new executable
+ set_num_executables(1 + get_num_executables());
+
+ RMC_executable *e = new struct RMC_executable;
+ e->exec_class = 0;
+ e->arch_class = get_num_arch_classes() - 1;
+ e->executable = strdup(exec_name);
+ e->attributes = ""; // Where is this used?
+ e->executable_name =
+ process_executable_name ( e->executable,
+ e->exec_class, e->arch_class );
+ worker_executables[get_num_executables() - 1] = e;
+}
+
+char* MWRMComm::process_executable_name( char *exec_name, int ex_cl, int ar_cl )
+{
+ char *newone = new char[strlen(exec_name) + 1];
+ strcpy ( newone, exec_name );
+ return newone;
+}
+
+// XXX Newly added get function so that we can know the target number of workers
+// and change the number for runtime adaptation
+
+int
+MWRMComm::get_target_num_workers ( int exec_class )
+{
+ if (exec_class == -1)
+ return target_num_workers;
+
+ if ( (exec_class > exec_classes) || (exec_class < -1) )
+ return -1;
+
+ return exec_class_target_num_workers[exec_class];
+}
+
+void
+MWRMComm::set_worker_increment(int newinc)
+{
+ if (newinc <= 0) {
+ MWprintf(1, "Unreasonable value: %d for set_worker_increment(). Ignoring.\n", newinc);
+ return;
+ }
+ hostinc_ = newinc < target_num_workers ? newinc : target_num_workers;
+}
+
+int
+MWRMComm::get_worker_increment() const
+{
+ return hostinc_;
+}
+
+void
+MWRMComm::set_target_num_workers ( int num_workers )
+{
+ set_target_num_workers ( -1, num_workers );
+}
+
+void
+MWRMComm::set_target_num_workers ( int exec_class, int num_workers )
+{
+ if ( exec_classes <= 0 )
+ {
+ exec_classes = 1;
+ exec_class_target_num_workers = new int[exec_classes];
+ exec_class_target_num_workers[0] = 0;
+ }
+
+ if ( exec_class < 0 )
+ {
+ exec_class_target_num_workers[0] = num_workers;
+ target_num_workers = exec_class_target_num_workers[0];
+ return;
+ }
+
+ target_num_workers -= exec_class_target_num_workers[exec_class];
+ exec_class_target_num_workers[exec_class] = num_workers;
+ target_num_workers += exec_class_target_num_workers[exec_class];
+ return;
+}
+
+void MWRMComm::set_worker_checkpointing( bool wc )
+{
+ if( wc == true )
+ MWprintf( 10, "Warning! Worker checkpointing not available in this CommRM implementation\n" );
+ worker_checkpointing = false;
+}
+
+void
+MWRMComm::verify_file_exists(const char *exec_name) {
+ FILE *f = fopen(exec_name, "r");
+ if (f == NULL) {
+ MWprintf(10, "ERROR: add_executable with %s, which doesn't exist or isn't readable\n", exec_name);
+ } else {
+ fclose(f);
+ }
+}
+
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq c-tab-always-indent nil)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/RMComm/MWRMComm.h b/MW/src/RMComm/MWRMComm.h
new file mode 100644
index 0000000..100bce0
--- /dev/null
+++ b/MW/src/RMComm/MWRMComm.h
@@ -0,0 +1,493 @@
+/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
+ *
+ * Condor Software Copyright Notice
+ * Copyright (C) 1990-2004, Condor Team, Computer Sciences Department,
+ * University of Wisconsin-Madison, WI.
+ *
+ * This source code is covered by the Condor Public License, which can
+ * be found in the accompanying LICENSE.TXT file, or online at
+ * www.condorproject.org.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
+ * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
+ * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
+ * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
+ * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
+ * RIGHT.
+ *
+ ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/
+#ifndef MWRMCOMM_H
+#define MWRMCOMM_H
+#include <MWWorkerID.h>
+#include "MWList.h"
+
+/** This class is an abstract layer over a Resource Management (RM) and
+ Communication (Comm) layer. Hence the RMComm name. It is designed
+ to abstract away the differences between various systems.
+
+ The member functions in this class fall into two categories:
+ Resource Management and Message Passing (Communication). The "master"
+ in a master-worker application will use both; the worker will only
+ use the communication facilities.
+*/
+
+enum MWRMCommErrors {
+ WORKER_TIMEOUT = -50,
+ UNABLE_TO_WAKE = -49,
+ CANNOT_OPEN_INPUT_FILE = -48,
+ SCANF_ERROR_ON_INPUT_FILE = -47,
+ MESSAGE_SEQUENCE_ERROR = -46,
+ UNKNOWN_DATA_TYPE = -45,
+ WAITFILE_PROTOCOL_ERROR = -44,
+ FAIL_MASTER_SEND = -43,
+ CHECKSUM_ERROR_EXIT = -42,
+ UNKNOWN_COMMAND = -41,
+ INIT_REPLY_FAILURE = -40,
+ UNPACK_FAILURE = -39
+};
+
+struct RMC_executable
+{
+ int arch_class;
+ int exec_class;
+ char *executable;
+ char *executable_name;
+ char *attributes;
+};
+
+class MWRMComm {
+
+ friend class MWDriver;
+
+public:
+
+ /** Constructor. Sets data to -1's. */
+ MWRMComm();
+
+ /// Destructor...
+ virtual ~MWRMComm();
+
+ /** @name A. Resource Management Functions
+
+ Here are all the methods you could want to have for managing
+ a set of machines. See each method for details...
+ */
+ //@{
+
+ /** System shutdown. Does not return.
+ @param exitval The value to call ::exit() with
+ */
+ virtual void exit( int exitval );
+
+ /** Initialization of the master process. This will be called
+ one time only when the master starts up.
+ @return 0 on success, -1 on failure
+ */
+ virtual int setup( int argc, char* argv[], int *my_id, int *master_id ) = 0;
+
+ /** This returns the state of the "virtual machine" - aka the
+ set of workers under the master's control.
+ @param nhosts The number of hosts
+ @param narches The number of architechture classes
+ @param w A pointer to a pointer to an array of pointers.
+ This should be NULL when called; config() will allocate
+ the memory using new and return it to you. Don't forget
+ to delete not only the elements in that array, but
+ also the array itself. The array will have nhosts
+ elements, and they will each represent a worker
+ machine.
+ @return 0 on success, -1 on error.
+ */
+ virtual int config( int *nhosts, int *narches, MWWorkerID ***w ) { return 0; };
+
+ /** Start a worker on a machine that has been given to you.
+ This is really only important if the process of starting
+ a worker is two-stage. For instance, in pvm, you
+ first get a machine. THEN you have to spawn an
+ executable on that machine. For something like MW-files,
+ once you get a worker it already has the executable
+ started on it. In that case this will basically be
+ a no-op.
+ @param w A pointer to a MWWorkerID. This must point
+ to allocated memory. It is filled with info like the
+ machine name, id2, and the arch.
+ @return id2 on success, -1 on failure
+ */
+ virtual int start_worker( MWWorkerID *w ) = 0;
+
+ /** This routine is used to start up multiple workers at
+ the beginning of a run. It should only be called one
+ time. It basically does a config() to find out what
+ machines are available, and then starts a worker on
+ each of them. You may want to check the implementations
+ for details...
+ @param nworkers The number of workers at the start (returned!)
+ @param workers A pointer to a pointer to an array of
+ MWWorkerID pointers. The memory management for this
+ is the same as it is for the config() call - it should
+ be null when called and will point to allocated memory
+ when it comes back.
+ @return 0 on success, -1 on failure
+ */
+ virtual int init_beginning_workers( int *nworkers, MWWorkerID ***workers ) = 0;
+
+ /** Remove a worker from the virtual machine. This call
+ will delete w, so don't reference that memory again!
+ @param w The MWWorkerID of the machine to remove.
+ @return 0 on success, a negative number on failure
+ */
+ virtual int removeWorker( MWWorkerID *w ) = 0;
+ //@}
+
+ /** @name B. Checkpointing Functions */
+ //@{
+ /** Write out internal state to a FILE *
+ */
+ virtual int write_checkpoint( FILE * fp );
+
+ /** Read in restart information from a FILE *
+ */
+ virtual int read_checkpoint( FILE * fp );
+
+ /** Some Low level specific read/write functions */
+ virtual int read_RMstate( FILE *fp );
+ ///
+ virtual int write_RMstate ( FILE *fp );
+
+ /** A function to restart the workers. This is called at restart from
+ a ckpt file and it is meant to re-init all the workers.
+ */
+ virtual int restart_beginning_workers ( int *num, MWWorkerID ***tempWorkers, MWmessages msg ) = 0;
+ //@}
+
+ /** @name C. Executable Management Interface functions */
+ //@{
+
+ /** Set the number of executable classes */
+ void set_num_exec_classes ( int num );
+
+ /** Returns the above number */
+ int get_num_exec_classes ( );
+
+ /** Set the number of arch classes */
+ void set_num_arch_classes( int n );
+
+ /** set the arch attribute */
+ void set_arch_class_attributes ( int arch_class, const char *attr );
+
+ /** Return the number of arch classes */
+ int get_num_arch_classes();
+
+ /** Set the number of executables */
+ void set_num_executables ( int num );
+
+ int get_num_executables();
+
+ /** Set the name of the binary and the requirements string
+ for an arch class. Technically, the requirements string
+ is not needed for MWPvmRC - it is defined in the submit
+ file. It *is* needed in the MWFileRC, however, for job
+ submission.
+ @param arch_class This specifies which arch class the above
+ requirements will apply to.
+ @param exec_name The name of the worker executable for
+ this arch class.
+ @param requirements A string containing the "requirements"
+ attribute of a given arch class of workers. This will
+ be something that can be used in a submit file, like
+ "(arch == \"INTEL\" && opsys == \"SOLARIS26\")"
+ */
+ void add_executable ( int exec_class, int arch_class, char *exec_name,
+ char *requirements );
+
+ // The new, better way to do the above
+ void add_executable(const char *exec_name, const char *requirements);
+
+ /** If the RM software needs to "process" the executable name in
+ some way, this is done here.
+ */
+ virtual char* process_executable_name ( char* exec_name, int ex_cl, int num_arc );
+
+ /** Set whether or not you would like worker checkpointing
+ (if the CommRM implementation has the capability)
+ */
+ virtual void set_worker_checkpointing( bool wc );
+
+protected:
+
+ /** The number of exec classes */
+ int exec_classes;
+
+ /** The number of different arch classes. */
+ int num_arches;
+
+ /** The arch attributes */
+ char **arch_class_attributes;
+
+ /** The number of executables */
+ int num_executables;
+ int tempnum_executables;
+
+ /** An array containing the {\bf full} pathnames of the executables.
+ Element 0 is for arch "0", element 1 is for arch "1", etc.
+ Usually read in get get_userinfo().
+ */
+ struct RMC_executable **worker_executables;
+
+ /// Would you like the workers to be checkpointed
+ bool worker_checkpointing;
+
+ /* moved here from MWDriver.C, to separate RMC and MW more */
+ int *MW_exec_class_num_workers;
+
+ //@}
+
+public:
+
+ /** @name D. Host Management Members */
+ //@{
+ /** Set a "target" number of workers across all arches. This
+ is useful if you don't care how many you get of each arch...
+ @param num_workers The target number of workers
+ */
+ void set_target_num_workers( int num_workers );
+
+ void set_target_num_workers( int exec_class, int num_workers );
+
+ // XXX Let the MWDriver/user know our current target number of workers
+ int get_target_num_workers(int exec_class = -1);
+
+ /** The RMComm will requests this many workers at a time */
+ void set_worker_increment(int newinc);
+
+ int get_worker_increment() const;
+
+protected:
+
+ /** This will figure out if we need to ask for more hosts
+ or remove hosts. It is called whenever a host is added
+ or removed from the system, or set_target_num_workers()
+ is called.
+ @param num_workers A pointer to an array of length
+ num_arches that contains the number of workers for
+ each arch class.
+ @return If we have more workers than we need, we return a
+ positive number as the "excess" that can be deleted.
+ */
+ virtual int hostaddlogic( int *num_workers ) = 0;
+
+ /** The desired number of workers */
+ int target_num_workers;
+
+ /** The desired number of workers, exec_class wise */
+ int *exec_class_target_num_workers;
+
+ /** The current */
+ int hostinc_;
+
+ //@}
+
+public:
+
+ /** @name The Communication Routines
+
+ These message passing routines are very closely modeled on
+ PVM's message passing facility. They are, however, pretty
+ generic in that any message passing interface should be
+ able to implement them.
+ */
+
+ //@{
+
+ /** Initialize a buffer for sending some data.
+ @param encoding Defined by each application. 0 = default */
+ virtual int initsend ( int encoding = 0 ) = 0;
+ /** Send the data that has been packed.
+ @param to_whom An identifier for the recipient
+ @param msgtag A 'tag' to identify that type of message */
+ virtual int send ( int to_whom, int msgtag ) = 0;
+
+ //by jae
+ virtual int pre_send ( int msgtag) { return -1; }
+ virtual void setPollTimeOut(int secs) {}
+
+ /** Receive some data that has been packed. Should make this
+ more PVM-independent; will do this sometime.
+ @param from_whom From a specific source; -1 is from all
+ @param msgtag With a certain tag; -1 is all. */
+ virtual int recv ( int from_whom, int msgtag ) = 0;
+
+ /** non-blocking receive. This is the same as recv except it
+ returns the NO_MESSAGE tag instead of blocking if there is
+ no data in the buffer */
+ virtual int nrecv( int from_whom, int msgtag){return ABORT;};
+
+ /** Provide info on the message just received */
+ virtual int bufinfo ( int buf_id, int *len, int *tag, int *from ) = 0;
+
+ /** For some system events like HOSTDELETE, TASKEXIT, etc, this will tell
+ who was affected */
+ virtual void who ( int *wh ) = 0;
+
+ /** Needed only for MW-Independent */
+ virtual void hostadd ( ) { };
+
+ /** @name Pack Functions
+
+ In the following pack() functions, there are some common themes.
+ First, each stuffs some data into a buffer to be sent. The
+ nitem parameter is just a count of the number of items. The
+ stride parameter specifies *which* items to pack. 1 implies
+ all, 2 would be every 2nd item, 3 is every 3rd item, etc.
+
+ The return value is user defined. It should be standardized,
+ but I'll do that later.
+ */
+ //@{
+
+ /// Pack some bytes
+ virtual int pack ( const char *bytes, int nitem, int stride = 1 ) = 0;
+ /// float
+ virtual int pack ( const float *f, int nitem, int stride = 1 ) = 0;
+ /// double
+ virtual int pack ( const double *d, int nitem, int stride = 1 ) = 0;
+ /// int
+ virtual int pack ( const int *i, int nitem, int stride = 1 ) = 0;
+ /// unsigned int
+ virtual int pack ( const unsigned int *ui, int nitem, int stride = 1 ) = 0;
+ /// short
+ virtual int pack ( const short *sh, int nitem, int stride = 1 ) = 0;
+ /// unsigned short
+ virtual int pack ( const unsigned short *ush, int nitem, int stride = 1 ) = 0;
+ /// long
+ virtual int pack ( const long *l, int nitem, int stride = 1 ) = 0;
+ /// unsigned long
+ virtual int pack ( const unsigned long *ul, int nitem, int stride = 1 ) = 0;
+ /// Pack a NULL-terminated string
+ virtual int pack ( const char *string ) = 0;
+
+ /// by jae
+ virtual void thread_start(int worker_id) {};
+ virtual void thread_stop(int worker_id) {};
+ /// Send raw data directly
+ virtual int raw_pack( char* buf, int len ) { return 0; };
+
+ /// Read raw data from Worker ID
+ virtual int raw_unpack( int from_whom, char* buf, int len ) { return 0; };
+
+ //@}
+
+ /** @name Unpack Functions
+
+ These unpack functions unpack data packed with the pack()
+ functions. See the pack() functions for more details.
+
+ */
+ //@{
+
+ /// Unpack some bytes
+ virtual int unpack ( char *bytes, int nitem, int stride = 1 ) = 0;
+ /// float
+ virtual int unpack ( float *f, int nitem, int stride = 1 ) = 0;
+ /// double
+ virtual int unpack ( double *d, int nitem, int stride = 1 ) = 0;
+ /// int
+ virtual int unpack ( int *i, int nitem, int stride = 1 ) = 0;
+ /// unsigned int
+ virtual int unpack ( unsigned int *ui, int nitem, int stride = 1 ) = 0;
+ /// short
+ virtual int unpack ( short *sh, int nitem, int stride = 1 ) = 0;
+ /// unsigned short
+ virtual int unpack ( unsigned short *ush, int nitem, int stride = 1 ) = 0;
+ /// long
+ virtual int unpack ( long *l, int nitem, int stride = 1 ) = 0;
+ /// unsigned long
+ virtual int unpack ( unsigned long *ul, int nitem, int stride = 1 ) = 0;
+ /// Unpack a NULL-terminated string
+ virtual int unpack ( char *string ) = 0;
+
+ //@}
+ //@}
+
+ ///
+ double get_bytes_packed() const { return bytes_packed_; }
+
+ ///
+ double get_bytes_unpacked() const { return bytes_unpacked_; }
+
+ /** When investigating the master-side bottleneck problem, we realized
+ * that sometimes the master can't handle all the messages sent from the
+ * many masters and the RMComm layer. The messages are accumulated in the
+ * RMComm layer's buffer (especially in the case of using MW-CondorPvm),
+ * but the master can't see them, not to mention process them or delete
+ * useless messages. This makes the master unable to accormodate the chanegs
+ * in the environment, also makes most of the workers waiting for new tasks.
+
+ * One way to deal with this situation is to pull all the messages in the
+ * underlying message passing layer and let the master buffer them by
+ * itself, to separate the message receiving and message processing steps.
+ *
+ * Thus we will introduce a FIFO list of buf_id (list of *int), each of the
+ * buf_id points to a message buffer in PVM (and likewise in the other
+ * RMComms). The original message processing steps are:
+ * RMC->recv()
+ * RMC->bufinfo()
+ * RMC->unpack(), RMC->unpack()
+ * And now the process will be the same, but implementation is different:
+ * RMC->recv_all() pull all messages out (in a non-blocking way) and
+ * put each message's buf_id into the FIFO list.
+ * RMC->recv() blocking recv
+ * RMC->bufinfo() examine the buf_info of the buffer with given buf_id
+ * RMC->setrbuf() will be used to switch the active receive buffer
+ * RMC->freebuf() will be used to free useless receive buffer
+ * RMC->unpack()
+ *
+ * All recv will via the buffer_list now!
+ */
+protected:
+ /* both the master and worker can have it! */
+ MWList<void> *recv_buf_list;
+
+ /// Keeps the number of bytes packed
+ double bytes_packed_;
+
+ /// Holds the number of bytes unpacked
+ double bytes_unpacked_;
+
+public:
+ /* returns the number of new buffers */
+ virtual int recv_all( int from_whom, int msgtag ) = 0;
+ /* switch the active receive buffer, return the old active buf_id */
+ virtual int setrbuf(int bid) = 0;
+ /* free the receive buffer. */
+ virtual int freebuf(int bid) = 0;
+ /* advance the active buffer to the next valid buffer in the recv_buf_list. */
+ virtual int next_buf() = 0;
+ /* return the recv_buf_list */
+ virtual MWList<void>* recv_buffers() = 0;
+ private:
+ void verify_file_exists(const char *);
+};
+
+#endif
+
+/*
+ Local Variables:
+ mode: c++
+ eval: (setq c-basic-offset 4)
+ eval: (setq c-comment-only-line-offset 4)
+ eval: (setq c-indent-level 4)
+ eval: (setq c-brace-imaginary-offset 0)
+ eval: (setq c-brace-offset 0)
+ eval: (setq c-argdecl-indent 0)
+ eval: (setq c-label-offset -4)
+ eval: (setq c-continued-statement-offset 4)
+ eval: (setq c-continued-brace-offset -4)
+ eval: (setq c-tab-always-indent nil)
+ eval: (setq tab-width 4)
+ End:
+*/
diff --git a/MW/src/RMComm/Makefile.in b/MW/src/RMComm/Makefile.in
new file mode 100644
index 0000000..7be0bdb
--- /dev/null
+++ b/MW/src/RMComm/Makefile.in
@@ -0,0 +1,155 @@
+#-------------------------------------------------------------------------
+# This file was automatically generated by Automake, and manually modified
+# to make it simpler and cleaner. There are three sections in the file:
+# 1) Macros
+# 2) Recursive Rules and Suffixes (implicit rules)
+# 3) Explicit Rules
+#-------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------
+# Section 1) Macros
+#-------------------------------------------------------------------------
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+CONDOR_DIR = @CONDOR_DIR@
+CXX = @CXX@
+MEASURE_DEFN = @MEASURE_DEFN@
+MISC_DEFN = @MISC_DEFN@
+MISC_LIB = @MISC_LIB@
+MW_LIBDIR = @MW_LIBDIR@
+MW_LIBDIR_DEBUG = @MW_LIBDIR_DEBUG@
+ENABLE_MWINDEPENDENT = @ENABLE_MWINDEPENDENT@
+PVM_ROOT = @PVM_ROOT@
+RANLIB = @RANLIB@
+USE_MWFILE = @USE_MWFILE@
+INSTALL = @INSTALL@
+SOCKET_LIB = @SOCKET_LIB@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+AR = ar
+
+DEFS = @DEFS@ -I.
+LIBS = @LIBS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@ -Wall
+
+# Subdirectories
+# only MW-Independent if building sans condor,
+ifeq ($(CONDOR_DIR), no)
+SUBDIRS := MW-Independent
+else
+
+# If we've got condor, we will have MW-Socket
+SUBDIRS := MW-Independent MW-Socket
+
+ifneq ($(PVM_ROOT), no)
+# Here we have Condor and pvm
+SUBDIRS := $(SUBDIRS) MW-CondorPVM
+endif
+
+ifneq ($(USE_MWFILE), no)
+# Here we have Condor and pvm
+SUBDIRS := $(SUBDIRS) MW-File
+endif
+
+ifneq ($(USE_MPI), no)
+SUBDIRS := $(SUBDIRS) MW-StaticMPI
+endif
+
+endif
+
+### Libraries to be built, and dependent source files
+# If ENDABLE_INDEPENDENT is yes (you can do that by configure --with-independent).
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+LIBRARIES = libMWRMComm.a libMWRMComm_indp.a
+else
+LIBRARIES = libMWRMComm.a
+endif
+
+libMWRMComm_a_SOURCES = MWRMComm.C
+libMWRMComm_a_OBJECTS = MWRMComm.o
+
+libMWRMComm_indp_a_OBJECTS = MWRMCommInd.o
+
+# To work with Insure, need to "setenv DEBUG_BUILD='insure'" and write/copy a good .psrc file
+ifdef DEBUG_BUILD
+DEBUG_CHECKER = $(DEBUG_BUILD)
+MW_LIBDIR = $(MW_LIBDIR_DEBUG)
+endif
+INCLUDES = -I. -I.. -I../src/MWControlTasks -IMW-File -IMW-CondorPVM -IMW-Socket $(MISC_DEFN) $(MEASURE_DEFN) #-I$(CONDOR_DIR)/include
+CXXCOMPILE = $(DEBUG_CHECKER) $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+INDP_CXXCOMPILE = $(CXXCOMPILE) -DINDEPENDENT
+
+INCLUDEFILES = MWRMComm.h
+
+#-------------------------------------------------------------------------
+# Section 2) Explicit and Implicit Rules
+#-------------------------------------------------------------------------
+
+all: $(LIBRARIES)
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+libMWRMComm.a: $(libMWRMComm_a_OBJECTS) $(libMWRMComm_a_DEPENDENCIES)
+ -rm -f libMWRMComm.a
+ $(AR) cru libMWRMComm.a $(libMWRMComm_a_OBJECTS) $(libMWRMComm_a_LIBADD)
+ $(RANLIB) libMWRMComm.a
+ cp libMWRMComm.a $(MW_LIBDIR)
+
+ifeq ($(ENABLE_MWINDEPENDENT), yes)
+libMWRMComm_indp.a: $(libMWRMComm_indp_a_OBJECTS)
+ -rm -f libMWRMComm_indp.a
+ $(AR) cru libMWRMComm_indp.a $(libMWRMComm_indp_a_OBJECTS)
+ $(RANLIB) libMWRMComm_indp.a
+ cp libMWRMComm_indp.a $(MW_LIBDIR)
+MWRMCommInd.o:MWRMComm.C
+ $(INDP_CXXCOMPILE) -o MWRMCommInd.o -c MWRMComm.C
+endif
+
+.SUFFIXES: .C .o
+
+.C.o:
+ $(CXXCOMPILE) -c $<
+
+#-------------------------------------------------------------------------
+# Section 3) Recursive Rules: Auto-generated
+#-------------------------------------------------------------------------
+install: $(LIBRARIES)
+ $(mkinstalldirs) $(libdir)
+ @list='$(LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(libdir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(libdir)/$$p; \
+ echo " $(RANLIB) $(libdir)/$$p"; \
+ $(RANLIB) $(libdir)/$$p; \
+ fi; \
+ done
+ $(mkinstalldirs) $(includedir)
+ @list='$(INCLUDEFILES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " ${INSTALL} -m 644 $$p $(includedir)/$$p"; \
+ $(INSTALL) -m 644 $$p $(includedir)/$$p; \
+ fi; \
+ done
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+check:
+
+clean:
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+distclean:
+ -rm -f Makefile *.tar *.gz
+ -rm -rf .deps
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -rm -f *.o *.a *core *.ii
+ [ "__$(SUBDIRS)" = "__" ] || for subdir in `echo "$(SUBDIRS)"`; do (cd $$subdir && $(MAKE) $@) ; done
+
+.PHONY: all check clean distclean install
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..4be7bb5
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,91 @@
+if HAVE_CONDOR
+ MAYBE_MW = MW
+endif
+
+ALWAYS_BUILT = src/util src/math src/seq src/manager src/fsa src/annealing src/main display perl examples doc html tests
+SUBDIRS = $(MAYBE_MW) $(ALWAYS_BUILT)
+DIST_SUBDIRS = $(ALWAYS_BUILT)
+
+EXTRA_DIST = LICENSE COPYING $(MW_DIST)
+
+# Possibly regenerate version file if this is a git repository.
+$(top_srcdir)/version.m4: FORCE
+ @cd $(top_srcdir); if test -r version.sh; then ./version.sh; fi
+.PHONY: FORCE
+
+MW_DIST = \
+ MW/acinclude.m4 \
+ MW/aclocal.m4 \
+ MW/configure \
+ MW/configure.in \
+ MW/COPYING \
+ MW/doxygen.conf \
+ MW/INSTALL \
+ MW/install-sh \
+ MW/Makefile.in \
+ MW/missing \
+ MW/mkinstalldirs \
+ MW/README \
+ MW/src/BlackBox/MWDriver_blackbox.C \
+ MW/src/BlackBox/MWDriver_blackbox.h \
+ MW/src/BlackBox/MWTask_blackbox.C \
+ MW/src/BlackBox/MWTask_blackbox.h \
+ MW/src/BlackBox/MWWorkerMain_blackbox.C \
+ MW/src/BlackBox/MWWorker_blackbox.C \
+ MW/src/BlackBox/MWWorker_blackbox.h \
+ MW/src/BlackBox/Makefile.in \
+ MW/src/MW.C \
+ MW/src/MW.h \
+ MW/src/MWControlTasks/MWNWSTask.C \
+ MW/src/MWControlTasks/MWNWSTask.h \
+ MW/src/MWControlTasks/Makefile.in \
+ MW/src/MWDriver.C \
+ MW/src/MWDriver.h \
+ MW/src/MWGroup.C \
+ MW/src/MWGroup.h \
+ MW/src/MWList.C \
+ MW/src/MWList.h \
+ MW/src/MWMasterMain.C \
+ MW/src/MWStats.C \
+ MW/src/MWStats.h \
+ MW/src/MWSystem.h \
+ MW/src/MWTask.C \
+ MW/src/MWTask.h \
+ MW/src/MWTaskContainer.C \
+ MW/src/MWTaskContainer.h \
+ MW/src/MWUnixSystem.C \
+ MW/src/MWWinSystem.C \
+ MW/src/MWWorker.C \
+ MW/src/MWWorker.h \
+ MW/src/MWWorkerID.C \
+ MW/src/MWWorkerID.h \
+ MW/src/MWWorkerMain.C \
+ MW/src/MWprintf.C \
+ MW/src/MWprintf.h \
+ MW/src/Makefile.in \
+ MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.C \
+ MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.h \
+ MW/src/RMComm/MW-CondorPVM/Makefile.in \
+ MW/src/RMComm/MW-File/MWFileError.h \
+ MW/src/RMComm/MW-File/MWFileRC.C \
+ MW/src/RMComm/MW-File/MWFileRC.h \
+ MW/src/RMComm/MW-File/MWFileRCSymbol.h \
+ MW/src/RMComm/MW-File/MWFileSend.h \
+ MW/src/RMComm/MW-File/MWFileTypes.h \
+ MW/src/RMComm/MW-File/MWFileWorker.h \
+ MW/src/RMComm/MW-File/Makefile.in \
+ MW/src/RMComm/MW-File/chirp_client.c \
+ MW/src/RMComm/MW-File/chirp_client.h \
+ MW/src/RMComm/MW-File/chirp_protocol.h \
+ MW/src/RMComm/MW-Independent/MWIndRC.C \
+ MW/src/RMComm/MW-Independent/MWIndRC.h \
+ MW/src/RMComm/MW-Independent/Makefile.in \
+ MW/src/RMComm/MW-Socket/MWSocketRC.C \
+ MW/src/RMComm/MW-Socket/MWSocketRC.h \
+ MW/src/RMComm/MW-Socket/Makefile.in \
+ MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.C \
+ MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.h \
+ MW/src/RMComm/MW-StaticMPI/Makefile.in \
+ MW/src/RMComm/MWRMComm.C \
+ MW/src/RMComm/MWRMComm.h \
+ MW/src/RMComm/Makefile.in
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..6db73e7
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,872 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/configure $(am__configure_deps) \
+ $(srcdir)/config.h.in $(top_srcdir)/display/mad/manifest.mf.in \
+ COPYING README build-aux/ar-lib build-aux/compile \
+ build-aux/config.guess build-aux/config.sub build-aux/depcomp \
+ build-aux/install-sh build-aux/missing \
+ $(top_srcdir)/build-aux/ar-lib $(top_srcdir)/build-aux/compile \
+ $(top_srcdir)/build-aux/config.guess \
+ $(top_srcdir)/build-aux/config.sub \
+ $(top_srcdir)/build-aux/install-sh \
+ $(top_srcdir)/build-aux/missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = display/mad/manifest.mf
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ cscope distdir dist dist-all distcheck
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+ $(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ if test -d "$(distdir)"; then \
+ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -rf "$(distdir)" \
+ || { sleep 5 && rm -rf "$(distdir)"; }; \
+ else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ at HAVE_CONDOR_TRUE@MAYBE_MW = MW
+ALWAYS_BUILT = src/util src/math src/seq src/manager src/fsa src/annealing src/main display perl examples doc html tests
+SUBDIRS = $(MAYBE_MW) $(ALWAYS_BUILT)
+DIST_SUBDIRS = $(ALWAYS_BUILT)
+EXTRA_DIST = LICENSE COPYING $(MW_DIST)
+MW_DIST = \
+ MW/acinclude.m4 \
+ MW/aclocal.m4 \
+ MW/configure \
+ MW/configure.in \
+ MW/COPYING \
+ MW/doxygen.conf \
+ MW/INSTALL \
+ MW/install-sh \
+ MW/Makefile.in \
+ MW/missing \
+ MW/mkinstalldirs \
+ MW/README \
+ MW/src/BlackBox/MWDriver_blackbox.C \
+ MW/src/BlackBox/MWDriver_blackbox.h \
+ MW/src/BlackBox/MWTask_blackbox.C \
+ MW/src/BlackBox/MWTask_blackbox.h \
+ MW/src/BlackBox/MWWorkerMain_blackbox.C \
+ MW/src/BlackBox/MWWorker_blackbox.C \
+ MW/src/BlackBox/MWWorker_blackbox.h \
+ MW/src/BlackBox/Makefile.in \
+ MW/src/MW.C \
+ MW/src/MW.h \
+ MW/src/MWControlTasks/MWNWSTask.C \
+ MW/src/MWControlTasks/MWNWSTask.h \
+ MW/src/MWControlTasks/Makefile.in \
+ MW/src/MWDriver.C \
+ MW/src/MWDriver.h \
+ MW/src/MWGroup.C \
+ MW/src/MWGroup.h \
+ MW/src/MWList.C \
+ MW/src/MWList.h \
+ MW/src/MWMasterMain.C \
+ MW/src/MWStats.C \
+ MW/src/MWStats.h \
+ MW/src/MWSystem.h \
+ MW/src/MWTask.C \
+ MW/src/MWTask.h \
+ MW/src/MWTaskContainer.C \
+ MW/src/MWTaskContainer.h \
+ MW/src/MWUnixSystem.C \
+ MW/src/MWWinSystem.C \
+ MW/src/MWWorker.C \
+ MW/src/MWWorker.h \
+ MW/src/MWWorkerID.C \
+ MW/src/MWWorkerID.h \
+ MW/src/MWWorkerMain.C \
+ MW/src/MWprintf.C \
+ MW/src/MWprintf.h \
+ MW/src/Makefile.in \
+ MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.C \
+ MW/src/RMComm/MW-CondorPVM/MWCondorPvmRC.h \
+ MW/src/RMComm/MW-CondorPVM/Makefile.in \
+ MW/src/RMComm/MW-File/MWFileError.h \
+ MW/src/RMComm/MW-File/MWFileRC.C \
+ MW/src/RMComm/MW-File/MWFileRC.h \
+ MW/src/RMComm/MW-File/MWFileRCSymbol.h \
+ MW/src/RMComm/MW-File/MWFileSend.h \
+ MW/src/RMComm/MW-File/MWFileTypes.h \
+ MW/src/RMComm/MW-File/MWFileWorker.h \
+ MW/src/RMComm/MW-File/Makefile.in \
+ MW/src/RMComm/MW-File/chirp_client.c \
+ MW/src/RMComm/MW-File/chirp_client.h \
+ MW/src/RMComm/MW-File/chirp_protocol.h \
+ MW/src/RMComm/MW-Independent/MWIndRC.C \
+ MW/src/RMComm/MW-Independent/MWIndRC.h \
+ MW/src/RMComm/MW-Independent/Makefile.in \
+ MW/src/RMComm/MW-Socket/MWSocketRC.C \
+ MW/src/RMComm/MW-Socket/MWSocketRC.h \
+ MW/src/RMComm/MW-Socket/Makefile.in \
+ MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.C \
+ MW/src/RMComm/MW-StaticMPI/MWStaticMPIRC.h \
+ MW/src/RMComm/MW-StaticMPI/Makefile.in \
+ MW/src/RMComm/MWRMComm.C \
+ MW/src/RMComm/MWRMComm.h \
+ MW/src/RMComm/Makefile.in
+
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh: Makefile
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+ @test -f $@ || rm -f stamp-h1
+ @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+display/mad/manifest.mf: $(top_builddir)/config.status $(top_srcdir)/display/mad/manifest.mf.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+ test ! -s cscope.files \
+ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+ -rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+ -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__post_remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+ $(am__post_remove_distdir)
+
+dist-lzip: distdir
+ tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+ $(am__post_remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+ $(am__post_remove_distdir)
+
+dist-tarZ: distdir
+ @echo WARNING: "Support for shar distribution archives is" \
+ "deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__post_remove_distdir)
+
+dist-shar: distdir
+ @echo WARNING: "Support for distribution archives compressed with" \
+ "legacy program 'compress' is deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__post_remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__post_remove_distdir)
+
+dist dist-all:
+ $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+ $(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lz*) \
+ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir)
+ chmod u+w $(distdir)
+ mkdir $(distdir)/_build $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build \
+ && ../configure \
+ $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ --srcdir=.. --prefix="$$dc_install_base" \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__post_remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @test -n '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: trying to run $@ with an empty' \
+ '$$(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ $(am__cd) '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) all install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--refresh check check-am clean clean-cscope clean-generic \
+ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+ distcheck distclean distclean-generic distclean-hdr \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Possibly regenerate version file if this is a git repository.
+$(top_srcdir)/version.m4: FORCE
+ @cd $(top_srcdir); if test -r version.sh; then ./version.sh; fi
+.PHONY: FORCE
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/README b/README
new file mode 100644
index 0000000..f77918d
--- /dev/null
+++ b/README
@@ -0,0 +1,357 @@
+
+==================================================================
+ FSA
+
+ Distance-based multiple sequence alignment
+==================================================================
+
+FSA is a probabilistic multiple sequence alignment algorithm which uses
+a "distance-based" approach to aligning homologous protein, RNA or DNA
+sequences. Much as distance-based phylogenetic reconstruction methods
+like Neighbor-Joining build a phylogeny using only pairwise divergence
+estimates, FSA builds a multiple alignment using only pairwise
+estimations of homology. This is made possible by the sequence
+annealing technique for constructing a multiple alignment from pairwise
+comparisons, developed by Ariel Schwartz in
+"Posterior Decoding Methods for Optimization and Control of Multiple
+Alignments." Ph.D. Thesis, UC Berkeley. 2007.
+
+FSA brings the high accuracies previously available only for small-scale
+analyses of proteins or RNAs to large-scale problems such as aligning
+thousands of sequences or megabase-long sequences. FSA introduces
+several novel methods for constructing better alignments:
+
+ * FSA uses machine-learning techniques to estimate gap and
+ substitution parameters on the fly for each set of input sequences.
+ This "query-specific learning" alignment method makes FSA very robust: it
+ can produce superior alignments of sets of homologous sequences
+ which are subject to very different evolutionary constraints.
+
+ * FSA is capable of aligning hundreds or even thousands of sequences
+ using a randomized inference algorithm to reduce the computational
+ cost of multiple alignment. This randomized inference can be over
+ ten times faster than a direct approach with little loss of
+ accuracy.
+
+ * FSA can quickly align very long sequences using the "anchor
+ annealing" technique for resolving anchors and projecting them with
+ transitive anchoring. It then stitches together the alignment
+ between the anchors using the methods described above.
+
+ * The included GUI, MAD (Multiple Alignment Display), can display
+ the intermediate alignments produced by FSA, where each character
+ is colored according to the probability that it is correctly
+ aligned.
+
+FSA was created by Robert Bradley. It was developed by Robert Bradley,
+Colin Dewey, Jaeyoung Do, Sudeep Juvekar, Lior Pachter, Adam Roberts,
+and Michael Smoot, along with assistance from many other people.
+All have made intellectual contributions and contributed code.
+
+Please contact us at fsa at math.berkeley.edu with any questions, feedback, etc.
+
+If you use FSA, please cite:
+Bradley RK, Roberts A, Smoot M, Juvekar S, Do J, Dewey C, Holmes I, Pachter L (2009) Fast Statistical Alignment. PLoS Computational Biology. 5:e1000392.
+(This manuscript can be found in the doc/ directory.)
+
+
+==================================================================
+
+ INSTALLATION
+
+FSA is built and installed by running the following commands:
+
+./configure
+make
+make install
+
+If you wish to install the fsa files in a location other than your
+system's standard directories (which usually requires root permissions),
+specify the top-level installation directory with the --prefix option to
+configure. For example,
+
+./configure --prefix=$HOME
+
+specifies that binaries should be installed in $HOME/bin, libraries in
+$HOME/lib, etc..
+
+If you wish to align long sequences, then you must install MUMmer,
+which FSA calls to get candidate anchors between sequences.
+You can download MUMmer from http://mummer.sourceforge.net/.
+When running configure, you must either have the mummer executable in your path
+or specify the executable with the --with-mummer option to configure, e.g.
+
+./configure --with-mummer=/usr/local/MUMmer3.20/mummer
+
+if it is located at /usr/local/MUMmer3.20/mummer.
+
+FSA can also call exonerate to detect remote homology.
+You can download exonerate from http://www.ebi.ac.uk/~guy/exonerate/.
+When running configure, you must either have the exonerate executable in your path
+or specify the executable with the --with-exonerate option to configure, e.g.
+
+./configure --with-exonerate=/usr/local/bin/exonerate
+
+if it is located at /usr/local/bin/exonerate.
+
+
+==================================================================
+
+ USAGE
+
+FSA accepts FASTA-format input files and outputs multi-FASTA
+alignments by default. The most basic usage is:
+ fsa <mysequences.fa> >myalignedsequences.mfa
+or
+ fsa --stockholm <mysequences.fa> >myalignedsequences.stk
+
+Many options are provided. Please see html/FAQ.html for more information.
+
+
+==================================================================
+
+ REFERENCES
+
+Source code in 'seq/' and 'util/' is from Ian Holmes's DART library,
+which is used for input and output routines.
+
+FSA's DP code was generated by HMMoC by Gerton Lunter. The
+'aligner' example distributed with HMMoC, which implements a
+learning procedure for gap parameters, was an inspiration for FSA's
+learning strategies. FSA's banding code is taken directly from the
+'aligner' example.
+
+The sequence annealing technique for constructing a multiple
+alignment from pairwise comparisons was developed by Ariel Schwartz.
+The implementation of sequence annealing in FSA is based on
+the original implementation in AMAP by Ariel Schwartz and Lior Pachter.
+
+The anchor annealing approach used in FSA is modeled after the recursive
+anchoring strategy used in MAVID by Nicolas Bray and Lior Pachter.
+
+The MAD GUI interface to FSA was written by Adam Roberts based on
+a preliminary version by Michael Smoot.
+
+Please see:
+
+I. Holmes and R. Durbin. "Dynamic Programming Alignment Accuracy." Journal of Computational Biology. 1998, 5 (3):493-504.
+G.A. Lunter. "HMMoC - a Compiler for Hidden Markov Models." Bioinformatics. 2007, 23 (18):2485-2487.
+A.S. Schwartz. "Posterior Decoding Methods for Optimization and Control of Multiple Alignments." Ph.D. Thesis, UC Berkeley. 2007.
+A.S. Schwartz and L. Pachter. "Multiple Alignment by Sequence Annealing." Bioinformatics. 2007, 23 (2):e24-e29.
+N. Bray and L. Pachter "MAVID: Constrained Ancestral Alignment of Multiple Sequences." Genome Research. 2004, 14:693-699.
+
+
+==================================================================
+
+ COPYRIGHT
+
+Copyright (C) 2008. The Regents of the University of California (Regents).
+All Rights Reserved. Permission to use, copy, modify, and distribute this software
+and its documentation for educational, research, and not-for-profit purposes,
+without fee and without a signed licensing agreement, is hereby granted,
+provided that the above copyright notice, this paragraph and the following two paragraphs
+appear in all copies, modifications, and distributions.
+Contact
+The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue,
+Suite 510, Berkeley, CA 94720-1620, (510) 643-7201
+for commercial licensing opportunities.
+Created by
+Robert K. Bradley, Departments of Math and Molecular and Cell Biology,
+University of California, Berkeley.
+
+IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
+AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
+ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
+REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+
+==================================================================
+
+ LICENSE
+
+
+Please see the file LICENSE distributed with FSA.
+
+
+FSA 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.
+
+FSA 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 FSA; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+==================================================================
+
+ VERSION HISTORY
+
+1.01, 7/10/2008
+ -- Initial import to Git (Robert Bradley)
+
+1.02, 7/21/08
+ -- Faster anchor annealing (Robert Bradley)
+ -- GUI added to package (Adam Roberts)
+
+1.03, 7/25/08
+ -- Improved GUI features (Adam Roberts)
+
+1.04, 7/28/08
+ -- Moved to autotools (Colin Dewey)
+
+1.05, 8/21/08
+ -- Optional anchor annealing in protein space (Robert Bradley)
+ -- Reduced GUI memory usage (Adam Roberts)
+ -- Many accuracy measures for GUI (Adam Roberts and Robert Bradley)
+
+1.06, 8/29/08
+ -- Homology no longer forced at anchor boundaries (Robert Bradley)
+ -- Scripts for evaluating alignment accuracies according to FSA's model (Robert Bradley)
+
+1.07, 9/2/08
+ -- GUI bugfix for displaying extremely certain alignments (Robert Bradley)
+ (Alignment inference is unaffected.)
+
+1.08, 9/15/08
+ -- Miscellaneous compilation fixes (Robert Bradley)
+ -- Fix for learning on highly-conserved alignments (Robert Bradley)
+
+1.09, 10/22/08
+ -- Much faster sequence annealing (Robert Bradley, Colin Dewey & Lior Pachter)
+ -- Better memory usage for long sequences (Robert Bradley)
+ -- Optional Mercator constraints (Robert Bradley and Colin Dewey)
+ -- Optional anchoring with exonerate (Robert Bradley)
+ -- GUI can export TIFF images (Robert Bradley)
+ -- gapcleaner fix (Robert Bradley)
+ -- Parallelization mode (Jaeyoung Do and Colin Dewey)
+ -- Database mode (Jaeyoung Do and Colin Dewey)
+ -- Added submitted manuscript as manual.
+
+(The below versions are labeled as "major.minor.bugfix")
+
+1.10.0, 10/30/08
+ -- --nucprot option and utility programs translate and prot2codon (Robert Bradley & Colin Dewey)
+ -- Bugfixes for anchoring with both Mercator & exonerate (Robert Bradley & Colin Dewey)
+ -- Bugfixes for parallelization & database modes (Jaeyoung Do & Colin Dewey)
+
+1.11.0, 11/11/08
+ -- housekeeping tasks (Robert Bradley):
+ - gaps stripped from input sequences
+ - error thrown if 2 alignable sequence are left unaligned due to RAM constraints
+ -- hardmasked sequence is left unaligned by default (Robert Bradley)
+
+1.11.1, 11/13/08
+ -- Bugfixes for anchoring with both Mercator & exonerate (Robert Bradley & Colin Dewey)
+ -- Compilation fixes for g++ 4.4 (Robert Bradley)
+
+1.11.2, 11/14/08
+ -- Bugfix for GUI compilation (Colin Dewey)
+
+1.12.0, 11/22/08
+ -- Perl scripts to interact with FSA-Mercator
+ whole-genome alignments (Robert Bradley & Colin Dewey)
+ -- Switch to using only ungapped exonerate anchors (Robert Bradley & Colin Dewey)
+
+1.12.1, 11/27/08
+ -- Source code documentation updated for Doxygen compatibility (Robert Bradley)
+
+1.13.0, 1/9/09
+ -- C++ tools for working with FSA-Mercator whole-genome alignments (Robert Bradley & Colin Dewey)
+ (Note that the deprecated Perl scripts had a serious bug for - strand extraction!)
+ -- Bugfix for softmasking with exonerate (Robert Bradley & Colin Dewey)
+ -- Completely re-written sequence and alignment representation code (Robert Bradley)
+ -- Use a model with 2 sets, rather than 1 set, of indel states by default
+ -- Turn iterative refinement on by default with an unlimited number of steps
+
+1.13.1, 1/9/09
+ -- Bugfix and better automated options for --nucprot (Robert Bradley)
+
+1.13.2, 1/12/09
+ -- Compilation fixes for g++ 4.4 (Robert Bradley)
+
+1.13.3, 1/14/09
+ -- Bugfix for alphabet case-sensitivity during learning (Robert Bradley)
+
+1.13.4, 2/6/09
+ -- Bugfix for % ID calculation for sliced alignments (Robert Bradley)
+ -- More intuitive default anchoring options (Colin Dewey)
+ -- Bugfix for hardmasked error after compilation without MUMmer on OS X 10.4 (Robert Bradley)
+
+1.14.0, 3/11/09
+ -- Added experimental --tree-weights option (Robert Bradley)
+ -- Added experimental --load-probs option (Robert Bradley)
+ -- Changed default behavior when two sequences have no detectable homology; see new option --require-homology (Robert Bradley)
+ -- New utility program slice_fasta to extract subsequences from FASTA files (Robert Bradley).
+
+1.14.1, 3/20/09
+ -- Changed Mercator-related short options to use upper-case letters (Robert Bradley).
+ -- Mercator slicing stuff now assumes a + strand if strand is unspecified; previously implicitly assumed - (Robert Bradley)
+ -- Tiny bugfix for map_gff_coords: --force-entry was accidentally on by default (Robert Bradley)
+ -- Bugfix for GUI compilation on Linux (Colin Dewey)
+
+1.14.2, 3/23/09
+ -- Updated FSA preprint (Robert Bradley).
+
+1.14.3, 3/31/09
+ -- Bugfix for recognizing DNA sequences with a lot of hardmasked sequence as protein (Robert Bradley)
+
+1.14.4, 4/2/09
+ -- Compilation bugfixes for some Linux systems where floor isn't declared (Robert Bradley)
+ -- Added FSA preprint accepted by PLoS Computational Biology (Robert Bradley)
+
+1.14.5, 4/14/09
+ -- Handle "NA" fields in Mercator maps (Robert Bradley)
+ -- Bugfix for automatic available RAM detection for some Linux distributions (Colin Dewey)
+ -- Parallelization and database modes are disabled by default (Colin Dewey)
+ -- Bugfix for strange behavior where all sequences are left unaligned under some older compilers (Colin Dewey)
+
+1.15.0, 6/12/09
+ -- Options to use k-mer similarities to choose sequence pairs for alignment, rather than just randomly (Robert Bradley & Colin Dewey)
+ * New options include --mst-min, --mst-max, --mst-palm, --degree and --kmer.
+ * Deprecated --training-number and --training-fraction options.
+ -- Memory usage in --maxsn mode reduced by ~2X (Robert Bradley & Colin Dewey)
+ The above two changes result in significantly-better large (> 100 sequences) alignments.
+ -- New program slice_fasta_gff (Robert Bradley)
+ -- Compiler flags for 64-bit systems to ensure that all available RAM is used if requested (Robert Bradley)
+ -- Published manuscript (http://www.ploscompbiol.org/article/info:doi/10.1371/journal.pcbi.1000392) included in doc/
+ -- Bugfix for automatic setting of --maxram for available RAM assessment (Colin Dewey)
+
+1.15.1, 7/15/09
+ -- Refactored alignment code to speed up the FSA-Mercator tools (Robert Bradley)
+
+1.15.2, 7/16/09
+ -- Minor compilation fix for g++ 4.1.2 (Robert Bradley)
+
+1.15.3, 10/14/09
+ -- Minor bugfix for running in --anchored --translated mode (Robert Bradley)
+
+1.15.4, 8/5/09
+ -- Minor bugfix for Mercator constraints which are all Ns in one species (Robert Bradley)
+
+1.15.5, 8/10/09
+ -- Use tr1/unordered_set for annealing if available (Robert Bradley)
+
+1.15.6, 6/22/11
+ -- Minor compilation fix for gcc 4.5.2 (Robert Bradley)
+
+1.15.7, 1/30/12
+ -- Minor compilation fix for gcc 4.6 (Robert Bradley)
+
+1.15.8, 11/22/13
+ -- Minor compilation fix for Ubuntu 13.04 (Robert Bradley; thanks to Alastair Fyfe for suggestion)
+
+1.15.9, 5/16/14
+ -- Compilation fix for HMMoC code, plus minor changes to prevent warnings on Apple LLVM version 5.1 (Robert Bradley; thanks to Renato Gama for suggestion)
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..c5587c9
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,114 @@
+
+AC_DEFUN([AC_CXX_NAMESPACES],
+[AC_CACHE_CHECK(whether the compiler implements namespaces,
+ac_cv_cxx_namespaces,
+[AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([namespace Outer { namespace Inner { int i = 0; }}],
+ [using namespace Outer::Inner; return i;],
+ ac_cv_cxx_namespaces=yes, ac_cv_cxx_namespaces=no)
+ AC_LANG_RESTORE
+])
+if test "$ac_cv_cxx_namespaces" = yes; then
+ AC_DEFINE(HAVE_NAMESPACES,,[define if the compiler implements namespaces])
+fi
+])
+
+AC_DEFUN([AC_CXX_GNUCXX_HASHMAP],[
+AC_CACHE_CHECK(whether the compiler supports __gnu_cxx::hash_map,
+ac_cv_cxx_gnucxx_hashmap,
+[AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <ext/hash_map>
+using __gnu_cxx::hash_map;],
+ [],
+ ac_cv_cxx_gnucxx_hashmap=yes, ac_cv_cxx_gnucxx_hashmap=no)
+ AC_LANG_RESTORE
+])
+if test "$ac_cv_cxx_gnucxx_hashmap" = yes; then
+ AC_DEFINE(HAVE_GNUCXX_HASHMAP,,[define if the compiler supports __gnu_cxx::hash_map])
+fi
+])
+
+AC_DEFUN([AC_CXX_HAVE_EXT_HASH_MAP],
+[AC_CACHE_CHECK(whether the compiler has ext/hash_map,
+ac_cv_cxx_have_ext_hash_map,
+[AC_REQUIRE([AC_CXX_NAMESPACES])
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <ext/hash_map>
+#ifdef HAVE_NAMESPACES
+using namespace std;
+#endif],[hash_map<int, int> t; return 0;],
+ ac_cv_cxx_have_ext_hash_map=yes, ac_cv_cxx_have_ext_hash_map=no)
+ AC_LANG_RESTORE
+])
+if test "$ac_cv_cxx_have_ext_hash_map" = yes; then
+ AC_DEFINE(HAVE_EXT_HASH_MAP,,[define if the compiler has ext/hash_map])
+fi
+])
+
+AC_DEFUN([AC_CXX_STLPORT_HASHMAP],[
+AC_CACHE_CHECK(whether the compiler supports std::hash_map,
+ac_cv_cxx_stlport_hashmap,
+[AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <hash_map>
+using std::hash_map;],
+ [],
+ ac_cv_cxx_stlport_hashmap=yes, ac_cv_cxx_stlport_hashmap=no)
+ AC_LANG_RESTORE
+])
+if test "$ac_cv_cxx_stlport_hashmap" = yes; then
+ AC_DEFINE(HAVE_STLPORT_HASHMAP,,[define if the compiler supports std::hash_map])
+fi
+])
+
+
+#################################################################################
+# The below definitions for AC_TYPE_UINTMAX_T AND AC_TYPE_UNSIGNED_LONG_LONG_INT
+# were taken from the Autoconf types.m4 file;
+# they're included here since older distributions of autoconf don't
+# have these macros defined.
+#################################################################################
+
+# AC_TYPE_UINTMAX_T
+# -----------------
+AC_DEFUN([AC_TYPE_UINTMAX_T],
+[
+ AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
+ AC_CHECK_TYPE([uintmax_t],
+ [AC_DEFINE([HAVE_UINTMAX_T], 1,
+ [Define to 1 if the system has the type `uintmax_t'.])],
+ [test $ac_cv_type_unsigned_long_long_int = yes \
+ && ac_type='unsigned long long int' \
+ || ac_type='unsigned long int'
+ AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type],
+ [Define to the widest unsigned integer type
+ if <stdint.h> and <inttypes.h> do not define.])])
+])
+
+
+# AC_TYPE_UNSIGNED_LONG_LONG_INT
+# ------------------------------
+AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
+[
+ AC_CACHE_CHECK([for unsigned long long int],
+ [ac_cv_type_unsigned_long_long_int],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[unsigned long long int ull = 18446744073709551615ULL;
+ typedef int a[(18446744073709551615ULL <= (unsigned long long int) -1
+ ? 1 : -1)];
+ int i = 63;]],
+ [[unsigned long long int ullmax = 18446744073709551615ull;
+ return (ull << 63 | ull >> 63 | ull << i | ull >> i
+ | ullmax / ull | ullmax % ull);]])],
+ [ac_cv_type_unsigned_long_long_int=yes],
+ [ac_cv_type_unsigned_long_long_int=no])])
+ if test $ac_cv_type_unsigned_long_long_int = yes; then
+ AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1,
+ [Define to 1 if the system has the type `unsigned long long int'.])
+ fi
+])
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..1cbf5e4
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1210 @@
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.14'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.14.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.14.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_AR([ACT-IF-FAIL])
+# -------------------------
+# Try to determine the archiver interface, and trigger the ar-lib wrapper
+# if it is needed. If the detection of archiver interface fails, run
+# ACT-IF-FAIL (default is to abort configure with a proper error message).
+AC_DEFUN([AM_PROG_AR],
+[AC_BEFORE([$0], [LT_INIT])dnl
+AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([ar-lib])dnl
+AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false])
+: ${AR=ar}
+
+AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface],
+ [AC_LANG_PUSH([C])
+ am_cv_ar_interface=ar
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])],
+ [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+ ])
+ AC_LANG_POP([C])])
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ m4_default([$1],
+ [AC_MSG_ERROR([could not determine $AR interface])])
+ ;;
+esac
+AC_SUBST([AR])dnl
+])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
+ [$1], [CXX], [depcc="$CXX" am_compiler_list=],
+ [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+ [$1], [UPC], [depcc="$UPC" am_compiler_list=],
+ [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+ [--enable-dependency-tracking],
+ [do not reject slow dependency extractors])
+AS_HELP_STRING(
+ [--disable-dependency-tracking],
+ [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named 'Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running 'make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "$am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+ [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+ m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+ [ok:ok],,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES([CC])],
+ [m4_define([AC_PROG_CC],
+ m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES([CXX])],
+ [m4_define([AC_PROG_CXX],
+ m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES([OBJC])],
+ [m4_define([AC_PROG_OBJC],
+ m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ [_AM_DEPENDENCIES([OBJCXX])],
+ [m4_define([AC_PROG_OBJCXX],
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake at gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+ fi
+fi])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+ [whether $CC understands -c and -o together],
+ [am_cv_prog_cc_c_o],
+ [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+ alias in your environment])
+ fi
+ if test "$[2]" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+ [AC_MSG_CHECKING([that generated files are newer than configure])
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+ [--enable-silent-rules],
+ [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+ [--disable-silent-rules],
+ [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+ [m4_case([$1],
+ [ustar],
+ [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+ if test $am_uid -le $am_max_uid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi
+ AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+ if test $am_gid -le $am_max_gid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi],
+
+ [pax],
+ [],
+
+ [m4_fatal([Unknown tar format])])
+
+ AC_MSG_CHECKING([how to create a $1 tar archive])
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ AM_RUN_LOG([cat conftest.dir/file])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acinclude.m4])
diff --git a/build-aux/ar-lib b/build-aux/ar-lib
new file mode 100755
index 0000000..fe2301e
--- /dev/null
+++ b/build-aux/ar-lib
@@ -0,0 +1,270 @@
+#! /bin/sh
+# Wrapper for Microsoft lib.exe
+
+me=ar-lib
+scriptversion=2012-03-01.08; # UTC
+
+# Copyright (C) 2010-2013 Free Software Foundation, Inc.
+# Written by Peter Rosin <peda at lysator.liu.se>.
+#
+# 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 2, 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 <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+
+# func_error message
+func_error ()
+{
+ echo "$me: $1" 1>&2
+ exit 1
+}
+
+file_conv=
+
+# func_file_conv build_file
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv in
+ mingw)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_at_file at_file operation archive
+# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
+# for each of them.
+# When interpreting the content of the @FILE, do NOT use func_file_conv,
+# since the user would need to supply preconverted file names to
+# binutils ar, at least for MinGW.
+func_at_file ()
+{
+ operation=$2
+ archive=$3
+ at_file_contents=`cat "$1"`
+ eval set x "$at_file_contents"
+ shift
+
+ for member
+ do
+ $AR -NOLOGO $operation:"$member" "$archive" || exit $?
+ done
+}
+
+case $1 in
+ '')
+ func_error "no command. Try '$0 --help' for more information."
+ ;;
+ -h | --h*)
+ cat <<EOF
+Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
+
+Members may be specified in a file named with @FILE.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "$me, version $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test $# -lt 3; then
+ func_error "you must specify a program, an action and an archive"
+fi
+
+AR=$1
+shift
+while :
+do
+ if test $# -lt 2; then
+ func_error "you must specify a program, an action and an archive"
+ fi
+ case $1 in
+ -lib | -LIB \
+ | -ltcg | -LTCG \
+ | -machine* | -MACHINE* \
+ | -subsystem* | -SUBSYSTEM* \
+ | -verbose | -VERBOSE \
+ | -wx* | -WX* )
+ AR="$AR $1"
+ shift
+ ;;
+ *)
+ action=$1
+ shift
+ break
+ ;;
+ esac
+done
+orig_archive=$1
+shift
+func_file_conv "$orig_archive"
+archive=$file
+
+# strip leading dash in $action
+action=${action#-}
+
+delete=
+extract=
+list=
+quick=
+replace=
+index=
+create=
+
+while test -n "$action"
+do
+ case $action in
+ d*) delete=yes ;;
+ x*) extract=yes ;;
+ t*) list=yes ;;
+ q*) quick=yes ;;
+ r*) replace=yes ;;
+ s*) index=yes ;;
+ S*) ;; # the index is always updated implicitly
+ c*) create=yes ;;
+ u*) ;; # TODO: don't ignore the update modifier
+ v*) ;; # TODO: don't ignore the verbose modifier
+ *)
+ func_error "unknown action specified"
+ ;;
+ esac
+ action=${action#?}
+done
+
+case $delete$extract$list$quick$replace,$index in
+ yes,* | ,yes)
+ ;;
+ yesyes*)
+ func_error "more than one action specified"
+ ;;
+ *)
+ func_error "no action specified"
+ ;;
+esac
+
+if test -n "$delete"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ for member
+ do
+ case $1 in
+ @*)
+ func_at_file "${1#@}" -REMOVE "$archive"
+ ;;
+ *)
+ func_file_conv "$1"
+ $AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
+ ;;
+ esac
+ done
+
+elif test -n "$extract"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ if test $# -gt 0; then
+ for member
+ do
+ case $1 in
+ @*)
+ func_at_file "${1#@}" -EXTRACT "$archive"
+ ;;
+ *)
+ func_file_conv "$1"
+ $AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
+ ;;
+ esac
+ done
+ else
+ $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
+ do
+ $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
+ done
+ fi
+
+elif test -n "$quick$replace"; then
+ if test ! -f "$orig_archive"; then
+ if test -z "$create"; then
+ echo "$me: creating $orig_archive"
+ fi
+ orig_archive=
+ else
+ orig_archive=$archive
+ fi
+
+ for member
+ do
+ case $1 in
+ @*)
+ func_file_conv "${1#@}"
+ set x "$@" "@$file"
+ ;;
+ *)
+ func_file_conv "$1"
+ set x "$@" "$file"
+ ;;
+ esac
+ shift
+ shift
+ done
+
+ if test -n "$orig_archive"; then
+ $AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
+ else
+ $AR -NOLOGO -OUT:"$archive" "$@" || exit $?
+ fi
+
+elif test -n "$list"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ $AR -NOLOGO -LIST "$archive" || exit $?
+fi
diff --git a/build-aux/compile b/build-aux/compile
new file mode 100755
index 0000000..531136b
--- /dev/null
+++ b/build-aux/compile
@@ -0,0 +1,347 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2012-10-14.11; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey at cygnus.com>.
+#
+# 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 2, 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 <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" "" $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv/,$2, in
+ *,$file_conv,*)
+ ;;
+ mingw/*)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin/*)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine/*)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+ func_file_conv "$1"
+ if test -z "$lib_path"; then
+ lib_path=$file
+ else
+ lib_path="$lib_path;$file"
+ fi
+ linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+ lib=$1
+ found=no
+ save_IFS=$IFS
+ IFS=';'
+ for dir in $lib_path $LIB
+ do
+ IFS=$save_IFS
+ if $shared && test -f "$dir/$lib.dll.lib"; then
+ found=yes
+ lib=$dir/$lib.dll.lib
+ break
+ fi
+ if test -f "$dir/$lib.lib"; then
+ found=yes
+ lib=$dir/$lib.lib
+ break
+ fi
+ if test -f "$dir/lib$lib.a"; then
+ found=yes
+ lib=$dir/lib$lib.a
+ break
+ fi
+ done
+ IFS=$save_IFS
+
+ if test "$found" != yes; then
+ lib=$lib.lib
+ fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+ # Assume a capable shell
+ lib_path=
+ shared=:
+ linker_opts=
+ for arg
+ do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ eat=1
+ case $2 in
+ *.o | *.[oO][bB][jJ])
+ func_file_conv "$2"
+ set x "$@" -Fo"$file"
+ shift
+ ;;
+ *)
+ func_file_conv "$2"
+ set x "$@" -Fe"$file"
+ shift
+ ;;
+ esac
+ ;;
+ -I)
+ eat=1
+ func_file_conv "$2" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -I*)
+ func_file_conv "${1#-I}" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -l)
+ eat=1
+ func_cl_dashl "$2"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -l*)
+ func_cl_dashl "${1#-l}"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -L)
+ eat=1
+ func_cl_dashL "$2"
+ ;;
+ -L*)
+ func_cl_dashL "${1#-L}"
+ ;;
+ -static)
+ shared=false
+ ;;
+ -Wl,*)
+ arg=${1#-Wl,}
+ save_ifs="$IFS"; IFS=','
+ for flag in $arg; do
+ IFS="$save_ifs"
+ linker_opts="$linker_opts $flag"
+ done
+ IFS="$save_ifs"
+ ;;
+ -Xlinker)
+ eat=1
+ linker_opts="$linker_opts $2"
+ ;;
+ -*)
+ set x "$@" "$1"
+ shift
+ ;;
+ *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+ func_file_conv "$1"
+ set x "$@" -Tp"$file"
+ shift
+ ;;
+ *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+ func_file_conv "$1" mingw
+ set x "$@" "$file"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+ done
+ if test -n "$linker_opts"; then
+ linker_opts="-link$linker_opts"
+ fi
+ exec "$@" $linker_opts
+ exit 1
+}
+
+eat=
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit $?
+ ;;
+ cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
+ func_cl_wrapper "$@" # Doesn't return...
+ ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ # So we strip '-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no '-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # '.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/build-aux/config.guess b/build-aux/config.guess
new file mode 100755
index 0000000..dc84c68
--- /dev/null
+++ b/build-aux/config.guess
@@ -0,0 +1,1501 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file 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 2 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner. Please send patches (context
+# diff format) to <config-patches at gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ LIBC=gnu
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-gnu
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel at ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes at openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf at swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ i386)
+ eval $set_cc_for_build
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ UNAME_PROCESSOR="x86_64"
+ fi
+ fi ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/build-aux/config.sub b/build-aux/config.sub
new file mode 100755
index 0000000..2a55a50
--- /dev/null
+++ b/build-aux/config.sub
@@ -0,0 +1,1705 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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 2 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/build-aux/depcomp b/build-aux/depcomp
new file mode 100755
index 0000000..df8eea7
--- /dev/null
+++ b/build-aux/depcomp
@@ -0,0 +1,630 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# 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 2, 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 <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva at dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+ # This is just like msvisualcpp but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u="sed s,\\\\\\\\,/,g"
+ depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> "$depfile"
+ echo >> "$depfile"
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${
+ s/^ *//
+ s/ \\*$//
+ s/$/:/
+ p
+ }' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no eat=no
+ for arg
+ do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ if test $eat = yes; then
+ eat=no
+ continue
+ fi
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -arch)
+ eat=yes ;;
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix=`echo "$object" | sed 's/^.*\././'`
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E 2>/dev/null |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvcmsys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/build-aux/install-sh b/build-aux/install-sh
new file mode 100755
index 0000000..6781b98
--- /dev/null
+++ b/build-aux/install-sh
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/build-aux/missing b/build-aux/missing
new file mode 100755
index 0000000..28055d2
--- /dev/null
+++ b/build-aux/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+
+# 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 2, 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 <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake at gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program). This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+ lex*|yacc*)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar*)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te*)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison*|yacc*)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex*|flex*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit $?
+ fi
+ ;;
+
+ makeinfo*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar*)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/build-aux/test-driver b/build-aux/test-driver
new file mode 100755
index 0000000..32bf39e
--- /dev/null
+++ b/build-aux/test-driver
@@ -0,0 +1,127 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2012-06-27.10; # UTC
+
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# 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 2, 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 <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+ echo "$0: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--] TEST-SCRIPT
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file= # Where to save the output of the test script.
+trs_file= # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "test-driver $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) enable_hard_errors=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ esac
+ shift
+done
+
+if test $color_tests = yes; then
+ # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+ red='[0;31m' # Red.
+ grn='[0;32m' # Green.
+ lgn='[1;32m' # Light green.
+ blu='[1;34m' # Blue.
+ mgn='[0;35m' # Magenta.
+ std='[m' # No color.
+else
+ red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+ estatus=1
+fi
+
+case $estatus:$expect_failure in
+ 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+ 0:*) col=$grn res=PASS recheck=no gcopy=no;;
+ 77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
+ 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
+ *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
+ *:*) col=$red res=FAIL recheck=yes gcopy=yes;;
+esac
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..0609867
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,167 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Path to exonerate */
+#undef EXONERATE_EXEC
+
+/* Define to 1 if you have condor */
+#undef HAVE_CONDOR
+
+/* Define to 1 if you have the declaration of `CTL_HW', and to 0 if you don't.
+ */
+#undef HAVE_DECL_CTL_HW
+
+/* Define to 1 if you have the declaration of `HW_PHYSMEM', and to 0 if you
+ don't. */
+#undef HAVE_DECL_HW_PHYSMEM
+
+/* Define to 1 if you have the declaration of `sysctl', and to 0 if you don't.
+ */
+#undef HAVE_DECL_SYSCTL
+
+/* Define to 1 if you have the `floor' function. */
+#undef HAVE_FLOOR
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have postgres */
+#undef HAVE_POSTGRES
+
+/* Define to 1 if you have the `pow' function. */
+#undef HAVE_POW
+
+/* Define to 1 if the system has the type `ptrdiff_t'. */
+#undef HAVE_PTRDIFF_T
+
+/* Define to 1 if you have the `regcomp' function. */
+#undef HAVE_REGCOMP
+
+/* Define to 1 if you have the `sqrt' function. */
+#undef HAVE_SQRT
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strcspn' function. */
+#undef HAVE_STRCSPN
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strspn' function. */
+#undef HAVE_STRSPN
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if `mem_unit' is a member of `struct sysinfo'. */
+#undef HAVE_STRUCT_SYSINFO_MEM_UNIT
+
+/* Define to 1 if `totalram' is a member of `struct sysinfo'. */
+#undef HAVE_STRUCT_SYSINFO_TOTALRAM
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <tr1/unordered_map> header file. */
+#undef HAVE_TR1_UNORDERED_MAP
+
+/* Define to 1 if you have the <tr1/unordered_set> header file. */
+#undef HAVE_TR1_UNORDERED_SET
+
+/* Define to 1 if the system has the type `uintmax_t'. */
+#undef HAVE_UINTMAX_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if the system has the type `unsigned long long int'. */
+#undef HAVE_UNSIGNED_LONG_LONG_INT
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Path to mummer */
+#undef MUMMER_EXEC
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
+ do not define. */
+#undef uintmax_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/configure b/configure
new file mode 100755
index 0000000..06b58de
--- /dev/null
+++ b/configure
@@ -0,0 +1,8958 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for FSA 1.15.9.
+#
+# Report bugs to <fsa at math.berkeley.edu>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf at gnu.org and
+$0: fsa at math.berkeley.edu about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='FSA'
+PACKAGE_TARNAME='fsa'
+PACKAGE_VERSION='1.15.9'
+PACKAGE_STRING='FSA 1.15.9'
+PACKAGE_BUGREPORT='fsa at math.berkeley.edu'
+PACKAGE_URL=''
+
+ac_unique_file="config.h.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+enable_option_checking=no
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+HAVE_JAVAC_FALSE
+HAVE_JAVAC_TRUE
+HAVE_JAVAC
+subdirs
+HAVE_CONDOR_FALSE
+HAVE_CONDOR_TRUE
+HAVE_CONDOR
+HAVE_POSTGRES_FALSE
+HAVE_POSTGRES_TRUE
+EXONERATE_EXEC
+MUMMER_EXEC
+MAD_MAIN_CLASS
+HAVE_CONDOR_COMPILE
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+EGREP
+GREP
+CXXCPP
+RANLIB
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+ac_ct_AR
+AR
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_dependency_tracking
+enable_universal
+enable_intel64
+enable_force_32bit
+enable_optim
+enable_debug
+enable_profile
+enable_fast_math
+enable_condor_compile
+enable_applet
+with_mummer
+with_exonerate
+with_postgresql
+with_condor
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CXXCPP
+MAD_MAIN_CLASS'
+ac_subdirs_all='MW'
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures FSA 1.15.9 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/fsa]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of FSA 1.15.9:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-silent-rules less verbose build output (undo: "make V=1")
+ --disable-silent-rules verbose build output (undo: "make V=0")
+ --enable-dependency-tracking
+ do not reject slow dependency extractors
+ --disable-dependency-tracking
+ speeds up one-time build
+ --enable-universal enable universal binary (Intel Apple only)
+ --enable-intel64 optimize for Intel64 CPU such as Xeon and Core2
+ --enable-force-32bit force 32-bit compilation (takes precedence over all
+ other compilation flags)
+ --enable-optim[=0|1|2|3]
+ set optimization level (default is 3)
+ --enable-debug enable debugging info (default is no)
+ --enable-profile enable profiling (default is no)
+ --disable-fast-math disable fast-math optimization
+ --enable-condor-compile Build for condor standard environment (default is
+ no)
+ --enable-applet Build the MAD GUI as an applet (default is no)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-mummer[=yes|no|check|PATH]
+ Use MUMmer for aligning long sequences. Specify PATH
+ to MUMmer executable if not in current path. [check]
+ --with-exonerate[=yes|no|check|PATH]
+ Use exonerate for aligning long sequences. Specify
+ PATH to exonerate executable if not in current path.
+ [check]
+ --with-postgresql[=yes|no|check]
+ Enable option to use database mode using PostgreSQL
+ [no]
+ --with-condor[=yes|no|check]
+ Enable option to use parallel mode using condor [no]
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+ MAD_MAIN_CLASS
+ Main class for MAD GUI
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <fsa at math.berkeley.edu>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+FSA configure 1.15.9
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_cxx_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ------------------------------------ ##
+## Report this to fsa at math.berkeley.edu ##
+## ------------------------------------ ##"
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_mongrel
+
+# ac_fn_cxx_try_run LINENO
+# ------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_cxx_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_run
+
+# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_cxx_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_compile
+
+# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES
+# ---------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_cxx_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_type
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_func
+
+# ac_fn_cxx_check_decl LINENO SYMBOL VAR INCLUDES
+# -----------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_cxx_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_decl
+
+# ac_fn_cxx_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ------------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_cxx_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by FSA $as_me 1.15.9, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_aux_dir=
+for ac_dir in build-aux "$srcdir"/build-aux; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+am__api_version='1.14'
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+ alias in your environment" "$LINENO" 5
+ fi
+ if test "$2" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if ${ac_cv_path_mkdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='fsa'
+ VERSION='1.15.9'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar plaintar pax cpio none'
+
+# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5
+$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; }
+ if test $am_uid -le $am_max_uid; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ _am_tools=none
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5
+$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; }
+ if test $am_gid -le $am_max_gid; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ _am_tools=none
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5
+$as_echo_n "checking how to create a ustar tar archive... " >&6; }
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_ustar-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ { echo "$as_me:$LINENO: $_am_tar --version" >&5
+ ($_am_tar --version) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && break
+ done
+ am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x ustar -w "$$tardir"'
+ am__tar_='pax -L -x ustar -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H ustar -L'
+ am__tar_='find "$tardir" -print | cpio -o -H ustar -L'
+ am__untar='cpio -i -H ustar -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_ustar}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+ (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+ ($am__untar <conftest.tar) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ { echo "$as_me:$LINENO: cat conftest.dir/file" >&5
+ (cat conftest.dir/file) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ if ${am_cv_prog_tar_ustar+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_prog_tar_ustar=$_am_tool
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5
+$as_echo "$am_cv_prog_tar_ustar" >&6; }
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake at gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+ fi
+fi
+
+# Set language to c++.
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+# Hack to get rid of a warning introduced by Automake 1.12
+# (see http://code.google.com/p/snappy/issues/detail?id=67).
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar lib "link -lib"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar lib "link -lib"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
+$as_echo_n "checking the archiver ($AR) interface... " >&6; }
+if ${am_cv_ar_interface+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ am_cv_ar_interface=ar
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int some_variable = 0;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
+$as_echo "$am_cv_ar_interface" >&6; }
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ as_fn_error $? "could not determine $AR interface" "$LINENO" 5
+ ;;
+esac
+
+
+ # Make sure CXXFLAGS is defined so that AC_PROG_CXX doesn't set it.
+CFLAGS="$CFLAGS"
+CXXFLAGS="$CXXFLAGS"
+
+# Check for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+# Check for header files.
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+ if ${ac_cv_prog_CXXCPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in stdlib.h string.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Check for typedefs, structures, and compiler characteristics.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <stdbool.h>
+ #ifndef bool
+ "error: bool is not defined"
+ #endif
+ #ifndef false
+ "error: false is not defined"
+ #endif
+ #if false
+ "error: false is not 0"
+ #endif
+ #ifndef true
+ "error: true is not defined"
+ #endif
+ #if true != 1
+ "error: true is not 1"
+ #endif
+ #ifndef __bool_true_false_are_defined
+ "error: __bool_true_false_are_defined is not defined"
+ #endif
+
+ struct s { _Bool s: 1; _Bool t; } s;
+
+ char a[true == 1 ? 1 : -1];
+ char b[false == 0 ? 1 : -1];
+ char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+ char d[(bool) 0.5 == true ? 1 : -1];
+ /* See body of main program for 'e'. */
+ char f[(_Bool) 0.0 == false ? 1 : -1];
+ char g[true];
+ char h[sizeof (_Bool)];
+ char i[sizeof s.t];
+ enum { j = false, k = true, l = false * true, m = true * 256 };
+ /* The following fails for
+ HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+ _Bool n[m];
+ char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+ char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+ /* Catch a bug in an HP-UX C compiler. See
+ http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+ http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+ */
+ _Bool q = true;
+ _Bool *pq = &q;
+
+int
+main ()
+{
+
+ bool e = &s;
+ *pq |= q;
+ *pq |= ! q;
+ /* Refer to every declared value, to avoid compiler optimizations. */
+ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+ + !m + !n + !o + !p + !q + !pq);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_header_stdbool_h=yes
+else
+ ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+ ac_fn_cxx_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+ac_fn_cxx_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+ac_fn_cxx_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
+$as_echo_n "checking for unsigned long long int... " >&6; }
+if ${ac_cv_type_unsigned_long_long_int+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+unsigned long long int ull = 18446744073709551615ULL;
+ typedef int a[(18446744073709551615ULL <= (unsigned long long int) -1
+ ? 1 : -1)];
+ int i = 63;
+int
+main ()
+{
+unsigned long long int ullmax = 18446744073709551615ull;
+ return (ull << 63 | ull >> 63 | ull << i | ull >> i
+ | ullmax / ull | ullmax % ull);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_type_unsigned_long_long_int=yes
+else
+ ac_cv_type_unsigned_long_long_int=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
+$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; }
+ if test $ac_cv_type_unsigned_long_long_int = yes; then
+
+$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
+
+ fi
+
+
+
+ ac_fn_cxx_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintmax_t" = xyes; then :
+
+$as_echo "#define HAVE_UINTMAX_T 1" >>confdefs.h
+
+else
+ test $ac_cv_type_unsigned_long_long_int = yes \
+ && ac_type='unsigned long long int' \
+ || ac_type='unsigned long int'
+
+cat >>confdefs.h <<_ACEOF
+#define uintmax_t $ac_type
+_ACEOF
+
+fi
+
+
+ac_fn_cxx_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default"
+if test "x$ac_cv_type_ptrdiff_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_PTRDIFF_T 1
+_ACEOF
+
+
+fi
+
+
+# Check for unordered_map.
+for ac_header in tr1/unordered_map tr1/unordered_set
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Check for library functions.
+for ac_header in vfork.h
+do :
+ ac_fn_cxx_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_fork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ ac_cv_func_fork_works=yes
+else
+ ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_vfork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ ac_cv_func_vfork_works=yes
+else
+ ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+for ac_func in floor memmove pow regcomp sqrt strchr strcspn strspn strstr
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check the platform information.
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+# Set CFLAGS and CXXFLAGS.
+user_CFLAGS=${CFLAGS}
+generic_CFLAGS="-Wall -Wno-tautological-compare"
+ext_CFLAGS=""
+debug_CFLAGS=""
+
+# Try to choose appropriate flags for 64-bit compilation.
+# (This code is borrowed from Cole Trapnell's TopHat (http://tophat.cbcb.umd.edu/).)
+case "${host_cpu}-${host_os}" in
+ i*86-*linux*)
+ ext_CFLAGS="-march=i686";;
+ i*86-darwin*)
+ # Check whether --enable-universal was given.
+if test "${enable_universal+set}" = set; then :
+ enableval=$enable_universal; is_uni=1
+else
+ is_uni=0
+fi
+
+ case $is_uni in
+ 1) CFLAGS="-m64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ext_CFLAGS="-arch x86_64 -arch i386 -arch ppc64 -arch ppc"
+else
+ ext_CFLAGS="-arch i386 -arch ppc"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext;;
+ 0) CFLAGS="-m64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ext_CFLAGS="-arch x86_64"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext;;
+ esac;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc accepts -m64" >&5
+$as_echo_n "checking if gcc accepts -m64... " >&6; }
+ CFLAGS="-m64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ext_CFLAGS="-m64"; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ ext_CFLAGS="-D_FILE_OFFSET_BITS=64"; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext;;
+esac
+
+# Check whether --enable-intel64 was given.
+if test "${enable_intel64+set}" = set; then :
+ enableval=$enable_intel64; ext_CFLAGS="${ext_CFLAGS} -mtune=nocona"
+fi
+
+
+# Option to manually force 32-bit compilation.
+# Check whether --enable-force-32bit was given.
+if test "${enable_force_32bit+set}" = set; then :
+ enableval=$enable_force_32bit; ext_CFLAGS=""
+fi
+
+
+# Add options for compiler flags.
+# Check whether --enable-optim was given.
+if test "${enable_optim+set}" = set; then :
+ enableval=$enable_optim; if test "x$enable_optim" = xyes; then enable_optim=3; fi
+else
+ enable_optim=3
+fi
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+ enableval=$enable_debug;
+else
+ enable_debug=no
+fi
+
+# Check whether --enable-profile was given.
+if test "${enable_profile+set}" = set; then :
+ enableval=$enable_profile;
+else
+ enable_profile=no
+fi
+
+# Check whether --enable-fast-math was given.
+if test "${enable_fast_math+set}" = set; then :
+ enableval=$enable_fast_math;
+else
+ enable_fast_math=yes
+fi
+
+
+# Set compiler flags according to specified options.
+if test "x$enable_optim" != xno; then :
+ ext_CFLAGS="$ext_CFLAGS -O$enable_optim"
+fi
+if test "x$enable_debug" = xyes; then :
+ debug_CFLAGS="-g -DDEBUG"
+else
+ debug_CFLAGS="-DNDEBUG"
+fi
+if test "x$enable_profile" = xyes; then :
+ ext_CFLAGS="$ext_CFLAGS -pg"
+fi
+if test "x$enable_fast_math" = xyes; then :
+ ext_CFLAGS="$ext_CFLAGS -ffast-math"
+fi
+
+# Set CFLAGS and CXXFLAGS with all of the specified options.
+CFLAGS="${generic_CFLAGS} ${ext_CFLAGS} ${user_CFLAGS} ${debug_CFLAGS}"
+CXXFLAGS="$CFLAGS"
+
+# Add option for compiling for condor standard environment.
+# Check whether --enable-condor-compile was given.
+if test "${enable_condor_compile+set}" = set; then :
+ enableval=$enable_condor_compile;
+else
+ enable_condor_compile=no
+fi
+
+
+# Set compiler depending on condor option.
+if test "x$enable_condor_compile" = xyes; then :
+ # Extract the first word of "condor_compile", so it can be a program name with args.
+set dummy condor_compile; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_HAVE_CONDOR_COMPILE+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$HAVE_CONDOR_COMPILE"; then
+ ac_cv_prog_HAVE_CONDOR_COMPILE="$HAVE_CONDOR_COMPILE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_HAVE_CONDOR_COMPILE=""yes""
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+HAVE_CONDOR_COMPILE=$ac_cv_prog_HAVE_CONDOR_COMPILE
+if test -n "$HAVE_CONDOR_COMPILE"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_CONDOR_COMPILE" >&5
+$as_echo "$HAVE_CONDOR_COMPILE" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x$HAVE_CONDOR_COMPILE" = xyes ; then
+ CXX="condor_compile $CXX"; CC="condor_compile $CC";
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "--enable-condor given, but condor_compile was not found in path
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+fi
+
+# Add option for building applet.
+# Check whether --enable-applet was given.
+if test "${enable_applet+set}" = set; then :
+ enableval=$enable_applet;
+else
+ enable_applet=no
+fi
+
+
+# Define whether to use applet or not.
+if test "x$enable_applet" = xyes; then :
+ MAD_MAIN_CLASS=mad.MadApplet
+else
+ MAD_MAIN_CLASS=mad.MAD
+fi
+
+
+# Add option for using mummer.
+
+# Check whether --with-mummer was given.
+if test "${with_mummer+set}" = set; then :
+ withval=$with_mummer;
+else
+ with_mummer=check
+fi
+
+
+# Search for mummer executable if not specified.
+if test "x$with_mummer" = xcheck || test "x$with_mummer" = xyes; then :
+ # Extract the first word of "mummer", so it can be a program name with args.
+set dummy mummer; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MUMMER_EXEC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MUMMER_EXEC in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MUMMER_EXEC="$MUMMER_EXEC" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_MUMMER_EXEC="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_MUMMER_EXEC" && ac_cv_path_MUMMER_EXEC=""no""
+ ;;
+esac
+fi
+MUMMER_EXEC=$ac_cv_path_MUMMER_EXEC
+if test -n "$MUMMER_EXEC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MUMMER_EXEC" >&5
+$as_echo "$MUMMER_EXEC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+else
+ MUMMER_EXEC=$with_mummer
+fi
+
+# Check mummer executable and if everything is correct, define macro.
+if test "x$MUMMER_EXEC" = xno && test "x$with_mummer" = xyes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "--with-mummer given, but mummer was not found in path
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+if test "x$MUMMER_EXEC" != xno && test ! -x $MUMMER_EXEC; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "\"$MUMMER_EXEC\" is not a valid mummer executable
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+if test "x$MUMMER_EXEC" != xno; then :
+
+cat >>confdefs.h <<_ACEOF
+#define MUMMER_EXEC "$MUMMER_EXEC"
+_ACEOF
+
+fi
+
+# Add option for using exonerate.
+
+# Check whether --with-exonerate was given.
+if test "${with_exonerate+set}" = set; then :
+ withval=$with_exonerate;
+else
+ with_exonerate=check
+fi
+
+
+# Search for exonerate executable if not specified.
+if test "x$with_exonerate" = xcheck || test "x$with_exonerate" = xyes; then :
+ # Extract the first word of "exonerate", so it can be a program name with args.
+set dummy exonerate; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_EXONERATE_EXEC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $EXONERATE_EXEC in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_EXONERATE_EXEC="$EXONERATE_EXEC" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_EXONERATE_EXEC="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_EXONERATE_EXEC" && ac_cv_path_EXONERATE_EXEC=""no""
+ ;;
+esac
+fi
+EXONERATE_EXEC=$ac_cv_path_EXONERATE_EXEC
+if test -n "$EXONERATE_EXEC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $EXONERATE_EXEC" >&5
+$as_echo "$EXONERATE_EXEC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+else
+ EXONERATE_EXEC=$with_exonerate
+fi
+
+# Check exonerate executable and if everything is correct, define macro.
+if test "x$EXONERATE_EXEC" = xno && test "x$with_exonerate" = xyes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "--with-exonerate given, but exonerate was not found in path
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+if test "x$EXONERATE_EXEC" != xno && test ! -x $EXONERATE_EXEC; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "\"$EXONERATE_EXEC\" is not a valid exonerate executable
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+if test "x$EXONERATE_EXEC" != xno; then :
+
+cat >>confdefs.h <<_ACEOF
+#define EXONERATE_EXEC "$EXONERATE_EXEC"
+_ACEOF
+
+fi
+
+# Add option for using postgresql.
+
+# Check whether --with-postgresql was given.
+if test "${with_postgresql+set}" = set; then :
+ withval=$with_postgresql;
+else
+ with_postgresql=no
+fi
+
+
+# Check for postgresql.
+if test "x$with_postgresql" = xcheck || test "x$with_postgresql" = xyes; then :
+ # Check for Postgres library
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQconnectdb in -lpq" >&5
+$as_echo_n "checking for PQconnectdb in -lpq... " >&6; }
+if ${ac_cv_lib_pq_PQconnectdb+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpq $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char PQconnectdb ();
+int
+main ()
+{
+return PQconnectdb ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_pq_PQconnectdb=yes
+else
+ ac_cv_lib_pq_PQconnectdb=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQconnectdb" >&5
+$as_echo "$ac_cv_lib_pq_PQconnectdb" >&6; }
+if test "x$ac_cv_lib_pq_PQconnectdb" = xyes; then :
+ # Check for Postgres header
+ ac_fn_cxx_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default"
+if test "x$ac_cv_header_libpq_fe_h" = xyes; then :
+ # Check for a function in the Postgres header
+ ac_fn_cxx_check_decl "$LINENO" "PQgetCopyData" "ac_cv_have_decl_PQgetCopyData" "#include <libpq-fe.h>
+"
+if test "x$ac_cv_have_decl_PQgetCopyData" = xyes; then :
+ HAVE_POSTGRES=yes
+fi
+
+fi
+
+
+fi
+
+fi
+
+if test "x$HAVE_POSTGRES" != xyes && test "x$with_postgresql" = xyes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "--with-postgresql given, but valid postgresql installation not found
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+if test "x$HAVE_POSTGRES" = xyes; then :
+ # Check for crypt library, which is required by postgres on Linux
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
+$as_echo_n "checking for crypt in -lcrypt... " >&6; }
+if ${ac_cv_lib_crypt_crypt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crypt ();
+int
+main ()
+{
+return crypt ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_crypt_crypt=yes
+else
+ ac_cv_lib_crypt_crypt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
+$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
+if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
+ LIBS="-lcrypt $LIBS"
+fi
+
+ # Add postgres library
+ LIBS="-lpq $LIBS";
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_POSTGRES 1
+_ACEOF
+
+fi
+ if test "x$HAVE_POSTGRES" = xyes; then
+ HAVE_POSTGRES_TRUE=
+ HAVE_POSTGRES_FALSE='#'
+else
+ HAVE_POSTGRES_TRUE='#'
+ HAVE_POSTGRES_FALSE=
+fi
+
+
+# Add option for using condor (parellel mode).
+
+# Check whether --with-condor was given.
+if test "${with_condor+set}" = set; then :
+ withval=$with_condor;
+else
+ with_condor=no
+fi
+
+
+# Check for condor.
+if test "x$with_condor" = xcheck || test "x$with_condor" = xyes; then :
+ # Extract the first word of "condor_submit", so it can be a program name with args.
+set dummy condor_submit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_HAVE_CONDOR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$HAVE_CONDOR"; then
+ ac_cv_prog_HAVE_CONDOR="$HAVE_CONDOR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_HAVE_CONDOR=""yes""
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+HAVE_CONDOR=$ac_cv_prog_HAVE_CONDOR
+if test -n "$HAVE_CONDOR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_CONDOR" >&5
+$as_echo "$HAVE_CONDOR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+if test "x$HAVE_CONDOR" != xyes && test "x$with_condor" = xyes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "--with-condor given, but valid condor installation not found
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+if test "x$HAVE_CONDOR" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CONDOR 1
+_ACEOF
+
+fi
+
+ if test "x$HAVE_CONDOR" = xyes; then
+ HAVE_CONDOR_TRUE=
+ HAVE_CONDOR_FALSE='#'
+else
+ HAVE_CONDOR_TRUE='#'
+ HAVE_CONDOR_FALSE=
+fi
+
+
+# Build with MW if Condor is found.
+
+
+if test "x$HAVE_CONDOR" = xyes; then :
+ subdirs="$subdirs MW"
+
+fi
+
+# Check for structures/functions that can be used to determine system memory.
+ac_fn_cxx_check_member "$LINENO" "struct sysinfo" "totalram" "ac_cv_member_struct_sysinfo_totalram" "#include <sys/sysinfo.h>
+"
+if test "x$ac_cv_member_struct_sysinfo_totalram" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SYSINFO_TOTALRAM 1
+_ACEOF
+
+
+fi
+ac_fn_cxx_check_member "$LINENO" "struct sysinfo" "mem_unit" "ac_cv_member_struct_sysinfo_mem_unit" "#include <sys/sysinfo.h>
+"
+if test "x$ac_cv_member_struct_sysinfo_mem_unit" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SYSINFO_MEM_UNIT 1
+_ACEOF
+
+
+fi
+
+ac_fn_cxx_check_decl "$LINENO" "sysctl" "ac_cv_have_decl_sysctl" "#include <sys/sysctl.h>
+"
+if test "x$ac_cv_have_decl_sysctl" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SYSCTL $ac_have_decl
+_ACEOF
+ac_fn_cxx_check_decl "$LINENO" "CTL_HW" "ac_cv_have_decl_CTL_HW" "#include <sys/sysctl.h>
+"
+if test "x$ac_cv_have_decl_CTL_HW" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_CTL_HW $ac_have_decl
+_ACEOF
+ac_fn_cxx_check_decl "$LINENO" "HW_PHYSMEM" "ac_cv_have_decl_HW_PHYSMEM" "#include <sys/sysctl.h>
+"
+if test "x$ac_cv_have_decl_HW_PHYSMEM" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_HW_PHYSMEM $ac_have_decl
+_ACEOF
+
+
+# Check for javac. If it exists, set automake conditional.
+# Extract the first word of "javac", so it can be a program name with args.
+set dummy javac; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_HAVE_JAVAC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$HAVE_JAVAC"; then
+ ac_cv_prog_HAVE_JAVAC="$HAVE_JAVAC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_HAVE_JAVAC="yes"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_HAVE_JAVAC" && ac_cv_prog_HAVE_JAVAC="no"
+fi
+fi
+HAVE_JAVAC=$ac_cv_prog_HAVE_JAVAC
+if test -n "$HAVE_JAVAC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_JAVAC" >&5
+$as_echo "$HAVE_JAVAC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x$HAVE_JAVAC" = xyes; then
+ HAVE_JAVAC_TRUE=
+ HAVE_JAVAC_FALSE='#'
+else
+ HAVE_JAVAC_TRUE='#'
+ HAVE_JAVAC_FALSE=
+fi
+
+
+ac_config_files="$ac_config_files Makefile src/main/Makefile src/manager/Makefile src/fsa/Makefile src/annealing/Makefile src/math/Makefile src/util/Makefile src/seq/Makefile display/Makefile display/mad/manifest.mf perl/Makefile examples/Makefile doc/Makefile doc/version.tex html/Makefile tests/Makefile"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_POSTGRES_TRUE}" && test -z "${HAVE_POSTGRES_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_POSTGRES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_CONDOR_TRUE}" && test -z "${HAVE_CONDOR_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_CONDOR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_JAVAC_TRUE}" && test -z "${HAVE_JAVAC_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_JAVAC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by FSA $as_me 1.15.9, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <fsa at math.berkeley.edu>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+FSA config.status 1.15.9
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "src/main/Makefile") CONFIG_FILES="$CONFIG_FILES src/main/Makefile" ;;
+ "src/manager/Makefile") CONFIG_FILES="$CONFIG_FILES src/manager/Makefile" ;;
+ "src/fsa/Makefile") CONFIG_FILES="$CONFIG_FILES src/fsa/Makefile" ;;
+ "src/annealing/Makefile") CONFIG_FILES="$CONFIG_FILES src/annealing/Makefile" ;;
+ "src/math/Makefile") CONFIG_FILES="$CONFIG_FILES src/math/Makefile" ;;
+ "src/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/util/Makefile" ;;
+ "src/seq/Makefile") CONFIG_FILES="$CONFIG_FILES src/seq/Makefile" ;;
+ "display/Makefile") CONFIG_FILES="$CONFIG_FILES display/Makefile" ;;
+ "display/mad/manifest.mf") CONFIG_FILES="$CONFIG_FILES display/mad/manifest.mf" ;;
+ "perl/Makefile") CONFIG_FILES="$CONFIG_FILES perl/Makefile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+ "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+ "doc/version.tex") CONFIG_FILES="$CONFIG_FILES doc/version.tex" ;;
+ "html/Makefile") CONFIG_FILES="$CONFIG_FILES html/Makefile" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named 'Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running 'make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "$am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file, --srcdir, and --disable-option-checking arguments
+ # so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ eval "set x $ac_configure_args"
+ shift
+ for ac_arg
+ do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case $ac_arg in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+ | --c=*)
+ ;;
+ --config-cache | -C)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ ;;
+ --disable-option-checking)
+ ;;
+ *)
+ case $ac_arg in
+ *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_sub_configure_args " '$ac_arg'" ;;
+ esac
+ done
+
+ # Always prepend --prefix to ensure using the same prefix
+ # in subdir configurations.
+ ac_arg="--prefix=$prefix"
+ case $ac_arg in
+ *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
+
+ # Pass --silent
+ if test "$silent" = yes; then
+ ac_sub_configure_args="--silent $ac_sub_configure_args"
+ fi
+
+ # Always prepend --disable-option-checking to silence warnings, since
+ # different subdirs can have different --enable and --with options.
+ ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args"
+
+ ac_popdir=`pwd`
+ for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ test -d "$srcdir/$ac_dir" || continue
+
+ ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
+ $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5
+ $as_echo "$ac_msg" >&6
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ cd "$ac_dir"
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ ac_sub_configure=$ac_srcdir/configure.gnu
+ elif test -f "$ac_srcdir/configure"; then
+ ac_sub_configure=$ac_srcdir/configure
+ elif test -f "$ac_srcdir/configure.in"; then
+ # This should be Cygnus configure.
+ ac_sub_configure=$ac_aux_dir/configure
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5
+$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+ # Make the cache file name correct relative to the subdirectory.
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+ *) # Relative name.
+ ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+ # The eval makes quoting arguments work.
+ eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
+ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
+ as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5
+ fi
+
+ cd "$ac_popdir"
+ done
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+
+# Dump some configuration confirmations.
+echo \
+"
+-- ${PACKAGE_STRING} Configuration Results --
+ C++ compiler: ${CXX} ${CXXFLAGS}"
+
+if test x"${GCC}" = x"yes" ; then
+ gcc_version=`${CC} --version | head -n 1`
+ echo " GCC version: ${gcc_version}"
+else
+ gcc_version=''
+fi
+
+echo \
+" Host System type: ${host}
+ Install prefix: ${prefix}
+
+ See config.h for further configuration information.
+ Email <${PACKAGE_BUGREPORT}> with questions and bug reports.
+"
diff --git a/configure.ac b/configure.ac
new file mode 100755
index 0000000..703abe2
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,303 @@
+
+# Initialize.
+m4_include([version.m4])
+AC_INIT([FSA], VERSION_NUMBER, [fsa at math.berkeley.edu])
+AC_CONFIG_SRCDIR([config.h.in])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([-Wall -Werror tar-ustar foreign])
+
+# Set language to c++.
+AC_LANG([C++])
+
+# Hack to get rid of a warning introduced by Automake 1.12
+# (see http://code.google.com/p/snappy/issues/detail?id=67).
+m4_pattern_allow([AM_PROG_AR])
+AM_PROG_AR
+
+ # Make sure CXXFLAGS is defined so that AC_PROG_CXX doesn't set it.
+CFLAGS="$CFLAGS"
+CXXFLAGS="$CXXFLAGS"
+
+# Check for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_AWK
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+
+# Check for header files.
+AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
+
+# Check for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_UINTMAX_T
+AC_CHECK_TYPES([ptrdiff_t])
+
+# Check for unordered_map.
+AC_CHECK_HEADERS([tr1/unordered_map tr1/unordered_set])
+
+# Check for library functions.
+AC_FUNC_FORK
+AC_CHECK_FUNCS([floor memmove pow regcomp sqrt strchr strcspn strspn strstr])
+
+# Check the platform information.
+AC_CANONICAL_HOST
+
+# Set CFLAGS and CXXFLAGS.
+user_CFLAGS=${CFLAGS}
+generic_CFLAGS="-Wall -Wno-tautological-compare"
+ext_CFLAGS=""
+debug_CFLAGS=""
+
+# Try to choose appropriate flags for 64-bit compilation.
+# (This code is borrowed from Cole Trapnell's TopHat (http://tophat.cbcb.umd.edu/).)
+case "${host_cpu}-${host_os}" in
+ i*86-*linux*)
+ ext_CFLAGS="-march=i686";;
+ i*86-darwin*)
+ AC_ARG_ENABLE([universal],
+ [AS_HELP_STRING([--enable-universal],
+ [enable universal binary (Intel Apple only)])],
+ [is_uni=1], [is_uni=0])
+ case $is_uni in
+ 1) CFLAGS="-m64"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [ext_CFLAGS="-arch x86_64 -arch i386 -arch ppc64 -arch ppc"],
+ [ext_CFLAGS="-arch i386 -arch ppc"]);;
+ 0) CFLAGS="-m64"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [ext_CFLAGS="-arch x86_64"],
+ []);;
+ esac;;
+ *)
+ AC_MSG_CHECKING([if gcc accepts -m64])
+ CFLAGS="-m64"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [ext_CFLAGS="-m64"; AC_MSG_RESULT([yes])],
+ [ext_CFLAGS="-D_FILE_OFFSET_BITS=64"; AC_MSG_RESULT([no])]);;
+esac
+
+AC_ARG_ENABLE([intel64],
+ [AS_HELP_STRING([--enable-intel64],
+ [optimize for Intel64 CPU such as Xeon and Core2])],
+ [ext_CFLAGS="${ext_CFLAGS} -mtune=nocona"], [])
+
+# Option to manually force 32-bit compilation.
+AC_ARG_ENABLE([force-32bit],
+ [AS_HELP_STRING([--enable-force-32bit],
+ [force 32-bit compilation (takes precedence over all other compilation flags)])],
+ [ext_CFLAGS=""], [])
+
+# Add options for compiler flags.
+AC_ARG_ENABLE([optim],
+ [AS_HELP_STRING([--enable-optim@<:@=0|1|2|3@:>@],
+ [set optimization level (default is 3)])],
+ [if test "x$enable_optim" = xyes; then enable_optim=3; fi],
+ [enable_optim=3])
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug],
+ [enable debugging info (default is no)])],
+ [], [enable_debug=no])
+AC_ARG_ENABLE([profile],
+ [AS_HELP_STRING([--enable-profile],
+ [enable profiling (default is no)])],
+ [], [enable_profile=no])
+AC_ARG_ENABLE([fast-math],
+ [AS_HELP_STRING([--disable-fast-math],
+ [disable fast-math optimization])],
+ [], [enable_fast_math=yes])
+
+# Set compiler flags according to specified options.
+AS_IF([test "x$enable_optim" != xno], [ext_CFLAGS="$ext_CFLAGS -O$enable_optim"])
+AS_IF([test "x$enable_debug" = xyes],
+ [debug_CFLAGS="-g -DDEBUG"],
+ [debug_CFLAGS="-DNDEBUG"])
+AS_IF([test "x$enable_profile" = xyes], [ext_CFLAGS="$ext_CFLAGS -pg"])
+AS_IF([test "x$enable_fast_math" = xyes], [ext_CFLAGS="$ext_CFLAGS -ffast-math"])
+
+# Set CFLAGS and CXXFLAGS with all of the specified options.
+CFLAGS="${generic_CFLAGS} ${ext_CFLAGS} ${user_CFLAGS} ${debug_CFLAGS}"
+CXXFLAGS="$CFLAGS"
+
+# Add option for compiling for condor standard environment.
+AC_ARG_ENABLE([condor-compile],
+ [AS_HELP_STRING([--enable-condor-compile],
+ [Build for condor standard environment
+ (default is no)])],
+ [], [enable_condor_compile=no])
+
+# Set compiler depending on condor option.
+AS_IF([test "x$enable_condor_compile" = xyes],
+ [AC_CHECK_PROG([HAVE_CONDOR_COMPILE],[condor_compile],["yes"])
+ if test "x$HAVE_CONDOR_COMPILE" = xyes ; then
+ CXX="condor_compile $CXX"; CC="condor_compile $CC";
+ else
+ AC_MSG_FAILURE([--enable-condor given, but condor_compile was not found in path])
+ fi])
+
+# Add option for building applet.
+AC_ARG_ENABLE([applet],
+ [AS_HELP_STRING([--enable-applet],
+ [Build the MAD GUI as an applet
+ (default is no)])],
+ [],
+ [enable_applet=no])
+
+# Define whether to use applet or not.
+AS_IF([test "x$enable_applet" = xyes],
+ [MAD_MAIN_CLASS=mad.MadApplet],
+ [MAD_MAIN_CLASS=mad.MAD])
+AC_ARG_VAR([MAD_MAIN_CLASS],[Main class for MAD GUI])
+
+# Add option for using mummer.
+AC_ARG_WITH([mummer],
+ [AS_HELP_STRING([--with-mummer@<:@=yes|no|check|PATH@:>@],
+ [Use MUMmer for aligning long sequences. Specify
+ PATH to MUMmer executable if not in current path.
+ [check]])],
+ [],
+ [with_mummer=check])
+
+# Search for mummer executable if not specified.
+AS_IF([test "x$with_mummer" = xcheck || test "x$with_mummer" = xyes],
+ [AC_PATH_PROG([MUMMER_EXEC],[mummer],["no"])],
+ [MUMMER_EXEC=$with_mummer])
+
+# Check mummer executable and if everything is correct, define macro.
+AS_IF([test "x$MUMMER_EXEC" = xno && test "x$with_mummer" = xyes],
+ [AC_MSG_FAILURE([--with-mummer given, but mummer was not found in path])])
+AS_IF([test "x$MUMMER_EXEC" != xno && test ! -x $MUMMER_EXEC],
+ [AC_MSG_FAILURE(["$MUMMER_EXEC" is not a valid mummer executable])])
+AS_IF([test "x$MUMMER_EXEC" != xno],
+ [AC_DEFINE_UNQUOTED([MUMMER_EXEC],["$MUMMER_EXEC"],[Path to mummer])])
+
+# Add option for using exonerate.
+AC_ARG_WITH([exonerate],
+ [AS_HELP_STRING([--with-exonerate@<:@=yes|no|check|PATH@:>@],
+ [Use exonerate for aligning long sequences. Specify
+ PATH to exonerate executable if not in current path.
+ [check]])],
+ [],
+ [with_exonerate=check])
+
+# Search for exonerate executable if not specified.
+AS_IF([test "x$with_exonerate" = xcheck || test "x$with_exonerate" = xyes],
+ [AC_PATH_PROG([EXONERATE_EXEC],[exonerate],["no"])],
+ [EXONERATE_EXEC=$with_exonerate])
+
+# Check exonerate executable and if everything is correct, define macro.
+AS_IF([test "x$EXONERATE_EXEC" = xno && test "x$with_exonerate" = xyes],
+ [AC_MSG_FAILURE([--with-exonerate given, but exonerate was not found in path])])
+AS_IF([test "x$EXONERATE_EXEC" != xno && test ! -x $EXONERATE_EXEC],
+ [AC_MSG_FAILURE(["$EXONERATE_EXEC" is not a valid exonerate executable])])
+AS_IF([test "x$EXONERATE_EXEC" != xno],
+ [AC_DEFINE_UNQUOTED([EXONERATE_EXEC],["$EXONERATE_EXEC"],[Path to exonerate])])
+
+# Add option for using postgresql.
+AC_ARG_WITH([postgresql],
+ [AS_HELP_STRING([--with-postgresql@<:@=yes|no|check@:>@],
+ [Enable option to use database mode using
+ PostgreSQL [no]])],
+ [],
+ [with_postgresql=no])
+
+# Check for postgresql.
+AS_IF([test "x$with_postgresql" = xcheck || test "x$with_postgresql" = xyes],
+ [# Check for Postgres library
+ AC_CHECK_LIB([pq], [PQconnectdb],
+ # Check for Postgres header
+ [AC_CHECK_HEADER([libpq-fe.h],
+ # Check for a function in the Postgres header
+ [AC_CHECK_DECL([PQgetCopyData],
+ [HAVE_POSTGRES=yes], [],
+ [#include <libpq-fe.h>])])])])
+
+AS_IF([test "x$HAVE_POSTGRES" != xyes && test "x$with_postgresql" = xyes],
+ [AC_MSG_FAILURE([--with-postgresql given, but valid postgresql installation not found])])
+
+AS_IF([test "x$HAVE_POSTGRES" = xyes],
+ [# Check for crypt library, which is required by postgres on Linux
+ AC_CHECK_LIB([crypt], [crypt], [LIBS="-lcrypt $LIBS"])
+ # Add postgres library
+ LIBS="-lpq $LIBS";
+ AC_DEFINE_UNQUOTED([HAVE_POSTGRES], [1],
+ [Define to 1 if you have postgres])])
+AM_CONDITIONAL([HAVE_POSTGRES], [test "x$HAVE_POSTGRES" = xyes])
+
+# Add option for using condor (parellel mode).
+AC_ARG_WITH([condor],
+ [AS_HELP_STRING([--with-condor@<:@=yes|no|check@:>@],
+ [Enable option to use parallel mode using
+ condor [no]])],
+ [],
+ [with_condor=no])
+
+# Check for condor.
+AS_IF([test "x$with_condor" = xcheck || test "x$with_condor" = xyes],
+ [AC_CHECK_PROG([HAVE_CONDOR],[condor_submit],["yes"])])
+
+AS_IF([test "x$HAVE_CONDOR" != xyes && test "x$with_condor" = xyes],
+ [AC_MSG_FAILURE([--with-condor given, but valid condor installation not found])])
+
+AS_IF([test "x$HAVE_CONDOR" = xyes],
+ [AC_DEFINE_UNQUOTED([HAVE_CONDOR],[1],[Define to 1 if you have condor])])
+
+AM_CONDITIONAL([HAVE_CONDOR], [test "x$HAVE_CONDOR" = xyes])
+
+# Build with MW if Condor is found.
+AS_IF([test "x$HAVE_CONDOR" = xyes], [AC_CONFIG_SUBDIRS([MW])])
+
+# Check for structures/functions that can be used to determine system memory.
+AC_CHECK_MEMBERS([struct sysinfo.totalram, struct sysinfo.mem_unit],
+ [], [], [#include <sys/sysinfo.h>])
+AC_CHECK_DECLS([sysctl, CTL_HW, HW_PHYSMEM], [], [], [#include <sys/sysctl.h>])
+
+# Check for javac. If it exists, set automake conditional.
+AC_CHECK_PROG([HAVE_JAVAC], [javac], [yes], [no])
+AM_CONDITIONAL([HAVE_JAVAC], [test "x$HAVE_JAVAC" = xyes])
+
+AC_CONFIG_FILES([Makefile
+ src/main/Makefile
+ src/manager/Makefile
+ src/fsa/Makefile
+ src/annealing/Makefile
+ src/math/Makefile
+ src/util/Makefile
+ src/seq/Makefile
+ display/Makefile
+ display/mad/manifest.mf
+ perl/Makefile
+ examples/Makefile
+ doc/Makefile
+ doc/version.tex
+ html/Makefile
+ tests/Makefile])
+
+AC_OUTPUT
+
+
+# Dump some configuration confirmations.
+echo \
+"
+-- ${PACKAGE_STRING} Configuration Results --
+ C++ compiler: ${CXX} ${CXXFLAGS}"
+
+if test x"${GCC}" = x"yes" ; then
+ gcc_version=`${CC} --version | head -n 1`
+ echo " GCC version: ${gcc_version}"
+else
+ gcc_version=''
+fi
+
+echo \
+" Host System type: ${host}
+ Install prefix: ${prefix}
+
+ See config.h for further configuration information.
+ Email <${PACKAGE_BUGREPORT}> with questions and bug reports.
+"
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 6276e6d..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,10 +0,0 @@
-fsa (1.15.9+dfsg-1) UNRELEASED; urgency=low
-
- * Initial release (Closes: #<bug>)
- Question to upstream was repeated here
- https://lists.debian.org/debian-med/2015/10/msg00068.html
- but the mail bounced with
- Final-Recipient: rfc822; rbradley at mit.edu
- Diagnostic-Code: smtp; 550 5.1.1 <rbradley at mit.edu>... User unknown
-
- -- Andreas Tille <tille at debian.org> Mon, 21 Dec 2015 16:49:55 +0100
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index d24d2fe..0000000
--- a/debian/control
+++ /dev/null
@@ -1,50 +0,0 @@
-Source: fsa
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille at debian.org>
-Section: science
-Priority: optional
-Build-Depends: debhelper (>= 9),
- dh-autoreconf,
- mummer,
- exonerate,
-# htcondor is a bit complex to be configured and thus we delay this one: htcondor,
- help2man
-Standards-Version: 3.9.6
-Vcs-Browser: http://anonscm.debian.org/viewvc/debian-med/trunk/packages/fsa/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/fsa/trunk/
-Homepage: http://fsa.sourceforge.net/
-
-Package: fsa
-Architecture: any
-Depends: ${shlibs:Depends},
- ${misc:Depends}
-Description: Fast Statistical Alignment of protein, RNA or DNA sequences
- FSA is a probabilistic multiple sequence alignment algorithm which uses
- a "distance-based" approach to aligning homologous protein, RNA or DNA
- sequences. Much as distance-based phylogenetic reconstruction methods
- like Neighbor-Joining build a phylogeny using only pairwise divergence
- estimates, FSA builds a multiple alignment using only pairwise
- estimations of homology. This is made possible by the sequence annealing
- technique for constructing a multiple alignment from pairwise
- comparisons, developed by Ariel Schwartz.
- .
- FSA brings the high accuracies previously available only for
- small-scale analyses of proteins or RNAs to large-scale problems such as
- aligning thousands of sequences or megabase-long sequences. FSA
- introduces several novel methods for constructing better alignments:
- * FSA uses machine-learning techniques to estimate gap and
- substitution parameters on the fly for each set of input sequences.
- This "query-specific learning" alignment method makes FSA very robust:
- it can produce superior alignments of sets of homologous sequences
- which are subject to very different evolutionary constraints.
- * FSA is capable of aligning hundreds or even thousands of sequences
- using a randomized inference algorithm to reduce the computational
- cost of multiple alignment. This randomized inference can be over ten
- times faster than a direct approach with little loss of accuracy.
- * FSA can quickly align very long sequences using the "anchor
- annealing" technique for resolving anchors and projecting them with
- transitive anchoring. It then stitches together the alignment between
- the anchors using the methods described above.
- * The included GUI, MAD (Multiple Alignment Display), can display the
- intermediate alignments produced by FSA, where each character is
- colored according to the probability that it is correctly aligned
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index ac05452..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,53 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: fsl
-Source: http://sourceforge.net/projects/fsa/files/
-Files-Excluded: */*.jar
- */*.class
- display/JMF-2.1.1e
- display/jai-1_1_3
- doc
-
-Files: *
-Copyright: © 2010-2014 Ariel Schwartz, Chuong Do, Robert Bradley, Jaeyoung Do, Colin Dewey, Ian Holmes, Lars Barquist
-License: GPL-2+
-
-Files: MW/*
-Copyright: 1990-2004, Condor Team, Computer Sciences Department,
- University of Wisconsin-Madison, WI.
-License: Condor-1.1
- This source code is covered by the Condor Public License, which can
- be found in the accompanying LICENSE.TXT file, or online at
- www.condorproject.org.
- .
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
- FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
- HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
- MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
- ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
- PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
- RIGHT.
-
-Files: debian/*
-Copyright: 2014 Andreas Tille <tille at debian.org>
-License: GPL-2+
-
-License: GPL-2+
- 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 <http://www.gnu.org/licenses/>.
- .
- On Debian systems, the complete text of the GNU General General
- Public License can be found at /usr/share/common-licenses/GPL-2.
-
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index 6e7abe4..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,3 +0,0 @@
-README
-html/*.html
-html/*.css
diff --git a/debian/examples b/debian/examples
deleted file mode 100644
index 6947f9d..0000000
--- a/debian/examples
+++ /dev/null
@@ -1 +0,0 @@
-examples/[N-Za-z]*
diff --git a/debian/patches/no-display.patch b/debian/patches/no-display.patch
deleted file mode 100644
index 7de4a54..0000000
--- a/debian/patches/no-display.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-Author: Andreas Tille <tille at debian.org>
-Last-Update: Mon, 21 Dec 2015 16:49:55 +0100
-Description: The GUI comes with several JARs without source including
- JAI which makes it definitely non-free - so simply do not build the GUI
- and go with the command line only
-
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2,7 +2,7 @@ if HAVE_CONDOR
- MAYBE_MW = MW
- endif
-
--ALWAYS_BUILT = src/util src/math src/seq src/manager src/fsa src/annealing src/main display perl examples doc html tests
-+ALWAYS_BUILT = src/util src/math src/seq src/manager src/fsa src/annealing src/main perl examples doc html tests
- SUBDIRS = $(MAYBE_MW) $(ALWAYS_BUILT)
- DIST_SUBDIRS = $(ALWAYS_BUILT)
-
diff --git a/debian/patches/removed-pdf-only-docs.patch b/debian/patches/removed-pdf-only-docs.patch
deleted file mode 100644
index 975f33d..0000000
--- a/debian/patches/removed-pdf-only-docs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2,7 +2,7 @@ if HAVE_CONDOR
- MAYBE_MW = MW
- endif
-
--ALWAYS_BUILT = src/util src/math src/seq src/manager src/fsa src/annealing src/main perl examples doc html tests
-+ALWAYS_BUILT = src/util src/math src/seq src/manager src/fsa src/annealing src/main perl examples html tests
- SUBDIRS = $(MAYBE_MW) $(ALWAYS_BUILT)
- DIST_SUBDIRS = $(ALWAYS_BUILT)
-
---- a/configure.ac
-+++ b/configure.ac
-@@ -273,8 +273,6 @@ AC_CONFIG_FILES([Makefile
- display/mad/manifest.mf
- perl/Makefile
- examples/Makefile
-- doc/Makefile
-- doc/version.tex
- html/Makefile
- tests/Makefile])
-
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 7032061..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,2 +0,0 @@
-no-display.patch
-removed-pdf-only-docs.patch
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index c0f6e8b..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/make -f
-
-# DH_VERBOSE := 1
-
-VERSION := $(shell dpkg-parsechangelog | grep Version: | cut -f2 -d' ' | cut -f1 -d- )
-DEBPKGNAME := $(shell dpkg-parsechangelog | awk '/^Source:/ {print $$2}')
-
-mandir=$(CURDIR)/debian/$(DEBPKGNAME)/usr/share/man/man1
-bindir=$(CURDIR)/debian/$(DEBPKGNAME)/usr/bin
-
-HELP2MAN = help2man --no-info --version-string="$(VERSION)"
-
-%:
- dh $@ --with autoreconf
-
-#override_dh_auto_configure:
-# htcondor is a bit complex to be configured and thus we delay this one
-# dh_auto_configure -- --enable-condor-compile
- # found automatically: --with-mummer=/usr/bin/mummer --with-exonerate=/usr/bin/exonerate
-
-override_dh_auto_test:
- echo "Tests seem to miss some files:"
- echo "make[4]: *** No rule to make target 'apps/isect_d.unmappable.bash', needed by 'apps/isect_d.unmappable.bash.log'. Stop."
-
-override_dh_installman:
- # try to create man pages whereever possible
- mkdir -p $(mandir)
- $(HELP2MAN) \
- --name='Distance-based alignment of DNA, RNA and proteins' \
- $(bindir)/fsa > $(mandir)/fsa.1
- $(HELP2MAN) \
- --name='Find the most-parsimonious ordering of indels' \
- $(bindir)/gapcleaner > $(mandir)/gapcleaner.1
- $(HELP2MAN) \
- --name='Calculate the percentage identity of the passed alignment' \
- $(bindir)/percentid > $(mandir)/percentid.1
- $(HELP2MAN) \
- --name='Find the codon alignment corresponding to the given protein alignment' \
- $(bindir)/prot2codon > $(mandir)/prot2codon.1
- $(HELP2MAN) \
- --name='Slice a subsequence from an input FASTA file' \
- $(bindir)/slice_fasta > $(mandir)/slice_fasta.1
- $(HELP2MAN) \
- --name='Slice subsequences from an input FASTA file' \
- $(bindir)/slice_fasta_gff > $(mandir)/slice_fasta_gff.1
- $(HELP2MAN) \
- --name='Translate input nucleotide sequences into protein sequence.' \
- $(bindir)/translate > $(mandir)/translate.1
-
-
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
deleted file mode 100644
index 7b5b080..0000000
--- a/debian/upstream/metadata
+++ /dev/null
@@ -1,12 +0,0 @@
-Reference:
- Author: Robert K. Bradley and Adam Roberts and Michael Smoot and Sudeep Juvekar and Jaeyoung Do and Colin Dewey and Ian Holmes and Lior Pachter
- Title: Fast Statistical Alignment
- Journal: PLoS Comput Biol.
- Year: 2009
- Volume: 5
- Number: 5
- Pages: e1000392
- DOI: 10.1371/journal.pcbi.1000392
- PMID: 19478997
- URL: http://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1000392
- eprint: http://journals.plos.org/ploscompbiol/article/asset?id=10.1371%2Fjournal.pcbi.1000392.PDF
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index 2b4ced5..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=3
-http://sf.net/fsa/fsa-(\d[\d\.]+)\.(?:tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
diff --git a/display/Makefile.am b/display/Makefile.am
new file mode 100644
index 0000000..4c936b4
--- /dev/null
+++ b/display/Makefile.am
@@ -0,0 +1,78 @@
+all: mad.jar
+
+JAVA_SOURCES = \
+ mad/AlignDAG.java \
+ mad/Alignment.java \
+ mad/AlignmentPanel.java \
+ mad/Alignments.java \
+ mad/BatchDocument.java \
+ mad/JpegImagesToMovie.java \
+ mad/MAD.java \
+ mad/MadApplet.java \
+ mad/MadPanel.java \
+ mad/Node.java \
+ mad/ProbabilityMatrices.java \
+ mad/PropertyChangeHandler.java \
+ mad/PropertyChangeIDs.java \
+ mad/SaveAsFastaAction.java \
+ mad/SaveAsTiffAction.java \
+ mad/SaveAsMovAction.java \
+ mad/SparseMatrix.java
+
+# Root directory for class files (to be passed as -d option to javac)
+JAVAROOT = .
+
+# JMF directory
+JMF_DIR = JMF-2.1.1e
+
+# JAE directory
+JAI_DIR = jai-1_1_3
+
+# Options to pass to javac
+AM_JAVACFLAGS = -extdirs $(srcdir)/$(JMF_DIR)/lib:$(srcdir)/$(JAI_DIR)/lib \
+ -source 1.5
+
+# Other files that should go into distribution package
+EXTRA_DIST = \
+ mad \
+ classnoinst.stamp \
+ mad.jar \
+ mad/legend.jpg \
+ $(JMF_DIR)/lib/customizer.jar \
+ $(JMF_DIR)/lib/jmf.jar \
+ $(JMF_DIR)/lib/jmf.properties \
+ $(JMF_DIR)/lib/mediaplayer.jar \
+ $(JMF_DIR)/lib/multiplayer.jar \
+ $(JMF_DIR)/readme.html \
+ $(JAI_DIR)/COPYRIGHT-jai.txt \
+ $(JAI_DIR)/LICENSE-jai.txt \
+ $(JAI_DIR)/DISTRIBUTIONREADME-jai.txt \
+ $(JAI_DIR)/THIRDPARTYLICENSEREADME-jai.txt \
+ $(JAI_DIR)/lib/jai_core.jar \
+ $(JAI_DIR)/lib/jai_codec.jar
+
+# Only specify rules for building MAD if javac is available
+if HAVE_JAVAC
+dist_noinst_JAVA = $(JAVA_SOURCES)
+
+mad.jar: mad/manifest.mf \
+ $(JMF_DIR)/lib/jmf.jar \
+ $(JAI_DIR)/lib/jai_core.jar \
+ $(JAI_DIR)/lib/jai_codec.jar \
+ classnoinst.stamp
+ jar cmf $< $@ \
+ -C $(srcdir) mad \
+ -C $(srcdir) $(JMF_DIR)/lib/jmf.jar \
+ -C $(srcdir) $(JAI_DIR)/lib/jai_core.jar \
+ -C $(srcdir) $(JAI_DIR)/lib/jai_codec.jar
+ jar uf $@ mad
+
+# Jar files should be cleaned as well
+CLEANFILES = mad.jar
+else
+EXTRA_DIST += $(JAVA_SOURCES)
+endif #HAVE_JAVAC
+
+# Custom clean hook to remove class files
+clean-local:
+ -find . -name "*.class" -exec rm {} \;
diff --git a/display/Makefile.in b/display/Makefile.in
new file mode 100644
index 0000000..775fe80
--- /dev/null
+++ b/display/Makefile.in
@@ -0,0 +1,503 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ at HAVE_JAVAC_FALSE@am__append_1 = $(JAVA_SOURCES)
+subdir = display
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(am__dist_noinst_JAVA_DIST)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__dist_noinst_JAVA_DIST = mad/AlignDAG.java mad/Alignment.java \
+ mad/AlignmentPanel.java mad/Alignments.java \
+ mad/BatchDocument.java mad/JpegImagesToMovie.java mad/MAD.java \
+ mad/MadApplet.java mad/MadPanel.java mad/Node.java \
+ mad/ProbabilityMatrices.java mad/PropertyChangeHandler.java \
+ mad/PropertyChangeIDs.java mad/SaveAsFastaAction.java \
+ mad/SaveAsTiffAction.java mad/SaveAsMovAction.java \
+ mad/SparseMatrix.java
+JAVAC = javac
+CLASSPATH_ENV = CLASSPATH=$(JAVAROOT):$(srcdir)/$(JAVAROOT)$${CLASSPATH:+":$$CLASSPATH"}
+am__java_sources = $(dist_noinst_JAVA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+JAVA_SOURCES = \
+ mad/AlignDAG.java \
+ mad/Alignment.java \
+ mad/AlignmentPanel.java \
+ mad/Alignments.java \
+ mad/BatchDocument.java \
+ mad/JpegImagesToMovie.java \
+ mad/MAD.java \
+ mad/MadApplet.java \
+ mad/MadPanel.java \
+ mad/Node.java \
+ mad/ProbabilityMatrices.java \
+ mad/PropertyChangeHandler.java \
+ mad/PropertyChangeIDs.java \
+ mad/SaveAsFastaAction.java \
+ mad/SaveAsTiffAction.java \
+ mad/SaveAsMovAction.java \
+ mad/SparseMatrix.java
+
+
+# Root directory for class files (to be passed as -d option to javac)
+JAVAROOT = .
+
+# JMF directory
+JMF_DIR = JMF-2.1.1e
+
+# JAE directory
+JAI_DIR = jai-1_1_3
+
+# Options to pass to javac
+AM_JAVACFLAGS = -extdirs $(srcdir)/$(JMF_DIR)/lib:$(srcdir)/$(JAI_DIR)/lib \
+ -source 1.5
+
+
+# Other files that should go into distribution package
+EXTRA_DIST = mad classnoinst.stamp mad.jar mad/legend.jpg \
+ $(JMF_DIR)/lib/customizer.jar $(JMF_DIR)/lib/jmf.jar \
+ $(JMF_DIR)/lib/jmf.properties $(JMF_DIR)/lib/mediaplayer.jar \
+ $(JMF_DIR)/lib/multiplayer.jar $(JMF_DIR)/readme.html \
+ $(JAI_DIR)/COPYRIGHT-jai.txt $(JAI_DIR)/LICENSE-jai.txt \
+ $(JAI_DIR)/DISTRIBUTIONREADME-jai.txt \
+ $(JAI_DIR)/THIRDPARTYLICENSEREADME-jai.txt \
+ $(JAI_DIR)/lib/jai_core.jar $(JAI_DIR)/lib/jai_codec.jar \
+ $(am__append_1)
+
+# Only specify rules for building MAD if javac is available
+ at HAVE_JAVAC_TRUE@dist_noinst_JAVA = $(JAVA_SOURCES)
+
+# Jar files should be cleaned as well
+ at HAVE_JAVAC_TRUE@CLEANFILES = mad.jar
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign display/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign display/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+classnoinst.stamp: $(am__java_sources)
+ @list1='$?'; list2=; if test -n "$$list1"; then \
+ for p in $$list1; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ list2="$$list2 $$d$$p"; \
+ done; \
+ echo '$(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) '"$$list2"; \
+ $(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) $$list2; \
+ else :; fi
+ echo timestamp > $@
+
+clean-noinstJAVA:
+ -rm -f *.class classnoinst.stamp
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile classnoinst.stamp
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local clean-noinstJAVA mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-local \
+ clean-noinstJAVA cscopelist-am ctags-am distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \
+ uninstall-am
+
+all: mad.jar
+
+ at HAVE_JAVAC_TRUE@mad.jar: mad/manifest.mf \
+ at HAVE_JAVAC_TRUE@ $(JMF_DIR)/lib/jmf.jar \
+ at HAVE_JAVAC_TRUE@ $(JAI_DIR)/lib/jai_core.jar \
+ at HAVE_JAVAC_TRUE@ $(JAI_DIR)/lib/jai_codec.jar \
+ at HAVE_JAVAC_TRUE@ classnoinst.stamp
+ at HAVE_JAVAC_TRUE@ jar cmf $< $@ \
+ at HAVE_JAVAC_TRUE@ -C $(srcdir) mad \
+ at HAVE_JAVAC_TRUE@ -C $(srcdir) $(JMF_DIR)/lib/jmf.jar \
+ at HAVE_JAVAC_TRUE@ -C $(srcdir) $(JAI_DIR)/lib/jai_core.jar \
+ at HAVE_JAVAC_TRUE@ -C $(srcdir) $(JAI_DIR)/lib/jai_codec.jar
+ at HAVE_JAVAC_TRUE@ jar uf $@ mad
+
+# Custom clean hook to remove class files
+clean-local:
+ -find . -name "*.class" -exec rm {} \;
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/display/classnoinst.stamp b/display/classnoinst.stamp
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/display/classnoinst.stamp
@@ -0,0 +1 @@
+timestamp
diff --git a/display/mad/AlignDAG.java b/display/mad/AlignDAG.java
new file mode 100644
index 0000000..35fe9a7
--- /dev/null
+++ b/display/mad/AlignDAG.java
@@ -0,0 +1,641 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ * Code for different accuracy measures was written by Robert Bradley.
+ */
+
+
+package mad;
+
+import java.util.*;
+//import it.unimi.dsi.fastutil.objects.*;
+
+public class AlignDAG{
+
+ private Node[] V; // Vertices in our order.
+ private Node[] oV; // Vertices in AMAP's order.
+ private Node[] startV; // Vertices that begin each sequence
+ private HashMap<Node, Node> mergeDict;
+
+ private double acc;
+ private double sps;
+ private double ppv;
+ private double cert;
+ private double cons;
+
+ private double accDenom;
+ private double spsDenom;
+ private double ppvDenom;
+ private double certDenom;
+ private double consDenom;
+
+ private double deltaAccNorm;
+ private double deltaSPSNorm;
+ private double deltaPPVNorm;
+ private double deltaCertNorm;
+ private double deltaConsNorm;
+
+ private double gapFactorCurrent; /// the current gap factor
+
+ private int colorScheme;
+ private int mergeOrder;
+
+ private Set<Node> activeNodes;
+ private int numSeqs;
+
+ public AlignDAG (List<String> keys, String[] sequences, HashMap<String, Integer> initDAG, ProbabilityMatrices pm) {
+ this.mergeDict = new HashMap<Node, Node>();
+ this.numSeqs = sequences.length;
+
+ this.colorScheme = 0;
+ this.mergeOrder = 0;
+
+ buildDagFromInit(keys, sequences, initDAG, pm);
+ }
+
+ public AlignDAG (List<String> keys, String[] sequences, String[] alignedSeqs, ProbabilityMatrices pm){
+ this.mergeDict = new HashMap<Node, Node>();
+ this.numSeqs = sequences.length;
+
+ this.colorScheme = 0;
+ this.mergeOrder = 0;
+
+ buildDagFromAlign(keys, sequences, alignedSeqs, pm);
+ }
+
+ /// Update color scheme for all active nodes.
+ /*
+ * Forces re-coloring of all columns according to the new scheme.
+ */
+ public void setColorScheme(int scheme) {
+ this.colorScheme = scheme;
+ Iterator iter = activeNodes.iterator();
+ while (iter.hasNext()) {
+ ((Node)iter.next()).setColorScheme(scheme);
+ }
+ }
+
+ private void buildDagFromAlign(List<String> keys, String[] sequences, String[] alignedSeqs, ProbabilityMatrices pm){
+
+ acc = 0;
+ sps = 0;
+ ppv = 0;
+ cert = 0;
+ cons = 0;
+
+ accDenom = 0;
+ spsDenom = 0;
+ ppvDenom = 0;
+ certDenom = 0;
+ consDenom = 0;
+
+ deltaAccNorm = 0;
+ deltaSPSNorm = 0;
+ deltaPPVNorm = 0;
+ deltaCertNorm = 0;
+ deltaConsNorm = 0;
+
+ gapFactorCurrent = -1;
+
+ //Find total length of all sequences and initialize nextIndex array
+ int[] nextIndex = new int[numSeqs];
+
+ for(int i = 0; i < numSeqs; i++)
+ nextIndex[i] = 0;
+
+ Node lastV = null;
+
+ int alignLength = alignedSeqs[0].length();
+ this.V = new Node[alignLength];
+ this.activeNodes = new HashSet<Node>();
+
+ //Ensure rows are flush.
+ for(int i = 0; i < numSeqs; i++){
+ if (alignedSeqs[i].length() != alignLength){
+ System.err.println("ERROR: Alternate alignment rows are not flush.");
+ System.exit(-1);
+ }
+ }
+
+ //Ensure sequences match.
+ for (int i = 0; i < alignLength; i++){
+ int[] seqIndices = new int[numSeqs];
+ int presentSeqs = 0;
+ int seqI = -1;
+
+ for(int j = 0; j < numSeqs; j++){
+ char c = alignedSeqs[j].charAt(i);
+ if (c == '-'){
+ seqIndices[j] = -1;
+ }
+ else if (sequences[j].length() > nextIndex[j] && c == sequences[j].charAt(nextIndex[j])){
+ seqIndices[j] = nextIndex[j]++;
+ presentSeqs++;
+ seqI = j;
+ }
+ else{
+ System.err.println("ERROR: Sequences in alternate alignment do not match; offending sequence is '" + keys.get(j) + "'.");
+ System.exit(-1);
+ }
+ }
+
+ Node v = new Node(seqIndices, seqI, pm);
+ v.isMerge = (presentSeqs > 1);
+ v.setColorScheme (colorScheme);
+ this.V[i] = v;
+ this.mergeDict.put(v,v);
+
+ this.acc += v.getAcc();
+ this.sps += v.getSPS();
+ this.ppv += v.getPPV();
+ this.cert += v.getCert();
+ this.cons += v.getCons();
+
+ this.accDenom += v.getAccDenom();
+ this.spsDenom += v.getSPSDenom();
+ this.ppvDenom += v.getPPVDenom();
+ this.certDenom += v.getCertDenom();
+ this.consDenom += v.getConsDenom();
+
+ this.activeNodes.add(v);
+
+ if (lastV != null)
+ lastV.fwdEdge = v;
+ lastV = v;
+
+ }
+
+ //Ensure we've reached the end of the original sequence.
+ for (int i = 0; i < numSeqs; i++){
+ if (nextIndex[i] != sequences[i].length()){
+ System.err.println("ERROR: Sequences in alternate alignment do not match; offending sequence is '" + keys.get(i) + "'.");
+ System.exit(-1);
+ }
+ }
+
+ this.startV = V;
+
+ }
+
+ private void buildDagFromInit(List<String> keys, String[] sequences, HashMap<String, Integer> initDAG, ProbabilityMatrices pm){
+ Node lastV;
+ String seq;
+
+ acc = 0;
+ sps = 0;
+ ppv = 0;
+ cert = 0;
+ cons = 0;
+
+ accDenom = 0;
+ spsDenom = 0;
+ ppvDenom = 0;
+ certDenom = 0;
+ consDenom = 0;
+
+ deltaAccNorm = 0;
+ deltaSPSNorm = 0;
+ deltaPPVNorm = 0;
+ deltaCertNorm = 0;
+ deltaConsNorm = 0;
+
+ gapFactorCurrent = -1;
+
+ //Find total length of all sequences
+ int totalLength = 0;
+ for (int i = 0; i < this.numSeqs; i++){
+ totalLength += sequences[i].length();
+ }
+
+ this.V = new Node[totalLength];
+ this.oV = new Node[totalLength];
+ this.startV = new Node[numSeqs];
+ this.activeNodes = new HashSet<Node>();
+
+ int k = 0;
+ for (int i = 0; i < this.numSeqs; i++){ // iterate through array of sequences
+ lastV = null;
+ seq = sequences[i];
+
+ for (int j = 0; j < seq.length(); j++){ // iterate through sequence
+
+ // Initialize empty column and indices arrays
+ Node v = new Node(i, j, pm);
+ v.setColorScheme (colorScheme);
+ this.V[k] = v;
+ // this.oV[initDAG.get(i + "." + (j+1))] = v; //j+1 because index starts at 1
+ this.oV[initDAG.get(i + "." + j)] = v; // j because index starts at 0
+ this.mergeDict.put(v,v);
+
+ this.acc += v.getAcc();
+ this.sps += v.getSPS();
+ this.ppv += v.getPPV();
+ this.cert += v.getCert();
+ this.cons += v.getCons();
+
+ this.accDenom += v.getAccDenom();
+ this.spsDenom += v.getSPSDenom();
+ this.ppvDenom += v.getPPVDenom();
+ this.certDenom += v.getCertDenom();
+ this.consDenom += v.getConsDenom();
+
+ this.activeNodes.add(v);
+ if (lastV != null)
+ lastV.fwdEdge = v;
+ else
+ startV[i] = v;
+ lastV = v;
+ k++;
+ }
+ }
+ }
+
+ /// Get normalized accuracy for alignment.
+ /*
+ * \return accuracy, or -1 if undefined
+ * Performs bounds-checking.
+ */
+ public double getAlignAccNorm(){
+ if (accDenom == 0.)
+ return -1;
+ return SparseMatrix.saneProb (acc / accDenom);
+ }
+
+ /// Get normalized SPS for alignment.
+ /*
+ * \return SPS, or -1 if undefined
+ */
+ public double getAlignSPSNorm(){
+ if (spsDenom == 0.)
+ return -1;
+ return SparseMatrix.saneProb (sps / spsDenom);
+ }
+
+ /// Get normalized PPV for alignment.
+ /*
+ * \return PPV, or -1 if undefined
+ */
+ public double getAlignPPVNorm(){
+ if (ppvDenom == 0.)
+ return -1;
+ return SparseMatrix.saneProb (ppv / ppvDenom);
+ }
+
+ /// Get normalized certainty for alignment.
+ /*
+ * \return certainty, or -1 if undefined
+ */
+ public double getAlignCertNorm(){
+ if (certDenom == 0.)
+ return -1;
+ return SparseMatrix.saneProb (Node.normalizedCertainty (cert / certDenom));
+ }
+
+ /// Get normalized consistency for alignment.
+ /*
+ * \return consistency, or -1 if undefined
+ */
+ public double getAlignConsNorm(){
+ if (consDenom == 0.)
+ return -1;
+ return SparseMatrix.saneProb (cons / consDenom);
+ }
+
+ /// Get the change in normalized accuracy.
+ public double getDeltaAccNorm(){
+ return deltaAccNorm;
+ }
+
+ /// Get the change in normalized SPS.
+ public double getDeltaSPSNorm(){
+ return deltaSPSNorm;
+ }
+
+ /// Get the change in normalized PPV.
+ public double getDeltaPPVNorm(){
+ return deltaPPVNorm;
+ }
+
+ /// Get the change in normalized certainty.
+ public double getDeltaCertNorm(){
+ return deltaCertNorm;
+ }
+
+ /// Get the change in normalized consistency.
+ public double getDeltaConsNorm(){
+ return deltaConsNorm;
+ }
+
+ /// Get the implicit current gap factor.
+ /*
+ * -1 if Infinity, implicit current gap factor otherwise
+ */
+ public double getGapFactor(){
+ return gapFactorCurrent;
+ }
+
+ /// Merge two nodes.
+ /*
+ * @param i index of source node in oV
+ * @param j index of dest node in oV
+ */
+ public void merge(int i, int j){
+
+ Node n1 = this.mergeDict.get(this.oV[i]);
+ Node n2 = this.mergeDict.get(this.oV[j]);
+
+ Node m = new Node(n1, n2, mergeOrder++);
+ m.setColorScheme (colorScheme);
+
+ // now update accuracies after the merge
+ // note that the calculation must be done on the unnormalized accuracies
+ deltaAccNorm = m.getAcc() - (n1.getAcc() + n2.getAcc());
+ deltaAccNorm /= (1.0 * m.getAccDenom());
+
+ deltaSPSNorm = m.getSPS() - (n1.getSPS() + n2.getSPS());
+ deltaSPSNorm /= (1.0 * m.getSPSDenom());
+
+ deltaPPVNorm = m.getPPV() - (n1.getPPV() + n2.getPPV());
+ deltaPPVNorm /= (1.0 * m.getPPVDenom());
+
+ deltaCertNorm = m.getCert() - (n1.getCert() + n2.getCert());
+ deltaCertNorm /= (1.0 * m.getCertDenom());
+
+ deltaConsNorm = m.getCons() - (n1.getCons() + n2.getCons());
+ deltaConsNorm /= (1.0 * m.getConsDenom());
+
+ gapFactorCurrent = m.getWeightTgf();
+
+// System.err.println ("m.getSPS() = " + m.getSPS()
+// + "m.getSPSDenom() = " + m.getSPSDenom()
+// + "; n1.getSPS() = " + n1.getSPS() + "; n2.getSPS() = " + n2.getSPS()
+// + "; n1.getSPSDenom() = " + n1.getSPSDenom() + "; n2.getSPSDenom() = " + n2.getSPSDenom());
+
+ acc += m.getAcc() - (n1.getAcc() + n2.getAcc());
+ sps += m.getSPS() - (n1.getSPS() + n2.getSPS());
+ ppv += m.getPPV() - (n1.getPPV() + n2.getPPV());
+ cert += m.getCert() - (n1.getCert() + n2.getCert());
+ cons += m.getCons() - (n1.getCons() + n2.getCons());
+
+ accDenom += m.getAccDenom() - (n1.getAccDenom() + n2.getAccDenom());
+ spsDenom += m.getSPSDenom() - (n1.getSPSDenom() + n2.getSPSDenom());
+ ppvDenom += m.getPPVDenom() - (n1.getPPVDenom() + n2.getPPVDenom());
+ certDenom += m.getCertDenom() - (n1.getCertDenom() + n2.getCertDenom());
+ consDenom += m.getConsDenom() - (n1.getConsDenom() + n2.getConsDenom());
+
+ activeNodes.remove(n1);
+ activeNodes.remove(n2);
+ activeNodes.add(m);
+ updateMergeDict(m, m);
+ }
+
+ /// Demerge a nodes.
+ /*
+ * @param i index of node to demerge in oV
+ * @param k index of node in oV
+ *
+ * The index k is necessary in order to update the gap factor
+ * after demerging a node.
+ */
+ public void demerge(int i, int k){
+
+ --mergeOrder;
+
+ Node m = this.mergeDict.get(this.oV[i]);
+ Node n1 = m.n1;
+ Node n2 = m.n2;
+
+ n1.setColorScheme (colorScheme);
+ n2.setColorScheme (colorScheme);
+
+ // this calculation must be done on the unnormalized accuracies
+ deltaAccNorm = (n1.getAcc() + n2.getAcc()) - m.getAcc();
+ deltaAccNorm /= (1.0 * m.getAccDenom());
+
+ deltaSPSNorm = (n1.getSPS() + n2.getSPS()) - m.getSPS();
+ deltaSPSNorm /= (1.0 * m.getSPSDenom());
+
+ deltaPPVNorm = (n1.getPPV() + n2.getPPV()) - m.getPPV();
+ deltaPPVNorm /= (1.0 * m.getPPVDenom());
+
+ deltaCertNorm = (n1.getCert() + n2.getCert()) - m.getCert();
+ deltaCertNorm /= (1.0 * m.getCertDenom());
+
+ deltaConsNorm = (n1.getCons() + n2.getCons()) - m.getCons();
+ deltaConsNorm /= (1.0 * m.getConsDenom());
+
+ // decrement the gap factor: look up the gap factor for the previous merge
+ if (k >= 0)
+ gapFactorCurrent = (this.mergeDict.get(this.oV[k])).getWeightTgf();
+ else // if no previous merge, set to dummy value
+ gapFactorCurrent = -1;
+
+ acc += (n1.getAcc() + n2.getAcc()) - m.getAcc();
+ sps += (n1.getSPS() + n2.getSPS()) - m.getSPS();
+ ppv += (n1.getPPV() + n2.getPPV()) - m.getPPV();
+ cert += (n1.getCert() + n2.getCert()) - m.getCert();
+ cons += (n1.getCons() + n2.getCons()) - m.getCons();
+
+ accDenom += (n1.getAccDenom() + n2.getAccDenom()) - m.getAccDenom();
+ spsDenom += (n1.getSPSDenom() + n2.getSPSDenom()) - m.getSPSDenom();
+ ppvDenom += (n1.getPPVDenom() + n2.getPPVDenom()) - m.getPPVDenom();
+ certDenom += (n1.getCertDenom() + n2.getCertDenom()) - m.getCertDenom();
+ consDenom += (n1.getConsDenom() + n2.getConsDenom()) - m.getConsDenom();
+
+ if (mergeDict.containsKey(m)){
+ System.out.println("found it!");
+ }
+
+ activeNodes.remove(m);
+ activeNodes.add(n1);
+ activeNodes.add(n2);
+ updateMergeDict(n1, n1);
+ updateMergeDict(n2, n2);
+ }
+
+ private void updateMergeDict(Node n, Node m){
+ if (n.isMerge){
+ Node n1 = n.n1;
+ Node n2 = n.n2;
+
+ updateMergeDict(n1, m);
+ updateMergeDict(n2, m);
+ }
+ else
+ this.mergeDict.put(n, m);
+ }
+
+ public Node[] topoSort(){
+ Stack<Node> toVisit = new Stack<Node>();
+ Node u, v, w;
+ Comparator<Node> byRevFinishTime = new NodeFinishTimeComparator();
+ int time = 0;
+
+ Iterator<Node> iter = activeNodes.iterator();
+ while (iter.hasNext()) {
+ v = iter.next();
+ v.visited = false;
+ v.finishTime = -1;
+ }
+
+ for (int i = 0; i < numSeqs; i++){
+ u = mergeDict.get(startV[i]);
+
+// System.out.print ("outer loop: ");
+// u.output();
+
+ if (!u.visited){
+ toVisit.push(u);
+// System.out.print (" pushed: ");
+// u.output();
+ }
+
+ while (!toVisit.empty()){
+ v = toVisit.pop();
+// System.out.print (" popped: ");
+// v.output();
+ if (v.visited){
+ if (v.finishTime < 0) // if not finished
+ v.finishTime = time++;
+ }
+ else{
+ v.visited = true;
+ toVisit.push(v);
+// System.out.print (" pushed: ");
+// v.output();
+
+ Node[] edges = processEdges(v.getFwdEdges());
+ for(int j = 0; j < edges.length; j++) {
+ w = edges[j];
+
+ if (!w.visited){
+ toVisit.push(w);
+// System.out.print (" pushed ");
+// w.output();
+ }
+ }
+ }
+ }
+ }
+
+ iter = activeNodes.iterator();
+
+ Node[] L = activeNodes.toArray(new Node[0]);
+ Arrays.sort(L, byRevFinishTime);
+ return L;
+ }
+
+ // Maps edges to their merged version and sorts array
+ private Node[] processEdges(Collection<Node> edges){
+ Node[] edgeArray = new Node[edges.size()];
+ Iterator<Node> iter = edges.iterator();
+
+ int i = 0;
+ while (iter.hasNext())
+ edgeArray[i++] = mergeDict.get(iter.next());
+
+ if (edgeArray.length > 1){
+ Comparator<Node> byNodeSequence = new NodeSequenceComparator();
+ Arrays.sort(edgeArray, byNodeSequence);
+ MySorter sorter = new MySorter();
+ edgeArray = sorter.sort(edgeArray);
+ }
+ return edgeArray;
+ }
+
+
+
+ private void checkSort(mad.Node[] nArray){
+ int[] maxArray = new int[numSeqs];
+ Node v;
+
+ for(int i = 0; i < numSeqs; i++){
+ maxArray[i] = -1;
+ }
+ for(int i = 0; i < nArray.length; i++){
+ v = nArray[i];
+ int[] seqIndices = v.getSeqIndices();
+ for(int j = 0; j < numSeqs; j++){
+ if (seqIndices[j] != -1 && maxArray[j] > seqIndices[j]){
+ System.err.println("Sanity check failed!");
+ System.exit(-1);
+ }
+ else if (seqIndices[j] != -1)
+ maxArray[j] = seqIndices[j];
+ }
+ }
+ }
+}
+
+class MySorter{
+
+
+ public MySorter(){}
+
+ public Node[] sort(Node[] nArray){
+ boolean isSorted = false;
+ int[] maxArray;
+ int numSeqs = nArray[0].pm.numSeqs;
+ Node v;
+
+ while (!isSorted){
+ isSorted = true;
+ maxArray = new int[numSeqs];
+ for(int i = 0; i < numSeqs; i++){
+ maxArray[i] = -1;
+ }
+ for(int i = 0; i < nArray.length; i++){
+ v = nArray[i];
+ boolean switched = false;
+ int[] seqIndices = v.getSeqIndices();
+ for(int j = 0; j < numSeqs; j++){
+ if (seqIndices[j] != -1 && maxArray[j] > seqIndices[j]){
+ if (!switched){
+ switchNodes(nArray, i-1, i);
+ switched = true;
+ isSorted = false;
+ }
+ }
+ else if (seqIndices[j] != -1)
+ maxArray[j] = seqIndices[j];
+ }
+ }
+ }
+ return nArray;
+ }
+
+
+ private Node[] switchNodes(Node[] nArray, int i, int j){
+ Node temp = nArray[i];
+ nArray[i] = nArray[j];
+ nArray[j] = temp;
+ return nArray;
+ }
+}
+
+class NodeFinishTimeComparator implements Comparator<Node> {
+
+ public int compare(Node n1, Node n2){
+ if (n1.finishTime > n2.finishTime)
+ return -1;
+ return 1;
+ }
+}
+
+class NodeSequenceComparator implements Comparator<Node>{
+
+ public int compare(Node n1, Node n2){
+ int[] seq1Indices = n1.getSeqIndices();
+ int[] seq2Indices = n2.getSeqIndices();
+ for (int i = 0; i < seq1Indices.length; i++){
+
+ if (seq1Indices[i] != -1 && seq2Indices[i] != -1)
+ if (seq1Indices[i] < seq2Indices[i])
+ return -1;
+ else
+ return 1;
+ }
+ return 0;
+ }
+}
diff --git a/display/mad/Alignment.java b/display/mad/Alignment.java
new file mode 100644
index 0000000..fd37cbf
--- /dev/null
+++ b/display/mad/Alignment.java
@@ -0,0 +1,328 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ * Code for different accuracy measures was written by Robert Bradley.
+ */
+
+package mad;
+
+import java.util.*;
+
+public class Alignment {
+
+ Node[] L; // nodes in topologically sorted order
+ String[] seqs;
+ String[] cols;
+ List<String> keys;
+ AlignDAG aDag;
+ String[] fullSequences;
+ boolean gapsSuppressed;
+ int colorScheme;
+
+ public Alignment(List<String> keys, String[] fullSequences, AlignDAG aDag, boolean suppressGaps, int colorScheme) {
+ this.keys = keys;
+ this.fullSequences = fullSequences;
+ this.aDag = aDag;
+ this.colorScheme = colorScheme;
+ buildSeqsAndCols(suppressGaps, colorScheme);
+ }
+
+
+ public void buildSeqsAndCols(boolean suppressGaps, int scheme){
+
+ // update color scheme
+ this.colorScheme = scheme;
+
+ int N = keys.size();
+
+ // Initialize empty StringBuffer array and sanity check
+ StringBuffer[] cols = new StringBuffer[N];
+ StringBuffer[] seqs = new StringBuffer[N];
+ int[] sanityCheck = new int[N];
+ for (int i = 0; i < N; i++){
+ seqs[i] = new StringBuffer();
+ cols[i] = new StringBuffer();
+ sanityCheck[i] = 0;
+ }
+
+ StringBuffer color = new StringBuffer();
+ char[] colors;
+ int[] seqIndices;
+ Node v;
+
+ // update color scheme
+ aDag.setColorScheme (colorScheme);
+ L = aDag.topoSort();
+
+ //Gap suppression variables
+ int [] gapCounts = new int[1];
+ int gapCountDown = 0;
+ int lastGapCount = 0;
+ int[] colorSum = new int[N];
+ if (suppressGaps)
+ gapCounts = getGapCounts(L);
+
+
+ // Hide consecutive graps of length greater than 3.
+ for(int i = 0; i < L.length; i++){
+
+ v = L[i];
+
+ int[] sI = v.getSeqIndices();
+ for (int z = 0; z<N; z++){
+ if (sI[z] != -1){
+ if (sI[z] != sanityCheck[z])
+ System.err.println("ERROR: " + z + " " + sI[z] + " " + sanityCheck[z]);
+ sanityCheck[z] ++;
+ }
+ }
+
+ //Handle gap suppression...
+ if (!suppressGaps){}
+
+ else if (gapCountDown-- == 1){
+ colorSum = sumArrays(colorSum, v.getColors());
+ String[][] gapFill = getGapFill(lastGapCount, colorSum, v.seqI);
+ for (int j = 0; j < N; j++){
+ seqs[j].append(gapFill[j][0]);
+ cols[j].append(gapFill[j][1]);
+ }
+ continue;
+ }
+
+ else if (gapCountDown+1 > 0){ // Adding 1 because we already decremented
+ colorSum = sumArrays(colorSum, v.getColors());
+ continue;
+ }
+
+ else if ((lastGapCount = gapCounts[i]) > 3){
+ gapCountDown = lastGapCount - 1;
+ colorSum = new int[N];
+ for (int x = 0; x < N; x++)
+ colorSum[x] = 0;
+ colorSum = sumArrays(colorSum, v.getColors());
+ continue;
+ }
+ //...done handling gap suppression.
+
+
+ colors = v.getColors();
+ seqIndices = v.getSeqIndices();
+
+ for (int j = 0; j < N; j++){
+ if (seqIndices[j] == -1)
+ seqs[j].append('-');
+ else
+ seqs[j].append(fullSequences[j].charAt(seqIndices[j]));
+ cols[j].append(colors[j]);
+ }
+ }
+
+ // Convert StringBuffers to Strings
+ this.cols = new String[N];
+ this.seqs = new String[N];
+
+ for (int i = 0; i < N; i++){
+ this.cols[i] = cols[i].toString();
+ this.seqs[i] = seqs[i].toString();
+ }
+
+ this.gapsSuppressed = suppressGaps;
+
+ }
+
+ // Creates an array specifying how many consecutive gaps follow at each starting point (i).
+ public int[] getGapCounts(Node[] L){
+
+ int[] gapCounts = new int[L.length];
+ int lastCount = 0;
+ int lastSeqI = -1;
+ Node u;
+
+ for (int i = L.length-1; i>=0; i--){
+ u = L[i];
+
+ if (u.isMerge){
+ lastCount = 0;
+ gapCounts[i] = 0;
+ }
+ else{
+ if (lastSeqI != u.seqI)
+ lastCount = 0;
+ gapCounts[i] = ++lastCount;
+ lastSeqI = u.seqI;
+ }
+ }
+
+ return gapCounts;
+ }
+
+ private int[] sumArrays(int[] a1, char[] a2){
+ for (int i = 0; i < a1.length; i ++){
+ int c = (int)a2[i];
+ if (c > 256) // Remove highlighting
+ c -= 256;
+ a1[i] += c;
+
+ }
+ return a1;
+ }
+
+ // Returns a sequences to suppress a gap of size nGaps.
+ private String[][] getGapFill(int nGaps, int[] colorSum, int seqI){
+ //String nonGapSeq = "\u25B6" + nGaps + "\u25C0";
+ String nonGapSeq = ">" + nGaps + "<";
+ StringBuffer col;
+ StringBuffer seq;
+
+ int N = keys.size();
+
+ String[][] results = new String[N][2];
+
+ char avgColor;
+
+ for (int i = 0; i < N; i ++){
+ seq = new StringBuffer("");
+ col = new StringBuffer("");
+ avgColor = (char)Math.rint(colorSum[i]/nGaps);
+ for (int j = 0; j < nonGapSeq.length(); j++){
+ seq.append('-');
+ col.append(avgColor);
+ }
+ results[i][0] = seq.toString();
+ results[i][1] = col.toString();
+ }
+
+ results[seqI][0] = nonGapSeq;
+
+ return results;
+ }
+
+
+ public List<String> getOrderedKeys() {
+ return keys;
+ }
+
+ public String[] getSequences() {
+ return seqs;
+ }
+
+ public String[] getColors() {
+ return cols;
+ }
+
+ /// Get normalized accuracy for alignment.
+ /*
+ * \return accuracy, or -1 if undefined
+ */
+ public double getAccNorm() {
+ return aDag.getAlignAccNorm();
+ }
+
+ /// Get normalized SPS for alignment.
+ /*
+ * \return SPS, or -1 if undefined
+ */
+ public double getSPSNorm() {
+ return aDag.getAlignSPSNorm();
+ }
+
+ /// Get normalized PPV for alignment.
+ /*
+ * \return PPV, or -1 if undefined
+ */
+ public double getPPVNorm() {
+ return aDag.getAlignPPVNorm();
+ }
+
+ /// Get normalized certainty for alignment.
+ /*
+ * \return certainty, or -1 if undefined
+ */
+ public double getCertNorm() {
+ return aDag.getAlignCertNorm();
+ }
+
+ /// Get normalized consistency for alignment.
+ /*
+ * \return consistency, or -1 if undefined
+ */
+ public double getConsNorm() {
+ return aDag.getAlignConsNorm();
+ }
+
+ /// Get the change in normalized accuracy.
+ public double getDeltaAccNorm(){
+ return aDag.getDeltaAccNorm();
+ }
+
+ /// Get the change in normalized SPS.
+ public double getDeltaSPSNorm(){
+ return aDag.getDeltaSPSNorm();
+ }
+
+ /// Get the change in normalized PPV.
+ public double getDeltaPPVNorm(){
+ return aDag.getDeltaPPVNorm();
+ }
+
+ /// Get the change in normalized certainty.
+ public double getDeltaCertNorm(){
+ return aDag.getDeltaCertNorm();
+ }
+
+ /// Get the change in normalized consistency.
+ public double getDeltaConsNorm(){
+ return aDag.getDeltaConsNorm();
+ }
+
+ /// Get the implicit gap factor.
+ /*
+ * \return -1 if Infinity, implicit current gap factor otherwise
+ */
+ public double getGapFactor(){
+ return aDag.getGapFactor();
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Weight = ");
+ sb.append((new Double(getAccNorm())).toString());
+ sb.append("\n");
+ int i = 0;
+ for ( String key : keys ) {
+ sb.append(key);
+ sb.append("\t");
+ sb.append(seqs[i]);
+ sb.append("\n");
+ i++;
+ }
+ sb.append("\n");
+ sb.append("\n");
+
+ return sb.toString();
+ }
+
+ public String toMultiFasta() {
+ if (gapsSuppressed) // This is so that the sequences will be saved without gaps suppression
+ buildSeqsAndCols(false, 0); // throwaway color scheme
+
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+
+ for ( String key : keys ) {
+ sb.append(">");
+ sb.append(key);
+ sb.append("\n");
+ sb.append(seqs[i]);
+ sb.append("\n");
+ i++;
+ }
+
+ if (gapsSuppressed)
+ buildSeqsAndCols(true, 0); // throwaway color scheme
+
+ return sb.toString();
+ }
+}
diff --git a/display/mad/AlignmentPanel.java b/display/mad/AlignmentPanel.java
new file mode 100644
index 0000000..42f780a
--- /dev/null
+++ b/display/mad/AlignmentPanel.java
@@ -0,0 +1,337 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Michael Smoot and Adam Roberts.
+ */
+
+
+package mad;
+
+
+import javax.swing.*;
+import javax.swing.text.*;
+import java.util.*;
+import java.awt.event.*;
+import java.awt.Dimension;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.font.FontRenderContext;
+
+import java.io.*;
+import java.awt.*;
+import java.awt.image.*;
+import com.sun.image.codec.jpeg.*;
+import javax.media.jai.*;
+import com.sun.media.jai.codec.*;
+
+public class AlignmentPanel extends JTextPane implements ComponentListener, MouseListener {
+
+ Alignments aligns;
+ String[] orderedKeys;
+ HashMap<Integer, Integer> caretToNode;
+ int index;
+ int numCharsAcross;
+ int nameWidth;
+ int glyphWidth;
+ int glyphHeight;
+ int len;
+ Font defaultFont;
+ int height;
+ int width;
+ int os;
+ int currPaintIndex;
+
+ boolean colored;
+
+ public AlignmentPanel(Alignments aligns, int initWidth, boolean colored) {
+ super();
+ this.addMouseListener(this);
+ this.aligns = aligns;
+ this.width = initWidth;
+ this.colored = colored;
+ String[] seqs = aligns.get(0).getSequences();
+
+ nameWidth = 0;
+ for (String key : aligns.keys)
+ nameWidth = Math.max(nameWidth, key.length());
+ nameWidth += 2;
+
+
+ orderedKeys = new String[aligns.keys.size()];
+ int i = 0;
+ for (String key : aligns.keys){
+ StringBuffer blanks = new StringBuffer("");
+ for (int j = 0; j < nameWidth-key.length(); j++)
+ blanks.append(" ");
+ orderedKeys[i++] = " " + key + blanks;
+ }
+
+
+ defaultFont = new Font("Courier",Font.BOLD,12);
+ glyphWidth=10;
+ glyphHeight=10;
+
+ index = 0;
+ currPaintIndex = -2;
+
+ // Aaaaargh
+ if ( System.getProperty("os.name").matches(".*[Mm][Aa][Cc].*") )
+ os = -1;
+ else
+ os = 1;
+
+ this.setEditable(false);
+
+ sizeScreen( new Dimension(initWidth,0) );
+ }
+
+
+ private void sizeScreen(Dimension d) {
+ width = (int)(d.getWidth());
+
+ // find the width of the sequence name
+ FontMetrics fm = getFontMetrics(defaultFont);
+
+ glyphWidth = fm.charWidth('W');
+ glyphHeight = fm.getHeight();
+
+
+ // figure out how many multiple alignment rows there will be
+ int seqAllowedWidth = width - 20 - 2*glyphWidth - nameWidth*glyphWidth - 2*glyphWidth - 20;
+ numCharsAcross = seqAllowedWidth/glyphWidth;
+
+ if (numCharsAcross > 0){
+ currPaintIndex = -2;
+ paint();
+ }
+
+ revalidate();
+ }
+
+
+ public void setIndex(int i) {
+ if ( i >= -1 && i < aligns.size() ){
+ index = i;
+ paint();
+ }
+ else
+ System.out.println("invalid index: " + i);
+ }
+
+ // The primitive type 'char' in Java acts as an unsigned int taking
+ // values from 0 to 2^16 (65,536).
+
+ public void paint() {
+
+ if (index == currPaintIndex)
+ return;
+
+ caretToNode = new HashMap<Integer, Integer>();
+ //System.out.println("Starting paint: " + index );
+ String[] seqs = aligns.get(index).getSequences();
+ String[] cols = aligns.get(index).getColors();
+
+
+ BatchDocument doc = new BatchDocument();
+ Style style = (Style) doc.getStyle(StyleContext.DEFAULT_STYLE);
+ StyleConstants.setFontFamily(style, "Courier");
+ StyleConstants.setBold(style, true);
+ StyleConstants.setFontSize(style, defaultFont.getSize());
+
+ int pos = 0;
+ int caretPos = 0;
+
+ while (pos < seqs[0].length()){
+
+ for (int i = 0; i < orderedKeys.length; i++ ) {
+ String name = orderedKeys[i];
+ String seq = seqs[i];
+ String colString = cols[i];
+
+ if ( seq == null )
+ continue;
+
+ StyleConstants.setForeground(style, Color.black);
+ StyleConstants.setBackground(style, Color.white);
+ doc.appendBatchString(name, style);
+ caretPos += name.length();
+ StyleConstants.setForeground(style, Color.white);
+
+ for(int j = pos; j < pos+numCharsAcross && j < seq.length() ; j++){
+
+ // get color code
+ // see Node::getColors() for a description of the encoding used
+ int colCode = new Integer(colString.charAt(j));
+
+ if (colored) {
+ // if highlighted
+ if (colCode == 65535) {
+ StyleConstants.setBackground(style, Color.black);
+ }
+ // if undefined
+ else if (colCode == 256) {
+ StyleConstants.setBackground(style, Color.lightGray);
+ }
+ // else regular coloration based on accuracy measure
+ else{
+ StyleConstants.setBackground(style, getColorFromCode(colCode));
+ }
+ }
+
+ else {
+ StyleConstants.setForeground(style, Color.black);
+ StyleConstants.setBackground(style, Color.lightGray);
+
+ // StyleConstants.setBackground(style, Color.lightGray);
+ }
+
+
+ doc.appendBatchString(seq.substring(j,j+1), style);
+
+ caretToNode.put(caretPos++, j);
+ }
+ doc.appendBatchLineFeed(style);
+ caretPos++;
+ }
+ pos += numCharsAcross;
+ doc.appendBatchLineFeed(style);
+ caretPos++;
+ }
+
+ try{ doc.processBatchUpdates(0);}
+ catch (BadLocationException badLocationException) {System.err.println("Oops");}
+ //System.out.println("Setting document: " + index);
+ this.setStyledDocument(doc);
+ //System.out.println("Finished paint: " + index + "\n");
+
+ currPaintIndex = index;
+ }
+
+ public void setColored(boolean colored){
+ this.colored = colored;
+ }
+
+ public Color getColorFromCode(int colCode){
+ if (colCode >= 256){ //Highlighted
+ return Color.black;
+ }
+ int r = (int)Math.max(Math.round(-0.015564*(colCode-127)*(colCode-382)),0);
+ int g = (int)Math.max(Math.round(-0.015564*(colCode)*(colCode-255)),0);
+ int b = (int)Math.max(Math.round(-0.015564*(colCode+127)*(colCode-127)),0);
+
+ return new Color(r,g,b);
+ }
+
+ /// Save the alignment as TIFF.
+ public void saveAsTiff(String filename){
+
+ try {
+
+ // get the iamge
+ BufferedImage saveImage = new BufferedImage (this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
+ // paint it
+ Graphics gc = saveImage.getGraphics();
+ paint(gc);
+
+ // Store the image in the TIFF format.
+ TIFFEncodeParam encodeParam = new TIFFEncodeParam();
+ // encodeParam.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
+
+// TIFFField[] extras = new TIFFField[3];
+// extras[0] = new TIFFField(282,TIFFField.TIFF_RATIONAL, 1, (Object)new long[][] {{300,(long)1},{(long)0 ,(long)0}});
+// extras[1] = new TIFFField(283,TIFFField.TIFF_RATIONAL, 1, (Object)new long[][] {{300,(long)1},{(long)0 ,(long)0}}); // x
+// extras[2] = new TIFFField(296, TIFFField.TIFF_SHORT, 1, (Object) new char[] {2}); //2 for inches //y //set resolution unit to inches
+// encodeParam.setExtraFields(extras);
+
+// final int XRES_TAG = 282;
+// final int YRES_TAG = 283;
+//
+// int[] resolution = { 300, 1};
+// TIFFField xRes = new TIFFField(XRES_TAG, TIFFField.TIFF_RATIONAL, 1, new int[][] { resolution });
+// TIFFField yRes = new TIFFField(YRES_TAG, TIFFField.TIFF_RATIONAL, 1, new int[][] { resolution });
+// encodeParam.setExtraFields(new TIFFField[] { xRes, yRes});
+
+// above are failed attempts to increase the resolution of the resulting image
+// -- RKB 10/15/08
+
+ RenderedOp op = JAI.create("filestore", saveImage, filename, "tiff", encodeParam);
+
+ } catch (Exception e) {
+ System.out.print (e.toString());
+ }
+
+ }
+
+ /// Save the alignment as JPEG.
+ public void saveAsJPEG(String filename){
+
+ File save_file;
+
+ // For encoder
+ BufferedImage saveImage;
+
+
+ try{
+ FileOutputStream file_out = new FileOutputStream(filename);
+
+ // get the image
+ saveImage = new BufferedImage(this.getWidth(), this.getHeight(),
+ BufferedImage.TYPE_INT_RGB);
+ // paint it
+ Graphics gc = saveImage.getGraphics();
+ paint(gc);
+
+ float quality = 0.25f;
+ com.sun.image.codec.jpeg.JPEGEncodeParam encodeParam = JPEGCodec.getDefaultJPEGEncodeParam(saveImage);
+ encodeParam.setQuality(quality,false);
+
+ JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(file_out, encodeParam);
+ encoder.encode(saveImage);
+ System.out.println("Saved frame: " + filename);
+ file_out.close();
+ }
+ catch(Exception ex)
+ {System.out.print(ex.toString());}
+ }
+
+
+
+ public void iResized(){
+ sizeScreen(this.getSize());
+ }
+
+ public void mouseClicked(MouseEvent e) {
+
+ Alignment align = aligns.currAlign;
+ int caretPos = this.getCaret().getMark();
+
+ if (align.gapsSuppressed || !caretToNode.containsKey(caretPos))
+ return;
+
+ int nodeI = caretToNode.get(caretPos);
+
+ Node v = align.L[nodeI];
+ v.setHighlight(!v.highlighted);
+ aligns.currAlign.buildSeqsAndCols(aligns.currAlign.gapsSuppressed, aligns.currAlign.colorScheme);
+ currPaintIndex = -2;
+ paint();
+ }
+
+ public void mousePressed(MouseEvent e) {}
+ public void mouseReleased(MouseEvent e) {}
+ public void mouseEntered(MouseEvent e) {}
+ public void mouseExited(MouseEvent e) {}
+
+
+
+
+ public void componentResized(ComponentEvent e) {
+ sizeScreen( e.getComponent().getSize() );
+ }
+
+ public void componentShown(ComponentEvent e) {};
+ public void componentHidden(ComponentEvent e) {};
+ public void componentMoved(ComponentEvent e) {};
+}
diff --git a/display/mad/Alignments.java b/display/mad/Alignments.java
new file mode 100644
index 0000000..4bcafc6
--- /dev/null
+++ b/display/mad/Alignments.java
@@ -0,0 +1,364 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ * Code for different accuracy measures was written by Robert Bradley.
+ */
+
+
+package mad;
+
+import java.util.Scanner;
+import java.util.*;
+import java.util.regex.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * Class Name: Alignments
+ *
+ * Description: Acts as a wrapper for the DAG to communicate with viewer as if it held a list
+ * of the different alignments. Also parses and stores data from the log file.
+ **/
+
+public class Alignments{
+
+ AlignDAG aDag;
+ Alignment currAlign;
+ Alignment altAlign = null;
+ ProbabilityMatrices probMatrices;
+ int index;
+ int size;
+ int[] seqLengths;
+ String[] sequences;
+
+ public Double[] alignAccs;
+ public Double[] alignSPSs;
+ public Double[] alignPPVs;
+ public Double[] alignCerts;
+ public Double[] alignConss;
+
+ public Double[] alignGFs;
+
+ LinkedList<String> keys;
+ int[][] merges; // Merge is indexed so that the current merge will take you to the next alignment.
+ boolean suppressGaps;
+ int colorScheme;
+
+ public Alignments(String seqPath, String guiPath, String probPath){
+ suppressGaps = true;
+ colorScheme = 0;
+ loadData(seqPath, guiPath, probPath);
+ makeAccArrays();
+ }
+
+ public Alignments(String seqPath, String guiPath, String probPath, String altAlignPath){
+ this(seqPath, guiPath, probPath);
+ loadAltAlign(altAlignPath);
+ }
+
+ public int size(){
+ return this.size;
+ }
+
+ private void loadAltAlign(String altAlignPath){
+ String[] altSeqs = new String[keys.size()];
+ String line;
+ BufferedReader br;
+
+ try{
+ if (altAlignPath.startsWith("http://")){
+ br = new BufferedReader( new InputStreamReader( (new URL(altAlignPath)).openStream() ));
+ }
+ else{
+ br = new BufferedReader( new FileReader(altAlignPath) );
+ }
+ line = br.readLine();
+ while (line != null && line.length() > 0){
+ String key = line.substring(1);
+ int i = keys.indexOf(key);
+
+ if (i == -1){
+ System.err.println("FATAL ERROR: Alternate alignment key '"+ key +"' does not match FSA alignment.");
+ System.exit(-1);
+ }
+
+ StringBuffer seq = new StringBuffer("");
+ while ((line = br.readLine()) != null && line.length() > 0 && line.charAt(0) != '>')
+ seq.append(line);
+ altSeqs[i] = seq.toString();
+ }
+ } catch (IOException ioe){
+ ioe.printStackTrace();
+ System.exit(-1);
+ }
+
+ AlignDAG altDag = new AlignDAG(keys, sequences, altSeqs, probMatrices);
+ this.altAlign = new Alignment(keys, sequences, altDag, suppressGaps, colorScheme);
+ }
+
+ private String firstWord(String s) {
+ int space_pos = s.indexOf(' ');
+ if (space_pos == -1) {
+ return s;
+ } else {
+ return s.substring(0, space_pos);
+ }
+ }
+
+ private void loadData(String seqPath, String guiPath, String probPath){
+
+ keys = new LinkedList<String>();
+ LinkedList<String> seqs = new LinkedList<String>();
+ LinkedList<int[]> merges = new LinkedList<int[]>();
+ HashMap<String, Integer> initDAG = new HashMap<String, Integer>();
+ String line;
+ BufferedReader br;
+ Scanner scan;
+
+
+ String x;
+ String y;
+
+ int i=0;
+
+ try{
+ if (seqPath.startsWith("http://")){
+ System.out.println("WEB");
+ br = new BufferedReader( new InputStreamReader( (new URL(seqPath)).openStream() ));
+ }
+ else{
+ br = new BufferedReader( new FileReader(seqPath) );
+ }
+ String key = null;
+ StringBuffer seq = new StringBuffer("");
+ while (true) {
+ line = br.readLine();
+
+ // Check for end of previous sequence
+ if ((line == null || line.startsWith(">")) && key != null) {
+ // Only use the first word of title line as key
+ keys.add(firstWord(key.trim()));
+ String sequence = seq.toString();
+ sequence = sequence.replaceAll("\\s", ""); // remove whitespace
+ sequence = sequence.replaceAll("[-_.]", ""); // remove gaps
+ seqs.add(sequence);
+ }
+
+ // Process next line
+ if (line == null) {
+ // end of file
+ break;
+ } else if (line.startsWith(">")) {
+ // start a new sequence
+ key = line.substring(1);
+ seq.setLength(0);
+ } else {
+ // add to current sequence
+ seq.append(line);
+ }
+ }
+
+ } catch (IOException ioe){
+ ioe.printStackTrace();
+ System.exit(-1);
+ }
+
+
+ try{
+ if (guiPath.startsWith("http://")){
+ br = new BufferedReader( new InputStreamReader( (new URL(guiPath)).openStream() ));
+ }
+ else{
+ br = new BufferedReader( new FileReader(guiPath) );
+ }
+
+ // Skip blank lines and comments.
+ while ((line = br.readLine()).length() == 0 || line.charAt(0) == ';')
+ continue;
+
+ // Read nodes.
+ while(line.length() > 0 ){
+ if (line.charAt(0) == ';'){ // Skip comments
+ line = br.readLine();
+ continue;
+ }
+
+ scan = new Scanner(line);
+ // scan.findInLine("(\\d+):\\s[(](\\d+),\\s(\\d+)[)]\\s=>\\s(\\d+.\\d+|\\d+)");
+ scan.findInLine("(\\d+):\\s[(](\\d+),\\s(\\d+)[)]");
+
+
+ MatchResult result = scan.match();
+ i = new Integer(result.group(1));
+ x = result.group(2);
+ y = result.group(3);
+ initDAG.put(x + "." + y, i); // preserve 0-based indexing
+ line = br.readLine();
+
+ }
+
+
+ //Skip blank lines and comments
+ while ((line = br.readLine()).length() == 0 || line.charAt(0) == ';')
+ continue;
+
+ // Read merges
+ while (line != null){
+ scan = new Scanner(line);
+ scan.findInLine("(\\d+)\\s->\\s(\\d+)");
+ MatchResult result = scan.match();
+ int[] merge = {new Integer(result.group(1)), new Integer(result.group(2))};
+ merges.add(merge);
+ line = br.readLine();
+ }
+
+ } catch (IOException ioe){
+ ioe.printStackTrace();
+ System.exit(-1);
+ }
+
+ // Read probabilities and set up matrix
+
+ seqLengths = new int[seqs.size()];
+ Iterator<String> iter = seqs.iterator();
+ i=0;
+ while(iter.hasNext())
+ seqLengths[i++] = iter.next().length();
+
+ probMatrices = new ProbabilityMatrices(seqLengths);
+
+ int seq1, seq2;
+ int i1, i2;
+ double prob;
+
+
+ try{
+ if (probPath.startsWith("http://")){
+ br = new BufferedReader( new InputStreamReader( (new URL(probPath)).openStream() ));
+ }
+ else{
+ br = new BufferedReader( new FileReader(probPath) );
+ }
+ while ((line = br.readLine()) != null){
+ if ( line.length() == 0 || line.charAt(0) == ';') // Skip comments and blanks
+ continue;
+ scan = new Scanner(line);
+ // cover case of scientific notation
+ scan.findInLine("[(](\\d+|-\\d+),\\s(\\d+|-\\d+)[)]\\s~\\s[(](\\d+|-\\d+),\\s(\\d+|-\\d+)[)]\\s=>\\s(\\d.\\d+|\\d+)\\*?[e|E]?(-\\d+)?");
+ MatchResult result = scan.match();
+
+ seq1 = new Integer(result.group(1)).intValue();
+ i1 = new Integer(result.group(2)).intValue();
+ seq2 = new Integer(result.group(3)).intValue();
+ i2 = new Integer(result.group(4)).intValue();
+ prob = new Double(result.group(5)).doubleValue();
+ if (result.group(6) != null) {
+ Integer exponent = new Integer((String) result.group(6));
+ prob *= Math.pow(10, (double) exponent);
+ }
+ probMatrices.addElement(seq1, seq2, i1, i2, prob); // preserve 0-based indexing
+
+ //double testProb = probMatrices.getElement(seq1, seq2, i1, i2);
+ //if (testProb != prob){
+ // System.err.println("(" + seq1 + ", " + i1 + ") ~ (" + seq2 + ", " + i2 + ") => " + prob + "/" + testProb);
+ // System.exit(-1);
+ //}
+ }
+ } catch (IOException ioe){
+ ioe.printStackTrace();
+ System.exit(-1);
+ }
+
+ this.index = 0;
+ this.merges = merges.toArray(new int[0][0]);
+ this.size = this.merges.length+1;
+ this.sequences = seqs.toArray(new String[0]);
+ this.aDag = new AlignDAG(keys, sequences, initDAG, probMatrices);
+ }
+
+
+ /// Calculate and store Accuracy, SPS, PPV, Certainty and Consistency for all alignments.
+ private void makeAccArrays(){
+ alignAccs = new Double[merges.length + 1];
+ alignSPSs = new Double[merges.length + 1];
+ alignPPVs = new Double[merges.length + 1];
+ alignCerts = new Double[merges.length + 1];
+ alignConss = new Double[merges.length + 1];
+ alignGFs = new Double[merges.length + 1];
+
+ alignAccs[0] = (Double) aDag.getAlignAccNorm();
+ alignSPSs[0] = (Double) aDag.getAlignSPSNorm();
+ alignPPVs[0] = (Double) aDag.getAlignPPVNorm();
+ alignCerts[0] = (Double) aDag.getAlignCertNorm();
+ alignConss[0] = (Double) aDag.getAlignConsNorm();
+ alignGFs[0] = (Double) aDag.getGapFactor();
+
+ for (int i = 0; i < merges.length; i ++){
+ next();
+ alignAccs[i+1] = (Double) aDag.getAlignAccNorm();
+ alignSPSs[i+1] = (Double) aDag.getAlignSPSNorm();
+ alignPPVs[i+1] = (Double) aDag.getAlignPPVNorm();
+ alignCerts[i+1] = (Double) aDag.getAlignCertNorm();
+ alignConss[i+1] = (Double) aDag.getAlignConsNorm();
+ alignGFs[i+1] = (Double) aDag.getGapFactor();
+ // System.err.println ("i = " + i + "; acc = " + alignAccs[i+1] + "; sps = " + alignSPSs[i+1] + "; ppv = " + alignPPVs[i+1] + "; cert = " + alignCerts[i+1]);
+ }
+ }
+
+ public Alignment get(int index){
+
+ if (index == -1){ // -1 should only be request when an alternate alignment is available
+ // otherwise the button is disabled
+ return this.altAlign;
+ }
+
+ if (this.index == index && currAlign != null)
+ return this.currAlign;
+
+ while (this.index < index)
+ next();
+
+ while (this.index > index)
+ previous();
+
+ currAlign = new Alignment(keys, sequences, aDag, suppressGaps, colorScheme);
+ System.gc();
+ return currAlign;
+ }
+
+ // Merges with the current index and then increments it.
+ private void next(){
+ aDag.merge(merges[index][0], merges[index][1]);
+ index++;
+ }
+
+ // Decrements the index and uses the last merge as a demerge.
+ // Tell AlignDAG::demerge about the next-to-last merge as well to lookup the previous gap factor.
+ private void previous(){
+ index --;
+ if (index > 0)
+ aDag.demerge(merges[index][0], merges[index-1][0]);
+ else
+ aDag.demerge(merges[index][0], -1);
+ }
+
+ public void setGapSuppress(boolean val){
+ suppressGaps = val;
+ currAlign = null;
+ if (altAlign != null && altAlign.gapsSuppressed != suppressGaps)
+ altAlign.buildSeqsAndCols(suppressGaps, colorScheme);
+ }
+
+ /// Set color scheme.
+ public void setColorScheme(int scheme){
+
+ aDag.setColorScheme (scheme);
+
+ this.colorScheme = scheme;
+ currAlign = null;
+ if (altAlign != null && altAlign.colorScheme != scheme)
+ altAlign.buildSeqsAndCols(suppressGaps, scheme);
+ }
+
+}
diff --git a/display/mad/BatchDocument.java b/display/mad/BatchDocument.java
new file mode 100644
index 0000000..622be58
--- /dev/null
+++ b/display/mad/BatchDocument.java
@@ -0,0 +1,87 @@
+
+/*
+ * Source code in this file is from
+ * http://javatechniques.com/blog/faster-jtextpane-text-insertion-part-ii/
+ * Copyright 2003-2007 - Philip Isenhour.
+ */
+
+
+package mad;
+
+import java.util.ArrayList;
+import javax.swing.text.Element;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultStyledDocument;
+
+/**
+ * DefaultDocument subclass that supports batching inserts.
+ */
+public class BatchDocument extends DefaultStyledDocument {
+ /**
+ * EOL tag that we re-use when creating ElementSpecs
+ */
+ private static final char[] EOL_ARRAY = { '\n' };
+
+ /**
+ * Batched ElementSpecs
+ */
+ private ArrayList<ElementSpec> batch = null;
+
+ public BatchDocument() {
+ batch = new ArrayList<ElementSpec>();
+ }
+
+ /**
+ * Adds a String (assumed to not contain linefeeds) for
+ * later batch insertion.
+ */
+ public void appendBatchString(String str,
+ AttributeSet a) {
+ // We could synchronize this if multiple threads
+ // would be in here. Since we're trying to boost speed,
+ // we'll leave it off for now.
+
+ // Make a copy of the attributes, since we will hang onto
+ // them indefinitely and the caller might change them
+ // before they are processed.
+ a = a.copyAttributes();
+ char[] chars = str.toCharArray();
+ batch.add(new ElementSpec(
+ a, ElementSpec.ContentType, chars, 0, str.length()));
+ }
+
+ /**
+ * Adds a linefeed for later batch processing
+ */
+ public void appendBatchLineFeed(AttributeSet a) {
+ // See sync notes above. In the interest of speed, this
+ // isn't synchronized.
+
+ // Add a spec with the linefeed characters
+ batch.add(new ElementSpec(
+ a, ElementSpec.ContentType, EOL_ARRAY, 0, 1));
+
+ // Then add attributes for element start/end tags. Ideally
+ // we'd get the attributes for the current position, but we
+ // don't know what those are yet if we have unprocessed
+ // batch inserts. Alternatives would be to get the last
+ // paragraph element (instead of the first), or to process
+ // any batch changes when a linefeed is inserted.
+ Element paragraph = getParagraphElement(0);
+ AttributeSet pattr = paragraph.getAttributes();
+ batch.add(new ElementSpec(null, ElementSpec.EndTagType));
+ batch.add(new ElementSpec(pattr, ElementSpec.StartTagType));
+ }
+
+ public void processBatchUpdates(int offs) throws
+ BadLocationException {
+ // As with insertBatchString, this could be synchronized if
+ // there was a chance multiple threads would be in here.
+ ElementSpec[] inserts = new ElementSpec[batch.size()];
+ batch.toArray(inserts);
+
+ // Process all of the inserts in bulk
+ super.insert(offs, inserts);
+ }
+}
diff --git a/display/mad/JpegImagesToMovie.java b/display/mad/JpegImagesToMovie.java
new file mode 100644
index 0000000..e751d0b
--- /dev/null
+++ b/display/mad/JpegImagesToMovie.java
@@ -0,0 +1,530 @@
+/*
+ * @(#)JpegImagesToMovie.java 1.3 01/03/13
+ *
+ * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
+ * modify and redistribute this software in source and binary code form,
+ * provided that i) this copyright notice and license appear on all copies of
+ * the software; and ii) Licensee does not utilize the software in a manner
+ * which is disparaging to Sun.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * This software is not designed or intended for use in on-line control of
+ * aircraft, air traffic, aircraft navigation or aircraft communications; or in
+ * the design, construction, operation or maintenance of any nuclear
+ * facility. Licensee represents and warrants that it will not use or
+ * redistribute the Software for such purposes.
+ */
+
+
+package mad;
+
+import java.io.*;
+import java.util.*;
+import java.awt.Dimension;
+
+import javax.media.*;
+import javax.media.control.*;
+import javax.media.protocol.*;
+import javax.media.protocol.DataSource;
+import javax.media.datasink.*;
+import javax.media.format.VideoFormat;
+
+
+/**
+ * This program takes a list of JPEG image files and convert them into
+ * a QuickTime movie.
+ */
+public class JpegImagesToMovie implements ControllerListener, DataSinkListener {
+
+ public boolean doIt2(int width, int height, int frameRate, Vector inFiles, String outFile){
+ MediaLocator outML = createMediaLocator(outFile);
+ return doIt(width, height, frameRate, inFiles, outML);
+ }
+
+ public boolean doIt(int width, int height, int frameRate, Vector inFiles, MediaLocator outML) {
+ ImageDataSource ids = new ImageDataSource(width, height, frameRate, inFiles);
+
+ Processor p;
+
+ try {
+ System.err.println("- create processor for the image datasource ...");
+ p = Manager.createProcessor(ids);
+ } catch (Exception e) {
+ System.err.println("Yikes! Cannot create a processor from the data source.");
+ return false;
+ }
+
+ p.addControllerListener(this);
+
+ // Put the Processor into configured state so we can set
+ // some processing options on the processor.
+ p.configure();
+ if (!waitForState(p, p.Configured)) {
+ System.err.println("Failed to configure the processor.");
+ return false;
+ }
+
+ // Set the output content descriptor to QuickTime.
+ p.setContentDescriptor(new ContentDescriptor(FileTypeDescriptor.QUICKTIME));
+
+ // Query for the processor for supported formats.
+ // Then set it on the processor.
+ TrackControl tcs[] = p.getTrackControls();
+ Format f[] = tcs[0].getSupportedFormats();
+ if (f == null || f.length <= 0) {
+ System.err.println("The mux does not support the input format: " + tcs[0].getFormat());
+ return false;
+ }
+
+ tcs[0].setFormat(f[0]);
+
+ System.err.println("Setting the track format to: " + f[0]);
+
+ // We are done with programming the processor. Let's just
+ // realize it.
+ p.realize();
+ if (!waitForState(p, p.Realized)) {
+ System.err.println("Failed to realize the processor.");
+ return false;
+ }
+
+ // Now, we'll need to create a DataSink.
+ DataSink dsink;
+ if ((dsink = createDataSink(p, outML)) == null) {
+ System.err.println("Failed to create a DataSink for the given output MediaLocator: " + outML);
+ return false;
+ }
+
+ dsink.addDataSinkListener(this);
+ fileDone = false;
+
+ System.err.println("start processing...");
+
+ // OK, we can now start the actual transcoding.
+ try {
+ p.start();
+ dsink.start();
+ } catch (IOException e) {
+ System.err.println("IO error during processing");
+ return false;
+ }
+
+ // Wait for EndOfStream event.
+ waitForFileDone();
+
+ // Cleanup.
+ try {
+ dsink.close();
+ } catch (Exception e) {}
+ p.removeControllerListener(this);
+
+ System.err.println("...done processing.");
+
+ return true;
+ }
+
+
+ /**
+ * Create the DataSink.
+ */
+ DataSink createDataSink(Processor p, MediaLocator outML) {
+
+ DataSource ds;
+
+ if ((ds = p.getDataOutput()) == null) {
+ System.err.println("Something is really wrong: the processor does not have an output DataSource");
+ return null;
+ }
+
+ DataSink dsink;
+
+ try {
+ System.err.println("- create DataSink for: " + outML);
+ dsink = Manager.createDataSink(ds, outML);
+ dsink.open();
+ } catch (Exception e) {
+ System.err.println("Cannot create the DataSink: " + e);
+ return null;
+ }
+
+ return dsink;
+ }
+
+
+ Object waitSync = new Object();
+ boolean stateTransitionOK = true;
+
+ /**
+ * Block until the processor has transitioned to the given state.
+ * Return false if the transition failed.
+ */
+ boolean waitForState(Processor p, int state) {
+ synchronized (waitSync) {
+ try {
+ while (p.getState() < state && stateTransitionOK)
+ waitSync.wait();
+ } catch (Exception e) {}
+ }
+ return stateTransitionOK;
+ }
+
+
+ /**
+ * Controller Listener.
+ */
+ public void controllerUpdate(ControllerEvent evt) {
+
+ if (evt instanceof ConfigureCompleteEvent ||
+ evt instanceof RealizeCompleteEvent ||
+ evt instanceof PrefetchCompleteEvent) {
+ synchronized (waitSync) {
+ stateTransitionOK = true;
+ waitSync.notifyAll();
+ }
+ } else if (evt instanceof ResourceUnavailableEvent) {
+ synchronized (waitSync) {
+ stateTransitionOK = false;
+ waitSync.notifyAll();
+ }
+ } else if (evt instanceof EndOfMediaEvent) {
+ evt.getSourceController().stop();
+ evt.getSourceController().close();
+ }
+ }
+
+
+ Object waitFileSync = new Object();
+ boolean fileDone = false;
+ boolean fileSuccess = true;
+
+ /**
+ * Block until file writing is done.
+ */
+ boolean waitForFileDone() {
+ synchronized (waitFileSync) {
+ try {
+ while (!fileDone)
+ waitFileSync.wait();
+ } catch (Exception e) {}
+ }
+ return fileSuccess;
+ }
+
+
+ /**
+ * Event handler for the file writer.
+ */
+ public void dataSinkUpdate(DataSinkEvent evt) {
+
+ if (evt instanceof EndOfStreamEvent) {
+ synchronized (waitFileSync) {
+ fileDone = true;
+ waitFileSync.notifyAll();
+ }
+ } else if (evt instanceof DataSinkErrorEvent) {
+ synchronized (waitFileSync) {
+ fileDone = true;
+ fileSuccess = false;
+ waitFileSync.notifyAll();
+ }
+ }
+ }
+
+
+ public static void main(String args[]) {
+
+ if (args.length == 0)
+ prUsage();
+
+ // Parse the arguments.
+ int i = 0;
+ int width = -1, height = -1, frameRate = 1;
+ Vector<String> inputFiles = new Vector<String>();
+ String outputURL = null;
+
+ while (i < args.length) {
+
+ if (args[i].equals("-w")) {
+ i++;
+ if (i >= args.length)
+ prUsage();
+ width = new Integer(args[i]).intValue();
+ } else if (args[i].equals("-h")) {
+ i++;
+ if (i >= args.length)
+ prUsage();
+ height = new Integer(args[i]).intValue();
+ } else if (args[i].equals("-f")) {
+ i++;
+ if (i >= args.length)
+ prUsage();
+ frameRate = new Integer(args[i]).intValue();
+ } else if (args[i].equals("-o")) {
+ i++;
+ if (i >= args.length)
+ prUsage();
+ outputURL = args[i];
+ } else {
+ inputFiles.addElement(args[i]);
+ }
+ i++;
+ }
+
+ if (outputURL == null || inputFiles.size() == 0)
+ prUsage();
+
+ // Check for output file extension.
+ if (!outputURL.endsWith(".mov") && !outputURL.endsWith(".MOV")) {
+ System.err.println("The output file extension should end with a .mov extension");
+ prUsage();
+ }
+
+ if (width < 0 || height < 0) {
+ System.err.println("Please specify the correct image size.");
+ prUsage();
+ }
+
+ // Check the frame rate.
+ if (frameRate < 1)
+ frameRate = 1;
+
+ // Generate the output media locators.
+ MediaLocator oml;
+
+ if ((oml = createMediaLocator(outputURL)) == null) {
+ System.err.println("Cannot build media locator from: " + outputURL);
+ System.exit(0);
+ }
+
+ JpegImagesToMovie imageToMovie = new JpegImagesToMovie();
+ imageToMovie.doIt(width, height, frameRate, inputFiles, oml);
+
+ System.exit(0);
+ }
+
+ static void prUsage() {
+ System.err.println("Usage: java JpegImagesToMovie -w <width> -h <height> -f <frame rate> -o <output URL> <input JPEG file 1> <input JPEG file 2> ...");
+ System.exit(-1);
+ }
+
+ /**
+ * Create a media locator from the given string.
+ */
+ static MediaLocator createMediaLocator(String url) {
+
+ MediaLocator ml;
+
+ if (url.indexOf(":") > 0 && (ml = new MediaLocator(url)) != null)
+ return ml;
+
+ if (url.startsWith(File.separator)) {
+ if ((ml = new MediaLocator("file:" + url)) != null)
+ return ml;
+ } else {
+ String file = "file:" + System.getProperty("user.dir") + File.separator + url;
+ if ((ml = new MediaLocator(file)) != null)
+ return ml;
+ }
+
+ return null;
+ }
+
+
+ ///////////////////////////////////////////////
+ //
+ // Inner classes.
+ ///////////////////////////////////////////////
+
+
+ /**
+ * A DataSource to read from a list of JPEG image files and
+ * turn that into a stream of JMF buffers.
+ * The DataSource is not seekable or positionable.
+ */
+ class ImageDataSource extends PullBufferDataSource {
+
+ ImageSourceStream streams[];
+
+ ImageDataSource(int width, int height, int frameRate, Vector images) {
+ streams = new ImageSourceStream[1];
+ streams[0] = new ImageSourceStream(width, height, frameRate, images);
+ }
+
+ public void setLocator(MediaLocator source) {
+ }
+
+ public MediaLocator getLocator() {
+ return null;
+ }
+
+ /**
+ * Content type is of RAW since we are sending buffers of video
+ * frames without a container format.
+ */
+ public String getContentType() {
+ return ContentDescriptor.RAW;
+ }
+
+ public void connect() {
+ }
+
+ public void disconnect() {
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+
+ /**
+ * Return the ImageSourceStreams.
+ */
+ public PullBufferStream[] getStreams() {
+ return streams;
+ }
+
+ /**
+ * We could have derived the duration from the number of
+ * frames and frame rate. But for the purpose of this program,
+ * it's not necessary.
+ */
+ public Time getDuration() {
+ return DURATION_UNKNOWN;
+ }
+
+ public Object[] getControls() {
+ return new Object[0];
+ }
+
+ public Object getControl(String type) {
+ return null;
+ }
+ }
+
+
+ /**
+ * The source stream to go along with ImageDataSource.
+ */
+ class ImageSourceStream implements PullBufferStream {
+
+ Vector images;
+ int width, height;
+ VideoFormat format;
+
+ int nextImage = 0; // index of the next image to be read.
+ boolean ended = false;
+
+ public ImageSourceStream(int width, int height, int frameRate, Vector images) {
+ this.width = width;
+ this.height = height;
+ this.images = images;
+
+ format = new VideoFormat(VideoFormat.JPEG,
+ new Dimension(width, height),
+ Format.NOT_SPECIFIED,
+ Format.byteArray,
+ (float)frameRate);
+ }
+
+ /**
+ * We should never need to block assuming data are read from files.
+ */
+ public boolean willReadBlock() {
+ return false;
+ }
+
+ /**
+ * This is called from the Processor to read a frame worth
+ * of video data.
+ */
+ public void read(Buffer buf) throws IOException {
+
+ // Check if we've finished all the frames.
+ if (nextImage >= images.size()) {
+ // We are done. Set EndOfMedia.
+ System.err.println("Done reading all images.");
+ buf.setEOM(true);
+ buf.setOffset(0);
+ buf.setLength(0);
+ ended = true;
+ return;
+ }
+
+ String imageFile = (String)images.elementAt(nextImage);
+ nextImage++;
+
+ System.err.println(" - reading image file: " + imageFile);
+
+ // Open a random access file for the next image.
+ RandomAccessFile raFile;
+ raFile = new RandomAccessFile(imageFile, "r");
+
+ byte data[] = null;
+
+ // Check the input buffer type & size.
+
+ if (buf.getData() instanceof byte[])
+ data = (byte[])buf.getData();
+
+ // Check to see the given buffer is big enough for the frame.
+ if (data == null || data.length < raFile.length()) {
+ data = new byte[(int)raFile.length()];
+ buf.setData(data);
+ }
+
+ // Read the entire JPEG image from the file.
+ raFile.readFully(data, 0, (int)raFile.length());
+
+ System.err.println(" read " + raFile.length() + " bytes.");
+
+ buf.setOffset(0);
+ buf.setLength((int)raFile.length());
+ buf.setFormat(format);
+ buf.setFlags(buf.getFlags() | buf.FLAG_KEY_FRAME);
+
+ // Close the random access file.
+ raFile.close();
+ }
+
+ /**
+ * Return the format of each video frame. That will be JPEG.
+ */
+ public Format getFormat() {
+ return format;
+ }
+
+ public ContentDescriptor getContentDescriptor() {
+ return new ContentDescriptor(ContentDescriptor.RAW);
+ }
+
+ public long getContentLength() {
+ return 0;
+ }
+
+ public boolean endOfStream() {
+ return ended;
+ }
+
+ public Object[] getControls() {
+ return new Object[0];
+ }
+
+ public Object getControl(String type) {
+ return null;
+ }
+ }
+}
diff --git a/display/mad/MAD.java b/display/mad/MAD.java
new file mode 100644
index 0000000..86ec5f8
--- /dev/null
+++ b/display/mad/MAD.java
@@ -0,0 +1,67 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Michael Smoot and Adam Roberts.
+ */
+
+package mad;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import java.awt.Dimension;
+
+public class MAD{
+
+ public static void main(String[] args){
+
+ System.out.print("Reading data and building structures...");
+ try {
+ Alignments aligns = null;
+ String fsaFile = "";
+ String altFile = "";
+ if (args.length == 1){
+ fsaFile = args[0];
+ aligns = new Alignments(fsaFile, fsaFile + ".gui", fsaFile + ".probs");
+
+ } else if (args.length == 2){
+ fsaFile = args[0];
+ altFile = args[1];
+ aligns = new Alignments(fsaFile, fsaFile + ".gui", fsaFile + ".probs", altFile);
+ } else{
+ System.out.println("USAGE: java -jar MAD.jar sequencefile [alternatealignfile]");
+ System.exit(1);
+ }
+
+ System.out.println("done");
+
+ final JFrame frame = new JFrame("Multiple Alignment Display: " + args[0] + " (FSA alignment)");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ MadPanel panel = new MadPanel(frame, aligns, fsaFile, altFile);
+ panel.setPreferredSize( new Dimension(900,700) );
+
+ JMenuBar menuBar = new JMenuBar();
+ JMenu fileMenu = new JMenu("File");
+ menuBar.add(fileMenu);
+ JMenuItem saveAsFasta = new JMenuItem( new SaveAsFastaAction(panel) );
+ JMenuItem saveAsTiff = new JMenuItem( new SaveAsTiffAction(panel) );
+ JMenuItem saveAsMov = new JMenuItem(new SaveAsMovAction(panel) );
+ fileMenu.add(saveAsFasta);
+ fileMenu.add(saveAsTiff);
+ fileMenu.add(saveAsMov);
+ frame.setJMenuBar(menuBar);
+
+
+ //Display the window.
+ frame.setContentPane(panel);
+ frame.pack();
+ frame.setVisible(true);
+
+
+ } catch (Exception ioe) {
+ ioe.printStackTrace();
+ }
+
+ }
+}
diff --git a/display/mad/MadApplet.java b/display/mad/MadApplet.java
new file mode 100644
index 0000000..5ae8f9b
--- /dev/null
+++ b/display/mad/MadApplet.java
@@ -0,0 +1,37 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ */
+
+package mad;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import java.applet.*;
+import java.awt.Dimension;
+
+public class MadApplet extends JApplet{
+ public void init() {
+ System.out.println("Applet initializing");
+ String fsaFile = getParameter("fsaFile");
+ Alignments aligns = new Alignments(fsaFile, fsaFile + ".gui", fsaFile + ".probs");
+ MadPanel panel = new MadPanel(aligns, fsaFile, "");
+ panel.setPreferredSize( new Dimension(900,700) );
+ getContentPane().add(panel);
+ }
+
+ public void start() {
+ System.out.println("Applet starting");
+ }
+ public void stop() {
+ System.out.println("Applet stopping");
+ }
+
+ public void destroy() {
+ System.out.println("Applet destroyed");
+ }
+
+
+}
diff --git a/display/mad/MadPanel.java b/display/mad/MadPanel.java
new file mode 100644
index 0000000..0d97ceb
--- /dev/null
+++ b/display/mad/MadPanel.java
@@ -0,0 +1,792 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Michael Smoot and Adam Roberts.
+ * Code for different accuracy measures was written by Robert Bradley.
+ */
+
+// to do:
+
+
+package mad;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.NumberFormatter;
+import java.beans.*;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.Iterator;
+
+
+import java.io.File;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import java.net.URL;
+
+
+public class MadPanel extends JPanel
+ implements ChangeListener, PropertyChangeListener, ActionListener, ItemListener {
+
+ AlignmentPanel alignPanel;
+ JFormattedTextField indexField;
+ JLabel legLabel;
+ JFormattedTextField accField;
+
+ JLabel accLabel;
+ JLabel dAccLabel;
+
+ JLabel gfLabel;
+ JFormattedTextField gfField;
+
+ JSlider alignSlider;
+ JSlider zoomSlider;
+ Alignments aligns;
+ JButton nextButton;
+ JButton prevButton;
+ JButton startStopButton;
+ JButton altAlignButton;
+ JCheckBox gapSuppressCheck;
+ JFrame parent = null;
+
+ JCheckBox coloredCheck;
+ JComboBox colorSchemes;
+ String[] colorSchemesList;
+ String[] colorSchemesLabels;
+
+ String fsaPath, altPath;
+
+ int maxSliderVal;
+ Map<Component,Boolean> ok2update;
+ Timer timer;
+ boolean frozen = true;
+ int delay = 100;
+
+ boolean inAlt = false;
+
+
+ public MadPanel(JFrame parent, Alignments aligns, String fsaPath, String altPath){
+ this(aligns, fsaPath, altPath);
+ this.parent = parent;
+
+ }
+ public MadPanel(Alignments aligns, String fsaPath, String altPath) {
+
+ this.aligns = aligns;
+ this.fsaPath = fsaPath;
+ this.altPath = altPath;
+
+ maxSliderVal = aligns.size()-1;
+
+ ok2update = new HashMap<Component,Boolean>();
+
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ // set up animation timer
+ timer = new Timer(delay,this);
+ timer.setCoalesce(true);
+
+ //Create the label.
+ JLabel sliderLabel = new JLabel("Alignment: ", JLabel.CENTER);
+ sliderLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ //Create the alignment number field
+ java.text.NumberFormat intFormat = java.text.NumberFormat.getIntegerInstance();
+ NumberFormatter intFormatter = new NumberFormatter(intFormat);
+ intFormatter.setMinimum(new Integer(0));
+ intFormatter.setMaximum(new Integer(maxSliderVal));
+ indexField = new JFormattedTextField(intFormatter);
+ indexField.setColumns(4); //get some space
+ indexField.addPropertyChangeListener( this );
+ handleEnterKeyStroke( indexField );
+ ok2update.put(indexField,false);
+
+ accLabel = new JLabel("Accuracy: ", JLabel.CENTER);
+ dAccLabel = new JLabel("\u0394 Accuracy: ", JLabel.CENTER);
+ gfLabel = new JLabel("Gap Factor: ", JLabel.CENTER);
+
+ //Create the alignment acc field
+ java.text.NumberFormat numFormat = java.text.NumberFormat.getNumberInstance();
+ NumberFormatter numFormatter = new NumberFormatter(numFormat);
+ numFormatter.setMinimum(new Float(0f));
+ numFormatter.setMaximum(new Float(Float.MAX_VALUE));
+ accField = new JFormattedTextField(numFormatter);
+ accField.setColumns(4); //get some space
+ accField.addPropertyChangeListener( this );
+ handleEnterKeyStroke( accField );
+ ok2update.put(accField,false);
+
+ //Create the alignment acc field
+ java.text.NumberFormat numFormat2 = java.text.NumberFormat.getNumberInstance();
+ NumberFormatter numFormatter2 = new NumberFormatter(numFormat);
+ numFormatter2.setMinimum(new Float(0f));
+ numFormatter2.setMaximum(new Float(Float.MAX_VALUE));
+ gfField = new JFormattedTextField(numFormatter2);
+ gfField.setColumns(4); //get some space
+ gfField.addPropertyChangeListener( this );
+ handleEnterKeyStroke( gfField );
+ ok2update.put(gfField,false);
+
+ // create next button
+ nextButton = new JButton("Next");
+ nextButton.addActionListener(this);
+
+ startStopButton = new JButton("Start Animation");
+ startStopButton.addActionListener(this);
+
+ // create prev button
+ prevButton = new JButton("Prev");
+ prevButton.addActionListener(this);
+
+ // create alternate alignment button
+ altAlignButton = new JButton("Alt Alignment");
+ altAlignButton.addActionListener(this);
+ altAlignButton.setEnabled(aligns.altAlign != null);
+
+ //Create the sliders.
+ alignSlider = new JSlider(JSlider.HORIZONTAL, 0, maxSliderVal, 0);
+ alignSlider.addChangeListener(this);
+ zoomSlider = new JSlider(JSlider.VERTICAL, 0, 20, 10);
+ zoomSlider.addChangeListener(this);
+
+ //Turn on labels at major tick marks.
+ alignSlider.setMajorTickSpacing(calcTickSpacing(maxSliderVal));
+ alignSlider.setPaintTicks(true);
+ alignSlider.setPaintLabels(true);
+
+ //Create gap suppression checkbox
+ gapSuppressCheck = new JCheckBox("Gap Suppression", true);
+ gapSuppressCheck.addItemListener(this);
+
+ //Create the panel that displays the animation.
+ alignPanel = new AlignmentPanel(aligns,450,true);
+ alignPanel.setBorder(BorderFactory.createCompoundBorder(
+ BorderFactory.createLoweredBevelBorder(),
+ BorderFactory.createEmptyBorder(10,10,10,10)));
+
+ // set up scrolling
+ JScrollPane alignScroll = new JScrollPane(alignPanel);
+ alignScroll.setPreferredSize(new Dimension(500,800));
+ alignScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ alignScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ alignScroll.addComponentListener(alignPanel);
+
+ // Set up zoompanel
+ JLabel plusLabel = new JLabel("+", JLabel.CENTER);
+ plusLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ JLabel minusLabel = new JLabel("-", JLabel.CENTER);
+ minusLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ JPanel zoomPanel = new JPanel();
+ zoomPanel.setLayout(new BoxLayout(zoomPanel, BoxLayout.Y_AXIS));
+ zoomPanel.add(plusLabel);
+ zoomPanel.add(zoomSlider);
+ zoomPanel.add(minusLabel);
+
+ JPanel alignAndZoom = new JPanel(new BorderLayout());
+ alignAndZoom.add(zoomPanel,BorderLayout.LINE_START);
+ alignAndZoom.add(alignScroll,BorderLayout.CENTER);
+
+ // create colorin checkbox
+ coloredCheck = new JCheckBox("Coloring", true);
+ coloredCheck.addItemListener(this);
+
+ // set up color schemes
+ colorSchemesList = new String[5];
+ colorSchemesList[0] = "Accuracy";
+ colorSchemesList[1] = "Sensitivity";
+ colorSchemesList[2] = "Specificity";
+ colorSchemesList[3] = "Certainty";
+ colorSchemesList[4] = "Consistency";
+
+ colorSchemesLabels = new String[5];
+ colorSchemesLabels[0] = "Low Accuracy High Accuracy";
+ colorSchemesLabels[1] = "Low Sensitivity High Sensitivity";
+ colorSchemesLabels[2] = "Low Specificity High Specificity";
+ colorSchemesLabels[3] = "Low Certainty High Certainty";
+ colorSchemesLabels[4] = "Low Consistency High Consistency";
+
+ colorSchemes = new JComboBox(colorSchemesList);
+ colorSchemes.setSelectedIndex(0);
+ colorSchemes.addActionListener(this);
+
+ //Create legend
+ URL imgURL = getClass().getResource("legend.jpg");
+ ImageIcon legIcon = new ImageIcon(imgURL);
+ legLabel = new JLabel("Low Accuracy High Accuracy", legIcon, JLabel.CENTER);
+ legLabel.setVerticalTextPosition(JLabel.BOTTOM);
+ legLabel.setHorizontalTextPosition(JLabel.CENTER);
+ legLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ // Create a subpanel for the label and text field.
+ JPanel labelAndTextField = new JPanel(); //use FlowLayout
+ labelAndTextField.add(colorSchemes);
+ labelAndTextField.add(Box.createRigidArea(new Dimension(20,0)));
+ labelAndTextField.add(legLabel);
+ labelAndTextField.add(Box.createRigidArea(new Dimension(20,0)));
+ labelAndTextField.add(accLabel);
+ labelAndTextField.add(accField);
+ labelAndTextField.add(Box.createRigidArea(new Dimension(10,0)));
+ labelAndTextField.add(dAccLabel);
+ labelAndTextField.add(Box.createRigidArea(new Dimension(20,0)));
+ labelAndTextField.add(gfLabel);
+ labelAndTextField.add(gfField);
+ labelAndTextField.add(Box.createRigidArea(new Dimension(20,0)));
+ labelAndTextField.add(sliderLabel);
+ labelAndTextField.add(indexField);
+
+ JPanel controlPane = new JPanel();
+ controlPane.add(prevButton);
+ controlPane.add(startStopButton);
+ controlPane.add(nextButton);
+ controlPane.add(altAlignButton);
+ controlPane.add(coloredCheck);
+ controlPane.add(gapSuppressCheck);
+
+ // Put everything together.
+ // The order in which these are added CANNOT be changed without
+ // also changing the indexing in actionPerformed().
+ add(alignAndZoom);
+ add(Box.createRigidArea(new Dimension(0, 10)));
+ add(labelAndTextField);
+ add(alignSlider);
+ add(controlPane);
+ setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+ update(maxSliderVal);
+ }
+
+ // Catch changes to sliders
+ public void stateChanged(ChangeEvent e) {
+
+ JSlider source = (JSlider)e.getSource();
+ if ( source == alignSlider && (boolean) ok2update.get(alignSlider)){
+ update((int)alignSlider.getValue());
+ }
+ else if (source == zoomSlider){
+ alignPanel.defaultFont = alignPanel.defaultFont.deriveFont(1 + (float)zoomSlider.getValue());
+ alignPanel.iResized();
+ //repaint();
+ }
+ }
+
+ // Changes the alignment frame
+ private void update(int index) {
+ Alignment align = aligns.get(index);
+ updatePicture(index);
+ ok2update.put(alignSlider, false);
+ alignSlider.setValue(index);
+ ok2update.put(alignSlider, true);
+ indexField.setText(Integer.toString(index));
+
+ // update accuracy field
+ accField.setText(getAccFieldString(align));
+
+ // update delta accuracy field
+ dAccLabel.setText(getDeltaAccFieldString(align, index));
+
+ // update gap factor field
+ gfField.setText(getGapFactorFieldString(align, index));
+ }
+
+ /// Get value for the accuracy field (varies based on color scheme).
+ private String getAccFieldString(Alignment align){
+
+ // displayed value depends on the chosen color scheme
+ double accFieldValue = 0;
+ switch (align.colorScheme) {
+ case 0: // Accuracy
+ accFieldValue = align.getAccNorm();
+ break;
+ case 1: // SPS
+ accFieldValue = align.getSPSNorm();
+ break;
+ case 2: // PPV
+ accFieldValue = align.getPPVNorm();
+ break;
+ case 3: // Certainty
+ accFieldValue = align.getCertNorm();
+ break;
+ case 4: // Consistency
+ accFieldValue = align.getConsNorm();
+ break;
+ default:
+ System.exit(1);
+ }
+
+ // test for undefined value
+ // (-1 is returned if undefined)
+ if (accFieldValue < 0)
+ return "Undefined";
+ else {
+ accFieldValue = Math.rint(accFieldValue*10000)/10000;
+ return Double.toString(accFieldValue);
+ }
+
+ }
+
+ /// Get value for the delta accuracy field (varies based on color scheme).
+ /*
+ * @param index index of the alignment
+ * \return 0 if first alignment, N/A if alternate alignment and delta accuracy otherwise
+ */
+ private String getDeltaAccFieldString(Alignment align, int index){
+
+ // displayed value depends on the chosen color scheme
+ double delta = 0;
+ switch (align.colorScheme) {
+ case 0: // Accuracy
+ delta = align.getDeltaAccNorm();
+ break;
+ case 1: // SPS
+ delta = align.getDeltaSPSNorm();
+ break;
+ case 2: // PPV
+ delta = align.getDeltaPPVNorm();
+ break;
+ case 3: // Certainty
+ delta = align.getDeltaCertNorm();
+ break;
+ case 4: // Consistency
+ delta = align.getDeltaConsNorm();
+ break;
+ default:
+ System.exit(1);
+ }
+
+ // handle case of first alignment
+ if (index == 0)
+ delta = 0;
+
+ // now format nicely
+ NumberFormat formatter;
+ if (delta < 0)
+ formatter = new DecimalFormat("#0.0000");
+ else
+ formatter = new DecimalFormat(" #0.0000");
+
+ String entry = "\u0394 Column " + colorSchemesList[align.colorScheme] + ": " + formatter.format(delta);
+
+ // handle case of alternate alignment
+ if (index == -1)
+ entry = "\u0394 Column " + colorSchemesList[align.colorScheme] + ": N/A ";
+
+ return entry;
+ }
+
+ /// Get value for the gap factor field.
+ /*
+ * @param index index of the alignment
+ * \return Infinity if first alignment, N/A if alternate alignment and implicit gap factor otherwise
+ */
+ private String getGapFactorFieldString(Alignment align, int index){
+
+ double gf = align.getGapFactor();
+ gf = Math.rint(gf * 10)/10;
+
+ String entry;
+ // handle case of alternate alignment
+ if (index == -1)
+ return "N/A";
+ // handle case of big gap factor
+ else if (gf > 100 || gf < 0)
+ return ">100";
+ else
+ return Double.toString(gf);
+
+ }
+
+ // Switch between alternate alignment and FSA alignment
+ private void toggleAltAlign(boolean toAlt){
+ if (toAlt){
+ inAlt = true;
+
+ Alignment align = aligns.get(-1);
+ indexField.setText("ALT");
+ updatePicture(-1);
+
+ // update accuracy field
+ accField.setText(getAccFieldString(align));
+
+ // update delta accuracy field
+ dAccLabel.setText(getDeltaAccFieldString(align, -1));
+
+ // update gap factor field
+ gfField.setText(getGapFactorFieldString(align, -1));
+
+ altAlignButton.setText("FSA Alignment");
+ if (parent != null)
+ parent.setTitle("Multiple Alignment Display: " + altPath + " (Alternate alignment)");
+ } else{
+ inAlt = false;
+
+ update((int)alignSlider.getValue());
+ altAlignButton.setText("Alt Alignment");
+ if (parent != null)
+ parent.setTitle("Multiple Alignment Display: " + fsaPath + " (FSA alignment)");
+ }
+
+ prevButton.setEnabled(!toAlt);
+ nextButton.setEnabled(!toAlt);
+ startStopButton.setEnabled(!toAlt);
+ accField.setEnabled(!toAlt);
+ gfField.setEnabled(!toAlt);
+ indexField.setEnabled(!toAlt);
+ alignSlider.setEnabled(!toAlt);
+
+ }
+
+ // Catch changes to text boxes
+ public void propertyChange(PropertyChangeEvent e) {
+ if (!"value".equals(e.getPropertyName()))
+ return;
+
+ // alignment index field
+ if ( e.getSource() == indexField && ok2update.get(indexField) ) {
+ Number value = (Number)e.getNewValue();
+ if (value != null) {
+ update(value.intValue());
+ ok2update.put(indexField,false);
+ }
+ }
+
+ // accuracy field
+ else if ( e.getSource() == accField && ok2update.get(accField) ) {
+ // Float acc = (Float) e.getNewValue();
+ int index = -1;
+ int scheme = colorSchemes.getSelectedIndex();
+ switch (scheme) {
+ case 0:
+ index = getIndexFromAcc ((Float)e.getNewValue());
+ break;
+ case 1:
+ index = getIndexFromSPS ((Float)e.getNewValue());
+ break;
+ case 2:
+ index = getIndexFromPPV ((Float)e.getNewValue());
+ break;
+ case 3:
+ index = getIndexFromCert ((Float)e.getNewValue());
+ break;
+ case 4:
+ index = getIndexFromCons ((Float)e.getNewValue());
+ break;
+ default:
+ System.exit(1);
+ }
+
+ // if runs off the left, go to first alignment
+ if (index < 0) {
+ update(0);
+ ok2update.put(accField, false);
+ }
+ // else go to the requested alignment
+ else if (index >= 0 && index <= maxSliderVal) {
+ update(index);
+ ok2update.put(accField ,false);
+ }
+ }
+
+ // gap factor field
+ else if ( e.getSource() == gfField && (boolean) ok2update.get(gfField) ) {
+
+ int index = getIndexFromGF ((Float)e.getNewValue());
+
+ // if runs off the left, go to first alignment
+ if (index < 0) {
+ update(0);
+ ok2update.put(gfField, false);
+ }
+ // else go to the requested alignment
+ else if (index >= 0 && index <= maxSliderVal) {
+ update(index);
+ ok2update.put(gfField ,false);
+ }
+ }
+
+ }
+
+ // Catch button clicks and timer
+ public void actionPerformed(ActionEvent e) {
+
+ int curr = !inAlt ? (int)alignSlider.getValue() : -1;
+
+ // next alignment
+ if ( e.getSource() == nextButton) {
+ if ( curr == maxSliderVal )
+ update(0);
+ else
+ update(curr+1);
+ }
+
+ // timer
+ else if (e.getSource() == timer){
+ if (curr == maxSliderVal ){
+ timer.stop();
+ frozen = true;
+ startStopButton.setText("Start Animation");
+ }
+ else
+ update(curr+1);
+ }
+ // previous alignment
+ else if ( e.getSource() == prevButton ) {
+ if ( curr == 0 )
+ update(maxSliderVal);
+ else
+ update(curr-1);
+ }
+ // start/stop animation
+ else if ( e.getSource() == startStopButton ) {
+ if ( frozen ) {
+ if (curr == maxSliderVal)
+ update(0);
+ timer.start();
+ startStopButton.setText("Stop Animation");
+ altAlignButton.setEnabled(false);
+ } else {
+ timer.stop();
+ startStopButton.setText("Start Animation");
+ if (aligns.altAlign != null)
+ altAlignButton.setEnabled(true);
+ }
+ frozen = !frozen;
+ }
+ // alternate alignment
+ else if ( e.getSource() == altAlignButton ) {
+ toggleAltAlign(altAlignButton.getText() == "Alt Alignment");
+ }
+ // color schemes
+ else if ( e.getSource() == colorSchemes ){
+
+ JComboBox cb = (JComboBox)e.getSource();
+
+ // get the integer index of the color scheme
+ int scheme = cb.getSelectedIndex();
+
+ // update the color scheme
+ aligns.setColorScheme(scheme);
+
+ // update the legend label
+ legLabel.setText(colorSchemesLabels[scheme]);
+
+ // update the accuracy field label
+ accLabel.setText(colorSchemesList[scheme] + ": ");
+
+ // to do: this needs to check whether in the alternate alignment;
+ // currently uses curr, which is always the FSA alignment
+ // (not updated properly for alternate alignment)
+
+ // update accuracy field value
+ // NB aligns.get(curr) returns the current Alignment object
+ accField.setText(getAccFieldString(aligns.get(curr)));
+
+ // update the delta accuracy label
+ dAccLabel.setText(getDeltaAccFieldString(aligns.get(curr), curr));
+
+ // update the gap factor label
+ gfField.setText(getGapFactorFieldString(aligns.get(curr), curr));
+
+ // redraw the panel
+ alignPanel.iResized();
+ }
+
+ }
+
+ // Catch check box change
+ public void itemStateChanged(ItemEvent e) {
+
+ Object source = e.getItemSelectable();
+
+ // colored
+ if (source == coloredCheck){
+ if (e.getStateChange() == ItemEvent.DESELECTED)
+ alignPanel.setColored(false);
+ else
+ alignPanel.setColored(true);
+ alignPanel.iResized();
+ }
+
+ // gap suppression
+ else if (source == gapSuppressCheck){
+ if (e.getStateChange() == ItemEvent.DESELECTED)
+ aligns.setGapSuppress(false);
+ else
+ aligns.setGapSuppress(true);
+ alignPanel.iResized();
+ //repaint();
+ }
+
+ }
+
+
+ public void alignmentToMov(){
+
+ // Get save path for movie file.
+ FileDialog chooseFile = new FileDialog(new Frame(), "Export as Quicktime Movie", FileDialog.SAVE);
+ chooseFile.setVisible(true);
+ String movFile = chooseFile.getFile();
+ if (movFile == null)
+ return;
+ if (!movFile.endsWith(".mov"))
+ movFile = movFile.concat(".mov");
+ String dirPath = chooseFile.getDirectory();
+ String movPath = dirPath + movFile;
+
+ Vector<String> files = new Vector<String>();
+ String fName;
+
+
+ // Ceate JPEGs
+ for (int i = 0; i < aligns.size(); i++){
+ update(i);
+ fName = String.format(dirPath + "/%08d.jpg",i);
+ files.add(fName);
+ alignPanel.saveAsJPEG(fName);
+ }
+
+ // Create movie
+ JpegImagesToMovie imageToMovie = new JpegImagesToMovie();
+ imageToMovie.doIt2(alignPanel.getWidth(), alignPanel.getHeight(), 5, files, movPath);
+
+ // Delete temporary JPEGs
+ Iterator iter = files.iterator();
+ while (iter.hasNext()){
+ fName = (String) iter.next();
+ (new File(fName)).delete();
+ }
+ }
+
+ protected void updatePicture(int frameNum) {
+ alignPanel.setIndex(frameNum);
+ }
+
+ protected int calcTickSpacing(int val) {
+ return ((val/10) - (val%10));
+ }
+
+ /// Get index for the alignment with specified accuracy.
+ private int getIndexFromAcc(Float a) {
+ int index = -1;
+ double minDiff = (double) Double.MAX_VALUE;
+ double diff;
+
+ for (int i = 0; i < aligns.alignAccs.length; i++){
+ diff = Math.abs(aligns.alignAccs[i].doubleValue() - a);
+ if (diff < minDiff){
+ minDiff = diff;
+ index = i;
+ }
+ }
+
+ return index;
+ }
+
+ /// Get index for the alignment with specified SPS.
+ private int getIndexFromSPS(Float a) {
+ int index = -1;
+ double minDiff = Double.MAX_VALUE;
+ double diff;
+
+ for (int i = 0; i < aligns.alignSPSs.length; i++){
+ diff = Math.abs(aligns.alignSPSs[i].doubleValue() - a);
+ if (diff < minDiff){
+ minDiff = diff;
+ index = i;
+ }
+ }
+
+ return index;
+ }
+
+ /// Get index for the alignment with specified PPV.
+ private int getIndexFromPPV(Float a) {
+ int index = -1;
+ double minDiff = Double.MAX_VALUE;
+ double diff;
+
+ for (int i = 0; i < aligns.alignPPVs.length; i++){
+ diff = Math.abs(aligns.alignPPVs[i].doubleValue() - a);
+ if (diff < minDiff){
+ minDiff = diff;
+ index = i;
+ }
+ }
+
+ return index;
+ }
+
+ /// Get index for the alignment with specified Certainty.
+ private int getIndexFromCert(Float a) {
+ int index = -1;
+ double minDiff = Double.MAX_VALUE;
+ double diff;
+
+ for (int i = 0; i < aligns.alignCerts.length; i++){
+ diff = Math.abs(aligns.alignCerts[i].doubleValue() - a);
+ if (diff < minDiff){
+ minDiff = diff;
+ index = i;
+ }
+ }
+
+ return index;
+ }
+
+ /// Get index for the alignment with specified Consistency.
+ private int getIndexFromCons(Float a) {
+ int index = -1;
+ double minDiff = Double.MAX_VALUE;
+ double diff;
+
+ for (int i = 0; i < aligns.alignConss.length; i++){
+ diff = Math.abs(aligns.alignConss[i].doubleValue() - a);
+ if (diff < minDiff){
+ minDiff = diff;
+ index = i;
+ }
+ }
+
+ return index;
+ }
+
+ /// Get index for the alignment with specified gap factor.
+ private int getIndexFromGF(Float a) {
+ int index = -1;
+ double minDiff = Double.MAX_VALUE;
+ double diff;
+
+ for (int i = 0; i < aligns.alignGFs.length; i++){
+ diff = Math.abs(aligns.alignGFs[i].doubleValue() - a);
+ if (diff < minDiff){
+ minDiff = diff;
+ index = i;
+ }
+ }
+
+ return index;
+ }
+
+
+ //React when the user presses Enter.
+ private void handleEnterKeyStroke( final JFormattedTextField field ) {
+ field.getInputMap().put(KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0), "check");
+ field.getActionMap().put("check", new AbstractAction() {
+ public void actionPerformed(ActionEvent e) {
+ //The text is invalid.
+ if (!field.isEditValid()) {
+ Toolkit.getDefaultToolkit().beep();
+ field.selectAll();
+ //The text is valid, so use it.
+ } else try {
+ ok2update.put(field,true);
+ field.commitEdit();
+ } catch (java.text.ParseException exc) { }
+ }
+ });
+ }
+}
+
diff --git a/display/mad/Node.java b/display/mad/Node.java
new file mode 100644
index 0000000..4879953
--- /dev/null
+++ b/display/mad/Node.java
@@ -0,0 +1,618 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ * Code for different accuracy measures was written by Robert Bradley.
+ */
+
+
+// to do:
+
+
+package mad;
+
+import java.util.*;
+
+//import it.unimi.dsi.fastutil.objects.*;
+
+public class Node{
+
+ private int[] seqVals;// Indices of position in each sequence contained in node
+ private char[] colors;
+ public int seqI; // If an initial node, what sequence I contain (useful for gap fills).
+ public int seqVal;
+ public int numSeqs;
+
+ public double acc;
+ public double sps;
+ public double ppv;
+ public double cert;
+ public double cons;
+
+ public double accDenom;
+ public double spsDenom;
+ public double ppvDenom;
+ public double certDenom;
+ public double consDenom;
+
+ public double weightTgf;
+
+ public Node fwdEdge;
+ public boolean highlighted = false;
+
+ public int mergeOrder;
+
+ /*
+ * 0 = Accuracy
+ * 1 = Sensitivity
+ * 2 = Specificity
+ * 3 = Certainty
+ * 4 = Consistency
+ */
+ public int colorScheme;
+
+ // Used for a merged node
+ public boolean isMerge;
+ public Node n1;
+ public Node n2;
+
+ // Used for topological sort (DFS)
+ public int finishTime;
+ public boolean visited;
+
+ public ProbabilityMatrices pm; // allows access to probabilities to calculate accurcy
+
+ public Node(int seqI, int seqVal, ProbabilityMatrices pm){
+ this.seqVal = seqVal;
+ this.seqI = seqI;
+ this.pm = pm;
+ this.isMerge = false;
+
+ this.acc = -1;
+ this.sps = -1;
+ this.ppv = -1;
+ this.cert = -1;
+ this.cons = -1;
+
+ this.accDenom = -1;
+ this.spsDenom = -1;
+ this.ppvDenom = -1;
+ this.certDenom = -1;
+ this.consDenom = -1;
+
+ this.weightTgf = -1;
+ this.mergeOrder = -1;
+
+ }
+
+ public Node(int[] seqVals, int seqI, ProbabilityMatrices pm){
+ this.seqVals = seqVals;
+ this.seqI = seqI;
+ this.pm = pm;
+ this.isMerge = false;
+
+ this.acc = -1;
+ this.sps = -1;
+ this.ppv = -1;
+ this.cert = -1;
+ this.cons = -1;
+
+ this.accDenom = -1;
+ this.spsDenom = -1;
+ this.ppvDenom = -1;
+ this.certDenom = -1;
+ this.consDenom = -1;
+
+ this.weightTgf = -1;
+ this.mergeOrder = -1;
+
+ }
+
+ public Node(Node n1, Node n2, int mergeOrder){
+
+ this.n1 = n1;
+ this.n2 = n2;
+ this.pm = n1.pm;
+ this.isMerge = true;
+
+ this.acc = -1;
+ this.sps = -1;
+ this.ppv = -1;
+ this.cert = -1;
+ this.cons = -1;
+
+ this.accDenom = -1;
+ this.spsDenom = -1;
+ this.ppvDenom = -1;
+ this.certDenom = -1;
+ this.consDenom = -1;
+
+ this.weightTgf = calcWeightTgf (n1, n2);
+ this.mergeOrder = mergeOrder;
+
+ mergeNodes();
+ }
+
+
+ private void mergeNodes(){
+// int[] s1 = n1.seqIndices;
+// int[] s2 = n2.seqIndices;
+//
+// seqIndices = new int[s1.length];
+//
+// //Merge columns.
+// for (int i = 0; i < s1.length; i++) {
+// if (s1[i] != -1 && s2[i] != -1)
+// System.out.println("Sanity Check Failed: Sequence has been overwritten.");
+//
+// if (s1[i] != -1)
+// seqIndices[i] = s1[i];
+// else if (s2[i] != -1)
+// seqIndices[i] = s2[i];
+// else
+// seqIndices[i] = -1;
+// }
+
+
+ //Merge highlighting
+ this.highlighted = (n1.highlighted || n2.highlighted);
+
+ //Merge edges
+ //this.fEdges = new HashSet<Node>();
+ //this.fEdges.addAll(n1.getFwdEdges());
+ //this.fEdges.addAll(n2.getFwdEdges());
+ }
+
+ public void setHighlight(boolean val){
+ if (val == highlighted)
+ return;
+
+ if (isMerge){
+ n1.setHighlight(val);
+ n2.setHighlight(val);
+ }
+
+ highlighted = val;
+ calcColorAccuracy();
+ }
+
+ /// Calculate (updated) tgf weight for the merged column.
+ private double calcWeightTgf(Node n1, Node n2){
+
+ // initialize
+ weightTgf = -1;
+
+ int x,y;
+ double prob;
+
+ double pMatch = 0.;
+ double pGap = 0.;
+
+ int[] n1SeqIndices = n1.getSeqIndices();
+ int[] n2SeqIndices = n2.getSeqIndices();
+
+ for(int seq1=0; seq1 < pm.numSeqs; seq1++){
+
+ x = n1SeqIndices[seq1];
+
+ for (int seq2 = 0; seq2 < pm.numSeqs; seq2++){
+
+ // if we don't have probability information for the sequence pair seq1, seq2 then skip it
+ if ((seq1 == seq2) || !pm.matrixExists(seq1, seq2))
+ continue;
+
+ y = n2SeqIndices[seq2];
+
+ // only look at pairs of characters
+ if (x == -1 || y == -1)
+ continue;
+
+ // increment pMatch
+ pMatch += pm.getElement(seq1,seq2,x,y);
+ // increment pGap
+ pGap += pm.getElement(seq1,seq2,x,-1);
+ pGap += pm.getElement(seq1,seq2,-1,y);
+
+ }
+
+ }
+
+// System.err.print ("n1: "); n1.output();
+// System.err.print ("n2: "); n2.output();
+// System.err.println (" => pMatch = " + pMatch + "; pGap = " + pGap);
+
+ return 2 * pMatch / pGap;
+
+ }
+
+ /// Calculate accuracy metrics for the column and store desired coloration.
+ /*
+ * Coloration is encoded as an array of chars.
+ * \see getColors()
+ */
+ private void calcColorAccuracy(){
+
+ // initialize
+ acc = 0;
+ sps = 0;
+ ppv = 0;
+ cert = 0;
+ cons = 0;
+
+ accDenom = 0;
+ spsDenom = 0;
+ ppvDenom = 0;
+ certDenom = 0;
+ consDenom = 0;
+
+ // coloration for each character or gap in column
+ // color scheme chosen based on this.colorScheme
+ Double[] colorAccs = new Double[pm.numSeqs];
+
+ double num; // per-character numerator
+ double denom; // per-character denominator (must be a double b/c takes non-integer values for SPS, Certainty and Consistency)
+
+ int x, y; // sequence positions
+ double prob; // probability (match or gap)
+
+ boolean hasMatch; // are there at least two characters in the column?
+
+ int[] seqIndices = getSeqIndices(); // map from sequences to sequence positions in column
+ for(int seq1=0; seq1 < pm.numSeqs; seq1++){
+
+ // initialize values
+ num = 0;
+ denom = 0;
+ colorAccs[seq1] = (Double) 0.0;
+ hasMatch = false;
+
+ x = seqIndices[seq1];
+
+ for (int seq2 = 0; seq2 < pm.numSeqs; seq2++){
+
+ // if we don't have probability information for the sequence pair seq1, seq2 then skip it
+ if ((seq1 == seq2) || !pm.matrixExists(seq1, seq2))
+ continue;
+
+ y = seqIndices[seq2];
+
+ int multiplier = 0;
+ if (x != -1 && y != -1) { // neither are gaps
+ multiplier = 2;
+ hasMatch = true;
+ }
+ else if (x != -1 || y != -1) { // exactly 1 is a gap
+ multiplier = 1;
+ }
+ else {
+ continue;
+ }
+
+ prob = pm.getElement(seq1,seq2,x,y);
+
+ // everything contributes to accuracy
+ acc += multiplier * prob;
+ accDenom += multiplier;
+ if (colorScheme == 0) { // Accuracy
+ num += multiplier * prob;
+ denom += multiplier;
+ }
+
+ // certainty is colored for both character and gaps,
+ // but we only add to the full certainty calculation if
+ // the currect position isn't a gap (otherwise we overcount the gap information)
+ if (colorScheme == 3) { // Certainty
+ num += multiplier * prob;
+ if (x != -1) // if x is not a gap, then use altmax_y P(x ~ y)
+ denom += multiplier * pm.getAltMaxProb(seq1,seq2,x,y);
+ else // if x is a gap, then use altmax_x P(x ~ y)
+ denom += multiplier * pm.getAltMaxProb(seq2,seq1,y,x);
+ }
+
+ // and for consistency
+ cons += multiplier * prob;
+ if (x != -1) // if x is not a gap, then use max_y P(x ~ y)
+ consDenom += multiplier * pm.getMaxProb(seq1,seq2,x);
+ else // if x is a gap, then use max_x P(x ~ y)
+ consDenom += multiplier * pm.getMaxProb(seq2,seq1,y);
+ if (colorScheme == 4) { // Consistency
+ num += multiplier * prob;
+ if (x != -1) // if x is not a gap, then use max_y P(x ~ y)
+ denom += multiplier * pm.getMaxProb(seq1,seq2,x);
+ else // if x is a gap, then use max_x P(x ~ y)
+ denom += multiplier * pm.getMaxProb(seq2,seq1,y);
+ }
+
+ // in contrast, SPS and PPV aren't defined for gaps
+ if (x != -1) {
+
+ // the numerator for SPS increases only if we're looking at aligned characters (y not a gap);
+ // the denominator increases regardless
+ // (this is guaranteed by the (multiplier - 1) factor)
+ sps += (multiplier - 1) * prob;
+ spsDenom += pm.getSumProb(seq1,seq2,x);
+ if (colorScheme == 1) { // SPS
+ num += (multiplier - 1) * prob;
+ denom += pm.getSumProb(seq1,seq2,x);
+ }
+
+ // only pairs of aligned characters contribute to PPV
+ // (both x and y ungapped)
+ if (y != -1) {
+ ppv += multiplier * prob;
+ ppvDenom += multiplier;
+ if (colorScheme == 2) { // PPV
+ num += multiplier * prob;
+ denom += multiplier;
+ }
+ }
+
+ // certainty
+ cert += multiplier * prob;
+ if (x != -1) // if x is not a gap, then use altmax_y P(x ~ y)
+ certDenom += multiplier * pm.getAltMaxProb(seq1,seq2,x,y);
+ else // if x is a gap, then use altmax_x P(x ~ y)
+ certDenom += multiplier * pm.getAltMaxProb(seq2,seq1,y,x);
+
+ }
+
+ }
+
+ // store value for this character or gap if it exists
+ // (if the denominator is defined)
+ if (denom > 0.0001) {
+
+ // sps and ppv are only defined if there is at least 1 match
+ if (colorScheme == 1 || colorScheme == 2) {
+ if (hasMatch)
+ colorAccs[seq1] = (Double) SparseMatrix.saneProb (num / denom);
+ else
+ colorAccs[seq1] = (Double) (-1.); // store (temporary) negative value
+ }
+
+ // certainty takes values in interval [0, 1/0.01], so it needs to be mapped to [0,1]
+ else if (colorScheme == 3)
+ colorAccs[seq1] = (Double) SparseMatrix.saneProb (Node.normalizedCertainty (num / denom));
+
+ // otherwise just store the normalized value
+ else
+ colorAccs[seq1] = (Double) SparseMatrix.saneProb (num / denom);
+
+ }
+ // if undefined, then store (temporary) negative value
+ else {
+ colorAccs[seq1] = (Double) (-1.);
+ }
+
+ }//Outer loop
+
+ // Generate color code array
+ colors = new char[seqIndices.length];
+ for (int i = 0; i < colors.length; i++){
+
+ double c;
+
+ // if highlighted
+ if (highlighted) {
+ c = 65535.;
+ }
+ // if undefined
+ else if (colorAccs[i].doubleValue() < 0.) {
+ c = 256.;
+ }
+ // else encode as integer in interval 0...255
+ else {
+ c = Math.rint(colorAccs[i].doubleValue()*255);
+ }
+
+ // now store the value as a char
+ // remember that 'char' acts as an unsigned short
+ colors[i] = (char)c;
+ }
+
+ }
+
+ /// Get unnormalized accuracy for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getAcc(){
+ if (acc < 0)
+ calcColorAccuracy();
+ return acc;
+ }
+
+ /// Get normalization for accuracy for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getAccDenom(){
+ if (accDenom < 0)
+ calcColorAccuracy();
+ return accDenom;
+ }
+
+ /// Get unnormalized SPS for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getSPS(){
+ if (sps < 0)
+ calcColorAccuracy();
+ return sps;
+ }
+
+ /// Get normalization for SPS for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getSPSDenom(){
+ if (spsDenom < 0)
+ calcColorAccuracy();
+ return spsDenom;
+ }
+
+ /// Get unnormalized PPV for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getPPV(){
+ if (ppv < 0)
+ calcColorAccuracy();
+ return ppv;
+ }
+
+ /// Get normalization for PPV for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getPPVDenom(){
+ if (ppvDenom < 0)
+ calcColorAccuracy();
+ return ppvDenom;
+ }
+
+ /// Get unnormalized certainty for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getCert(){
+ if (cert < 0)
+ calcColorAccuracy();
+ return cert;
+ }
+
+ /// Get normalization for certainty for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getCertDenom(){
+ if (certDenom < 0)
+ calcColorAccuracy();
+ return certDenom;
+ }
+
+ /// Get unnormalized consistency for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getCons(){
+ if (cons < 0)
+ calcColorAccuracy();
+ return cons;
+ }
+
+ /// Get normalization for consistency for column.
+ /*
+ * Re-calculate if necessary.
+ */
+ public double getConsDenom(){
+ if (consDenom < 0)
+ calcColorAccuracy();
+ return consDenom;
+ }
+
+ /// Get the tgf weight of the column.
+ public double getWeightTgf(){
+ if (weightTgf < 0)
+ calcColorAccuracy();
+ return weightTgf;
+ }
+
+ public int[] getSeqIndices(){
+ if (seqVals != null)
+ return seqVals;
+ int[] seqIndices = new int[pm.numSeqs];
+ Arrays.fill(seqIndices, -1);
+ return addSeqIndices(seqIndices);
+ }
+
+ // Recursive method that adds all of the children's sequence indices to the array.
+ public int[] addSeqIndices(int[] seqIndices){
+ if (!isMerge){
+ seqIndices[seqI] = seqVal;
+ return seqIndices;
+ }
+
+ seqIndices = n1.addSeqIndices(seqIndices);
+ seqIndices = n2.addSeqIndices(seqIndices);
+
+ return seqIndices;
+ }
+
+
+ /// Update color scheme for node.
+ /*
+ * Updates coloration.
+ * It is the responsibility of the parent object
+ * to call this function whenever the color scheme is updated globally.
+ */
+ public void setColorScheme(int scheme){
+ this.colorScheme = scheme;
+ calcColorAccuracy();
+ }
+
+ /// Return an array of chars, each char representing a color.
+ /*
+ * Chars act as unsigned shorts, taking values from 0 to 2^16.
+ * Colors are encoded as:
+ * 0...255 coloration for accuracy (=> 256 possible colors in total)
+ * 256 indicates highlighting
+ * 65,535 indicates undefined
+ * (this value is 2^16 - 1)
+ */
+ public char[] getColors(){
+ if (colors == null)
+ calcColorAccuracy();
+ return colors;
+ }
+
+ public Set<Node> getFwdEdges(){
+ Set<Node> fwdEdges = new HashSet<Node>();
+ return addFwdEdges(fwdEdges);
+ }
+
+ // Recursive method that adds all of the children's edges to the set.
+ public Set<Node> addFwdEdges(Set<Node> fwdEdges){
+
+ if (isMerge && n1 != null){ // Alternate alignments have merges that w/o any child nodes
+ n1.addFwdEdges(fwdEdges);
+ n2.addFwdEdges(fwdEdges);
+ }
+ else if (fwdEdge != null){
+ fwdEdges.add(fwdEdge);
+ }
+
+ return fwdEdges;
+ }
+
+ public void output(){
+ StringBuffer s = new StringBuffer("");
+ s.append(finishTime + ": ");
+ int[] seqIndices = getSeqIndices();
+ for (int i = 0; i < seqIndices.length; i++)
+ s.append("(" + i + ", " + seqIndices[i] + ") ~ ");
+
+ System.out.println(s);
+ }
+
+ /// Normalize a certainty value to interval [0,1].
+ /*
+ * @param c certainty in range [0, 1 / 0.01]
+ * Uses a logarithmic transform.
+ */
+ static double normalizedCertainty (double c) {
+
+ // if there was a better alternative, then return 0
+ if (c < 1.0)
+ return 0;
+ // if it was 10 times better than the best alternative, then return 1
+ else if (c >= 5.0)
+ return 1;
+ // else perform a logarithmic transform
+ else
+ return Math.log (c) / Math.log (5.0);
+
+ }
+
+}
diff --git a/display/mad/ProbabilityMatrices.java b/display/mad/ProbabilityMatrices.java
new file mode 100644
index 0000000..a3895f7
--- /dev/null
+++ b/display/mad/ProbabilityMatrices.java
@@ -0,0 +1,169 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ * Code for calculating and storing the sum and max probabilities
+ * was written by Robert Bradley.
+ */
+
+
+package mad;
+
+import java.util.*;
+
+public class ProbabilityMatrices{
+ int numSeqs;
+ int[] seqLengths;
+ int[][] index;
+ SparseMatrix[] matrices;
+
+ public ProbabilityMatrices(int[] seqLengths){
+ this.seqLengths = seqLengths;
+ this.numSeqs = seqLengths.length;
+ this.matrices = new SparseMatrix[numSeqs*(numSeqs-1)/2];
+ buildIndex();
+ }
+
+ private void buildIndex(){
+ int x = 0;
+ this.index = new int[numSeqs][numSeqs];
+ for (int i = 0; i < numSeqs; i++)
+ for (int j = i+1; j < numSeqs; j++){
+ this.index[i][j] = x;
+ this.index[j][i] = x++;
+ }
+ }
+
+ public void addElement(int seq1, int seq2, int i1, int i2, double prob){
+
+ //Handle gaps and index change from input file
+ if (i1 < 0)
+ i1 = seqLengths[seq1];
+ if (i2 < 0)
+ i2 = seqLengths[seq2];
+
+ if (seq1 > seq2){
+ int temp = i1;
+ i1 = i2;
+ i2 = temp;
+ }
+
+ if (!matrixExists(seq1, seq2))
+ addMatrix(seq1, seq2);
+
+ matrices[getIndex(seq1,seq2)].put(i1, i2, prob);
+ }
+
+ public double getElement(int seq1, int seq2, int i1, int i2){
+
+ if (!matrixExists(seq1, seq2))
+ return 0.0;
+
+ // Handle gaps
+ if (i1 < 0)
+ i1 = seqLengths[seq1];
+ if (i2 < 0)
+ i2 = seqLengths[seq2];
+
+ if (seq1 > seq2){
+ int temp = i1;
+ i1 = i2;
+ i2 = temp;
+ }
+ return matrices[getIndex(seq1,seq2)].get(i1, i2);
+ }
+
+ /// Get sum_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+ public double getSumProb(int seq1, int seq2, int pos1){
+
+ if (!matrixExists(seq1, seq2)) {
+ System.err.println ("Probability matrix for sequences " + seq1 + " and " + seq2 + " does not exist.");
+ System.exit(1);
+ }
+
+ // no gaps
+ if (pos1 < 0) {
+ System.err.println ("Sum probability is undefined for gaps; offending sequences are " + seq1 + " and " + seq2 + ".");
+ System.exit(1);
+ }
+
+ if (seq1 < seq2)
+ return matrices[getIndex(seq1,seq2)].getSumProbI(pos1);
+ else
+ return matrices[getIndex(seq2,seq1)].getSumProbJ(pos1);
+
+ }
+
+ /// Get max_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+ public double getMaxProb(int seq1, int seq2, int pos1){
+
+ if (!matrixExists(seq1, seq2)) {
+ System.err.println ("Probability matrix for sequences " + seq1 + " and " + seq2 + " does not exist.");
+ System.exit(1);
+ }
+
+ // no gaps
+ if (pos1 < 0) {
+ System.err.println ("Max probability is undefined for gaps; offending sequences are " + seq1 + " and " + seq2 + ".");
+ System.exit(1);
+ }
+
+ if (seq1 < seq2)
+ return matrices[getIndex(seq1,seq2)].getMaxProbI(pos1);
+ else
+ return matrices[getIndex(seq2,seq1)].getMaxProbJ(pos1);
+
+ }
+
+ /// Get altmax_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+ public double getAltMaxProb(int seq1, int seq2, int pos1, int pos2){
+
+ if (!matrixExists(seq1, seq2)) {
+ System.err.println ("Probability matrix for sequences " + seq1 + " and " + seq2 + " does not exist.");
+ System.exit(1);
+ }
+
+ // handle gaps
+ if (pos1 < 0) {
+ System.err.println ("Alt max probability is undefined for gaps in first sequence; offending sequences are " + seq1 + " and " + seq2 + ".");
+ System.exit(1);
+ }
+ else if (pos2 < 0) {
+ pos2 = seqLengths[seq2]; // convert to indexing used by SparseMatrix
+ }
+
+ if (seq1 < seq2) {
+ return matrices[getIndex(seq1,seq2)].getAltMaxProbI(pos1,pos2);
+ }
+ else {
+ return matrices[getIndex(seq2,seq1)].getAltMaxProbJ(pos2,pos1);
+ }
+
+ }
+
+
+
+ private int getIndex(int seq1, int seq2){
+ return index[seq1][seq2];
+ }
+
+ private void addMatrix(int seq1, int seq2){
+
+ if (seq1 > seq2){
+ int temp = seq1;
+ seq1 = seq2;
+ seq2 = temp;
+ }
+ matrices[getIndex(seq1, seq2)] = new SparseMatrix(seqLengths[seq1]+1, seqLengths[seq2]+1);
+ }
+
+
+ public boolean matrixExists(int seq1, int seq2){
+ if (seq1 == seq2)
+ return false;
+ return matrices[getIndex(seq1, seq2)] != null;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/display/mad/PropertyChangeHandler.java b/display/mad/PropertyChangeHandler.java
new file mode 100644
index 0000000..b3dd843
--- /dev/null
+++ b/display/mad/PropertyChangeHandler.java
@@ -0,0 +1,37 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Michael Smoot.
+ */
+
+package mad;
+
+import java.util.*;
+import java.beans.*;
+
+
+public class PropertyChangeHandler {
+
+ private static PropertyChangeSupport pcs;
+ private static Object o;
+
+ static {
+ o = new Object();
+ pcs = new PropertyChangeSupport( o );
+ }
+
+ public static PropertyChangeSupport getPropertyChangeSupport() {
+ return pcs;
+ }
+
+ public static void firePropertyChange(String id, Object oldValue, Object newValue) {
+ try {
+ PropertyChangeIDs.valueOf(id);
+ } catch (IllegalArgumentException ex) {
+ System.err.println("Illegal PropertyChangeEvent ID: " + id + " ignoring!");
+ return;
+ }
+ PropertyChangeEvent e = new PropertyChangeEvent(pcs, id, oldValue, newValue);
+ pcs.firePropertyChange(e);
+ }
+}
diff --git a/display/mad/PropertyChangeIDs.java b/display/mad/PropertyChangeIDs.java
new file mode 100644
index 0000000..6a339f6
--- /dev/null
+++ b/display/mad/PropertyChangeIDs.java
@@ -0,0 +1,11 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Michael Smoot.
+ */
+
+package mad;
+
+public enum PropertyChangeIDs {
+ CHANGE_ALIGNMENT,
+}
diff --git a/display/mad/SaveAsFastaAction.java b/display/mad/SaveAsFastaAction.java
new file mode 100644
index 0000000..f1c4469
--- /dev/null
+++ b/display/mad/SaveAsFastaAction.java
@@ -0,0 +1,59 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Michael Smoot and Adam Roberts.
+ */
+
+package mad;
+
+import java.util.*;
+import java.beans.*;
+import java.io.*;
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.Component;
+
+
+public class SaveAsFastaAction extends AbstractAction implements PropertyChangeListener {
+
+ Alignments aligns;
+ MadPanel parent;
+ JFileChooser fc;
+
+ SaveAsFastaAction(MadPanel parent ) {
+ super("Save as Multi-FASTA");
+ this.parent = parent;
+ fc = new JFileChooser();
+ PropertyChangeHandler.getPropertyChangeSupport()
+ .addPropertyChangeListener(PropertyChangeIDs.CHANGE_ALIGNMENT.toString(), this);
+ aligns = parent.aligns;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ Alignment a = aligns.get(aligns.index);
+ System.out.print ("Saving as Multi-FASTA file...");
+ if ( a != null ) {
+ try {
+ int returnVal = fc.showSaveDialog(parent);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File file = fc.getSelectedFile();
+ FileWriter fw = new FileWriter(file);
+ String mfa = a.toMultiFasta();
+ fw.write(mfa,0,mfa.length());
+ fw.close();
+ System.out.println ("done");
+ }
+ } catch (Exception ioe) {
+ JOptionPane.showMessageDialog(parent,
+ "Failed to save Multi-FASTA file:\n\n" + ioe.getMessage(),
+ "Error saving file.",
+ JOptionPane.ERROR_MESSAGE);
+ ioe.printStackTrace();
+ }
+ } else
+ System.err.println("No alignment found.");
+
+ }
+
+ public void propertyChange(PropertyChangeEvent e) {}
+}
diff --git a/display/mad/SaveAsMovAction.java b/display/mad/SaveAsMovAction.java
new file mode 100644
index 0000000..ea9b07b
--- /dev/null
+++ b/display/mad/SaveAsMovAction.java
@@ -0,0 +1,31 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ */
+
+
+package mad;
+
+import java.util.*;
+import java.beans.*;
+import java.io.*;
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.*;
+
+
+public class SaveAsMovAction extends AbstractAction {
+
+ MadPanel parent;
+
+ SaveAsMovAction(MadPanel parent ) {
+ super("Export as Quicktime Movie");
+ this.parent = parent;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ this.parent.alignmentToMov();
+ }
+
+}
diff --git a/display/mad/SaveAsTiffAction.java b/display/mad/SaveAsTiffAction.java
new file mode 100644
index 0000000..27b0ba5
--- /dev/null
+++ b/display/mad/SaveAsTiffAction.java
@@ -0,0 +1,53 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Robert Bradley.
+ */
+
+package mad;
+
+import java.util.*;
+import java.beans.*;
+import java.io.*;
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.Component;
+
+public class SaveAsTiffAction extends AbstractAction implements PropertyChangeListener {
+
+ AlignmentPanel parentAlignPanel;
+ MadPanel parent;
+ JFileChooser fc;
+
+ SaveAsTiffAction(MadPanel parent ) {
+ super("Save as TIFF file");
+ this.parent = parent;
+ fc = new JFileChooser();
+ PropertyChangeHandler.getPropertyChangeSupport()
+ .addPropertyChangeListener(PropertyChangeIDs.CHANGE_ALIGNMENT.toString(), this);
+ parentAlignPanel = parent.alignPanel;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+
+ System.out.print("Saving as TIFF image...");
+
+ try {
+ int returnVal = fc.showSaveDialog(parent);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File file = fc.getSelectedFile();
+ parentAlignPanel.saveAsTiff (file.getPath());
+ System.out.println("done");
+ }
+ } catch (Exception ioe) {
+ JOptionPane.showMessageDialog(parent,
+ "Failed to save TIFF file:\n\n" + ioe.getMessage(),
+ "Error saving file.",
+ JOptionPane.ERROR_MESSAGE);
+ ioe.printStackTrace();
+ }
+
+ }
+
+ public void propertyChange(PropertyChangeEvent e) {}
+}
diff --git a/display/mad/SparseMatrix.java b/display/mad/SparseMatrix.java
new file mode 100644
index 0000000..683e123
--- /dev/null
+++ b/display/mad/SparseMatrix.java
@@ -0,0 +1,257 @@
+
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Adam Roberts.
+ * Code for calculating and storing the sum and max probabilities
+ * was written by Robert Bradley.
+ */
+
+
+package mad;
+
+//import it.unimi.dsi.fastutil.ints.*;
+import java.util.*;
+import java.lang.Math.*;
+
+public class SparseMatrix{
+
+ private int length, width;
+ private Vector<Double> values;
+ private Map<Integer, Integer> indexMap;
+
+ private Double[] sumProbI;
+ private Double[][] maxProbI;
+
+ private Double[] sumProbJ;
+ private Double[][] maxProbJ;
+
+ public SparseMatrix(int length, int width){
+ this.length = length; // length == length of first sequence + 1
+ this.width = width; // width == length of second sequence + 1
+
+ indexMap = new HashMap<Integer, Integer>();
+ values = new Vector<Double>(100, 10);
+
+ sumProbI = new Double[length-1];
+ maxProbI = new Double[length-1][2];
+
+ sumProbJ = new Double[width-1];
+ maxProbJ = new Double[width-1][2];
+
+ }
+
+ public void put(int i, int j, double e){
+ int index = j*length+i;
+
+ if (indexMap.containsKey(index)){
+ System.err.println("SANITY CHECK FAILED: Matrix index repeated (i = " + i + ", j = " + j + ", index = " + index + ")");
+ System.exit(-1);
+ }
+
+ // check that the probability is valid
+ e = SparseMatrix.saneProb (e);
+
+ indexMap.put(index, values.size());
+ values.addElement(e);
+
+ // Note that max is over all possible positions in the other sequence, including gapped.
+ // The below check over single indices ensures that the possibility of gaps
+ // in the other sequence are properly taken into account when finding the max (and alternate max).
+
+ // first sequence
+ if (i < length-1) { // i == (length - 1) corresponds to first sequence gapped
+ // (NB sequence position indices are 0-based)
+
+ // if max prob undefined, store new value
+ if (maxProbI[i][0] == null) {
+ maxProbI[i][0] = (Double) e;
+ }
+
+ // if new max, then store new value and update alternate max
+ else if (maxProbI[i][0].doubleValue() < e) {
+ maxProbI[i][1] = maxProbI[i][0];
+ maxProbI[i][0] = (Double) e;
+ }
+
+ // if new alternate max b/c alternate max is undefined
+ else if (maxProbI[i][1] == null) {
+ maxProbI[i][1] = (Double) e;
+ }
+
+ // if new alternate max
+ else if (maxProbI[i][1].doubleValue() < e) {
+ maxProbI[i][1] = (Double) e;
+ }
+
+ }
+
+ // second sequence
+ if (j < width-1) { // j == (width - 1) corresponds to second sequence gapped
+
+ // if max prob undefined, store new value
+ // and initialize alternate max
+ if (maxProbJ[j][0] == null) {
+ maxProbJ[j][0] = (Double) e;
+ }
+
+ // if new max, then store new value and update alternate max
+ else if (maxProbJ[j][0].doubleValue() < e) {
+ maxProbJ[j][1] = maxProbJ[j][0];
+ maxProbJ[j][0] = (Double) e;
+ }
+
+ // if new alternate max b/c alternate max is undefined
+ else if (maxProbJ[j][1] == null) {
+ maxProbJ[j][1] = (Double) e;
+ }
+
+ // if new alternate max
+ else if (maxProbJ[j][1].doubleValue() < e) {
+ maxProbJ[j][1] = (Double) e;
+ }
+
+ }
+
+ // sum is only over possible aligned character pairs
+ // (if gaps are included then all sums be 1. b/c they're normalized probability distributions)
+ if ((i < length-1) && (j < width-1)) {
+
+ if (sumProbI[i] == null)
+ sumProbI[i] = (Double) e;
+ else
+ sumProbI[i] += (Double) e;
+
+ if (sumProbJ[j] == null)
+ sumProbJ[j] = (Double) e;
+ else
+ sumProbJ[j] += (Double) e;
+
+ }
+
+ }
+
+ public double get(int i, int j){
+ int index = j*length+i;
+ if (!indexMap.containsKey(index))
+ return 0.0;
+ return SparseMatrix.saneProb (values.get(indexMap.get(index)));
+ }
+
+ /// Get sum_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+ /*
+ * Cover the case of no entry for a match probability > 0.01.
+ */
+ public double getSumProbI(int pos){
+ if (sumProbI[pos] == null) // cover case of no input data (no match prob above FSA's threshold)
+ return 0.01;
+ return SparseMatrix.saneProb (sumProbI[pos]);
+ }
+
+ /// Get sum_pos1 P((seq1, pos1) ~ (seq2, pos2)).
+ /*
+ * Cover the case of no entry for a match probability > 0.01.
+ */
+ public double getSumProbJ(int pos){
+ if (sumProbJ[pos] == null) // cover case of no input data (no match prob above FSA's threshold)
+ return 0.01;
+ return SparseMatrix.saneProb (sumProbJ[pos]);
+ }
+
+ /// Get max_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+ public double getMaxProbI(int pos){
+ // sanity check
+ if (maxProbI[pos][0] == null) {
+ System.err.println ("A max prob is null; this should never happen!");
+ System.exit(1);
+ }
+ return SparseMatrix.saneProb (maxProbI[pos][0]);
+ }
+
+ /// Get altmax_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+ /*
+ * \return second-best probability, or 0.01 if undefined
+ * Minimum value of 0.01 is due to the inherent coarse-graining
+ * of the probability reported by FSA.
+ */
+ public double getAltMaxProbI(int pos1, int pos2){
+
+ // sanity check
+ if (maxProbI[pos1][0] == null) {
+ System.err.println ("A max prob is null; this should never happen!");
+ System.exit(1);
+ }
+
+ // get probability to determine best alternate
+ double prob = get(pos1,pos2);
+
+ // if prob is the max, then return the second-best alternate
+ if (Math.abs (prob - maxProbI[pos1][0].doubleValue()) < 0.0001) {
+ if (maxProbI[pos1][1] != null)
+ return SparseMatrix.saneProb (maxProbI[pos1][1]);
+ else
+ return 0.01;
+ }
+ // else return the max
+ else
+ return SparseMatrix.saneProb (maxProbI[pos1][0]);
+
+ }
+
+ /// Get altmax_pos1 P((seq1, pos1) ~ (seq2, pos2)).
+ /*
+ * \return second-best probability, or 0.01 if undefined
+ * Minimum value of 0.01 is due to the inherent coarse-graining
+ * of the probability reported by FSA.
+ */
+ public double getAltMaxProbJ(int pos1, int pos2){
+
+ // sanity check
+ if (maxProbJ[pos2][0] == null) {
+ System.err.println ("A max prob is null; this should never happen!");
+ System.exit(1);
+ }
+
+ // get probability to determine best alternate
+ double prob = get(pos1,pos2);
+
+ // if prob is the max, then return the second-best alternate
+ if (Math.abs (prob - maxProbJ[pos2][0].doubleValue()) < 0.0001) {
+ if (maxProbJ[pos2][1] != null)
+ return SparseMatrix.saneProb (maxProbJ[pos2][1]);
+ else
+ return 0.01;
+ }
+ // else return the max
+ else
+ return SparseMatrix.saneProb (maxProbJ[pos2][0]);
+
+ }
+
+ /// Get max_pos1 P((seq1, pos1) ~ (seq2, pos2)).
+ public double getMaxProbJ(int pos){
+
+ // sanity check
+ if (maxProbJ[pos][0] == null) {
+ System.err.println ("A max prob is null; this should never happen!");
+ System.exit(1);
+ }
+
+ return SparseMatrix.saneProb (maxProbJ[pos][0]);
+ }
+
+ /// Bounds-checking for a valid probability.
+ static double saneProb (double p) {
+ if (p < -0.0001 || p > 1.0001) {
+ System.err.println("Error: probability " + p + " is out of bounds.");
+ System.exit(1);
+ }
+ p = (p < -0.0001) ? 0. : p;
+ p = (p > 1.0001) ? 1.0 : p;
+ return p;
+ }
+
+ static double saneProb (Double p) {
+ return saneProb (p.doubleValue());
+ }
+
+}
\ No newline at end of file
diff --git a/display/mad/legend.jpg b/display/mad/legend.jpg
new file mode 100644
index 0000000..86972bc
Binary files /dev/null and b/display/mad/legend.jpg differ
diff --git a/display/mad/manifest.mf b/display/mad/manifest.mf
new file mode 100644
index 0000000..93b0654
--- /dev/null
+++ b/display/mad/manifest.mf
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Created-By: 1.6.0 (Sun Microsystems Inc.)
+Class-Path: JMF-2.1.1e/lib/jmf.jar jai-1_1_3/lib/jai_codec.jar jai-1_1_3/lib/jai_core.jar
+Main-Class: mad.MAD
diff --git a/display/mad/manifest.mf.in b/display/mad/manifest.mf.in
new file mode 100644
index 0000000..1804577
--- /dev/null
+++ b/display/mad/manifest.mf.in
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Created-By: 1.6.0 (Sun Microsystems Inc.)
+Class-Path: JMF-2.1.1e/lib/jmf.jar jai-1_1_3/lib/jai_codec.jar jai-1_1_3/lib/jai_core.jar
+Main-Class: @MAD_MAIN_CLASS@
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..de7be8a
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,23 @@
+EXTRA_DIST = \
+ README \
+ RV12.BBS12030.fasta \
+ RV12.BBS12030.fasta.gui \
+ RV12.BBS12030.fasta.probs \
+ RV12.BBS12030.mfa \
+ RV12.BBS12030.reference.mfa \
+ RV12.BBS12030.reference.stock \
+ RV12.BBS12030.stock \
+ U5.aln1.fasta \
+ U5.aln1.fasta.gui \
+ U5.aln1.fasta.probs \
+ U5.aln1.mfa \
+ U5.aln1.reference.mfa \
+ U5.aln1.reference.stock \
+ U5.aln1.stock \
+ tRNA.aln1.fasta \
+ tRNA.aln1.fasta.gui \
+ tRNA.aln1.fasta.probs \
+ tRNA.aln1.mfa \
+ tRNA.aln1.reference.mfa \
+ tRNA.aln1.reference.stock \
+ tRNA.aln1.stock
diff --git a/examples/Makefile.in b/examples/Makefile.in
new file mode 100644
index 0000000..0f89184
--- /dev/null
+++ b/examples/Makefile.in
@@ -0,0 +1,431 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = examples
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ README \
+ RV12.BBS12030.fasta \
+ RV12.BBS12030.fasta.gui \
+ RV12.BBS12030.fasta.probs \
+ RV12.BBS12030.mfa \
+ RV12.BBS12030.reference.mfa \
+ RV12.BBS12030.reference.stock \
+ RV12.BBS12030.stock \
+ U5.aln1.fasta \
+ U5.aln1.fasta.gui \
+ U5.aln1.fasta.probs \
+ U5.aln1.mfa \
+ U5.aln1.reference.mfa \
+ U5.aln1.reference.stock \
+ U5.aln1.stock \
+ tRNA.aln1.fasta \
+ tRNA.aln1.fasta.gui \
+ tRNA.aln1.fasta.probs \
+ tRNA.aln1.mfa \
+ tRNA.aln1.reference.mfa \
+ tRNA.aln1.reference.stock \
+ tRNA.aln1.stock
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign examples/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
+ ctags-am distclean distclean-generic distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/examples/README b/examples/README
new file mode 100644
index 0000000..836b246
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,36 @@
+
+Guide to sequence and alignment files:
+.fasta file is the unaligned sequences
+.reference.{mfa,stock} is the reference alignment
+.{mfa,stock} is the alignment produced by FSA run with the options
+ --noindel2 (for only 1 set of indel states)
+ --refinement 0 (for no iterative refinement)
+
+Origins of sequence and alignment files in example/:
+
+****************************
+BRalibaseII:
+****************************
+
+tRNA.aln1
+U5.aln1
+
+References:
+1. Gardner PP, Wilm A & Washietl S (2005) A benchmark of multiple sequence alignment programs upon structural RNAs. Nucleic Acids Research. 33(8):2433-2439.Supp. Mat.
+
+
+****************************
+Balibase:
+****************************
+
+RV12.BBS12030
+
+References:
+1. Thompson JD, Plewniak F, Poch O. BAliBASE: a benchmark alignment database for the evaluation of multiple alignment programs.
+Bioinformatics. 1999 Jan;15(1):87-8.
+
+2. Thompson JD, Plewniak F, Poch O. A comprehensive comparison of multiple sequence alignment programs.
+Nucleic Acids Res. 1999 Jul 1;27(13):2682-90
+
+3. Bahr A, Thompson JD, Thierry JC, Poch O. BAliBASE (Benchmark Alignment dataBASE): enhancements for repeats, transmembrane sequences and circular permutations.
+Nucleic Acids Res. 2001 Jan 1;29(1):323-6.
diff --git a/examples/RV12.BBS12030.fasta b/examples/RV12.BBS12030.fasta
new file mode 100644
index 0000000..c8a25e6
--- /dev/null
+++ b/examples/RV12.BBS12030.fasta
@@ -0,0 +1,36 @@
+>POL_MPMV
+APQQCAEPITWKSDEPVWVDQWPLTNDKLAAAQQLVQEQLEAGHITESSS
+PWNTPIFVIKKKSGKWRLLQDLRAVNATMVLMGALQPGLPSPVAIPQGYL
+KIIIDLKDCFFSIPLHPSDQKRFAFSLPSTNFKEPMQRFQWKVLPQGMAN
+SPTLCQKYVATAIHKVRHAWKQMYIIHYMDDILIAGKDGQQVLQCFDQLK
+QELTAAGLHIAPEKVQLQDPYTYLGFELNGPKI
+>POL_BIV06
+HTEKIEPLPVKVRGPGPKVPQWPLTKEKYQALKEIVKDLLAEGKISEAAW
+DNPYNTPVFVIKKKGTGRWRMLMDFRELNKITVKGQEFSTGLPYPPGIKE
+CEHLTAIDIKDAYFTIPLHEDFRPFTAFSVVPVNREGPIERFQWNVLPQG
+WVCSPAIYQTTTQKIIENIKKSHPDVMLYQYMDDLLIGSNRDDHKQIVQE
+IRDKLGSYGFKTPDEKVQEERVKWIGFELTPKKW
+>POL_CAEVC
+LEEKRIPITKVKLKEGCTGPHVPQWPLTEEKLKGLTEIIDKLVEEGKLGK
+APPHWTCNTPIFCIKKKSGKWRMLIDFRELNKQTEDLTEAQLGLPHPGGL
+QKKKHVTILDIGDAYFTIPLYEPYREYTCFTLLSPNNLGPCKRYYWKVLP
+QGWKLSPSVYQFTMQEILEDWIQQHPEIQFGIYMDDIYIGSDLEIKKHRE
+IVKDLANYIAQYGFTLPEEKRQKGYPAKWLGFELHPQTW
+>1bqm_A
+PISPIETVPVKLKPGMDGPKVKQWPLTEEKIKALVEICTEMEKEGKISKI
+GPENPYNTPVFAIKKKDSTKWRKLVDFRELNKRTQDFWEVQLGIPHPAGL
+KKKKSVTVLDVGDAYFSVPLDEDFRKYTAFTIPSINNETPGIRYQYNVLP
+QGWKGSPAIFQSSMTKILEPFKKQNPDIVIYQYMDDLYVGSDLEIGQHRT
+KIEELRQHLLRWGLTTPDKKHQKEPPFLWMGYELHPDKW
+>1d0e_A
+LAVRQAPLIIPLKATSTPVSIKQYPMSQEARLGIKPHIQRLLDQGILVPC
+QSPWNTPLLPVKKPGTNDYRPVQDLREVNKRVEDIHPTVPNPYNLLSGLP
+PSHQWYTVLDLKDAFFCLRLHPTSQPLFAFEWRDPEMGISGQLTWTRLPQ
+GFKNSPTLFDEALHRDLADFRIQHPDLILLQYVDDLLLAATSELDCQQGT
+RALLQTLGNLGYRASAKKAQICQKQVKYLGYLLKEGQR
+>POL_RSVP
+VALHLAIPLKWKPDHTPVWIDQWPLPEGKLVALTQLVEKELQLGHIEPSL
+SCWNTPVFVIRKASGSYRLLHDLRAVNAKLVPFGAVQQGAPVLSALPRGW
+PLMVLDLKDCFFSIPLAEQDREAFAFTLPSVNNQAPARRFQWKVLPQGMT
+CSPTICQLVVGQVLEPLRLKHPSLCMLHYMDDLLLAASSHDGLEAAGEEV
+ISTLERAGFTISPDKVQREPGVQYLGYKLGSTYV
diff --git a/examples/RV12.BBS12030.fasta.gui b/examples/RV12.BBS12030.fasta.gui
new file mode 100644
index 0000000..b10a55c
--- /dev/null
+++ b/examples/RV12.BBS12030.fasta.gui
@@ -0,0 +1,2599 @@
+; Initial DAG
+; Format is:
+; column: (sequence, position)
+; sequence is 0-based and position is 0-based
+
+0: (0, 0)
+1: (1, 0)
+2: (2, 0)
+3: (3, 0)
+4: (4, 0)
+5: (5, 0)
+6: (0, 1)
+7: (1, 1)
+8: (2, 1)
+9: (3, 1)
+10: (4, 1)
+11: (5, 1)
+12: (0, 2)
+13: (1, 2)
+14: (2, 2)
+15: (3, 2)
+16: (4, 2)
+17: (5, 2)
+18: (0, 3)
+19: (1, 3)
+20: (2, 3)
+21: (3, 3)
+22: (4, 3)
+23: (5, 3)
+24: (0, 4)
+25: (1, 4)
+26: (2, 4)
+27: (3, 4)
+28: (4, 4)
+29: (5, 4)
+30: (0, 5)
+31: (1, 5)
+32: (2, 5)
+33: (3, 5)
+34: (4, 5)
+35: (5, 5)
+36: (0, 6)
+37: (1, 6)
+38: (2, 6)
+39: (3, 6)
+40: (4, 6)
+41: (5, 6)
+42: (0, 7)
+43: (1, 7)
+44: (2, 7)
+45: (3, 7)
+46: (4, 7)
+47: (5, 7)
+48: (0, 8)
+49: (1, 8)
+50: (2, 8)
+51: (3, 8)
+52: (4, 8)
+53: (5, 8)
+54: (0, 9)
+55: (1, 9)
+56: (2, 9)
+57: (3, 9)
+58: (4, 9)
+59: (5, 9)
+60: (0, 10)
+61: (1, 10)
+62: (2, 10)
+63: (3, 10)
+64: (4, 10)
+65: (5, 10)
+66: (0, 11)
+67: (1, 11)
+68: (2, 11)
+69: (3, 11)
+70: (4, 11)
+71: (5, 11)
+72: (0, 12)
+73: (1, 12)
+74: (2, 12)
+75: (3, 12)
+76: (4, 12)
+77: (5, 12)
+78: (0, 13)
+79: (1, 13)
+80: (2, 13)
+81: (3, 13)
+82: (4, 13)
+83: (5, 13)
+84: (0, 14)
+85: (1, 14)
+86: (2, 14)
+87: (3, 14)
+88: (4, 14)
+89: (5, 14)
+90: (0, 15)
+91: (1, 15)
+92: (2, 15)
+93: (3, 15)
+94: (4, 15)
+95: (5, 15)
+96: (0, 16)
+97: (1, 16)
+98: (2, 16)
+99: (3, 16)
+100: (4, 16)
+101: (5, 16)
+102: (0, 17)
+103: (1, 17)
+104: (2, 17)
+105: (3, 17)
+106: (4, 17)
+107: (5, 17)
+108: (0, 18)
+109: (1, 18)
+110: (2, 18)
+111: (3, 18)
+112: (4, 18)
+113: (5, 18)
+114: (0, 19)
+115: (1, 19)
+116: (2, 19)
+117: (3, 19)
+118: (4, 19)
+119: (5, 19)
+120: (0, 20)
+121: (1, 20)
+122: (2, 20)
+123: (3, 20)
+124: (4, 20)
+125: (5, 20)
+126: (0, 21)
+127: (1, 21)
+128: (2, 21)
+129: (3, 21)
+130: (4, 21)
+131: (5, 21)
+132: (0, 22)
+133: (1, 22)
+134: (2, 22)
+135: (3, 22)
+136: (4, 22)
+137: (5, 22)
+138: (0, 23)
+139: (1, 23)
+140: (2, 23)
+141: (3, 23)
+142: (4, 23)
+143: (5, 23)
+144: (0, 24)
+145: (1, 24)
+146: (2, 24)
+147: (3, 24)
+148: (4, 24)
+149: (5, 24)
+150: (0, 25)
+151: (1, 25)
+152: (2, 25)
+153: (3, 25)
+154: (4, 25)
+155: (5, 25)
+156: (0, 26)
+157: (1, 26)
+158: (2, 26)
+159: (3, 26)
+160: (4, 26)
+161: (5, 26)
+162: (0, 27)
+163: (1, 27)
+164: (2, 27)
+165: (3, 27)
+166: (4, 27)
+167: (5, 27)
+168: (0, 28)
+169: (1, 28)
+170: (2, 28)
+171: (3, 28)
+172: (4, 28)
+173: (5, 28)
+174: (0, 29)
+175: (1, 29)
+176: (2, 29)
+177: (3, 29)
+178: (4, 29)
+179: (5, 29)
+180: (0, 30)
+181: (1, 30)
+182: (2, 30)
+183: (3, 30)
+184: (4, 30)
+185: (5, 30)
+186: (0, 31)
+187: (1, 31)
+188: (2, 31)
+189: (3, 31)
+190: (4, 31)
+191: (5, 31)
+192: (0, 32)
+193: (1, 32)
+194: (2, 32)
+195: (3, 32)
+196: (4, 32)
+197: (5, 32)
+198: (0, 33)
+199: (1, 33)
+200: (2, 33)
+201: (3, 33)
+202: (4, 33)
+203: (5, 33)
+204: (0, 34)
+205: (1, 34)
+206: (2, 34)
+207: (3, 34)
+208: (4, 34)
+209: (5, 34)
+210: (0, 35)
+211: (1, 35)
+212: (2, 35)
+213: (3, 35)
+214: (4, 35)
+215: (5, 35)
+216: (0, 36)
+217: (1, 36)
+218: (2, 36)
+219: (3, 36)
+220: (4, 36)
+221: (5, 36)
+222: (0, 37)
+223: (1, 37)
+224: (2, 37)
+225: (3, 37)
+226: (4, 37)
+227: (5, 37)
+228: (0, 38)
+229: (1, 38)
+230: (2, 38)
+231: (3, 38)
+232: (4, 38)
+233: (5, 38)
+234: (0, 39)
+235: (1, 39)
+236: (2, 39)
+237: (3, 39)
+238: (4, 39)
+239: (5, 39)
+240: (0, 40)
+241: (1, 40)
+242: (2, 40)
+243: (3, 40)
+244: (4, 40)
+245: (5, 40)
+246: (0, 41)
+247: (1, 41)
+248: (2, 41)
+249: (3, 41)
+250: (4, 41)
+251: (5, 41)
+252: (0, 42)
+253: (1, 42)
+254: (2, 42)
+255: (3, 42)
+256: (4, 42)
+257: (5, 42)
+258: (0, 43)
+259: (1, 43)
+260: (2, 43)
+261: (3, 43)
+262: (4, 43)
+263: (5, 43)
+264: (0, 44)
+265: (1, 44)
+266: (2, 44)
+267: (3, 44)
+268: (4, 44)
+269: (5, 44)
+270: (0, 45)
+271: (1, 45)
+272: (2, 45)
+273: (3, 45)
+274: (4, 45)
+275: (5, 45)
+276: (0, 46)
+277: (1, 46)
+278: (2, 46)
+279: (3, 46)
+280: (4, 46)
+281: (5, 46)
+282: (0, 47)
+283: (1, 47)
+284: (2, 47)
+285: (3, 47)
+286: (4, 47)
+287: (5, 47)
+288: (0, 48)
+289: (1, 48)
+290: (2, 48)
+291: (3, 48)
+292: (4, 48)
+293: (5, 48)
+294: (0, 49)
+295: (1, 49)
+296: (2, 49)
+297: (3, 49)
+298: (4, 49)
+299: (5, 49)
+300: (0, 50)
+301: (1, 50)
+302: (2, 50)
+303: (3, 50)
+304: (4, 50)
+305: (5, 50)
+306: (0, 51)
+307: (1, 51)
+308: (2, 51)
+309: (3, 51)
+310: (4, 51)
+311: (5, 51)
+312: (0, 52)
+313: (1, 52)
+314: (2, 52)
+315: (3, 52)
+316: (4, 52)
+317: (5, 52)
+318: (0, 53)
+319: (1, 53)
+320: (2, 53)
+321: (3, 53)
+322: (4, 53)
+323: (5, 53)
+324: (0, 54)
+325: (1, 54)
+326: (2, 54)
+327: (3, 54)
+328: (4, 54)
+329: (5, 54)
+330: (0, 55)
+331: (1, 55)
+332: (2, 55)
+333: (3, 55)
+334: (4, 55)
+335: (5, 55)
+336: (0, 56)
+337: (1, 56)
+338: (2, 56)
+339: (3, 56)
+340: (4, 56)
+341: (5, 56)
+342: (0, 57)
+343: (1, 57)
+344: (2, 57)
+345: (3, 57)
+346: (4, 57)
+347: (5, 57)
+348: (0, 58)
+349: (1, 58)
+350: (2, 58)
+351: (3, 58)
+352: (4, 58)
+353: (5, 58)
+354: (0, 59)
+355: (1, 59)
+356: (2, 59)
+357: (3, 59)
+358: (4, 59)
+359: (5, 59)
+360: (0, 60)
+361: (1, 60)
+362: (2, 60)
+363: (3, 60)
+364: (4, 60)
+365: (5, 60)
+366: (0, 61)
+367: (1, 61)
+368: (2, 61)
+369: (3, 61)
+370: (4, 61)
+371: (5, 61)
+372: (0, 62)
+373: (1, 62)
+374: (2, 62)
+375: (3, 62)
+376: (4, 62)
+377: (5, 62)
+378: (0, 63)
+379: (1, 63)
+380: (2, 63)
+381: (3, 63)
+382: (4, 63)
+383: (5, 63)
+384: (0, 64)
+385: (1, 64)
+386: (2, 64)
+387: (3, 64)
+388: (4, 64)
+389: (5, 64)
+390: (0, 65)
+391: (1, 65)
+392: (2, 65)
+393: (3, 65)
+394: (4, 65)
+395: (5, 65)
+396: (0, 66)
+397: (1, 66)
+398: (2, 66)
+399: (3, 66)
+400: (4, 66)
+401: (5, 66)
+402: (0, 67)
+403: (1, 67)
+404: (2, 67)
+405: (3, 67)
+406: (4, 67)
+407: (5, 67)
+408: (0, 68)
+409: (1, 68)
+410: (2, 68)
+411: (3, 68)
+412: (4, 68)
+413: (5, 68)
+414: (0, 69)
+415: (1, 69)
+416: (2, 69)
+417: (3, 69)
+418: (4, 69)
+419: (5, 69)
+420: (0, 70)
+421: (1, 70)
+422: (2, 70)
+423: (3, 70)
+424: (4, 70)
+425: (5, 70)
+426: (0, 71)
+427: (1, 71)
+428: (2, 71)
+429: (3, 71)
+430: (4, 71)
+431: (5, 71)
+432: (0, 72)
+433: (1, 72)
+434: (2, 72)
+435: (3, 72)
+436: (4, 72)
+437: (5, 72)
+438: (0, 73)
+439: (1, 73)
+440: (2, 73)
+441: (3, 73)
+442: (4, 73)
+443: (5, 73)
+444: (0, 74)
+445: (1, 74)
+446: (2, 74)
+447: (3, 74)
+448: (4, 74)
+449: (5, 74)
+450: (0, 75)
+451: (1, 75)
+452: (2, 75)
+453: (3, 75)
+454: (4, 75)
+455: (5, 75)
+456: (0, 76)
+457: (1, 76)
+458: (2, 76)
+459: (3, 76)
+460: (4, 76)
+461: (5, 76)
+462: (0, 77)
+463: (1, 77)
+464: (2, 77)
+465: (3, 77)
+466: (4, 77)
+467: (5, 77)
+468: (0, 78)
+469: (1, 78)
+470: (2, 78)
+471: (3, 78)
+472: (4, 78)
+473: (5, 78)
+474: (0, 79)
+475: (1, 79)
+476: (2, 79)
+477: (3, 79)
+478: (4, 79)
+479: (5, 79)
+480: (0, 80)
+481: (1, 80)
+482: (2, 80)
+483: (3, 80)
+484: (4, 80)
+485: (5, 80)
+486: (0, 81)
+487: (1, 81)
+488: (2, 81)
+489: (3, 81)
+490: (4, 81)
+491: (5, 81)
+492: (0, 82)
+493: (1, 82)
+494: (2, 82)
+495: (3, 82)
+496: (4, 82)
+497: (5, 82)
+498: (0, 83)
+499: (1, 83)
+500: (2, 83)
+501: (3, 83)
+502: (4, 83)
+503: (5, 83)
+504: (0, 84)
+505: (1, 84)
+506: (2, 84)
+507: (3, 84)
+508: (4, 84)
+509: (5, 84)
+510: (0, 85)
+511: (1, 85)
+512: (2, 85)
+513: (3, 85)
+514: (4, 85)
+515: (5, 85)
+516: (0, 86)
+517: (1, 86)
+518: (2, 86)
+519: (3, 86)
+520: (4, 86)
+521: (5, 86)
+522: (0, 87)
+523: (1, 87)
+524: (2, 87)
+525: (3, 87)
+526: (4, 87)
+527: (5, 87)
+528: (0, 88)
+529: (1, 88)
+530: (2, 88)
+531: (3, 88)
+532: (4, 88)
+533: (5, 88)
+534: (0, 89)
+535: (1, 89)
+536: (2, 89)
+537: (3, 89)
+538: (4, 89)
+539: (5, 89)
+540: (0, 90)
+541: (1, 90)
+542: (2, 90)
+543: (3, 90)
+544: (4, 90)
+545: (5, 90)
+546: (0, 91)
+547: (1, 91)
+548: (2, 91)
+549: (3, 91)
+550: (4, 91)
+551: (5, 91)
+552: (0, 92)
+553: (1, 92)
+554: (2, 92)
+555: (3, 92)
+556: (4, 92)
+557: (5, 92)
+558: (0, 93)
+559: (1, 93)
+560: (2, 93)
+561: (3, 93)
+562: (4, 93)
+563: (5, 93)
+564: (0, 94)
+565: (1, 94)
+566: (2, 94)
+567: (3, 94)
+568: (4, 94)
+569: (5, 94)
+570: (0, 95)
+571: (1, 95)
+572: (2, 95)
+573: (3, 95)
+574: (4, 95)
+575: (5, 95)
+576: (0, 96)
+577: (1, 96)
+578: (2, 96)
+579: (3, 96)
+580: (4, 96)
+581: (5, 96)
+582: (0, 97)
+583: (1, 97)
+584: (2, 97)
+585: (3, 97)
+586: (4, 97)
+587: (5, 97)
+588: (0, 98)
+589: (1, 98)
+590: (2, 98)
+591: (3, 98)
+592: (4, 98)
+593: (5, 98)
+594: (0, 99)
+595: (1, 99)
+596: (2, 99)
+597: (3, 99)
+598: (4, 99)
+599: (5, 99)
+600: (0, 100)
+601: (1, 100)
+602: (2, 100)
+603: (3, 100)
+604: (4, 100)
+605: (5, 100)
+606: (0, 101)
+607: (1, 101)
+608: (2, 101)
+609: (3, 101)
+610: (4, 101)
+611: (5, 101)
+612: (0, 102)
+613: (1, 102)
+614: (2, 102)
+615: (3, 102)
+616: (4, 102)
+617: (5, 102)
+618: (0, 103)
+619: (1, 103)
+620: (2, 103)
+621: (3, 103)
+622: (4, 103)
+623: (5, 103)
+624: (0, 104)
+625: (1, 104)
+626: (2, 104)
+627: (3, 104)
+628: (4, 104)
+629: (5, 104)
+630: (0, 105)
+631: (1, 105)
+632: (2, 105)
+633: (3, 105)
+634: (4, 105)
+635: (5, 105)
+636: (0, 106)
+637: (1, 106)
+638: (2, 106)
+639: (3, 106)
+640: (4, 106)
+641: (5, 106)
+642: (0, 107)
+643: (1, 107)
+644: (2, 107)
+645: (3, 107)
+646: (4, 107)
+647: (5, 107)
+648: (0, 108)
+649: (1, 108)
+650: (2, 108)
+651: (3, 108)
+652: (4, 108)
+653: (5, 108)
+654: (0, 109)
+655: (1, 109)
+656: (2, 109)
+657: (3, 109)
+658: (4, 109)
+659: (5, 109)
+660: (0, 110)
+661: (1, 110)
+662: (2, 110)
+663: (3, 110)
+664: (4, 110)
+665: (5, 110)
+666: (0, 111)
+667: (1, 111)
+668: (2, 111)
+669: (3, 111)
+670: (4, 111)
+671: (5, 111)
+672: (0, 112)
+673: (1, 112)
+674: (2, 112)
+675: (3, 112)
+676: (4, 112)
+677: (5, 112)
+678: (0, 113)
+679: (1, 113)
+680: (2, 113)
+681: (3, 113)
+682: (4, 113)
+683: (5, 113)
+684: (0, 114)
+685: (1, 114)
+686: (2, 114)
+687: (3, 114)
+688: (4, 114)
+689: (5, 114)
+690: (0, 115)
+691: (1, 115)
+692: (2, 115)
+693: (3, 115)
+694: (4, 115)
+695: (5, 115)
+696: (0, 116)
+697: (1, 116)
+698: (2, 116)
+699: (3, 116)
+700: (4, 116)
+701: (5, 116)
+702: (0, 117)
+703: (1, 117)
+704: (2, 117)
+705: (3, 117)
+706: (4, 117)
+707: (5, 117)
+708: (0, 118)
+709: (1, 118)
+710: (2, 118)
+711: (3, 118)
+712: (4, 118)
+713: (5, 118)
+714: (0, 119)
+715: (1, 119)
+716: (2, 119)
+717: (3, 119)
+718: (4, 119)
+719: (5, 119)
+720: (0, 120)
+721: (1, 120)
+722: (2, 120)
+723: (3, 120)
+724: (4, 120)
+725: (5, 120)
+726: (0, 121)
+727: (1, 121)
+728: (2, 121)
+729: (3, 121)
+730: (4, 121)
+731: (5, 121)
+732: (0, 122)
+733: (1, 122)
+734: (2, 122)
+735: (3, 122)
+736: (4, 122)
+737: (5, 122)
+738: (0, 123)
+739: (1, 123)
+740: (2, 123)
+741: (3, 123)
+742: (4, 123)
+743: (5, 123)
+744: (0, 124)
+745: (1, 124)
+746: (2, 124)
+747: (3, 124)
+748: (4, 124)
+749: (5, 124)
+750: (0, 125)
+751: (1, 125)
+752: (2, 125)
+753: (3, 125)
+754: (4, 125)
+755: (5, 125)
+756: (0, 126)
+757: (1, 126)
+758: (2, 126)
+759: (3, 126)
+760: (4, 126)
+761: (5, 126)
+762: (0, 127)
+763: (1, 127)
+764: (2, 127)
+765: (3, 127)
+766: (4, 127)
+767: (5, 127)
+768: (0, 128)
+769: (1, 128)
+770: (2, 128)
+771: (3, 128)
+772: (4, 128)
+773: (5, 128)
+774: (0, 129)
+775: (1, 129)
+776: (2, 129)
+777: (3, 129)
+778: (4, 129)
+779: (5, 129)
+780: (0, 130)
+781: (1, 130)
+782: (2, 130)
+783: (3, 130)
+784: (4, 130)
+785: (5, 130)
+786: (0, 131)
+787: (1, 131)
+788: (2, 131)
+789: (3, 131)
+790: (4, 131)
+791: (5, 131)
+792: (0, 132)
+793: (1, 132)
+794: (2, 132)
+795: (3, 132)
+796: (4, 132)
+797: (5, 132)
+798: (0, 133)
+799: (1, 133)
+800: (2, 133)
+801: (3, 133)
+802: (4, 133)
+803: (5, 133)
+804: (0, 134)
+805: (1, 134)
+806: (2, 134)
+807: (3, 134)
+808: (4, 134)
+809: (5, 134)
+810: (0, 135)
+811: (1, 135)
+812: (2, 135)
+813: (3, 135)
+814: (4, 135)
+815: (5, 135)
+816: (0, 136)
+817: (1, 136)
+818: (2, 136)
+819: (3, 136)
+820: (4, 136)
+821: (5, 136)
+822: (0, 137)
+823: (1, 137)
+824: (2, 137)
+825: (3, 137)
+826: (4, 137)
+827: (5, 137)
+828: (0, 138)
+829: (1, 138)
+830: (2, 138)
+831: (3, 138)
+832: (4, 138)
+833: (5, 138)
+834: (0, 139)
+835: (1, 139)
+836: (2, 139)
+837: (3, 139)
+838: (4, 139)
+839: (5, 139)
+840: (0, 140)
+841: (1, 140)
+842: (2, 140)
+843: (3, 140)
+844: (4, 140)
+845: (5, 140)
+846: (0, 141)
+847: (1, 141)
+848: (2, 141)
+849: (3, 141)
+850: (4, 141)
+851: (5, 141)
+852: (0, 142)
+853: (1, 142)
+854: (2, 142)
+855: (3, 142)
+856: (4, 142)
+857: (5, 142)
+858: (0, 143)
+859: (1, 143)
+860: (2, 143)
+861: (3, 143)
+862: (4, 143)
+863: (5, 143)
+864: (0, 144)
+865: (1, 144)
+866: (2, 144)
+867: (3, 144)
+868: (4, 144)
+869: (5, 144)
+870: (0, 145)
+871: (1, 145)
+872: (2, 145)
+873: (3, 145)
+874: (4, 145)
+875: (5, 145)
+876: (0, 146)
+877: (1, 146)
+878: (2, 146)
+879: (3, 146)
+880: (4, 146)
+881: (5, 146)
+882: (0, 147)
+883: (1, 147)
+884: (2, 147)
+885: (3, 147)
+886: (4, 147)
+887: (5, 147)
+888: (0, 148)
+889: (1, 148)
+890: (2, 148)
+891: (3, 148)
+892: (4, 148)
+893: (5, 148)
+894: (0, 149)
+895: (1, 149)
+896: (2, 149)
+897: (3, 149)
+898: (4, 149)
+899: (5, 149)
+900: (0, 150)
+901: (1, 150)
+902: (2, 150)
+903: (3, 150)
+904: (4, 150)
+905: (5, 150)
+906: (0, 151)
+907: (1, 151)
+908: (2, 151)
+909: (3, 151)
+910: (4, 151)
+911: (5, 151)
+912: (0, 152)
+913: (1, 152)
+914: (2, 152)
+915: (3, 152)
+916: (4, 152)
+917: (5, 152)
+918: (0, 153)
+919: (1, 153)
+920: (2, 153)
+921: (3, 153)
+922: (4, 153)
+923: (5, 153)
+924: (0, 154)
+925: (1, 154)
+926: (2, 154)
+927: (3, 154)
+928: (4, 154)
+929: (5, 154)
+930: (0, 155)
+931: (1, 155)
+932: (2, 155)
+933: (3, 155)
+934: (4, 155)
+935: (5, 155)
+936: (0, 156)
+937: (1, 156)
+938: (2, 156)
+939: (3, 156)
+940: (4, 156)
+941: (5, 156)
+942: (0, 157)
+943: (1, 157)
+944: (2, 157)
+945: (3, 157)
+946: (4, 157)
+947: (5, 157)
+948: (0, 158)
+949: (1, 158)
+950: (2, 158)
+951: (3, 158)
+952: (4, 158)
+953: (5, 158)
+954: (0, 159)
+955: (1, 159)
+956: (2, 159)
+957: (3, 159)
+958: (4, 159)
+959: (5, 159)
+960: (0, 160)
+961: (1, 160)
+962: (2, 160)
+963: (3, 160)
+964: (4, 160)
+965: (5, 160)
+966: (0, 161)
+967: (1, 161)
+968: (2, 161)
+969: (3, 161)
+970: (4, 161)
+971: (5, 161)
+972: (0, 162)
+973: (1, 162)
+974: (2, 162)
+975: (3, 162)
+976: (4, 162)
+977: (5, 162)
+978: (0, 163)
+979: (1, 163)
+980: (2, 163)
+981: (3, 163)
+982: (4, 163)
+983: (5, 163)
+984: (0, 164)
+985: (1, 164)
+986: (2, 164)
+987: (3, 164)
+988: (4, 164)
+989: (5, 164)
+990: (0, 165)
+991: (1, 165)
+992: (2, 165)
+993: (3, 165)
+994: (4, 165)
+995: (5, 165)
+996: (0, 166)
+997: (1, 166)
+998: (2, 166)
+999: (3, 166)
+1000: (4, 166)
+1001: (5, 166)
+1002: (0, 167)
+1003: (1, 167)
+1004: (2, 167)
+1005: (3, 167)
+1006: (4, 167)
+1007: (5, 167)
+1008: (0, 168)
+1009: (1, 168)
+1010: (2, 168)
+1011: (3, 168)
+1012: (4, 168)
+1013: (5, 168)
+1014: (0, 169)
+1015: (1, 169)
+1016: (2, 169)
+1017: (3, 169)
+1018: (4, 169)
+1019: (5, 169)
+1020: (0, 170)
+1021: (1, 170)
+1022: (2, 170)
+1023: (3, 170)
+1024: (4, 170)
+1025: (5, 170)
+1026: (0, 171)
+1027: (1, 171)
+1028: (2, 171)
+1029: (3, 171)
+1030: (4, 171)
+1031: (5, 171)
+1032: (0, 172)
+1033: (1, 172)
+1034: (2, 172)
+1035: (3, 172)
+1036: (4, 172)
+1037: (5, 172)
+1038: (0, 173)
+1039: (1, 173)
+1040: (2, 173)
+1041: (3, 173)
+1042: (4, 173)
+1043: (5, 173)
+1044: (0, 174)
+1045: (1, 174)
+1046: (2, 174)
+1047: (3, 174)
+1048: (4, 174)
+1049: (5, 174)
+1050: (0, 175)
+1051: (1, 175)
+1052: (2, 175)
+1053: (3, 175)
+1054: (4, 175)
+1055: (5, 175)
+1056: (0, 176)
+1057: (1, 176)
+1058: (2, 176)
+1059: (3, 176)
+1060: (4, 176)
+1061: (5, 176)
+1062: (0, 177)
+1063: (1, 177)
+1064: (2, 177)
+1065: (3, 177)
+1066: (4, 177)
+1067: (5, 177)
+1068: (0, 178)
+1069: (1, 178)
+1070: (2, 178)
+1071: (3, 178)
+1072: (4, 178)
+1073: (5, 178)
+1074: (0, 179)
+1075: (1, 179)
+1076: (2, 179)
+1077: (3, 179)
+1078: (4, 179)
+1079: (5, 179)
+1080: (0, 180)
+1081: (1, 180)
+1082: (2, 180)
+1083: (3, 180)
+1084: (4, 180)
+1085: (5, 180)
+1086: (0, 181)
+1087: (1, 181)
+1088: (2, 181)
+1089: (3, 181)
+1090: (4, 181)
+1091: (5, 181)
+1092: (0, 182)
+1093: (1, 182)
+1094: (2, 182)
+1095: (3, 182)
+1096: (4, 182)
+1097: (5, 182)
+1098: (0, 183)
+1099: (1, 183)
+1100: (2, 183)
+1101: (3, 183)
+1102: (4, 183)
+1103: (5, 183)
+1104: (0, 184)
+1105: (1, 184)
+1106: (2, 184)
+1107: (3, 184)
+1108: (4, 184)
+1109: (5, 184)
+1110: (0, 185)
+1111: (1, 185)
+1112: (2, 185)
+1113: (3, 185)
+1114: (4, 185)
+1115: (5, 185)
+1116: (0, 186)
+1117: (1, 186)
+1118: (2, 186)
+1119: (3, 186)
+1120: (4, 186)
+1121: (5, 186)
+1122: (0, 187)
+1123: (1, 187)
+1124: (2, 187)
+1125: (3, 187)
+1126: (4, 187)
+1127: (5, 187)
+1128: (0, 188)
+1129: (1, 188)
+1130: (2, 188)
+1131: (3, 188)
+1132: (4, 188)
+1133: (5, 188)
+1134: (0, 189)
+1135: (1, 189)
+1136: (2, 189)
+1137: (3, 189)
+1138: (4, 189)
+1139: (5, 189)
+1140: (0, 190)
+1141: (1, 190)
+1142: (2, 190)
+1143: (3, 190)
+1144: (4, 190)
+1145: (5, 190)
+1146: (0, 191)
+1147: (1, 191)
+1148: (2, 191)
+1149: (3, 191)
+1150: (4, 191)
+1151: (5, 191)
+1152: (0, 192)
+1153: (1, 192)
+1154: (2, 192)
+1155: (3, 192)
+1156: (4, 192)
+1157: (5, 192)
+1158: (0, 193)
+1159: (1, 193)
+1160: (2, 193)
+1161: (3, 193)
+1162: (4, 193)
+1163: (5, 193)
+1164: (0, 194)
+1165: (1, 194)
+1166: (2, 194)
+1167: (3, 194)
+1168: (4, 194)
+1169: (5, 194)
+1170: (0, 195)
+1171: (1, 195)
+1172: (2, 195)
+1173: (3, 195)
+1174: (4, 195)
+1175: (5, 195)
+1176: (0, 196)
+1177: (1, 196)
+1178: (2, 196)
+1179: (3, 196)
+1180: (4, 196)
+1181: (5, 196)
+1182: (0, 197)
+1183: (1, 197)
+1184: (2, 197)
+1185: (3, 197)
+1186: (4, 197)
+1187: (5, 197)
+1188: (0, 198)
+1189: (1, 198)
+1190: (2, 198)
+1191: (3, 198)
+1192: (4, 198)
+1193: (5, 198)
+1194: (0, 199)
+1195: (1, 199)
+1196: (2, 199)
+1197: (3, 199)
+1198: (4, 199)
+1199: (5, 199)
+1200: (0, 200)
+1201: (1, 200)
+1202: (2, 200)
+1203: (3, 200)
+1204: (4, 200)
+1205: (5, 200)
+1206: (0, 201)
+1207: (1, 201)
+1208: (2, 201)
+1209: (3, 201)
+1210: (4, 201)
+1211: (5, 201)
+1212: (0, 202)
+1213: (1, 202)
+1214: (2, 202)
+1215: (3, 202)
+1216: (4, 202)
+1217: (5, 202)
+1218: (0, 203)
+1219: (1, 203)
+1220: (2, 203)
+1221: (3, 203)
+1222: (4, 203)
+1223: (5, 203)
+1224: (0, 204)
+1225: (1, 204)
+1226: (2, 204)
+1227: (3, 204)
+1228: (4, 204)
+1229: (5, 204)
+1230: (0, 205)
+1231: (1, 205)
+1232: (2, 205)
+1233: (3, 205)
+1234: (4, 205)
+1235: (5, 205)
+1236: (0, 206)
+1237: (1, 206)
+1238: (2, 206)
+1239: (3, 206)
+1240: (4, 206)
+1241: (5, 206)
+1242: (0, 207)
+1243: (1, 207)
+1244: (2, 207)
+1245: (3, 207)
+1246: (4, 207)
+1247: (5, 207)
+1248: (0, 208)
+1249: (1, 208)
+1250: (2, 208)
+1251: (3, 208)
+1252: (4, 208)
+1253: (5, 208)
+1254: (0, 209)
+1255: (1, 209)
+1256: (2, 209)
+1257: (3, 209)
+1258: (4, 209)
+1259: (5, 209)
+1260: (0, 210)
+1261: (1, 210)
+1262: (2, 210)
+1263: (3, 210)
+1264: (4, 210)
+1265: (5, 210)
+1266: (0, 211)
+1267: (1, 211)
+1268: (2, 211)
+1269: (3, 211)
+1270: (4, 211)
+1271: (5, 211)
+1272: (0, 212)
+1273: (1, 212)
+1274: (2, 212)
+1275: (3, 212)
+1276: (4, 212)
+1277: (5, 212)
+1278: (0, 213)
+1279: (1, 213)
+1280: (2, 213)
+1281: (3, 213)
+1282: (4, 213)
+1283: (5, 213)
+1284: (0, 214)
+1285: (1, 214)
+1286: (2, 214)
+1287: (3, 214)
+1288: (4, 214)
+1289: (5, 214)
+1290: (0, 215)
+1291: (1, 215)
+1292: (2, 215)
+1293: (3, 215)
+1294: (4, 215)
+1295: (5, 215)
+1296: (0, 216)
+1297: (1, 216)
+1298: (2, 216)
+1299: (3, 216)
+1300: (4, 216)
+1301: (5, 216)
+1302: (0, 217)
+1303: (1, 217)
+1304: (2, 217)
+1305: (3, 217)
+1306: (4, 217)
+1307: (5, 217)
+1308: (0, 218)
+1309: (1, 218)
+1310: (2, 218)
+1311: (3, 218)
+1312: (4, 218)
+1313: (5, 218)
+1314: (0, 219)
+1315: (1, 219)
+1316: (2, 219)
+1317: (3, 219)
+1318: (4, 219)
+1319: (5, 219)
+1320: (0, 220)
+1321: (1, 220)
+1322: (2, 220)
+1323: (3, 220)
+1324: (4, 220)
+1325: (5, 220)
+1326: (0, 221)
+1327: (1, 221)
+1328: (2, 221)
+1329: (3, 221)
+1330: (4, 221)
+1331: (5, 221)
+1332: (0, 222)
+1333: (1, 222)
+1334: (2, 222)
+1335: (3, 222)
+1336: (4, 222)
+1337: (5, 222)
+1338: (0, 223)
+1339: (1, 223)
+1340: (2, 223)
+1341: (3, 223)
+1342: (4, 223)
+1343: (5, 223)
+1344: (0, 224)
+1345: (1, 224)
+1346: (2, 224)
+1347: (3, 224)
+1348: (4, 224)
+1349: (5, 224)
+1350: (0, 225)
+1351: (1, 225)
+1352: (2, 225)
+1353: (3, 225)
+1354: (4, 225)
+1355: (5, 225)
+1356: (0, 226)
+1357: (1, 226)
+1358: (2, 226)
+1359: (3, 226)
+1360: (4, 226)
+1361: (5, 226)
+1362: (0, 227)
+1363: (1, 227)
+1364: (2, 227)
+1365: (3, 227)
+1366: (4, 227)
+1367: (5, 227)
+1368: (0, 228)
+1369: (1, 228)
+1370: (2, 228)
+1371: (3, 228)
+1372: (4, 228)
+1373: (5, 228)
+1374: (0, 229)
+1375: (1, 229)
+1376: (2, 229)
+1377: (3, 229)
+1378: (4, 229)
+1379: (5, 229)
+1380: (0, 230)
+1381: (1, 230)
+1382: (2, 230)
+1383: (3, 230)
+1384: (4, 230)
+1385: (5, 230)
+1386: (0, 231)
+1387: (1, 231)
+1388: (2, 231)
+1389: (3, 231)
+1390: (4, 231)
+1391: (5, 231)
+1392: (0, 232)
+1393: (1, 232)
+1394: (2, 232)
+1395: (3, 232)
+1396: (4, 232)
+1397: (5, 232)
+1398: (1, 233)
+1399: (2, 233)
+1400: (3, 233)
+1401: (4, 233)
+1402: (5, 233)
+1403: (2, 234)
+1404: (3, 234)
+1405: (4, 234)
+1406: (2, 235)
+1407: (3, 235)
+1408: (4, 235)
+1409: (2, 236)
+1410: (3, 236)
+1411: (4, 236)
+1412: (2, 237)
+1413: (3, 237)
+1414: (4, 237)
+1415: (2, 238)
+1416: (3, 238)
+
+; Merges (added edges)
+; Format is:
+; source_column -> dest_column
+; (new accuracy is source_column_accuracy + dest_column_accuracy + accuracy_change)
+; (note that all accuracies are unnormalized)
+
+120 -> 131
+1357 -> 1388
+126 -> 137
+750 -> 761
+756 -> 767
+1266 -> 1277
+1344 -> 1355
+762 -> 773
+1062 -> 1073
+1068 -> 1079
+768 -> 779
+846 -> 857
+906 -> 917
+918 -> 929
+924 -> 935
+923 -> 912
+852 -> 863
+870 -> 881
+882 -> 893
+887 -> 876
+858 -> 869
+875 -> 864
+828 -> 839
+834 -> 845
+851 -> 840
+306 -> 317
+312 -> 323
+390 -> 401
+630 -> 641
+654 -> 665
+660 -> 671
+678 -> 689
+666 -> 677
+683 -> 672
+636 -> 647
+642 -> 653
+659 -> 648
+396 -> 407
+420 -> 431
+426 -> 437
+432 -> 443
+318 -> 329
+324 -> 335
+330 -> 341
+336 -> 347
+889 -> 902
+895 -> 908
+1272 -> 1283
+755 -> 744
+450 -> 461
+1067 -> 1056
+1074 -> 1085
+635 -> 624
+438 -> 449
+455 -> 444
+378 -> 389
+132 -> 143
+258 -> 269
+1350 -> 1361
+425 -> 414
+395 -> 384
+402 -> 413
+342 -> 353
+1278 -> 1289
+1080 -> 1091
+911 -> 900
+573 -> 572
+749 -> 738
+419 -> 408
+263 -> 252
+133 -> 147
+1349 -> 1338
+1271 -> 1260
+1149 -> 1148
+459 -> 458
+576 -> 587
+146 -> 141
+896 -> 883
+804 -> 815
+833 -> 822
+125 -> 114
+1137 -> 1136
+1155 -> 1154
+1143 -> 1142
+555 -> 554
+561 -> 560
+567 -> 566
+477 -> 476
+465 -> 464
+348 -> 359
+445 -> 459
+774 -> 785
+582 -> 593
+498 -> 509
+319 -> 333
+325 -> 339
+1404 -> 1403
+1395 -> 1394
+1400 -> 1399
+915 -> 914
+657 -> 656
+669 -> 668
+675 -> 674
+681 -> 680
+579 -> 578
+483 -> 482
+471 -> 470
+453 -> 452
+158 -> 153
+503 -> 492
+133 -> 152
+581 -> 570
+383 -> 372
+1265 -> 1254
+1382 -> 1383
+1119 -> 1118
+1125 -> 1124
+1131 -> 1130
+777 -> 776
+759 -> 758
+663 -> 662
+549 -> 548
+743 -> 732
+138 -> 149
+456 -> 467
+204 -> 215
+889 -> 903
+1416 -> 1415
+1161 -> 1160
+771 -> 770
+504 -> 515
+210 -> 221
+146 -> 127
+895 -> 909
+727 -> 741
+451 -> 465
+897 -> 896
+765 -> 764
+687 -> 686
+693 -> 692
+684 -> 695
+865 -> 879
+337 -> 351
+327 -> 313
+345 -> 331
+1284 -> 1295
+1113 -> 1112
+827 -> 816
+164 -> 159
+711 -> 710
+821 -> 810
+780 -> 791
+453 -> 439
+1407 -> 1406
+1107 -> 1106
+747 -> 746
+409 -> 423
+888 -> 899
+834 -> 853
+1275 -> 1274
+753 -> 752
+1259 -> 1248
+905 -> 894
+699 -> 698
+116 -> 111
+697 -> 711
+343 -> 357
+891 -> 890
+705 -> 704
+543 -> 542
+1416 -> 1398
+1253 -> 1242
+809 -> 798
+1081 -> 1095
+873 -> 859
+354 -> 365
+168 -> 179
+457 -> 471
+1087 -> 1101
+846 -> 878
+651 -> 650
+173 -> 162
+1045 -> 1059
+1356 -> 1367
+182 -> 177
+188 -> 183
+1089 -> 1075
+939 -> 938
+639 -> 638
+803 -> 792
+194 -> 189
+510 -> 521
+679 -> 693
+140 -> 135
+871 -> 885
+687 -> 673
+1167 -> 1166
+170 -> 165
+377 -> 366
+681 -> 667
+797 -> 786
+489 -> 488
+200 -> 195
+176 -> 171
+371 -> 360
+930 -> 941
+1377 -> 1376
+597 -> 596
+462 -> 473
+1247 -> 1236
+931 -> 945
+645 -> 644
+513 -> 512
+463 -> 477
+705 -> 691
+139 -> 158
+951 -> 950
+591 -> 590
+699 -> 685
+349 -> 363
+259 -> 273
+585 -> 584
+122 -> 117
+783 -> 782
+209 -> 198
+1363 -> 1395
+633 -> 632
+501 -> 500
+264 -> 275
+897 -> 875
+1053 -> 1039
+265 -> 279
+1005 -> 1004
+1061 -> 1050
+999 -> 998
+957 -> 956
+507 -> 506
+1343 -> 1332
+234 -> 245
+257 -> 246
+1083 -> 1069
+735 -> 721
+218 -> 213
+852 -> 884
+272 -> 267
+206 -> 201
+128 -> 123
+495 -> 494
+1185 -> 1184
+110 -> 105
+251 -> 240
+216 -> 227
+306 -> 322
+390 -> 422
+396 -> 428
+943 -> 957
+643 -> 657
+891 -> 877
+1371 -> 1370
+901 -> 915
+870 -> 889
+47 -> 42
+963 -> 962
+921 -> 920
+447 -> 446
+144 -> 155
+1269 -> 1268
+537 -> 536
+134 -> 129
+468 -> 479
+981 -> 980
+174 -> 185
+933 -> 932
+819 -> 818
+212 -> 207
+717 -> 716
+497 -> 486
+321 -> 307
+847 -> 828
+813 -> 812
+311 -> 300
+312 -> 328
+474 -> 485
+222 -> 233
+239 -> 228
+1362 -> 1373
+553 -> 567
+415 -> 429
+356 -> 337
+469 -> 483
+203 -> 192
+1413 -> 1412
+854 -> 855
+575 -> 564
+1011 -> 1010
+675 -> 661
+1410 -> 1409
+180 -> 191
+167 -> 156
+516 -> 527
+872 -> 851
+1382 -> 1344
+161 -> 150
+751 -> 765
+757 -> 771
+53 -> 48
+763 -> 777
+531 -> 530
+993 -> 992
+491 -> 480
+1249 -> 1275
+1290 -> 1301
+1299 -> 1298
+703 -> 717
+1086 -> 1097
+1350 -> 1389
+759 -> 745
+727 -> 740
+733 -> 747
+1281 -> 1280
+197 -> 186
+927 -> 926
+441 -> 440
+649 -> 663
+378 -> 410
+1046 -> 1047
+837 -> 836
+690 -> 724
+987 -> 986
+416 -> 395
+305 -> 294
+834 -> 867
+1369 -> 1400
+421 -> 434
+1093 -> 1107
+588 -> 599
+522 -> 533
+1055 -> 1044
+271 -> 285
+1173 -> 1172
+860 -> 861
+951 -> 937
+972 -> 983
+1350 -> 1357
+1179 -> 1178
+627 -> 626
+795 -> 762
+978 -> 989
+642 -> 676
+870 -> 898
+729 -> 715
+1191 -> 1190
+939 -> 925
+1049 -> 1038
+1052 -> 1053
+629 -> 618
+753 -> 739
+975 -> 974
+723 -> 722
+336 -> 368
+669 -> 655
+224 -> 219
+969 -> 968
+949 -> 963
+990 -> 1001
+996 -> 1007
+1092 -> 1103
+995 -> 984
+1054 -> 1045
+1043 -> 1032
+145 -> 164
+977 -> 966
+936 -> 947
+944 -> 931
+1381 -> 1407
+891 -> 858
+1255 -> 1281
+719 -> 708
+705 -> 683
+621 -> 620
+603 -> 602
+825 -> 824
+41 -> 36
+1100 -> 1087
+519 -> 518
+448 -> 426
+696 -> 707
+1329 -> 1328
+1404 -> 1375
+831 -> 830
+971 -> 960
+948 -> 959
+699 -> 666
+447 -> 433
+561 -> 547
+965 -> 954
+421 -> 435
+1017 -> 1016
+133 -> 132
+1241 -> 1230
+702 -> 713
+1041 -> 1040
+737 -> 726
+906 -> 934
+355 -> 369
+272 -> 253
+1287 -> 1286
+953 -> 942
+615 -> 614
+872 -> 873
+609 -> 608
+525 -> 524
+35 -> 30
+849 -> 848
+5 -> 0
+887 -> 904
+843 -> 842
+361 -> 375
+1305 -> 1304
+1077 -> 1063
+714 -> 725
+789 -> 756
+731 -> 720
+723 -> 709
+659 -> 682
+1402 -> 1392
+282 -> 293
+559 -> 573
+887 -> 895
+404 -> 383
+1051 -> 1065
+1263 -> 1262
+270 -> 281
+1090 -> 1081
+1293 -> 1292
+1335 -> 1334
+1037 -> 1026
+266 -> 261
+441 -> 427
+623 -> 612
+92 -> 87
+299 -> 288
+350 -> 345
+734 -> 735
+287 -> 276
+104 -> 99
+728 -> 729
+199 -> 218
+871 -> 852
+670 -> 636
+1015 -> 1029
+1323 -> 1322
+119 -> 108
+1021 -> 1035
+1317 -> 1316
+296 -> 291
+451 -> 432
+1227 -> 1226
+865 -> 846
+29 -> 24
+98 -> 93
+1351 -> 1378
+259 -> 278
+1311 -> 1310
+569 -> 558
+1071 -> 1057
+1022 -> 1023
+442 -> 420
+23 -> 18
+11 -> 6
+140 -> 121
+1099 -> 1113
+1048 -> 1031
+807 -> 806
+985 -> 999
+230 -> 225
+17 -> 12
+675 -> 642
+801 -> 800
+1098 -> 1109
+841 -> 854
+991 -> 1005
+625 -> 639
+1002 -> 1013
+1413 -> 1393
+1372 -> 1345
+783 -> 750
+860 -> 847
+1068 -> 1096
+59 -> 54
+187 -> 206
+1042 -> 1025
+367 -> 381
+126 -> 142
+163 -> 182
+1337 -> 1326
+659 -> 681
+1410 -> 1387
+1008 -> 1019
+679 -> 660
+212 -> 193
+617 -> 606
+933 -> 919
+651 -> 637
+1221 -> 1220
+176 -> 157
+817 -> 831
+823 -> 837
+342 -> 374
+451 -> 454
+1074 -> 1102
+348 -> 380
+170 -> 151
+633 -> 619
+362 -> 343
+654 -> 688
+993 -> 979
+417 -> 403
+1397 -> 1386
+834 -> 866
+236 -> 231
+928 -> 911
+1365 -> 1364
+1046 -> 1033
+200 -> 181
+315 -> 301
+594 -> 605
+1257 -> 1256
+1269 -> 1243
+645 -> 631
+1080 -> 1108
+242 -> 237
+1251 -> 1250
+373 -> 387
+1207 -> 1233
+611 -> 600
+1368 -> 1379
+248 -> 243
+1331 -> 1320
+1391 -> 1380
+1084 -> 1089
+169 -> 188
+1245 -> 1244
+1385 -> 1374
+1341 -> 1340
+528 -> 539
+302 -> 297
+555 -> 541
+923 -> 940
+1239 -> 1238
+379 -> 393
+1296 -> 1307
+260 -> 255
+314 -> 309
+1215 -> 1214
+1235 -> 1224
+475 -> 489
+534 -> 545
+254 -> 249
+308 -> 303
+1353 -> 1352
+1359 -> 1358
+194 -> 175
+939 -> 906
+1302 -> 1313
+1356 -> 1363
+354 -> 386
+445 -> 448
+318 -> 334
+136 -> 120
+1366 -> 1339
+678 -> 697
+1105 -> 1119
+1104 -> 1115
+583 -> 597
+955 -> 969
+398 -> 377
+1229 -> 1218
+205 -> 224
+789 -> 788
+65 -> 60
+392 -> 371
+388 -> 385
+1347 -> 1346
+892 -> 897
+627 -> 613
+565 -> 579
+997 -> 1011
+1377 -> 1349
+438 -> 457
+1223 -> 1212
+1325 -> 1314
+1319 -> 1308
+1197 -> 1196
+687 -> 654
+591 -> 577
+987 -> 973
+669 -> 670
+133 -> 148
+1209 -> 1208
+882 -> 910
+1052 -> 1048
+961 -> 975
+801 -> 768
+540 -> 551
+113 -> 102
+453 -> 442
+933 -> 928
+138 -> 139
+841 -> 833
+981 -> 967
+664 -> 630
+563 -> 552
+1100 -> 1068
+557 -> 546
+585 -> 571
+411 -> 397
+266 -> 247
+1203 -> 1202
+825 -> 811
+86 -> 81
+415 -> 418
+344 -> 325
+922 -> 905
+405 -> 391
+679 -> 694
+1263 -> 1237
+265 -> 284
+1111 -> 1125
+455 -> 463
+658 -> 643
+916 -> 921
+649 -> 664
+1273 -> 1299
+1217 -> 1206
+794 -> 795
+362 -> 330
+75 -> 71
+211 -> 230
+923 -> 944
+1090 -> 1062
+409 -> 412
+316 -> 311
+774 -> 807
+927 -> 913
+436 -> 425
+882 -> 901
+799 -> 813
+1261 -> 1287
+1371 -> 1343
+1117 -> 1131
+1211 -> 1200
+916 -> 888
+819 -> 805
+134 -> 115
+356 -> 324
+126 -> 146
+1246 -> 1231
+621 -> 607
+438 -> 460
+1293 -> 1267
+918 -> 951
+3 -> 1
+1205 -> 1194
+528 -> 561
+763 -> 755
+260 -> 241
+555 -> 522
+804 -> 823
+534 -> 553
+849 -> 835
+1199 -> 1188
+843 -> 829
+128 -> 109
+684 -> 703
+1064 -> 1051
+27 -> 25
+1362 -> 1369
+589 -> 603
+229 -> 248
+1046 -> 1042
+927 -> 922
+849 -> 827
+1110 -> 1121
+1225 -> 1251
+1003 -> 1017
+1193 -> 1182
+254 -> 235
+843 -> 821
+549 -> 516
+310 -> 305
+595 -> 609
+21 -> 19
+615 -> 601
+916 -> 907
+9 -> 7
+1187 -> 1176
+130 -> 125
+450 -> 469
+1083 -> 1078
+924 -> 943
+799 -> 780
+783 -> 769
+15 -> 13
+543 -> 510
+1041 -> 1027
+356 -> 340
+918 -> 946
+1245 -> 1219
+419 -> 441
+1086 -> 1114
+33 -> 31
+1227 -> 1201
+1350 -> 1384
+1077 -> 1072
+699 -> 700
+217 -> 236
+263 -> 268
+1071 -> 1066
+242 -> 223
+658 -> 635
+4 -> 2
+455 -> 466
+1249 -> 1247
+1207 -> 1232
+112 -> 107
+145 -> 144
+1239 -> 1213
+364 -> 361
+74 -> 69
+481 -> 495
+1360 -> 1333
+292 -> 287
+336 -> 349
+930 -> 949
+1279 -> 1305
+421 -> 402
+447 -> 436
+1221 -> 1195
+1181 -> 1170
+1034 -> 1021
+304 -> 299
+124 -> 119
+1123 -> 1137
+1116 -> 1127
+298 -> 282
+1058 -> 1054
+415 -> 396
+1094 -> 1090
+1351 -> 1382
+1365 -> 1337
+370 -> 367
+358 -> 355
+1175 -> 1164
+1022 -> 1009
+271 -> 290
+1074 -> 1093
+487 -> 501
+1092 -> 1120
+1028 -> 1015
+138 -> 154
+886 -> 891
+170 -> 161
+1060 -> 1043
+706 -> 705
+701 -> 723
+122 -> 103
+540 -> 559
+924 -> 952
+1122 -> 1133
+424 -> 421
+1169 -> 1158
+286 -> 270
+419 -> 430
+1084 -> 1067
+1012 -> 1003
+258 -> 274
+277 -> 296
+376 -> 373
+1098 -> 1126
+1128 -> 1139
+1163 -> 1152
+1157 -> 1146
+1134 -> 1145
+280 -> 264
+1253 -> 1255
+417 -> 406
+1151 -> 1140
+774 -> 793
+1041 -> 1036
+106 -> 101
+749 -> 772
+1022 -> 1018
+557 -> 565
+350 -> 318
+68 -> 63
+450 -> 472
+1006 -> 997
+1080 -> 1099
+1359 -> 1331
+817 -> 809
+797 -> 819
+712 -> 678
+283 -> 302
+382 -> 379
+537 -> 504
+825 -> 803
+775 -> 789
+1215 -> 1189
+517 -> 531
+118 -> 113
+549 -> 535
+262 -> 257
+493 -> 507
+718 -> 684
+167 -> 176
+388 -> 399
+519 -> 497
+1368 -> 1404
+652 -> 651
+140 -> 136
+563 -> 585
+394 -> 405
+1058 -> 1037
+1083 -> 1061
+1024 -> 996
+411 -> 400
+1285 -> 1311
+250 -> 234
+513 -> 499
+936 -> 955
+1240 -> 1223
+525 -> 511
+256 -> 251
+569 -> 591
+1356 -> 1390
+1077 -> 1055
+714 -> 748
+1000 -> 991
+1034 -> 1030
+930 -> 958
+1362 -> 1396
+1071 -> 1049
+409 -> 390
+338 -> 319
+116 -> 97
+575 -> 583
+1246 -> 1229
+1064 -> 1060
+1269 -> 1241
+731 -> 754
+1353 -> 1325
+173 -> 163
+1354 -> 1327
+1234 -> 1217
+543 -> 529
+1296 -> 1335
+1022 -> 990
+953 -> 961
+794 -> 781
+39 -> 37
+766 -> 743
+1302 -> 1341
+1024 -> 1028
+801 -> 787
+1413 -> 1397
+1329 -> 1290
+1006 -> 978
+1104 -> 1132
+1012 -> 995
+332 -> 327
+1279 -> 1266
+985 -> 977
+1416 -> 1402
+1000 -> 972
+45 -> 43
+1008 -> 1041
+346 -> 362
+742 -> 719
+1347 -> 1319
+749 -> 757
+51 -> 49
+948 -> 981
+1385 -> 1381
+10 -> 8
+1034 -> 1002
+1410 -> 1391
+1052 -> 1020
+1317 -> 1278
+244 -> 239
+1209 -> 1183
+987 -> 982
+1263 -> 1235
+690 -> 701
+936 -> 964
+160 -> 145
+493 -> 474
+112 -> 96
+993 -> 971
+1088 -> 1084
+238 -> 222
+880 -> 871
+232 -> 216
+1046 -> 1014
+1071 -> 1070
+760 -> 737
+537 -> 523
+953 -> 970
+289 -> 308
+1323 -> 1284
+167 -> 172
+487 -> 468
+1076 -> 1077
+948 -> 976
+763 -> 778
+326 -> 321
+696 -> 730
+987 -> 965
+314 -> 295
+352 -> 336
+733 -> 714
+1228 -> 1211
+1082 -> 1083
+513 -> 491
+1291 -> 1317
+1416 -> 1414
+1411 -> 1413
+1285 -> 1272
+104 -> 95
+1282 -> 1265
+993 -> 988
+456 -> 475
+481 -> 462
+994 -> 985
+727 -> 742
+753 -> 731
+1368 -> 1401
+696 -> 728
+505 -> 519
+734 -> 736
+320 -> 315
+517 -> 498
+203 -> 212
+734 -> 702
+205 -> 220
+760 -> 759
+645 -> 646
+1110 -> 1138
+214 -> 199
+1271 -> 1288
+344 -> 312
+92 -> 83
+1276 -> 1259
+80 -> 76
+202 -> 187
+62 -> 57
+166 -> 170
+98 -> 89
+226 -> 210
+203 -> 208
+1385 -> 1405
+1408 -> 1410
+16 -> 14
+652 -> 629
+581 -> 589
+86 -> 77
+525 -> 503
+874 -> 865
+576 -> 595
+1372 -> 1377
+1323 -> 1297
+1129 -> 1143
+196 -> 180
+202 -> 197
+1203 -> 1177
+184 -> 168
+364 -> 348
+868 -> 872
+766 -> 751
+209 -> 214
+22 -> 20
+633 -> 611
+627 -> 594
+1150 -> 1122
+1222 -> 1205
+28 -> 26
+110 -> 106
+617 -> 625
+190 -> 174
+1144 -> 1116
+1249 -> 1264
+184 -> 169
+34 -> 32
+178 -> 173
+40 -> 38
+1216 -> 1199
+582 -> 615
+645 -> 623
+196 -> 200
+66 -> 61
+1159 -> 1185
+104 -> 100
+1261 -> 1276
+1197 -> 1171
+1366 -> 1371
+1270 -> 1253
+272 -> 263
+74 -> 70
+358 -> 342
+1191 -> 1165
+205 -> 204
+621 -> 588
+1163 -> 1180
+1174 -> 1157
+1271 -> 1273
+266 -> 262
+1175 -> 1192
+190 -> 194
+65 -> 55
+1210 -> 1193
+1086 -> 1105
+1168 -> 1151
+1348 -> 1321
+1204 -> 1187
+1228 -> 1239
+1303 -> 1329
+1216 -> 1227
+134 -> 130
+259 -> 258
+1186 -> 1169
+1092 -> 1111
+1293 -> 1282
+260 -> 256
+254 -> 250
+1198 -> 1181
+1222 -> 1207
+1128 -> 1156
+456 -> 478
+1279 -> 1294
+265 -> 280
+1098 -> 1117
+1285 -> 1300
+1342 -> 1315
+1291 -> 1306
+72 -> 67
+90 -> 85
+417 -> 416
+244 -> 229
+84 -> 79
+78 -> 73
+68 -> 64
+1365 -> 1360
+783 -> 784
+1221 -> 1210
+128 -> 124
+10 -> 9
+59 -> 51
+1234 -> 1245
+640 -> 617
+862 -> 834
+211 -> 226
+40 -> 39
+98 -> 94
+22 -> 21
+411 -> 378
+16 -> 15
+238 -> 242
+232 -> 217
+1162 -> 1134
+46 -> 45
+34 -> 33
+80 -> 75
+110 -> 91
+62 -> 58
+1168 -> 1153
+1225 -> 1240
+1258 -> 1269
+1323 -> 1312
+856 -> 860
+1257 -> 1246
+370 -> 354
+4 -> 3
+1215 -> 1204
+481 -> 484
+376 -> 392
+775 -> 790
+86 -> 82
+88 -> 92
+534 -> 538
+394 -> 404
+1359 -> 1354
+28 -> 27
+1303 -> 1318
+122 -> 118
+1135 -> 1149
+11 -> 10
+1336 -> 1309
+68 -> 66
+528 -> 532
+1104 -> 1123
+17 -> 16
+326 -> 310
+1263 -> 1252
+1110 -> 1129
+557 -> 550
+540 -> 544
+46 -> 44
+74 -> 72
+794 -> 796
+23 -> 22
+1186 -> 1197
+271 -> 286
+487 -> 490
+1144 -> 1135
+801 -> 802
+774 -> 808
+116 -> 112
+634 -> 633
+80 -> 78
+1175 -> 1203
+1209 -> 1198
+850 -> 841
+277 -> 292
+1147 -> 1128
+1141 -> 1150
+5 -> 4
+817 -> 826
+1336 -> 1302
+1353 -> 1348
+382 -> 398
+1191 -> 1163
+843 -> 838
+1159 -> 1174
+832 -> 804
+496 -> 493
+1179 -> 1168
+283 -> 298
+555 -> 526
+1347 -> 1342
+316 -> 332
+338 -> 306
+29 -> 28
+1141 -> 1155
+1161 -> 1147
+502 -> 513
+799 -> 814
+1324 -> 1296
+52 -> 47
+844 -> 849
+65 -> 62
+1162 -> 1167
+53 -> 50
+628 -> 627
+59 -> 56
+84 -> 86
+35 -> 34
+556 -> 563
+797 -> 820
+304 -> 289
+586 -> 569
+46 -> 41
+622 -> 621
+508 -> 505
+549 -> 520
+575 -> 592
+543 -> 514
+104 -> 90
+581 -> 598
+616 -> 582
+604 -> 576
diff --git a/examples/RV12.BBS12030.fasta.probs b/examples/RV12.BBS12030.fasta.probs
new file mode 100644
index 0000000..5f32d8a
--- /dev/null
+++ b/examples/RV12.BBS12030.fasta.probs
@@ -0,0 +1,12627 @@
+; Sparse posterior probability matrix for sequences 0 and 1
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (1, 0) => 0.89986
+(0, 1) ~ (1, 0) => 0.0901648
+(0, 1) ~ (1, 1) => 0.763527
+(0, 2) ~ (1, 1) => 0.223249
+(0, 2) ~ (1, 2) => 0.66554
+(0, 3) ~ (1, 2) => 0.32216
+(0, 3) ~ (1, 3) => 0.566657
+(0, 4) ~ (1, 3) => 0.420167
+(0, 4) ~ (1, 4) => 0.348624
+(0, 5) ~ (1, 4) => 0.636536
+(0, 5) ~ (1, 5) => 0.13273
+(0, 5) ~ (1, 6) => 0.0285437
+(0, 6) ~ (1, 5) => 0.836738
+(0, 6) ~ (1, 6) => 0.0620544
+(0, 6) ~ (1, 7) => 0.0598981
+(0, 7) ~ (1, 6) => 0.87152
+(0, 7) ~ (1, 8) => 0.1194
+(0, 8) ~ (1, 7) => 0.869057
+(0, 8) ~ (1, 9) => 0.127402
+(0, 9) ~ (1, 8) => 0.861457
+(0, 9) ~ (1, 10) => 0.132766
+(0, 10) ~ (1, 9) => 0.855653
+(0, 10) ~ (1, 11) => 0.13784
+(0, 11) ~ (1, 10) => 0.849625
+(0, 11) ~ (1, 12) => 0.142508
+(0, 12) ~ (1, 11) => 0.815944
+(0, 12) ~ (1, 12) => 0.0276572
+(0, 12) ~ (1, 13) => 0.150591
+(0, 13) ~ (1, 12) => 0.782076
+(0, 13) ~ (1, 13) => 0.0518783
+(0, 13) ~ (1, 14) => 0.157371
+(0, 14) ~ (1, 13) => 0.752851
+(0, 14) ~ (1, 14) => 0.0760803
+(0, 14) ~ (1, 15) => 0.162424
+(0, 15) ~ (1, 14) => 0.728604
+(0, 15) ~ (1, 15) => 0.0958991
+(0, 15) ~ (1, 16) => 0.16695
+(0, 16) ~ (1, 15) => 0.407686
+(0, 16) ~ (1, 16) => 0.411177
+(0, 16) ~ (1, 17) => 0.107603
+(0, 17) ~ (1, 16) => 0.228637
+(0, 17) ~ (1, 17) => 0.651948
+(0, 17) ~ (1, 18) => 0.025584
+(0, 18) ~ (1, 17) => 0.0237921
+(0, 18) ~ (1, 18) => 0.943645
+(0, 18) ~ (1, 19) => 0.0117118
+(0, 19) ~ (1, 19) => 0.97949
+(0, 20) ~ (1, 20) => 0.997798
+(0, 21) ~ (1, 21) => 0.999964
+(0, 22) ~ (1, 22) => 0.999993
+(0, 23) ~ (1, 23) => 0.99998
+(0, 24) ~ (1, 24) => 0.99988
+(0, 25) ~ (1, 25) => 0.999589
+(0, 26) ~ (1, 26) => 0.999548
+(0, 27) ~ (1, 27) => 0.999611
+(0, 28) ~ (1, 28) => 0.998805
+(0, 29) ~ (1, 29) => 0.997862
+(0, 30) ~ (1, 30) => 0.997611
+(0, 31) ~ (1, 31) => 0.997352
+(0, 32) ~ (1, 32) => 0.998013
+(0, 33) ~ (1, 33) => 0.998607
+(0, 34) ~ (1, 34) => 0.999066
+(0, 35) ~ (1, 35) => 0.999166
+(0, 36) ~ (1, 36) => 0.998037
+(0, 37) ~ (1, 37) => 0.997197
+(0, 38) ~ (1, 38) => 0.996661
+(0, 39) ~ (1, 39) => 0.99736
+(0, 40) ~ (1, 40) => 0.99737
+(0, 41) ~ (1, 41) => 0.997629
+(0, 42) ~ (1, 42) => 0.999505
+(0, 43) ~ (1, 43) => 0.999097
+(0, 44) ~ (1, 44) => 0.998495
+(0, 45) ~ (1, 45) => 0.984006
+(0, 45) ~ (1, 47) => 0.0133551
+(0, 46) ~ (1, 46) => 0.955807
+(0, 46) ~ (1, 48) => 0.0364919
+(0, 47) ~ (1, 47) => 0.855012
+(0, 47) ~ (1, 48) => 0.0194927
+(0, 47) ~ (1, 49) => 0.119346
+(0, 48) ~ (1, 48) => 0.591986
+(0, 48) ~ (1, 49) => 0.0162982
+(0, 48) ~ (1, 50) => 0.382829
+(0, 49) ~ (1, 49) => 0.18099
+(0, 49) ~ (1, 50) => 0.0172235
+(0, 49) ~ (1, 51) => 0.795034
+(0, 50) ~ (1, 50) => 0.0125432
+(0, 50) ~ (1, 52) => 0.985908
+(0, 51) ~ (1, 53) => 0.99801
+(0, 52) ~ (1, 54) => 0.999877
+(0, 53) ~ (1, 55) => 0.999978
+(0, 54) ~ (1, 56) => 0.999984
+(0, 55) ~ (1, 57) => 0.999917
+(0, 56) ~ (1, 58) => 0.999684
+(0, 57) ~ (1, 59) => 0.996121
+(0, 58) ~ (1, 60) => 0.989716
+(0, 59) ~ (1, 61) => 0.909098
+(0, 59) ~ (1, 62) => 0.0895553
+(0, 60) ~ (1, 62) => 0.82865
+(0, 60) ~ (1, 63) => 0.169068
+(0, 61) ~ (1, 63) => 0.748562
+(0, 61) ~ (1, 64) => 0.248703
+(0, 62) ~ (1, 64) => 0.219225
+(0, 62) ~ (1, 65) => 0.777294
+(0, 63) ~ (1, 65) => 0.0288552
+(0, 63) ~ (1, 66) => 0.968397
+(0, 64) ~ (1, 67) => 0.991767
+(0, 65) ~ (1, 68) => 0.999785
+(0, 66) ~ (1, 69) => 0.999959
+(0, 67) ~ (1, 70) => 0.999645
+(0, 68) ~ (1, 71) => 0.999529
+(0, 69) ~ (1, 72) => 0.999584
+(0, 70) ~ (1, 73) => 0.999902
+(0, 71) ~ (1, 74) => 0.999942
+(0, 72) ~ (1, 75) => 0.999946
+(0, 73) ~ (1, 76) => 0.999794
+(0, 74) ~ (1, 77) => 0.999675
+(0, 75) ~ (1, 78) => 0.999007
+(0, 76) ~ (1, 79) => 0.981745
+(0, 77) ~ (1, 79) => 0.0119672
+(0, 77) ~ (1, 80) => 0.966108
+(0, 78) ~ (1, 80) => 0.0221349
+(0, 78) ~ (1, 81) => 0.961193
+(0, 79) ~ (1, 81) => 0.0262796
+(0, 79) ~ (1, 82) => 0.957397
+(0, 80) ~ (1, 82) => 0.0330955
+(0, 80) ~ (1, 83) => 0.938467
+(0, 81) ~ (1, 83) => 0.0521752
+(0, 81) ~ (1, 84) => 0.928304
+(0, 82) ~ (1, 84) => 0.0632947
+(0, 82) ~ (1, 85) => 0.929046
+(0, 83) ~ (1, 85) => 0.0347337
+(0, 83) ~ (1, 86) => 0.960032
+(0, 84) ~ (1, 86) => 0.0123726
+(0, 84) ~ (1, 87) => 0.983973
+(0, 85) ~ (1, 88) => 0.991948
+(0, 86) ~ (1, 89) => 0.995131
+(0, 87) ~ (1, 90) => 0.999474
+(0, 88) ~ (1, 91) => 0.999927
+(0, 89) ~ (1, 92) => 0.999782
+(0, 90) ~ (1, 93) => 0.997797
+(0, 91) ~ (1, 94) => 0.996803
+(0, 92) ~ (1, 95) => 0.995126
+(0, 93) ~ (1, 96) => 0.994351
+(0, 94) ~ (1, 97) => 0.992259
+(0, 95) ~ (1, 98) => 0.963007
+(0, 95) ~ (1, 99) => 0.0229394
+(0, 96) ~ (1, 98) => 0.0109689
+(0, 96) ~ (1, 99) => 0.944609
+(0, 96) ~ (1, 100) => 0.0358478
+(0, 97) ~ (1, 99) => 0.0146147
+(0, 97) ~ (1, 100) => 0.885341
+(0, 97) ~ (1, 101) => 0.081701
+(0, 98) ~ (1, 100) => 0.026206
+(0, 98) ~ (1, 101) => 0.814957
+(0, 98) ~ (1, 102) => 0.143989
+(0, 99) ~ (1, 101) => 0.0302855
+(0, 99) ~ (1, 102) => 0.798267
+(0, 99) ~ (1, 103) => 0.154841
+(0, 100) ~ (1, 102) => 0.0337123
+(0, 100) ~ (1, 103) => 0.799999
+(0, 100) ~ (1, 104) => 0.127588
+(0, 101) ~ (1, 103) => 0.0320211
+(0, 101) ~ (1, 104) => 0.832705
+(0, 101) ~ (1, 105) => 0.0858481
+(0, 102) ~ (1, 104) => 0.0171666
+(0, 102) ~ (1, 105) => 0.890861
+(0, 102) ~ (1, 106) => 0.0441244
+(0, 103) ~ (1, 106) => 0.95103
+(0, 104) ~ (1, 107) => 0.997753
+(0, 105) ~ (1, 108) => 0.999529
+(0, 106) ~ (1, 109) => 0.999925
+(0, 107) ~ (1, 110) => 0.999982
+(0, 108) ~ (1, 111) => 0.999952
+(0, 109) ~ (1, 112) => 0.999905
+(0, 110) ~ (1, 113) => 0.99992
+(0, 111) ~ (1, 114) => 0.99996
+(0, 112) ~ (1, 115) => 0.999976
+(0, 113) ~ (1, 116) => 0.999982
+(0, 114) ~ (1, 117) => 0.999794
+(0, 115) ~ (1, 118) => 0.998263
+(0, 116) ~ (1, 119) => 0.957666
+(0, 117) ~ (1, 119) => 0.0396389
+(0, 117) ~ (1, 120) => 0.916317
+(0, 118) ~ (1, 120) => 0.079775
+(0, 118) ~ (1, 121) => 0.911768
+(0, 119) ~ (1, 121) => 0.0764868
+(0, 119) ~ (1, 122) => 0.911401
+(0, 120) ~ (1, 122) => 0.0824834
+(0, 120) ~ (1, 123) => 0.907496
+(0, 121) ~ (1, 123) => 0.0851558
+(0, 121) ~ (1, 124) => 0.900234
+(0, 122) ~ (1, 124) => 0.0925551
+(0, 122) ~ (1, 125) => 0.905522
+(0, 123) ~ (1, 125) => 0.0165443
+(0, 123) ~ (1, 126) => 0.983043
+(0, 124) ~ (1, 127) => 0.999155
+(0, 125) ~ (1, 128) => 0.9992
+(0, 126) ~ (1, 129) => 0.994038
+(0, 127) ~ (1, 130) => 0.988902
+(0, 128) ~ (1, 131) => 0.988926
+(0, 129) ~ (1, 132) => 0.994843
+(0, 130) ~ (1, 133) => 0.998442
+(0, 131) ~ (1, 134) => 0.99075
+(0, 132) ~ (1, 135) => 0.990016
+(0, 133) ~ (1, 136) => 0.991062
+(0, 134) ~ (1, 137) => 0.999256
+(0, 135) ~ (1, 138) => 0.999737
+(0, 136) ~ (1, 139) => 0.999897
+(0, 137) ~ (1, 140) => 0.999975
+(0, 138) ~ (1, 141) => 0.999998
+(0, 139) ~ (1, 142) => 0.999999
+(0, 140) ~ (1, 143) => 0.999992
+(0, 141) ~ (1, 144) => 0.999962
+(0, 142) ~ (1, 145) => 0.999948
+(0, 143) ~ (1, 146) => 0.999968
+(0, 144) ~ (1, 147) => 0.999994
+(0, 145) ~ (1, 148) => 0.999992
+(0, 146) ~ (1, 149) => 0.999958
+(0, 147) ~ (1, 150) => 0.999411
+(0, 148) ~ (1, 151) => 0.999232
+(0, 149) ~ (1, 152) => 0.99941
+(0, 150) ~ (1, 153) => 0.999824
+(0, 151) ~ (1, 154) => 0.999936
+(0, 152) ~ (1, 155) => 0.999733
+(0, 153) ~ (1, 156) => 0.999554
+(0, 154) ~ (1, 157) => 0.999387
+(0, 155) ~ (1, 158) => 0.999133
+(0, 156) ~ (1, 159) => 0.996898
+(0, 157) ~ (1, 160) => 0.994502
+(0, 158) ~ (1, 161) => 0.993165
+(0, 159) ~ (1, 162) => 0.993092
+(0, 160) ~ (1, 163) => 0.993472
+(0, 161) ~ (1, 164) => 0.995053
+(0, 162) ~ (1, 165) => 0.997151
+(0, 163) ~ (1, 166) => 0.997662
+(0, 164) ~ (1, 167) => 0.997914
+(0, 165) ~ (1, 168) => 0.998867
+(0, 166) ~ (1, 169) => 0.998422
+(0, 167) ~ (1, 170) => 0.99797
+(0, 168) ~ (1, 171) => 0.998112
+(0, 169) ~ (1, 172) => 0.998082
+(0, 170) ~ (1, 173) => 0.997326
+(0, 171) ~ (1, 174) => 0.996704
+(0, 172) ~ (1, 175) => 0.994489
+(0, 173) ~ (1, 176) => 0.992809
+(0, 174) ~ (1, 177) => 0.994191
+(0, 175) ~ (1, 178) => 0.994731
+(0, 176) ~ (1, 179) => 0.997462
+(0, 177) ~ (1, 180) => 0.999688
+(0, 178) ~ (1, 181) => 0.999938
+(0, 179) ~ (1, 182) => 0.998343
+(0, 180) ~ (1, 183) => 0.996774
+(0, 181) ~ (1, 184) => 0.955323
+(0, 182) ~ (1, 184) => 0.0412435
+(0, 182) ~ (1, 185) => 0.926103
+(0, 183) ~ (1, 185) => 0.0672819
+(0, 183) ~ (1, 186) => 0.879701
+(0, 183) ~ (1, 187) => 0.0135791
+(0, 184) ~ (1, 186) => 0.105123
+(0, 184) ~ (1, 187) => 0.590665
+(0, 184) ~ (1, 188) => 0.110689
+(0, 184) ~ (1, 189) => 0.0121664
+(0, 185) ~ (1, 187) => 0.283092
+(0, 185) ~ (1, 188) => 0.448533
+(0, 185) ~ (1, 189) => 0.198462
+(0, 185) ~ (1, 190) => 0.0371411
+(0, 186) ~ (1, 188) => 0.299401
+(0, 186) ~ (1, 189) => 0.281772
+(0, 186) ~ (1, 190) => 0.270462
+(0, 186) ~ (1, 191) => 0.114133
+(0, 187) ~ (1, 189) => 0.316976
+(0, 187) ~ (1, 190) => 0.180498
+(0, 187) ~ (1, 191) => 0.277852
+(0, 187) ~ (1, 192) => 0.188208
+(0, 188) ~ (1, 190) => 0.33704
+(0, 188) ~ (1, 191) => 0.137804
+(0, 188) ~ (1, 192) => 0.228958
+(0, 188) ~ (1, 193) => 0.207168
+(0, 189) ~ (1, 191) => 0.380007
+(0, 189) ~ (1, 192) => 0.121588
+(0, 189) ~ (1, 193) => 0.199134
+(0, 189) ~ (1, 194) => 0.226222
+(0, 190) ~ (1, 192) => 0.427224
+(0, 190) ~ (1, 193) => 0.102048
+(0, 190) ~ (1, 194) => 0.148625
+(0, 190) ~ (1, 195) => 0.247372
+(0, 191) ~ (1, 193) => 0.46187
+(0, 191) ~ (1, 194) => 0.059552
+(0, 191) ~ (1, 195) => 0.0348289
+(0, 191) ~ (1, 196) => 0.247228
+(0, 192) ~ (1, 194) => 0.534345
+(0, 192) ~ (1, 196) => 0.027454
+(0, 192) ~ (1, 197) => 0.233477
+(0, 193) ~ (1, 195) => 0.701222
+(0, 193) ~ (1, 197) => 0.012185
+(0, 193) ~ (1, 198) => 0.207691
+(0, 194) ~ (1, 196) => 0.716232
+(0, 194) ~ (1, 199) => 0.0298545
+(0, 195) ~ (1, 197) => 0.74629
+(0, 195) ~ (1, 200) => 0.0126273
+(0, 196) ~ (1, 198) => 0.782822
+(0, 197) ~ (1, 199) => 0.955678
+(0, 198) ~ (1, 200) => 0.979821
+(0, 199) ~ (1, 201) => 0.98912
+(0, 200) ~ (1, 202) => 0.991518
+(0, 201) ~ (1, 203) => 0.994707
+(0, 202) ~ (1, 204) => 0.99691
+(0, 203) ~ (1, 205) => 0.996252
+(0, 204) ~ (1, 206) => 0.996681
+(0, 205) ~ (1, 207) => 0.997704
+(0, 206) ~ (1, 208) => 0.999451
+(0, 207) ~ (1, 209) => 0.998695
+(0, 208) ~ (1, 210) => 0.99611
+(0, 209) ~ (1, 211) => 0.989077
+(0, 210) ~ (1, 212) => 0.983429
+(0, 211) ~ (1, 212) => 0.0151349
+(0, 211) ~ (1, 213) => 0.983655
+(0, 212) ~ (1, 214) => 0.991641
+(0, 213) ~ (1, 215) => 0.992954
+(0, 214) ~ (1, 216) => 0.988114
+(0, 215) ~ (1, 217) => 0.951903
+(0, 216) ~ (1, 217) => 0.0378741
+(0, 216) ~ (1, 218) => 0.441162
+(0, 217) ~ (1, 218) => 0.542396
+(0, 217) ~ (1, 219) => 0.334715
+(0, 218) ~ (1, 218) => 0.0112233
+(0, 218) ~ (1, 219) => 0.648809
+(0, 218) ~ (1, 220) => 0.212576
+(0, 219) ~ (1, 220) => 0.772227
+(0, 219) ~ (1, 221) => 0.109443
+(0, 220) ~ (1, 221) => 0.879386
+(0, 220) ~ (1, 222) => 0.0374198
+(0, 221) ~ (1, 222) => 0.954372
+(0, 222) ~ (1, 223) => 0.992936
+(0, 223) ~ (1, 224) => 0.998152
+(0, 224) ~ (1, 225) => 0.999938
+(0, 225) ~ (1, 226) => 0.999991
+(0, 226) ~ (1, 227) => 0.999935
+(0, 227) ~ (1, 228) => 0.999265
+(0, 228) ~ (1, 229) => 0.98897
+(0, 229) ~ (1, 229) => 0.0105571
+(0, 229) ~ (1, 230) => 0.978965
+(0, 230) ~ (1, 230) => 0.020106
+(0, 230) ~ (1, 231) => 0.978905
+(0, 231) ~ (1, 231) => 0.0130771
+(0, 231) ~ (1, 232) => 0.98667
+(0, 232) ~ (1, 233) => 0.994388
+
+; gap posteriors
+(0, 0) ~ (1, -1) => 0.10014
+(0, 1) ~ (1, -1) => 0.146309
+(0, 2) ~ (1, -1) => 0.111212
+(0, 3) ~ (1, -1) => 0.111183
+(0, 4) ~ (1, -1) => 0.231209
+(0, 5) ~ (1, -1) => 0.20219
+(0, 6) ~ (1, -1) => 0.0413098
+(0, 7) ~ (1, -1) => 0.00907975
+(0, 8) ~ (1, -1) => 0.00354095
+(0, 9) ~ (1, -1) => 0.00577657
+(0, 10) ~ (1, -1) => 0.00650714
+(0, 11) ~ (1, -1) => 0.00786735
+(0, 12) ~ (1, -1) => 0.00580733
+(0, 13) ~ (1, -1) => 0.00867404
+(0, 14) ~ (1, -1) => 0.00864452
+(0, 15) ~ (1, -1) => 0.00854623
+(0, 16) ~ (1, -1) => 0.0735349
+(0, 17) ~ (1, -1) => 0.0938304
+(0, 18) ~ (1, -1) => 0.0208514
+(0, 19) ~ (1, -1) => 0.0205101
+(0, 20) ~ (1, -1) => 0.00220186
+(0, 21) ~ (1, -1) => 0.0001
+(0, 22) ~ (1, -1) => 0.0001
+(0, 23) ~ (1, -1) => 0.0001
+(0, 24) ~ (1, -1) => 0.000120163
+(0, 25) ~ (1, -1) => 0.000410736
+(0, 26) ~ (1, -1) => 0.000452399
+(0, 27) ~ (1, -1) => 0.000389159
+(0, 28) ~ (1, -1) => 0.00119466
+(0, 29) ~ (1, -1) => 0.0021382
+(0, 30) ~ (1, -1) => 0.00238943
+(0, 31) ~ (1, -1) => 0.0026477
+(0, 32) ~ (1, -1) => 0.00198716
+(0, 33) ~ (1, -1) => 0.00139296
+(0, 34) ~ (1, -1) => 0.000933647
+(0, 35) ~ (1, -1) => 0.00083369
+(0, 36) ~ (1, -1) => 0.00196308
+(0, 37) ~ (1, -1) => 0.00280279
+(0, 38) ~ (1, -1) => 0.00333869
+(0, 39) ~ (1, -1) => 0.00263965
+(0, 40) ~ (1, -1) => 0.00263011
+(0, 41) ~ (1, -1) => 0.00237125
+(0, 42) ~ (1, -1) => 0.000494719
+(0, 43) ~ (1, -1) => 0.00090313
+(0, 44) ~ (1, -1) => 0.0015046
+(0, 45) ~ (1, -1) => 0.00263894
+(0, 46) ~ (1, -1) => 0.00770151
+(0, 47) ~ (1, -1) => 0.00614866
+(0, 48) ~ (1, -1) => 0.00888637
+(0, 49) ~ (1, -1) => 0.00675267
+(0, 50) ~ (1, -1) => 0.00154907
+(0, 51) ~ (1, -1) => 0.00199014
+(0, 52) ~ (1, -1) => 0.000123322
+(0, 53) ~ (1, -1) => 0.0001
+(0, 54) ~ (1, -1) => 0.0001
+(0, 55) ~ (1, -1) => 0.0001
+(0, 56) ~ (1, -1) => 0.000316441
+(0, 57) ~ (1, -1) => 0.00387931
+(0, 58) ~ (1, -1) => 0.0102841
+(0, 59) ~ (1, -1) => 0.00134643
+(0, 60) ~ (1, -1) => 0.00228235
+(0, 61) ~ (1, -1) => 0.0027348
+(0, 62) ~ (1, -1) => 0.00348157
+(0, 63) ~ (1, -1) => 0.00274771
+(0, 64) ~ (1, -1) => 0.00823337
+(0, 65) ~ (1, -1) => 0.000215173
+(0, 66) ~ (1, -1) => 0.0001
+(0, 67) ~ (1, -1) => 0.000354707
+(0, 68) ~ (1, -1) => 0.000471473
+(0, 69) ~ (1, -1) => 0.000415862
+(0, 70) ~ (1, -1) => 0.0001
+(0, 71) ~ (1, -1) => 0.0001
+(0, 72) ~ (1, -1) => 0.0001
+(0, 73) ~ (1, -1) => 0.000205636
+(0, 74) ~ (1, -1) => 0.000324786
+(0, 75) ~ (1, -1) => 0.000992835
+(0, 76) ~ (1, -1) => 0.0182546
+(0, 77) ~ (1, -1) => 0.0219248
+(0, 78) ~ (1, -1) => 0.0166726
+(0, 79) ~ (1, -1) => 0.0163233
+(0, 80) ~ (1, -1) => 0.028438
+(0, 81) ~ (1, -1) => 0.019521
+(0, 82) ~ (1, -1) => 0.0076592
+(0, 83) ~ (1, -1) => 0.00523466
+(0, 84) ~ (1, -1) => 0.00365406
+(0, 85) ~ (1, -1) => 0.00805235
+(0, 86) ~ (1, -1) => 0.0048694
+(0, 87) ~ (1, -1) => 0.000526488
+(0, 88) ~ (1, -1) => 0.0001
+(0, 89) ~ (1, -1) => 0.000217736
+(0, 90) ~ (1, -1) => 0.00220287
+(0, 91) ~ (1, -1) => 0.00319672
+(0, 92) ~ (1, -1) => 0.00487357
+(0, 93) ~ (1, -1) => 0.00564867
+(0, 94) ~ (1, -1) => 0.0077408
+(0, 95) ~ (1, -1) => 0.014054
+(0, 96) ~ (1, -1) => 0.00857422
+(0, 97) ~ (1, -1) => 0.0183429
+(0, 98) ~ (1, -1) => 0.0148479
+(0, 99) ~ (1, -1) => 0.0166062
+(0, 100) ~ (1, -1) => 0.0387008
+(0, 101) ~ (1, -1) => 0.0494262
+(0, 102) ~ (1, -1) => 0.0478482
+(0, 103) ~ (1, -1) => 0.0489703
+(0, 104) ~ (1, -1) => 0.0022471
+(0, 105) ~ (1, -1) => 0.000470698
+(0, 106) ~ (1, -1) => 0.0001
+(0, 107) ~ (1, -1) => 0.0001
+(0, 108) ~ (1, -1) => 0.0001
+(0, 109) ~ (1, -1) => 0.0001
+(0, 110) ~ (1, -1) => 0.0001
+(0, 111) ~ (1, -1) => 0.0001
+(0, 112) ~ (1, -1) => 0.0001
+(0, 113) ~ (1, -1) => 0.0001
+(0, 114) ~ (1, -1) => 0.00020647
+(0, 115) ~ (1, -1) => 0.00173736
+(0, 116) ~ (1, -1) => 0.0423336
+(0, 117) ~ (1, -1) => 0.0440441
+(0, 118) ~ (1, -1) => 0.00845748
+(0, 119) ~ (1, -1) => 0.0121118
+(0, 120) ~ (1, -1) => 0.0100206
+(0, 121) ~ (1, -1) => 0.0146102
+(0, 122) ~ (1, -1) => 0.00192297
+(0, 123) ~ (1, -1) => 0.00041312
+(0, 124) ~ (1, -1) => 0.000845373
+(0, 125) ~ (1, -1) => 0.000799775
+(0, 126) ~ (1, -1) => 0.00596184
+(0, 127) ~ (1, -1) => 0.0110984
+(0, 128) ~ (1, -1) => 0.0110739
+(0, 129) ~ (1, -1) => 0.00515676
+(0, 130) ~ (1, -1) => 0.0015583
+(0, 131) ~ (1, -1) => 0.00924969
+(0, 132) ~ (1, -1) => 0.00998437
+(0, 133) ~ (1, -1) => 0.00893778
+(0, 134) ~ (1, -1) => 0.000743985
+(0, 135) ~ (1, -1) => 0.000263393
+(0, 136) ~ (1, -1) => 0.000102758
+(0, 137) ~ (1, -1) => 0.0001
+(0, 138) ~ (1, -1) => 0.0001
+(0, 139) ~ (1, -1) => 0.0001
+(0, 140) ~ (1, -1) => 0.0001
+(0, 141) ~ (1, -1) => 0.0001
+(0, 142) ~ (1, -1) => 0.0001
+(0, 143) ~ (1, -1) => 0.0001
+(0, 144) ~ (1, -1) => 0.0001
+(0, 145) ~ (1, -1) => 0.0001
+(0, 146) ~ (1, -1) => 0.0001
+(0, 147) ~ (1, -1) => 0.000588715
+(0, 148) ~ (1, -1) => 0.000768244
+(0, 149) ~ (1, -1) => 0.000590444
+(0, 150) ~ (1, -1) => 0.000175655
+(0, 151) ~ (1, -1) => 0.0001
+(0, 152) ~ (1, -1) => 0.000267088
+(0, 153) ~ (1, -1) => 0.00044632
+(0, 154) ~ (1, -1) => 0.000612974
+(0, 155) ~ (1, -1) => 0.000867426
+(0, 156) ~ (1, -1) => 0.00310183
+(0, 157) ~ (1, -1) => 0.00549775
+(0, 158) ~ (1, -1) => 0.00683546
+(0, 159) ~ (1, -1) => 0.00690812
+(0, 160) ~ (1, -1) => 0.00652766
+(0, 161) ~ (1, -1) => 0.00494701
+(0, 162) ~ (1, -1) => 0.0028494
+(0, 163) ~ (1, -1) => 0.00233835
+(0, 164) ~ (1, -1) => 0.00208575
+(0, 165) ~ (1, -1) => 0.00113332
+(0, 166) ~ (1, -1) => 0.00157809
+(0, 167) ~ (1, -1) => 0.0020299
+(0, 168) ~ (1, -1) => 0.00188786
+(0, 169) ~ (1, -1) => 0.0019179
+(0, 170) ~ (1, -1) => 0.00267404
+(0, 171) ~ (1, -1) => 0.00329608
+(0, 172) ~ (1, -1) => 0.00551105
+(0, 173) ~ (1, -1) => 0.00719106
+(0, 174) ~ (1, -1) => 0.00580871
+(0, 175) ~ (1, -1) => 0.00526905
+(0, 176) ~ (1, -1) => 0.00253832
+(0, 177) ~ (1, -1) => 0.000311613
+(0, 178) ~ (1, -1) => 0.0001
+(0, 179) ~ (1, -1) => 0.00165713
+(0, 180) ~ (1, -1) => 0.00322604
+(0, 181) ~ (1, -1) => 0.0446772
+(0, 182) ~ (1, -1) => 0.0326536
+(0, 183) ~ (1, -1) => 0.0394381
+(0, 184) ~ (1, -1) => 0.181356
+(0, 185) ~ (1, -1) => 0.0327724
+(0, 186) ~ (1, -1) => 0.0342316
+(0, 187) ~ (1, -1) => 0.0364658
+(0, 188) ~ (1, -1) => 0.0890302
+(0, 189) ~ (1, -1) => 0.0730489
+(0, 190) ~ (1, -1) => 0.0747308
+(0, 191) ~ (1, -1) => 0.196521
+(0, 192) ~ (1, -1) => 0.204724
+(0, 193) ~ (1, -1) => 0.0789018
+(0, 194) ~ (1, -1) => 0.253913
+(0, 195) ~ (1, -1) => 0.241083
+(0, 196) ~ (1, -1) => 0.217178
+(0, 197) ~ (1, -1) => 0.0443221
+(0, 198) ~ (1, -1) => 0.0201795
+(0, 199) ~ (1, -1) => 0.0108798
+(0, 200) ~ (1, -1) => 0.00848156
+(0, 201) ~ (1, -1) => 0.00529325
+(0, 202) ~ (1, -1) => 0.00308996
+(0, 203) ~ (1, -1) => 0.00374812
+(0, 204) ~ (1, -1) => 0.00331867
+(0, 205) ~ (1, -1) => 0.00229561
+(0, 206) ~ (1, -1) => 0.00054878
+(0, 207) ~ (1, -1) => 0.00130475
+(0, 208) ~ (1, -1) => 0.0038898
+(0, 209) ~ (1, -1) => 0.0109231
+(0, 210) ~ (1, -1) => 0.0165706
+(0, 211) ~ (1, -1) => 0.00121051
+(0, 212) ~ (1, -1) => 0.00835872
+(0, 213) ~ (1, -1) => 0.00704634
+(0, 214) ~ (1, -1) => 0.0118859
+(0, 215) ~ (1, -1) => 0.0480969
+(0, 216) ~ (1, -1) => 0.520964
+(0, 217) ~ (1, -1) => 0.122889
+(0, 218) ~ (1, -1) => 0.127392
+(0, 219) ~ (1, -1) => 0.11833
+(0, 220) ~ (1, -1) => 0.0831937
+(0, 221) ~ (1, -1) => 0.0456284
+(0, 222) ~ (1, -1) => 0.00706357
+(0, 223) ~ (1, -1) => 0.00184834
+(0, 224) ~ (1, -1) => 0.0001
+(0, 225) ~ (1, -1) => 0.0001
+(0, 226) ~ (1, -1) => 0.0001
+(0, 227) ~ (1, -1) => 0.000734568
+(0, 228) ~ (1, -1) => 0.0110296
+(0, 229) ~ (1, -1) => 0.0104784
+(0, 230) ~ (1, -1) => 0.000988483
+(0, 231) ~ (1, -1) => 0.000252426
+(0, 232) ~ (1, -1) => 0.00561154
+
+(0, -1) ~ (1, 0) => 0.00997552
+(0, -1) ~ (1, 1) => 0.0132247
+(0, -1) ~ (1, 2) => 0.0123008
+(0, -1) ~ (1, 3) => 0.0131763
+(0, -1) ~ (1, 4) => 0.0148393
+(0, -1) ~ (1, 5) => 0.0305325
+(0, -1) ~ (1, 6) => 0.0378817
+(0, -1) ~ (1, 7) => 0.0710449
+(0, -1) ~ (1, 8) => 0.0191429
+(0, -1) ~ (1, 9) => 0.0169454
+(0, -1) ~ (1, 10) => 0.0176087
+(0, -1) ~ (1, 11) => 0.0462157
+(0, -1) ~ (1, 12) => 0.0477588
+(0, -1) ~ (1, 13) => 0.0446793
+(0, -1) ~ (1, 14) => 0.037944
+(0, -1) ~ (1, 15) => 0.333991
+(0, -1) ~ (1, 16) => 0.193235
+(0, -1) ~ (1, 17) => 0.216657
+(0, -1) ~ (1, 18) => 0.0307713
+(0, -1) ~ (1, 19) => 0.0087983
+(0, -1) ~ (1, 20) => 0.00220186
+(0, -1) ~ (1, 21) => 0.0001
+(0, -1) ~ (1, 22) => 0.0001
+(0, -1) ~ (1, 23) => 0.0001
+(0, -1) ~ (1, 24) => 0.000120163
+(0, -1) ~ (1, 25) => 0.000410736
+(0, -1) ~ (1, 26) => 0.000452399
+(0, -1) ~ (1, 27) => 0.000389159
+(0, -1) ~ (1, 28) => 0.00119466
+(0, -1) ~ (1, 29) => 0.0021382
+(0, -1) ~ (1, 30) => 0.00238943
+(0, -1) ~ (1, 31) => 0.0026477
+(0, -1) ~ (1, 32) => 0.00198716
+(0, -1) ~ (1, 33) => 0.00139296
+(0, -1) ~ (1, 34) => 0.000933647
+(0, -1) ~ (1, 35) => 0.00083369
+(0, -1) ~ (1, 36) => 0.00196308
+(0, -1) ~ (1, 37) => 0.00280279
+(0, -1) ~ (1, 38) => 0.00333869
+(0, -1) ~ (1, 39) => 0.00263965
+(0, -1) ~ (1, 40) => 0.00263011
+(0, -1) ~ (1, 41) => 0.00237125
+(0, -1) ~ (1, 42) => 0.000494719
+(0, -1) ~ (1, 43) => 0.00090313
+(0, -1) ~ (1, 44) => 0.0015046
+(0, -1) ~ (1, 45) => 0.015994
+(0, -1) ~ (1, 46) => 0.0441934
+(0, -1) ~ (1, 47) => 0.131633
+(0, -1) ~ (1, 48) => 0.352029
+(0, -1) ~ (1, 49) => 0.683366
+(0, -1) ~ (1, 50) => 0.587404
+(0, -1) ~ (1, 51) => 0.204966
+(0, -1) ~ (1, 52) => 0.0140923
+(0, -1) ~ (1, 53) => 0.00199014
+(0, -1) ~ (1, 54) => 0.000123322
+(0, -1) ~ (1, 55) => 0.0001
+(0, -1) ~ (1, 56) => 0.0001
+(0, -1) ~ (1, 57) => 0.0001
+(0, -1) ~ (1, 58) => 0.000316441
+(0, -1) ~ (1, 59) => 0.00387931
+(0, -1) ~ (1, 60) => 0.0102841
+(0, -1) ~ (1, 61) => 0.0909017
+(0, -1) ~ (1, 62) => 0.081795
+(0, -1) ~ (1, 63) => 0.0823697
+(0, -1) ~ (1, 64) => 0.532072
+(0, -1) ~ (1, 65) => 0.193851
+(0, -1) ~ (1, 66) => 0.0316029
+(0, -1) ~ (1, 67) => 0.00823337
+(0, -1) ~ (1, 68) => 0.000215173
+(0, -1) ~ (1, 69) => 0.0001
+(0, -1) ~ (1, 70) => 0.000354707
+(0, -1) ~ (1, 71) => 0.000471473
+(0, -1) ~ (1, 72) => 0.000415862
+(0, -1) ~ (1, 73) => 0.0001
+(0, -1) ~ (1, 74) => 0.0001
+(0, -1) ~ (1, 75) => 0.0001
+(0, -1) ~ (1, 76) => 0.000205636
+(0, -1) ~ (1, 77) => 0.000324786
+(0, -1) ~ (1, 78) => 0.000992835
+(0, -1) ~ (1, 79) => 0.00628748
+(0, -1) ~ (1, 80) => 0.0117571
+(0, -1) ~ (1, 81) => 0.0125278
+(0, -1) ~ (1, 82) => 0.00950738
+(0, -1) ~ (1, 83) => 0.00935825
+(0, -1) ~ (1, 84) => 0.00840153
+(0, -1) ~ (1, 85) => 0.0362202
+(0, -1) ~ (1, 86) => 0.0275958
+(0, -1) ~ (1, 87) => 0.0160266
+(0, -1) ~ (1, 88) => 0.00805235
+(0, -1) ~ (1, 89) => 0.0048694
+(0, -1) ~ (1, 90) => 0.000526488
+(0, -1) ~ (1, 91) => 0.0001
+(0, -1) ~ (1, 92) => 0.000217736
+(0, -1) ~ (1, 93) => 0.00220287
+(0, -1) ~ (1, 94) => 0.00319672
+(0, -1) ~ (1, 95) => 0.00487357
+(0, -1) ~ (1, 96) => 0.00564867
+(0, -1) ~ (1, 97) => 0.0077408
+(0, -1) ~ (1, 98) => 0.0260246
+(0, -1) ~ (1, 99) => 0.0178368
+(0, -1) ~ (1, 100) => 0.052605
+(0, -1) ~ (1, 101) => 0.0730563
+(0, -1) ~ (1, 102) => 0.0240318
+(0, -1) ~ (1, 103) => 0.0131384
+(0, -1) ~ (1, 104) => 0.022541
+(0, -1) ~ (1, 105) => 0.0232911
+(0, -1) ~ (1, 106) => 0.00484586
+(0, -1) ~ (1, 107) => 0.0022471
+(0, -1) ~ (1, 108) => 0.000470698
+(0, -1) ~ (1, 109) => 0.0001
+(0, -1) ~ (1, 110) => 0.0001
+(0, -1) ~ (1, 111) => 0.0001
+(0, -1) ~ (1, 112) => 0.0001
+(0, -1) ~ (1, 113) => 0.0001
+(0, -1) ~ (1, 114) => 0.0001
+(0, -1) ~ (1, 115) => 0.0001
+(0, -1) ~ (1, 116) => 0.0001
+(0, -1) ~ (1, 117) => 0.00020647
+(0, -1) ~ (1, 118) => 0.00173736
+(0, -1) ~ (1, 119) => 0.00269475
+(0, -1) ~ (1, 120) => 0.00390804
+(0, -1) ~ (1, 121) => 0.0117457
+(0, -1) ~ (1, 122) => 0.00611517
+(0, -1) ~ (1, 123) => 0.00734827
+(0, -1) ~ (1, 124) => 0.00721081
+(0, -1) ~ (1, 125) => 0.0779338
+(0, -1) ~ (1, 126) => 0.0169574
+(0, -1) ~ (1, 127) => 0.000845373
+(0, -1) ~ (1, 128) => 0.000799775
+(0, -1) ~ (1, 129) => 0.00596184
+(0, -1) ~ (1, 130) => 0.0110984
+(0, -1) ~ (1, 131) => 0.0110739
+(0, -1) ~ (1, 132) => 0.00515676
+(0, -1) ~ (1, 133) => 0.0015583
+(0, -1) ~ (1, 134) => 0.00924969
+(0, -1) ~ (1, 135) => 0.00998437
+(0, -1) ~ (1, 136) => 0.00893778
+(0, -1) ~ (1, 137) => 0.000743985
+(0, -1) ~ (1, 138) => 0.000263393
+(0, -1) ~ (1, 139) => 0.000102758
+(0, -1) ~ (1, 140) => 0.0001
+(0, -1) ~ (1, 141) => 0.0001
+(0, -1) ~ (1, 142) => 0.0001
+(0, -1) ~ (1, 143) => 0.0001
+(0, -1) ~ (1, 144) => 0.0001
+(0, -1) ~ (1, 145) => 0.0001
+(0, -1) ~ (1, 146) => 0.0001
+(0, -1) ~ (1, 147) => 0.0001
+(0, -1) ~ (1, 148) => 0.0001
+(0, -1) ~ (1, 149) => 0.0001
+(0, -1) ~ (1, 150) => 0.000588715
+(0, -1) ~ (1, 151) => 0.000768244
+(0, -1) ~ (1, 152) => 0.000590444
+(0, -1) ~ (1, 153) => 0.000175655
+(0, -1) ~ (1, 154) => 0.0001
+(0, -1) ~ (1, 155) => 0.000267088
+(0, -1) ~ (1, 156) => 0.00044632
+(0, -1) ~ (1, 157) => 0.000612974
+(0, -1) ~ (1, 158) => 0.000867426
+(0, -1) ~ (1, 159) => 0.00310183
+(0, -1) ~ (1, 160) => 0.00549775
+(0, -1) ~ (1, 161) => 0.00683546
+(0, -1) ~ (1, 162) => 0.00690812
+(0, -1) ~ (1, 163) => 0.00652766
+(0, -1) ~ (1, 164) => 0.00494701
+(0, -1) ~ (1, 165) => 0.0028494
+(0, -1) ~ (1, 166) => 0.00233835
+(0, -1) ~ (1, 167) => 0.00208575
+(0, -1) ~ (1, 168) => 0.00113332
+(0, -1) ~ (1, 169) => 0.00157809
+(0, -1) ~ (1, 170) => 0.0020299
+(0, -1) ~ (1, 171) => 0.00188786
+(0, -1) ~ (1, 172) => 0.0019179
+(0, -1) ~ (1, 173) => 0.00267404
+(0, -1) ~ (1, 174) => 0.00329608
+(0, -1) ~ (1, 175) => 0.00551105
+(0, -1) ~ (1, 176) => 0.00719106
+(0, -1) ~ (1, 177) => 0.00580871
+(0, -1) ~ (1, 178) => 0.00526905
+(0, -1) ~ (1, 179) => 0.00253832
+(0, -1) ~ (1, 180) => 0.000311613
+(0, -1) ~ (1, 181) => 0.0001
+(0, -1) ~ (1, 182) => 0.00165713
+(0, -1) ~ (1, 183) => 0.00322604
+(0, -1) ~ (1, 184) => 0.00343365
+(0, -1) ~ (1, 185) => 0.00661527
+(0, -1) ~ (1, 186) => 0.0151756
+(0, -1) ~ (1, 187) => 0.112665
+(0, -1) ~ (1, 188) => 0.141377
+(0, -1) ~ (1, 189) => 0.190624
+(0, -1) ~ (1, 190) => 0.174859
+(0, -1) ~ (1, 191) => 0.0902042
+(0, -1) ~ (1, 192) => 0.0340222
+(0, -1) ~ (1, 193) => 0.0297794
+(0, -1) ~ (1, 194) => 0.031256
+(0, -1) ~ (1, 195) => 0.0165769
+(0, -1) ~ (1, 196) => 0.00908566
+(0, -1) ~ (1, 197) => 0.00804824
+(0, -1) ~ (1, 198) => 0.00948673
+(0, -1) ~ (1, 199) => 0.0144676
+(0, -1) ~ (1, 200) => 0.00755221
+(0, -1) ~ (1, 201) => 0.0108798
+(0, -1) ~ (1, 202) => 0.00848156
+(0, -1) ~ (1, 203) => 0.00529325
+(0, -1) ~ (1, 204) => 0.00308996
+(0, -1) ~ (1, 205) => 0.00374812
+(0, -1) ~ (1, 206) => 0.00331867
+(0, -1) ~ (1, 207) => 0.00229561
+(0, -1) ~ (1, 208) => 0.00054878
+(0, -1) ~ (1, 209) => 0.00130475
+(0, -1) ~ (1, 210) => 0.0038898
+(0, -1) ~ (1, 211) => 0.0109231
+(0, -1) ~ (1, 212) => 0.00143566
+(0, -1) ~ (1, 213) => 0.0163454
+(0, -1) ~ (1, 214) => 0.00835872
+(0, -1) ~ (1, 215) => 0.00704634
+(0, -1) ~ (1, 216) => 0.0118859
+(0, -1) ~ (1, 217) => 0.0102228
+(0, -1) ~ (1, 218) => 0.00521811
+(0, -1) ~ (1, 219) => 0.0164766
+(0, -1) ~ (1, 220) => 0.0151965
+(0, -1) ~ (1, 221) => 0.0111705
+(0, -1) ~ (1, 222) => 0.00820863
+(0, -1) ~ (1, 223) => 0.00706357
+(0, -1) ~ (1, 224) => 0.00184834
+(0, -1) ~ (1, 225) => 0.0001
+(0, -1) ~ (1, 226) => 0.0001
+(0, -1) ~ (1, 227) => 0.0001
+(0, -1) ~ (1, 228) => 0.000734568
+(0, -1) ~ (1, 229) => 0.000472467
+(0, -1) ~ (1, 230) => 0.00092946
+(0, -1) ~ (1, 231) => 0.00801743
+(0, -1) ~ (1, 232) => 0.0133295
+(0, -1) ~ (1, 233) => 0.00561154
+
+; Sparse posterior probability matrix for sequences 0 and 2
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (2, 0) => 0.983607
+(0, 1) ~ (2, 0) => 0.0128121
+(0, 1) ~ (2, 1) => 0.962194
+(0, 2) ~ (2, 1) => 0.0319362
+(0, 2) ~ (2, 2) => 0.952387
+(0, 3) ~ (2, 2) => 0.0397051
+(0, 3) ~ (2, 3) => 0.941118
+(0, 4) ~ (2, 3) => 0.0474095
+(0, 4) ~ (2, 4) => 0.918483
+(0, 5) ~ (2, 4) => 0.0645879
+(0, 5) ~ (2, 5) => 0.897614
+(0, 6) ~ (2, 5) => 0.0811618
+(0, 6) ~ (2, 6) => 0.855541
+(0, 7) ~ (2, 6) => 0.120507
+(0, 7) ~ (2, 7) => 0.846589
+(0, 7) ~ (2, 9) => 0.0104856
+(0, 8) ~ (2, 7) => 0.122328
+(0, 8) ~ (2, 8) => 0.8438
+(0, 8) ~ (2, 10) => 0.0127542
+(0, 9) ~ (2, 8) => 0.114622
+(0, 9) ~ (2, 9) => 0.847883
+(0, 9) ~ (2, 11) => 0.0134658
+(0, 10) ~ (2, 9) => 0.0605391
+(0, 10) ~ (2, 10) => 0.881439
+(0, 10) ~ (2, 12) => 0.0171103
+(0, 10) ~ (2, 13) => 0.0125936
+(0, 10) ~ (2, 14) => 0.0111072
+(0, 11) ~ (2, 10) => 0.031585
+(0, 11) ~ (2, 11) => 0.891644
+(0, 11) ~ (2, 13) => 0.0189395
+(0, 11) ~ (2, 14) => 0.0215229
+(0, 11) ~ (2, 15) => 0.0178301
+(0, 12) ~ (2, 11) => 0.0239857
+(0, 12) ~ (2, 12) => 0.868108
+(0, 12) ~ (2, 14) => 0.0149805
+(0, 12) ~ (2, 15) => 0.0352955
+(0, 12) ~ (2, 16) => 0.0333216
+(0, 13) ~ (2, 12) => 0.0189655
+(0, 13) ~ (2, 13) => 0.859822
+(0, 13) ~ (2, 15) => 0.0119852
+(0, 13) ~ (2, 16) => 0.0438492
+(0, 13) ~ (2, 17) => 0.0386053
+(0, 14) ~ (2, 13) => 0.0167482
+(0, 14) ~ (2, 14) => 0.838576
+(0, 14) ~ (2, 17) => 0.0742632
+(0, 14) ~ (2, 18) => 0.0418754
+(0, 15) ~ (2, 14) => 0.0116211
+(0, 15) ~ (2, 15) => 0.661587
+(0, 15) ~ (2, 18) => 0.237612
+(0, 15) ~ (2, 19) => 0.0607021
+(0, 16) ~ (2, 16) => 0.506643
+(0, 16) ~ (2, 19) => 0.407144
+(0, 16) ~ (2, 20) => 0.0234943
+(0, 17) ~ (2, 17) => 0.066981
+(0, 17) ~ (2, 20) => 0.899752
+(0, 18) ~ (2, 21) => 0.981772
+(0, 19) ~ (2, 22) => 0.990562
+(0, 20) ~ (2, 23) => 0.998385
+(0, 21) ~ (2, 24) => 0.999906
+(0, 22) ~ (2, 25) => 0.999966
+(0, 23) ~ (2, 26) => 0.999995
+(0, 24) ~ (2, 27) => 0.999989
+(0, 25) ~ (2, 28) => 0.999961
+(0, 26) ~ (2, 29) => 0.999959
+(0, 27) ~ (2, 30) => 0.999974
+(0, 28) ~ (2, 31) => 0.999941
+(0, 29) ~ (2, 32) => 0.999726
+(0, 30) ~ (2, 33) => 0.999598
+(0, 31) ~ (2, 34) => 0.999502
+(0, 32) ~ (2, 35) => 0.999544
+(0, 33) ~ (2, 36) => 0.999636
+(0, 34) ~ (2, 37) => 0.999678
+(0, 35) ~ (2, 38) => 0.999686
+(0, 36) ~ (2, 39) => 0.999548
+(0, 37) ~ (2, 40) => 0.99943
+(0, 38) ~ (2, 41) => 0.99935
+(0, 39) ~ (2, 42) => 0.999456
+(0, 40) ~ (2, 43) => 0.999735
+(0, 41) ~ (2, 44) => 0.999696
+(0, 42) ~ (2, 45) => 0.999676
+(0, 43) ~ (2, 46) => 0.998698
+(0, 44) ~ (2, 47) => 0.99722
+(0, 45) ~ (2, 48) => 0.986571
+(0, 46) ~ (2, 49) => 0.979398
+(0, 46) ~ (2, 51) => 0.0134602
+(0, 47) ~ (2, 50) => 0.964226
+(0, 47) ~ (2, 52) => 0.0211103
+(0, 48) ~ (2, 51) => 0.94148
+(0, 48) ~ (2, 53) => 0.0361107
+(0, 49) ~ (2, 51) => 0.0150438
+(0, 49) ~ (2, 52) => 0.922469
+(0, 49) ~ (2, 54) => 0.0491523
+(0, 50) ~ (2, 52) => 0.0202728
+(0, 50) ~ (2, 53) => 0.902038
+(0, 50) ~ (2, 55) => 0.0700271
+(0, 51) ~ (2, 53) => 0.0159468
+(0, 51) ~ (2, 54) => 0.894513
+(0, 51) ~ (2, 56) => 0.0852831
+(0, 52) ~ (2, 55) => 0.0583747
+(0, 52) ~ (2, 57) => 0.939657
+(0, 53) ~ (2, 58) => 0.992086
+(0, 54) ~ (2, 59) => 0.999671
+(0, 55) ~ (2, 60) => 0.999953
+(0, 56) ~ (2, 61) => 0.999995
+(0, 57) ~ (2, 62) => 0.999988
+(0, 58) ~ (2, 63) => 0.999988
+(0, 59) ~ (2, 64) => 0.999984
+(0, 60) ~ (2, 65) => 0.999979
+(0, 61) ~ (2, 66) => 0.999985
+(0, 62) ~ (2, 67) => 0.999997
+(0, 63) ~ (2, 68) => 0.999999
+(0, 64) ~ (2, 69) => 0.999999
+(0, 65) ~ (2, 70) => 1
+(0, 66) ~ (2, 71) => 0.999997
+(0, 67) ~ (2, 72) => 0.999954
+(0, 68) ~ (2, 73) => 0.999937
+(0, 69) ~ (2, 74) => 0.999938
+(0, 70) ~ (2, 75) => 0.999982
+(0, 71) ~ (2, 76) => 0.999987
+(0, 72) ~ (2, 77) => 0.99999
+(0, 73) ~ (2, 78) => 0.999972
+(0, 74) ~ (2, 79) => 0.999959
+(0, 75) ~ (2, 80) => 0.999896
+(0, 76) ~ (2, 81) => 0.998635
+(0, 77) ~ (2, 82) => 0.997509
+(0, 78) ~ (2, 83) => 0.997173
+(0, 79) ~ (2, 84) => 0.996852
+(0, 80) ~ (2, 85) => 0.996148
+(0, 81) ~ (2, 86) => 0.996439
+(0, 82) ~ (2, 87) => 0.99678
+(0, 83) ~ (2, 88) => 0.997148
+(0, 84) ~ (2, 89) => 0.997419
+(0, 85) ~ (2, 90) => 0.999462
+(0, 86) ~ (2, 91) => 0.999604
+(0, 87) ~ (2, 92) => 0.999941
+(0, 88) ~ (2, 93) => 0.999956
+(0, 89) ~ (2, 94) => 0.999875
+(0, 90) ~ (2, 95) => 0.998996
+(0, 91) ~ (2, 96) => 0.998122
+(0, 92) ~ (2, 97) => 0.995935
+(0, 93) ~ (2, 98) => 0.995108
+(0, 94) ~ (2, 99) => 0.99414
+(0, 95) ~ (2, 100) => 0.988342
+(0, 96) ~ (2, 101) => 0.984411
+(0, 97) ~ (2, 102) => 0.979584
+(0, 98) ~ (2, 103) => 0.975227
+(0, 98) ~ (2, 104) => 0.0118768
+(0, 99) ~ (2, 104) => 0.974553
+(0, 99) ~ (2, 105) => 0.0119954
+(0, 100) ~ (2, 105) => 0.975549
+(0, 101) ~ (2, 106) => 0.982397
+(0, 102) ~ (2, 107) => 0.990699
+(0, 103) ~ (2, 108) => 0.99547
+(0, 104) ~ (2, 109) => 0.999744
+(0, 105) ~ (2, 110) => 0.999895
+(0, 106) ~ (2, 111) => 0.99994
+(0, 107) ~ (2, 112) => 0.999984
+(0, 108) ~ (2, 113) => 0.999991
+(0, 109) ~ (2, 114) => 0.99999
+(0, 110) ~ (2, 115) => 0.999991
+(0, 111) ~ (2, 116) => 0.999995
+(0, 112) ~ (2, 117) => 0.999996
+(0, 113) ~ (2, 118) => 0.999985
+(0, 114) ~ (2, 119) => 0.999822
+(0, 115) ~ (2, 120) => 0.998808
+(0, 116) ~ (2, 121) => 0.997296
+(0, 117) ~ (2, 122) => 0.996766
+(0, 118) ~ (2, 123) => 0.996641
+(0, 119) ~ (2, 124) => 0.996893
+(0, 120) ~ (2, 125) => 0.996959
+(0, 121) ~ (2, 126) => 0.997183
+(0, 122) ~ (2, 127) => 0.99786
+(0, 123) ~ (2, 128) => 0.999298
+(0, 124) ~ (2, 129) => 0.99991
+(0, 125) ~ (2, 130) => 0.999943
+(0, 126) ~ (2, 131) => 0.999868
+(0, 127) ~ (2, 132) => 0.999768
+(0, 128) ~ (2, 133) => 0.999793
+(0, 129) ~ (2, 134) => 0.999694
+(0, 130) ~ (2, 135) => 0.999625
+(0, 131) ~ (2, 136) => 0.99944
+(0, 132) ~ (2, 137) => 0.99943
+(0, 133) ~ (2, 138) => 0.999652
+(0, 134) ~ (2, 139) => 0.99994
+(0, 135) ~ (2, 140) => 0.999961
+(0, 136) ~ (2, 141) => 0.999971
+(0, 137) ~ (2, 142) => 0.999986
+(0, 138) ~ (2, 143) => 0.999963
+(0, 139) ~ (2, 144) => 0.999959
+(0, 140) ~ (2, 145) => 0.999993
+(0, 141) ~ (2, 146) => 0.999998
+(0, 142) ~ (2, 147) => 0.999997
+(0, 143) ~ (2, 148) => 0.999997
+(0, 144) ~ (2, 149) => 0.999999
+(0, 145) ~ (2, 150) => 0.999998
+(0, 146) ~ (2, 151) => 0.999987
+(0, 147) ~ (2, 152) => 0.999871
+(0, 148) ~ (2, 153) => 0.999746
+(0, 149) ~ (2, 154) => 0.999733
+(0, 150) ~ (2, 155) => 0.999916
+(0, 151) ~ (2, 156) => 0.999962
+(0, 152) ~ (2, 157) => 0.999871
+(0, 153) ~ (2, 158) => 0.999633
+(0, 154) ~ (2, 159) => 0.999079
+(0, 155) ~ (2, 160) => 0.998255
+(0, 156) ~ (2, 161) => 0.993442
+(0, 157) ~ (2, 162) => 0.992499
+(0, 158) ~ (2, 163) => 0.992344
+(0, 159) ~ (2, 164) => 0.992016
+(0, 160) ~ (2, 165) => 0.991732
+(0, 161) ~ (2, 166) => 0.991858
+(0, 162) ~ (2, 167) => 0.992201
+(0, 163) ~ (2, 168) => 0.991425
+(0, 164) ~ (2, 169) => 0.99029
+(0, 165) ~ (2, 170) => 0.987755
+(0, 166) ~ (2, 171) => 0.986861
+(0, 167) ~ (2, 172) => 0.986994
+(0, 168) ~ (2, 173) => 0.987454
+(0, 169) ~ (2, 174) => 0.988138
+(0, 170) ~ (2, 175) => 0.989027
+(0, 171) ~ (2, 176) => 0.98925
+(0, 172) ~ (2, 177) => 0.989455
+(0, 173) ~ (2, 178) => 0.9887
+(0, 174) ~ (2, 179) => 0.989995
+(0, 175) ~ (2, 180) => 0.990789
+(0, 176) ~ (2, 181) => 0.992202
+(0, 177) ~ (2, 182) => 0.999129
+(0, 178) ~ (2, 183) => 0.999911
+(0, 179) ~ (2, 184) => 0.999581
+(0, 180) ~ (2, 185) => 0.999084
+(0, 181) ~ (2, 186) => 0.988496
+(0, 182) ~ (2, 187) => 0.953219
+(0, 182) ~ (2, 188) => 0.011222
+(0, 183) ~ (2, 187) => 0.0309581
+(0, 183) ~ (2, 188) => 0.910198
+(0, 183) ~ (2, 189) => 0.015096
+(0, 184) ~ (2, 188) => 0.063015
+(0, 184) ~ (2, 189) => 0.681409
+(0, 184) ~ (2, 190) => 0.0691852
+(0, 184) ~ (2, 193) => 0.0161878
+(0, 185) ~ (2, 189) => 0.213417
+(0, 185) ~ (2, 190) => 0.583851
+(0, 185) ~ (2, 191) => 0.118771
+(0, 185) ~ (2, 194) => 0.0246532
+(0, 186) ~ (2, 190) => 0.231169
+(0, 186) ~ (2, 191) => 0.424571
+(0, 186) ~ (2, 192) => 0.202593
+(0, 186) ~ (2, 195) => 0.0667658
+(0, 187) ~ (2, 190) => 0.0151276
+(0, 187) ~ (2, 191) => 0.24593
+(0, 187) ~ (2, 192) => 0.215124
+(0, 187) ~ (2, 193) => 0.387406
+(0, 187) ~ (2, 196) => 0.0734905
+(0, 188) ~ (2, 191) => 0.0204526
+(0, 188) ~ (2, 192) => 0.203744
+(0, 188) ~ (2, 193) => 0.185169
+(0, 188) ~ (2, 194) => 0.437372
+(0, 188) ~ (2, 197) => 0.0781191
+(0, 189) ~ (2, 192) => 0.0351806
+(0, 189) ~ (2, 193) => 0.150887
+(0, 189) ~ (2, 194) => 0.103764
+(0, 189) ~ (2, 195) => 0.56183
+(0, 189) ~ (2, 197) => 0.0106668
+(0, 189) ~ (2, 198) => 0.0821699
+(0, 190) ~ (2, 193) => 0.0417367
+(0, 190) ~ (2, 194) => 0.0709281
+(0, 190) ~ (2, 195) => 0.0762573
+(0, 190) ~ (2, 196) => 0.663308
+(0, 190) ~ (2, 198) => 0.0105526
+(0, 190) ~ (2, 199) => 0.0818701
+(0, 191) ~ (2, 194) => 0.0446032
+(0, 191) ~ (2, 195) => 0.0437612
+(0, 191) ~ (2, 196) => 0.0474161
+(0, 191) ~ (2, 197) => 0.720848
+(0, 191) ~ (2, 200) => 0.0795003
+(0, 192) ~ (2, 194) => 0.0108244
+(0, 192) ~ (2, 195) => 0.0387856
+(0, 192) ~ (2, 196) => 0.0291392
+(0, 192) ~ (2, 197) => 0.0320127
+(0, 192) ~ (2, 198) => 0.762645
+(0, 192) ~ (2, 201) => 0.0689563
+(0, 193) ~ (2, 195) => 0.0100998
+(0, 193) ~ (2, 196) => 0.0354724
+(0, 193) ~ (2, 197) => 0.018905
+(0, 193) ~ (2, 198) => 0.0188927
+(0, 193) ~ (2, 199) => 0.806473
+(0, 193) ~ (2, 202) => 0.049258
+(0, 194) ~ (2, 197) => 0.0326149
+(0, 194) ~ (2, 200) => 0.83823
+(0, 194) ~ (2, 203) => 0.0125828
+(0, 195) ~ (2, 198) => 0.02926
+(0, 195) ~ (2, 201) => 0.865463
+(0, 196) ~ (2, 199) => 0.0285537
+(0, 196) ~ (2, 202) => 0.894063
+(0, 197) ~ (2, 200) => 0.0252415
+(0, 197) ~ (2, 203) => 0.935606
+(0, 198) ~ (2, 201) => 0.0242767
+(0, 198) ~ (2, 204) => 0.948484
+(0, 199) ~ (2, 202) => 0.0238855
+(0, 199) ~ (2, 205) => 0.951111
+(0, 200) ~ (2, 203) => 0.0203246
+(0, 200) ~ (2, 206) => 0.955336
+(0, 201) ~ (2, 204) => 0.0141161
+(0, 201) ~ (2, 207) => 0.962499
+(0, 202) ~ (2, 208) => 0.975351
+(0, 203) ~ (2, 209) => 0.981655
+(0, 204) ~ (2, 210) => 0.986373
+(0, 205) ~ (2, 211) => 0.991767
+(0, 206) ~ (2, 212) => 0.998725
+(0, 207) ~ (2, 213) => 0.999224
+(0, 208) ~ (2, 214) => 0.99932
+(0, 209) ~ (2, 215) => 0.999438
+(0, 210) ~ (2, 216) => 0.998833
+(0, 211) ~ (2, 217) => 0.998889
+(0, 212) ~ (2, 218) => 0.999326
+(0, 213) ~ (2, 219) => 0.999669
+(0, 214) ~ (2, 220) => 0.999595
+(0, 215) ~ (2, 221) => 0.999469
+(0, 216) ~ (2, 222) => 0.999058
+(0, 217) ~ (2, 223) => 0.998999
+(0, 218) ~ (2, 224) => 0.999173
+(0, 219) ~ (2, 225) => 0.999688
+(0, 220) ~ (2, 226) => 0.999683
+(0, 221) ~ (2, 227) => 0.999805
+(0, 222) ~ (2, 228) => 0.999937
+(0, 223) ~ (2, 229) => 0.999991
+(0, 224) ~ (2, 230) => 0.999999
+(0, 225) ~ (2, 231) => 1
+(0, 226) ~ (2, 232) => 0.999993
+(0, 227) ~ (2, 233) => 0.999937
+(0, 228) ~ (2, 234) => 0.999155
+(0, 229) ~ (2, 235) => 0.996956
+(0, 230) ~ (2, 236) => 0.996809
+(0, 231) ~ (2, 237) => 0.997297
+(0, 232) ~ (2, 238) => 0.998014
+
+; gap posteriors
+(0, 0) ~ (2, -1) => 0.0163932
+(0, 1) ~ (2, -1) => 0.0249941
+(0, 2) ~ (2, -1) => 0.0156772
+(0, 3) ~ (2, -1) => 0.0191768
+(0, 4) ~ (2, -1) => 0.0341071
+(0, 5) ~ (2, -1) => 0.0377984
+(0, 6) ~ (2, -1) => 0.0632976
+(0, 7) ~ (2, -1) => 0.0224177
+(0, 8) ~ (2, -1) => 0.0211184
+(0, 9) ~ (2, -1) => 0.0240292
+(0, 10) ~ (2, -1) => 0.0172112
+(0, 11) ~ (2, -1) => 0.0184786
+(0, 12) ~ (2, -1) => 0.0243085
+(0, 13) ~ (2, -1) => 0.0267729
+(0, 14) ~ (2, -1) => 0.028537
+(0, 15) ~ (2, -1) => 0.028478
+(0, 16) ~ (2, -1) => 0.0627189
+(0, 17) ~ (2, -1) => 0.0332673
+(0, 18) ~ (2, -1) => 0.0182276
+(0, 19) ~ (2, -1) => 0.00943756
+(0, 20) ~ (2, -1) => 0.00161451
+(0, 21) ~ (2, -1) => 0.0001
+(0, 22) ~ (2, -1) => 0.0001
+(0, 23) ~ (2, -1) => 0.0001
+(0, 24) ~ (2, -1) => 0.0001
+(0, 25) ~ (2, -1) => 0.0001
+(0, 26) ~ (2, -1) => 0.0001
+(0, 27) ~ (2, -1) => 0.0001
+(0, 28) ~ (2, -1) => 0.0001
+(0, 29) ~ (2, -1) => 0.000273824
+(0, 30) ~ (2, -1) => 0.000401914
+(0, 31) ~ (2, -1) => 0.000497699
+(0, 32) ~ (2, -1) => 0.000455797
+(0, 33) ~ (2, -1) => 0.000364482
+(0, 34) ~ (2, -1) => 0.000322104
+(0, 35) ~ (2, -1) => 0.000314415
+(0, 36) ~ (2, -1) => 0.000451982
+(0, 37) ~ (2, -1) => 0.000570059
+(0, 38) ~ (2, -1) => 0.000649989
+(0, 39) ~ (2, -1) => 0.000543773
+(0, 40) ~ (2, -1) => 0.000265121
+(0, 41) ~ (2, -1) => 0.000303626
+(0, 42) ~ (2, -1) => 0.000324249
+(0, 43) ~ (2, -1) => 0.00130188
+(0, 44) ~ (2, -1) => 0.00278038
+(0, 45) ~ (2, -1) => 0.0134289
+(0, 46) ~ (2, -1) => 0.00714164
+(0, 47) ~ (2, -1) => 0.0146641
+(0, 48) ~ (2, -1) => 0.022409
+(0, 49) ~ (2, -1) => 0.0133352
+(0, 50) ~ (2, -1) => 0.00766244
+(0, 51) ~ (2, -1) => 0.00425665
+(0, 52) ~ (2, -1) => 0.00196797
+(0, 53) ~ (2, -1) => 0.00791413
+(0, 54) ~ (2, -1) => 0.000329316
+(0, 55) ~ (2, -1) => 0.0001
+(0, 56) ~ (2, -1) => 0.0001
+(0, 57) ~ (2, -1) => 0.0001
+(0, 58) ~ (2, -1) => 0.0001
+(0, 59) ~ (2, -1) => 0.0001
+(0, 60) ~ (2, -1) => 0.0001
+(0, 61) ~ (2, -1) => 0.0001
+(0, 62) ~ (2, -1) => 0.0001
+(0, 63) ~ (2, -1) => 0.0001
+(0, 64) ~ (2, -1) => 0.0001
+(0, 65) ~ (2, -1) => 0.0001
+(0, 66) ~ (2, -1) => 0.0001
+(0, 67) ~ (2, -1) => 0.0001
+(0, 68) ~ (2, -1) => 0.0001
+(0, 69) ~ (2, -1) => 0.0001
+(0, 70) ~ (2, -1) => 0.0001
+(0, 71) ~ (2, -1) => 0.0001
+(0, 72) ~ (2, -1) => 0.0001
+(0, 73) ~ (2, -1) => 0.0001
+(0, 74) ~ (2, -1) => 0.0001
+(0, 75) ~ (2, -1) => 0.00010407
+(0, 76) ~ (2, -1) => 0.00136471
+(0, 77) ~ (2, -1) => 0.00249064
+(0, 78) ~ (2, -1) => 0.00282675
+(0, 79) ~ (2, -1) => 0.00314844
+(0, 80) ~ (2, -1) => 0.00385171
+(0, 81) ~ (2, -1) => 0.00356066
+(0, 82) ~ (2, -1) => 0.0032205
+(0, 83) ~ (2, -1) => 0.00285214
+(0, 84) ~ (2, -1) => 0.00258136
+(0, 85) ~ (2, -1) => 0.000537813
+(0, 86) ~ (2, -1) => 0.000395596
+(0, 87) ~ (2, -1) => 0.0001
+(0, 88) ~ (2, -1) => 0.0001
+(0, 89) ~ (2, -1) => 0.000125289
+(0, 90) ~ (2, -1) => 0.00100362
+(0, 91) ~ (2, -1) => 0.00187784
+(0, 92) ~ (2, -1) => 0.0040645
+(0, 93) ~ (2, -1) => 0.00489247
+(0, 94) ~ (2, -1) => 0.00585985
+(0, 95) ~ (2, -1) => 0.0116577
+(0, 96) ~ (2, -1) => 0.0155891
+(0, 97) ~ (2, -1) => 0.0204161
+(0, 98) ~ (2, -1) => 0.0128961
+(0, 99) ~ (2, -1) => 0.0134518
+(0, 100) ~ (2, -1) => 0.0244514
+(0, 101) ~ (2, -1) => 0.0176026
+(0, 102) ~ (2, -1) => 0.00930136
+(0, 103) ~ (2, -1) => 0.00452977
+(0, 104) ~ (2, -1) => 0.000255823
+(0, 105) ~ (2, -1) => 0.000105441
+(0, 106) ~ (2, -1) => 0.0001
+(0, 107) ~ (2, -1) => 0.0001
+(0, 108) ~ (2, -1) => 0.0001
+(0, 109) ~ (2, -1) => 0.0001
+(0, 110) ~ (2, -1) => 0.0001
+(0, 111) ~ (2, -1) => 0.0001
+(0, 112) ~ (2, -1) => 0.0001
+(0, 113) ~ (2, -1) => 0.0001
+(0, 114) ~ (2, -1) => 0.000178277
+(0, 115) ~ (2, -1) => 0.00119191
+(0, 116) ~ (2, -1) => 0.00270385
+(0, 117) ~ (2, -1) => 0.00323367
+(0, 118) ~ (2, -1) => 0.00335908
+(0, 119) ~ (2, -1) => 0.00310689
+(0, 120) ~ (2, -1) => 0.00304073
+(0, 121) ~ (2, -1) => 0.00281745
+(0, 122) ~ (2, -1) => 0.00214016
+(0, 123) ~ (2, -1) => 0.000702262
+(0, 124) ~ (2, -1) => 0.0001
+(0, 125) ~ (2, -1) => 0.0001
+(0, 126) ~ (2, -1) => 0.000132024
+(0, 127) ~ (2, -1) => 0.000231624
+(0, 128) ~ (2, -1) => 0.000206947
+(0, 129) ~ (2, -1) => 0.000305951
+(0, 130) ~ (2, -1) => 0.000375211
+(0, 131) ~ (2, -1) => 0.000559568
+(0, 132) ~ (2, -1) => 0.000570238
+(0, 133) ~ (2, -1) => 0.000347853
+(0, 134) ~ (2, -1) => 0.0001
+(0, 135) ~ (2, -1) => 0.0001
+(0, 136) ~ (2, -1) => 0.0001
+(0, 137) ~ (2, -1) => 0.0001
+(0, 138) ~ (2, -1) => 0.0001
+(0, 139) ~ (2, -1) => 0.0001
+(0, 140) ~ (2, -1) => 0.0001
+(0, 141) ~ (2, -1) => 0.0001
+(0, 142) ~ (2, -1) => 0.0001
+(0, 143) ~ (2, -1) => 0.0001
+(0, 144) ~ (2, -1) => 0.0001
+(0, 145) ~ (2, -1) => 0.0001
+(0, 146) ~ (2, -1) => 0.0001
+(0, 147) ~ (2, -1) => 0.000129044
+(0, 148) ~ (2, -1) => 0.000253975
+(0, 149) ~ (2, -1) => 0.000267029
+(0, 150) ~ (2, -1) => 0.0001
+(0, 151) ~ (2, -1) => 0.0001
+(0, 152) ~ (2, -1) => 0.000129104
+(0, 153) ~ (2, -1) => 0.000366747
+(0, 154) ~ (2, -1) => 0.000921428
+(0, 155) ~ (2, -1) => 0.00174505
+(0, 156) ~ (2, -1) => 0.0065583
+(0, 157) ~ (2, -1) => 0.0075013
+(0, 158) ~ (2, -1) => 0.0076564
+(0, 159) ~ (2, -1) => 0.00798392
+(0, 160) ~ (2, -1) => 0.00826848
+(0, 161) ~ (2, -1) => 0.00814223
+(0, 162) ~ (2, -1) => 0.00779921
+(0, 163) ~ (2, -1) => 0.00857532
+(0, 164) ~ (2, -1) => 0.00970978
+(0, 165) ~ (2, -1) => 0.0122453
+(0, 166) ~ (2, -1) => 0.0131392
+(0, 167) ~ (2, -1) => 0.0130062
+(0, 168) ~ (2, -1) => 0.012546
+(0, 169) ~ (2, -1) => 0.0118616
+(0, 170) ~ (2, -1) => 0.0109733
+(0, 171) ~ (2, -1) => 0.0107499
+(0, 172) ~ (2, -1) => 0.0105447
+(0, 173) ~ (2, -1) => 0.0113001
+(0, 174) ~ (2, -1) => 0.0100055
+(0, 175) ~ (2, -1) => 0.0092113
+(0, 176) ~ (2, -1) => 0.00779849
+(0, 177) ~ (2, -1) => 0.000871122
+(0, 178) ~ (2, -1) => 0.0001
+(0, 179) ~ (2, -1) => 0.000418842
+(0, 180) ~ (2, -1) => 0.000915647
+(0, 181) ~ (2, -1) => 0.0115041
+(0, 182) ~ (2, -1) => 0.0355589
+(0, 183) ~ (2, -1) => 0.0437483
+(0, 184) ~ (2, -1) => 0.170203
+(0, 185) ~ (2, -1) => 0.0593081
+(0, 186) ~ (2, -1) => 0.0749021
+(0, 187) ~ (2, -1) => 0.0629224
+(0, 188) ~ (2, -1) => 0.0751439
+(0, 189) ~ (2, -1) => 0.0555011
+(0, 190) ~ (2, -1) => 0.0553475
+(0, 191) ~ (2, -1) => 0.063871
+(0, 192) ~ (2, -1) => 0.057637
+(0, 193) ~ (2, -1) => 0.0608994
+(0, 194) ~ (2, -1) => 0.116572
+(0, 195) ~ (2, -1) => 0.105277
+(0, 196) ~ (2, -1) => 0.0773835
+(0, 197) ~ (2, -1) => 0.0391524
+(0, 198) ~ (2, -1) => 0.0272396
+(0, 199) ~ (2, -1) => 0.025003
+(0, 200) ~ (2, -1) => 0.0243393
+(0, 201) ~ (2, -1) => 0.0233846
+(0, 202) ~ (2, -1) => 0.024649
+(0, 203) ~ (2, -1) => 0.0183448
+(0, 204) ~ (2, -1) => 0.0136271
+(0, 205) ~ (2, -1) => 0.00823325
+(0, 206) ~ (2, -1) => 0.0012747
+(0, 207) ~ (2, -1) => 0.000776112
+(0, 208) ~ (2, -1) => 0.000680208
+(0, 209) ~ (2, -1) => 0.000561833
+(0, 210) ~ (2, -1) => 0.00116718
+(0, 211) ~ (2, -1) => 0.00111145
+(0, 212) ~ (2, -1) => 0.000674307
+(0, 213) ~ (2, -1) => 0.000330806
+(0, 214) ~ (2, -1) => 0.000405371
+(0, 215) ~ (2, -1) => 0.000531256
+(0, 216) ~ (2, -1) => 0.000941575
+(0, 217) ~ (2, -1) => 0.00100148
+(0, 218) ~ (2, -1) => 0.000826597
+(0, 219) ~ (2, -1) => 0.000311911
+(0, 220) ~ (2, -1) => 0.000317156
+(0, 221) ~ (2, -1) => 0.000195444
+(0, 222) ~ (2, -1) => 0.0001
+(0, 223) ~ (2, -1) => 0.0001
+(0, 224) ~ (2, -1) => 0.0001
+(0, 225) ~ (2, -1) => 0.0001
+(0, 226) ~ (2, -1) => 0.0001
+(0, 227) ~ (2, -1) => 0.0001
+(0, 228) ~ (2, -1) => 0.000845432
+(0, 229) ~ (2, -1) => 0.00304359
+(0, 230) ~ (2, -1) => 0.00319093
+(0, 231) ~ (2, -1) => 0.00270259
+(0, 232) ~ (2, -1) => 0.00198627
+
+(0, -1) ~ (2, 0) => 0.00358114
+(0, -1) ~ (2, 1) => 0.00587003
+(0, -1) ~ (2, 2) => 0.00790827
+(0, -1) ~ (2, 3) => 0.0114724
+(0, -1) ~ (2, 4) => 0.0169288
+(0, -1) ~ (2, 5) => 0.0212245
+(0, -1) ~ (2, 6) => 0.023952
+(0, -1) ~ (2, 7) => 0.0310831
+(0, -1) ~ (2, 8) => 0.0415779
+(0, -1) ~ (2, 9) => 0.0810926
+(0, -1) ~ (2, 10) => 0.0742222
+(0, -1) ~ (2, 11) => 0.0709047
+(0, -1) ~ (2, 12) => 0.0958161
+(0, -1) ~ (2, 13) => 0.0918968
+(0, -1) ~ (2, 14) => 0.102192
+(0, -1) ~ (2, 15) => 0.273302
+(0, -1) ~ (2, 16) => 0.416186
+(0, -1) ~ (2, 17) => 0.82015
+(0, -1) ~ (2, 18) => 0.720513
+(0, -1) ~ (2, 19) => 0.532154
+(0, -1) ~ (2, 20) => 0.076754
+(0, -1) ~ (2, 21) => 0.0182276
+(0, -1) ~ (2, 22) => 0.00943756
+(0, -1) ~ (2, 23) => 0.00161451
+(0, -1) ~ (2, 24) => 0.0001
+(0, -1) ~ (2, 25) => 0.0001
+(0, -1) ~ (2, 26) => 0.0001
+(0, -1) ~ (2, 27) => 0.0001
+(0, -1) ~ (2, 28) => 0.0001
+(0, -1) ~ (2, 29) => 0.0001
+(0, -1) ~ (2, 30) => 0.0001
+(0, -1) ~ (2, 31) => 0.0001
+(0, -1) ~ (2, 32) => 0.000273824
+(0, -1) ~ (2, 33) => 0.000401914
+(0, -1) ~ (2, 34) => 0.000497699
+(0, -1) ~ (2, 35) => 0.000455797
+(0, -1) ~ (2, 36) => 0.000364482
+(0, -1) ~ (2, 37) => 0.000322104
+(0, -1) ~ (2, 38) => 0.000314415
+(0, -1) ~ (2, 39) => 0.000451982
+(0, -1) ~ (2, 40) => 0.000570059
+(0, -1) ~ (2, 41) => 0.000649989
+(0, -1) ~ (2, 42) => 0.000543773
+(0, -1) ~ (2, 43) => 0.000265121
+(0, -1) ~ (2, 44) => 0.000303626
+(0, -1) ~ (2, 45) => 0.000324249
+(0, -1) ~ (2, 46) => 0.00130188
+(0, -1) ~ (2, 47) => 0.00278038
+(0, -1) ~ (2, 48) => 0.0134289
+(0, -1) ~ (2, 49) => 0.0206019
+(0, -1) ~ (2, 50) => 0.0357744
+(0, -1) ~ (2, 51) => 0.0300157
+(0, -1) ~ (2, 52) => 0.0361483
+(0, -1) ~ (2, 53) => 0.0459048
+(0, -1) ~ (2, 54) => 0.0563343
+(0, -1) ~ (2, 55) => 0.871598
+(0, -1) ~ (2, 56) => 0.914717
+(0, -1) ~ (2, 57) => 0.0603427
+(0, -1) ~ (2, 58) => 0.00791413
+(0, -1) ~ (2, 59) => 0.000329316
+(0, -1) ~ (2, 60) => 0.0001
+(0, -1) ~ (2, 61) => 0.0001
+(0, -1) ~ (2, 62) => 0.0001
+(0, -1) ~ (2, 63) => 0.0001
+(0, -1) ~ (2, 64) => 0.0001
+(0, -1) ~ (2, 65) => 0.0001
+(0, -1) ~ (2, 66) => 0.0001
+(0, -1) ~ (2, 67) => 0.0001
+(0, -1) ~ (2, 68) => 0.0001
+(0, -1) ~ (2, 69) => 0.0001
+(0, -1) ~ (2, 70) => 0.0001
+(0, -1) ~ (2, 71) => 0.0001
+(0, -1) ~ (2, 72) => 0.0001
+(0, -1) ~ (2, 73) => 0.0001
+(0, -1) ~ (2, 74) => 0.0001
+(0, -1) ~ (2, 75) => 0.0001
+(0, -1) ~ (2, 76) => 0.0001
+(0, -1) ~ (2, 77) => 0.0001
+(0, -1) ~ (2, 78) => 0.0001
+(0, -1) ~ (2, 79) => 0.0001
+(0, -1) ~ (2, 80) => 0.00010407
+(0, -1) ~ (2, 81) => 0.00136471
+(0, -1) ~ (2, 82) => 0.00249064
+(0, -1) ~ (2, 83) => 0.00282675
+(0, -1) ~ (2, 84) => 0.00314844
+(0, -1) ~ (2, 85) => 0.00385171
+(0, -1) ~ (2, 86) => 0.00356066
+(0, -1) ~ (2, 87) => 0.0032205
+(0, -1) ~ (2, 88) => 0.00285214
+(0, -1) ~ (2, 89) => 0.00258136
+(0, -1) ~ (2, 90) => 0.000537813
+(0, -1) ~ (2, 91) => 0.000395596
+(0, -1) ~ (2, 92) => 0.0001
+(0, -1) ~ (2, 93) => 0.0001
+(0, -1) ~ (2, 94) => 0.000125289
+(0, -1) ~ (2, 95) => 0.00100362
+(0, -1) ~ (2, 96) => 0.00187784
+(0, -1) ~ (2, 97) => 0.0040645
+(0, -1) ~ (2, 98) => 0.00489247
+(0, -1) ~ (2, 99) => 0.00585985
+(0, -1) ~ (2, 100) => 0.0116577
+(0, -1) ~ (2, 101) => 0.0155891
+(0, -1) ~ (2, 102) => 0.0204161
+(0, -1) ~ (2, 103) => 0.0247729
+(0, -1) ~ (2, 104) => 0.0135704
+(0, -1) ~ (2, 105) => 0.0124559
+(0, -1) ~ (2, 106) => 0.0176026
+(0, -1) ~ (2, 107) => 0.00930136
+(0, -1) ~ (2, 108) => 0.00452977
+(0, -1) ~ (2, 109) => 0.000255823
+(0, -1) ~ (2, 110) => 0.000105441
+(0, -1) ~ (2, 111) => 0.0001
+(0, -1) ~ (2, 112) => 0.0001
+(0, -1) ~ (2, 113) => 0.0001
+(0, -1) ~ (2, 114) => 0.0001
+(0, -1) ~ (2, 115) => 0.0001
+(0, -1) ~ (2, 116) => 0.0001
+(0, -1) ~ (2, 117) => 0.0001
+(0, -1) ~ (2, 118) => 0.0001
+(0, -1) ~ (2, 119) => 0.000178277
+(0, -1) ~ (2, 120) => 0.00119191
+(0, -1) ~ (2, 121) => 0.00270385
+(0, -1) ~ (2, 122) => 0.00323367
+(0, -1) ~ (2, 123) => 0.00335908
+(0, -1) ~ (2, 124) => 0.00310689
+(0, -1) ~ (2, 125) => 0.00304073
+(0, -1) ~ (2, 126) => 0.00281745
+(0, -1) ~ (2, 127) => 0.00214016
+(0, -1) ~ (2, 128) => 0.000702262
+(0, -1) ~ (2, 129) => 0.0001
+(0, -1) ~ (2, 130) => 0.0001
+(0, -1) ~ (2, 131) => 0.000132024
+(0, -1) ~ (2, 132) => 0.000231624
+(0, -1) ~ (2, 133) => 0.000206947
+(0, -1) ~ (2, 134) => 0.000305951
+(0, -1) ~ (2, 135) => 0.000375211
+(0, -1) ~ (2, 136) => 0.000559568
+(0, -1) ~ (2, 137) => 0.000570238
+(0, -1) ~ (2, 138) => 0.000347853
+(0, -1) ~ (2, 139) => 0.0001
+(0, -1) ~ (2, 140) => 0.0001
+(0, -1) ~ (2, 141) => 0.0001
+(0, -1) ~ (2, 142) => 0.0001
+(0, -1) ~ (2, 143) => 0.0001
+(0, -1) ~ (2, 144) => 0.0001
+(0, -1) ~ (2, 145) => 0.0001
+(0, -1) ~ (2, 146) => 0.0001
+(0, -1) ~ (2, 147) => 0.0001
+(0, -1) ~ (2, 148) => 0.0001
+(0, -1) ~ (2, 149) => 0.0001
+(0, -1) ~ (2, 150) => 0.0001
+(0, -1) ~ (2, 151) => 0.0001
+(0, -1) ~ (2, 152) => 0.000129044
+(0, -1) ~ (2, 153) => 0.000253975
+(0, -1) ~ (2, 154) => 0.000267029
+(0, -1) ~ (2, 155) => 0.0001
+(0, -1) ~ (2, 156) => 0.0001
+(0, -1) ~ (2, 157) => 0.000129104
+(0, -1) ~ (2, 158) => 0.000366747
+(0, -1) ~ (2, 159) => 0.000921428
+(0, -1) ~ (2, 160) => 0.00174505
+(0, -1) ~ (2, 161) => 0.0065583
+(0, -1) ~ (2, 162) => 0.0075013
+(0, -1) ~ (2, 163) => 0.0076564
+(0, -1) ~ (2, 164) => 0.00798392
+(0, -1) ~ (2, 165) => 0.00826848
+(0, -1) ~ (2, 166) => 0.00814223
+(0, -1) ~ (2, 167) => 0.00779921
+(0, -1) ~ (2, 168) => 0.00857532
+(0, -1) ~ (2, 169) => 0.00970978
+(0, -1) ~ (2, 170) => 0.0122453
+(0, -1) ~ (2, 171) => 0.0131392
+(0, -1) ~ (2, 172) => 0.0130062
+(0, -1) ~ (2, 173) => 0.012546
+(0, -1) ~ (2, 174) => 0.0118616
+(0, -1) ~ (2, 175) => 0.0109733
+(0, -1) ~ (2, 176) => 0.0107499
+(0, -1) ~ (2, 177) => 0.0105447
+(0, -1) ~ (2, 178) => 0.0113001
+(0, -1) ~ (2, 179) => 0.0100055
+(0, -1) ~ (2, 180) => 0.0092113
+(0, -1) ~ (2, 181) => 0.00779849
+(0, -1) ~ (2, 182) => 0.000871122
+(0, -1) ~ (2, 183) => 0.0001
+(0, -1) ~ (2, 184) => 0.000418842
+(0, -1) ~ (2, 185) => 0.000915647
+(0, -1) ~ (2, 186) => 0.0115041
+(0, -1) ~ (2, 187) => 0.0158229
+(0, -1) ~ (2, 188) => 0.0155655
+(0, -1) ~ (2, 189) => 0.0900781
+(0, -1) ~ (2, 190) => 0.100668
+(0, -1) ~ (2, 191) => 0.190276
+(0, -1) ~ (2, 192) => 0.343359
+(0, -1) ~ (2, 193) => 0.218613
+(0, -1) ~ (2, 194) => 0.307855
+(0, -1) ~ (2, 195) => 0.2025
+(0, -1) ~ (2, 196) => 0.151174
+(0, -1) ~ (2, 197) => 0.106833
+(0, -1) ~ (2, 198) => 0.09648
+(0, -1) ~ (2, 199) => 0.0831036
+(0, -1) ~ (2, 200) => 0.0570283
+(0, -1) ~ (2, 201) => 0.0413042
+(0, -1) ~ (2, 202) => 0.0327936
+(0, -1) ~ (2, 203) => 0.0314865
+(0, -1) ~ (2, 204) => 0.0374002
+(0, -1) ~ (2, 205) => 0.0488885
+(0, -1) ~ (2, 206) => 0.044664
+(0, -1) ~ (2, 207) => 0.0375007
+(0, -1) ~ (2, 208) => 0.024649
+(0, -1) ~ (2, 209) => 0.0183448
+(0, -1) ~ (2, 210) => 0.0136271
+(0, -1) ~ (2, 211) => 0.00823325
+(0, -1) ~ (2, 212) => 0.0012747
+(0, -1) ~ (2, 213) => 0.000776112
+(0, -1) ~ (2, 214) => 0.000680208
+(0, -1) ~ (2, 215) => 0.000561833
+(0, -1) ~ (2, 216) => 0.00116718
+(0, -1) ~ (2, 217) => 0.00111145
+(0, -1) ~ (2, 218) => 0.000674307
+(0, -1) ~ (2, 219) => 0.000330806
+(0, -1) ~ (2, 220) => 0.000405371
+(0, -1) ~ (2, 221) => 0.000531256
+(0, -1) ~ (2, 222) => 0.000941575
+(0, -1) ~ (2, 223) => 0.00100148
+(0, -1) ~ (2, 224) => 0.000826597
+(0, -1) ~ (2, 225) => 0.000311911
+(0, -1) ~ (2, 226) => 0.000317156
+(0, -1) ~ (2, 227) => 0.000195444
+(0, -1) ~ (2, 228) => 0.0001
+(0, -1) ~ (2, 229) => 0.0001
+(0, -1) ~ (2, 230) => 0.0001
+(0, -1) ~ (2, 231) => 0.0001
+(0, -1) ~ (2, 232) => 0.0001
+(0, -1) ~ (2, 233) => 0.0001
+(0, -1) ~ (2, 234) => 0.000845432
+(0, -1) ~ (2, 235) => 0.00304359
+(0, -1) ~ (2, 236) => 0.00319093
+(0, -1) ~ (2, 237) => 0.00270259
+(0, -1) ~ (2, 238) => 0.00198627
+
+; Sparse posterior probability matrix for sequences 0 and 3
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (3, 0) => 0.514813
+(0, 0) ~ (3, 1) => 0.0267797
+(0, 0) ~ (3, 2) => 0.1484
+(0, 0) ~ (3, 3) => 0.0100961
+(0, 1) ~ (3, 0) => 0.293745
+(0, 1) ~ (3, 1) => 0.382295
+(0, 1) ~ (3, 2) => 0.0428307
+(0, 1) ~ (3, 3) => 0.227108
+(0, 1) ~ (3, 4) => 0.020482
+(0, 2) ~ (3, 1) => 0.309294
+(0, 2) ~ (3, 2) => 0.344229
+(0, 2) ~ (3, 3) => 0.0475929
+(0, 2) ~ (3, 4) => 0.208346
+(0, 2) ~ (3, 5) => 0.0453192
+(0, 3) ~ (3, 2) => 0.323826
+(0, 3) ~ (3, 3) => 0.304373
+(0, 3) ~ (3, 4) => 0.0637306
+(0, 3) ~ (3, 5) => 0.204256
+(0, 3) ~ (3, 6) => 0.0514972
+(0, 4) ~ (3, 3) => 0.33791
+(0, 4) ~ (3, 4) => 0.272916
+(0, 4) ~ (3, 5) => 0.0802968
+(0, 4) ~ (3, 6) => 0.151937
+(0, 4) ~ (3, 7) => 0.0569922
+(0, 5) ~ (3, 4) => 0.359347
+(0, 5) ~ (3, 5) => 0.203911
+(0, 5) ~ (3, 6) => 0.180431
+(0, 5) ~ (3, 7) => 0.129578
+(0, 5) ~ (3, 8) => 0.0595082
+(0, 6) ~ (3, 5) => 0.376834
+(0, 6) ~ (3, 6) => 0.134624
+(0, 6) ~ (3, 7) => 0.270089
+(0, 6) ~ (3, 8) => 0.059676
+(0, 6) ~ (3, 9) => 0.070046
+(0, 7) ~ (3, 6) => 0.310302
+(0, 7) ~ (3, 7) => 0.0199317
+(0, 7) ~ (3, 8) => 0.509028
+(0, 7) ~ (3, 9) => 0.0397365
+(0, 7) ~ (3, 10) => 0.0953032
+(0, 8) ~ (3, 7) => 0.303682
+(0, 8) ~ (3, 9) => 0.517125
+(0, 8) ~ (3, 10) => 0.024616
+(0, 8) ~ (3, 11) => 0.132073
+(0, 9) ~ (3, 8) => 0.29235
+(0, 9) ~ (3, 10) => 0.511032
+(0, 9) ~ (3, 11) => 0.0258647
+(0, 9) ~ (3, 12) => 0.148107
+(0, 10) ~ (3, 9) => 0.282905
+(0, 10) ~ (3, 11) => 0.503508
+(0, 10) ~ (3, 12) => 0.028719
+(0, 10) ~ (3, 13) => 0.163121
+(0, 11) ~ (3, 10) => 0.266261
+(0, 11) ~ (3, 12) => 0.489795
+(0, 11) ~ (3, 13) => 0.0363559
+(0, 11) ~ (3, 14) => 0.189513
+(0, 12) ~ (3, 11) => 0.17955
+(0, 12) ~ (3, 13) => 0.368414
+(0, 12) ~ (3, 14) => 0.074291
+(0, 12) ~ (3, 15) => 0.345575
+(0, 13) ~ (3, 12) => 0.10648
+(0, 13) ~ (3, 14) => 0.142597
+(0, 13) ~ (3, 15) => 0.0961825
+(0, 13) ~ (3, 16) => 0.613809
+(0, 14) ~ (3, 12) => 0.0206354
+(0, 14) ~ (3, 13) => 0.0753847
+(0, 14) ~ (3, 15) => 0.065411
+(0, 14) ~ (3, 16) => 0.184391
+(0, 14) ~ (3, 17) => 0.620348
+(0, 15) ~ (3, 13) => 0.0274866
+(0, 15) ~ (3, 14) => 0.055961
+(0, 15) ~ (3, 16) => 0.0436467
+(0, 15) ~ (3, 17) => 0.224346
+(0, 15) ~ (3, 18) => 0.619655
+(0, 16) ~ (3, 14) => 0.0208178
+(0, 16) ~ (3, 15) => 0.0416291
+(0, 16) ~ (3, 17) => 0.0250435
+(0, 16) ~ (3, 18) => 0.277239
+(0, 16) ~ (3, 19) => 0.380961
+(0, 17) ~ (3, 15) => 0.0175353
+(0, 17) ~ (3, 16) => 0.0129838
+(0, 17) ~ (3, 18) => 0.0149752
+(0, 17) ~ (3, 19) => 0.554923
+(0, 17) ~ (3, 20) => 0.0818338
+(0, 18) ~ (3, 20) => 0.900597
+(0, 18) ~ (3, 21) => 0.0323831
+(0, 19) ~ (3, 21) => 0.959243
+(0, 20) ~ (3, 22) => 0.994815
+(0, 21) ~ (3, 23) => 0.999918
+(0, 22) ~ (3, 24) => 0.999994
+(0, 23) ~ (3, 25) => 0.999988
+(0, 24) ~ (3, 26) => 0.999936
+(0, 25) ~ (3, 27) => 0.999753
+(0, 26) ~ (3, 28) => 0.999716
+(0, 27) ~ (3, 29) => 0.999748
+(0, 28) ~ (3, 30) => 0.999147
+(0, 29) ~ (3, 31) => 0.997694
+(0, 30) ~ (3, 32) => 0.997105
+(0, 31) ~ (3, 33) => 0.995592
+(0, 32) ~ (3, 34) => 0.995535
+(0, 33) ~ (3, 35) => 0.996566
+(0, 34) ~ (3, 36) => 0.99685
+(0, 35) ~ (3, 37) => 0.99653
+(0, 36) ~ (3, 38) => 0.995223
+(0, 37) ~ (3, 39) => 0.993722
+(0, 38) ~ (3, 40) => 0.987608
+(0, 39) ~ (3, 41) => 0.985913
+(0, 40) ~ (3, 42) => 0.987189
+(0, 41) ~ (3, 43) => 0.991909
+(0, 42) ~ (3, 44) => 0.996245
+(0, 43) ~ (3, 45) => 0.990441
+(0, 44) ~ (3, 46) => 0.983726
+(0, 45) ~ (3, 47) => 0.920085
+(0, 45) ~ (3, 49) => 0.0626211
+(0, 46) ~ (3, 48) => 0.726134
+(0, 46) ~ (3, 50) => 0.242387
+(0, 47) ~ (3, 49) => 0.324821
+(0, 47) ~ (3, 50) => 0.0222893
+(0, 47) ~ (3, 51) => 0.624472
+(0, 47) ~ (3, 52) => 0.0101649
+(0, 48) ~ (3, 50) => 0.198142
+(0, 48) ~ (3, 51) => 0.0178333
+(0, 48) ~ (3, 52) => 0.758879
+(0, 49) ~ (3, 51) => 0.0823622
+(0, 49) ~ (3, 53) => 0.894614
+(0, 50) ~ (3, 54) => 0.989894
+(0, 51) ~ (3, 55) => 0.998903
+(0, 52) ~ (3, 56) => 0.999891
+(0, 53) ~ (3, 57) => 0.999981
+(0, 54) ~ (3, 58) => 0.999977
+(0, 55) ~ (3, 59) => 0.999728
+(0, 56) ~ (3, 60) => 0.99886
+(0, 57) ~ (3, 61) => 0.973886
+(0, 57) ~ (3, 62) => 0.0257788
+(0, 58) ~ (3, 62) => 0.965748
+(0, 58) ~ (3, 63) => 0.0337701
+(0, 59) ~ (3, 63) => 0.862898
+(0, 59) ~ (3, 64) => 0.136007
+(0, 60) ~ (3, 64) => 0.7602
+(0, 60) ~ (3, 65) => 0.238096
+(0, 61) ~ (3, 65) => 0.657848
+(0, 61) ~ (3, 66) => 0.340352
+(0, 62) ~ (3, 66) => 0.168717
+(0, 62) ~ (3, 67) => 0.829581
+(0, 63) ~ (3, 67) => 0.0911778
+(0, 63) ~ (3, 68) => 0.907216
+(0, 64) ~ (3, 68) => 0.0169918
+(0, 64) ~ (3, 69) => 0.982688
+(0, 65) ~ (3, 70) => 0.999768
+(0, 66) ~ (3, 71) => 0.999758
+(0, 67) ~ (3, 72) => 0.998631
+(0, 68) ~ (3, 73) => 0.998603
+(0, 69) ~ (3, 74) => 0.99885
+(0, 70) ~ (3, 75) => 0.999803
+(0, 71) ~ (3, 76) => 0.99992
+(0, 72) ~ (3, 77) => 0.999954
+(0, 73) ~ (3, 78) => 0.999862
+(0, 74) ~ (3, 79) => 0.999792
+(0, 75) ~ (3, 80) => 0.999387
+(0, 76) ~ (3, 81) => 0.991378
+(0, 77) ~ (3, 82) => 0.980662
+(0, 77) ~ (3, 83) => 0.0168353
+(0, 78) ~ (3, 83) => 0.978418
+(0, 78) ~ (3, 84) => 0.0168635
+(0, 79) ~ (3, 84) => 0.977064
+(0, 79) ~ (3, 85) => 0.0158169
+(0, 80) ~ (3, 85) => 0.976706
+(0, 80) ~ (3, 86) => 0.0167812
+(0, 81) ~ (3, 86) => 0.978793
+(0, 81) ~ (3, 87) => 0.0156804
+(0, 82) ~ (3, 87) => 0.980733
+(0, 83) ~ (3, 88) => 0.989764
+(0, 84) ~ (3, 89) => 0.994745
+(0, 85) ~ (3, 90) => 0.99903
+(0, 86) ~ (3, 91) => 0.999285
+(0, 87) ~ (3, 92) => 0.999861
+(0, 88) ~ (3, 93) => 0.999874
+(0, 89) ~ (3, 94) => 0.999823
+(0, 90) ~ (3, 95) => 0.999397
+(0, 91) ~ (3, 96) => 0.998983
+(0, 92) ~ (3, 97) => 0.997115
+(0, 93) ~ (3, 98) => 0.995936
+(0, 94) ~ (3, 99) => 0.994726
+(0, 95) ~ (3, 100) => 0.984092
+(0, 96) ~ (3, 101) => 0.97506
+(0, 96) ~ (3, 102) => 0.0123873
+(0, 97) ~ (3, 102) => 0.963228
+(0, 97) ~ (3, 103) => 0.017366
+(0, 98) ~ (3, 103) => 0.952933
+(0, 98) ~ (3, 104) => 0.0220295
+(0, 99) ~ (3, 104) => 0.947447
+(0, 99) ~ (3, 105) => 0.0251221
+(0, 100) ~ (3, 104) => 0.0104867
+(0, 100) ~ (3, 105) => 0.94829
+(0, 100) ~ (3, 106) => 0.021518
+(0, 101) ~ (3, 105) => 0.0105598
+(0, 101) ~ (3, 106) => 0.961473
+(0, 101) ~ (3, 107) => 0.0147668
+(0, 102) ~ (3, 107) => 0.978764
+(0, 103) ~ (3, 108) => 0.989581
+(0, 104) ~ (3, 109) => 0.999403
+(0, 105) ~ (3, 110) => 0.999714
+(0, 106) ~ (3, 111) => 0.99982
+(0, 107) ~ (3, 112) => 0.999952
+(0, 108) ~ (3, 113) => 0.999964
+(0, 109) ~ (3, 114) => 0.999948
+(0, 110) ~ (3, 115) => 0.99996
+(0, 111) ~ (3, 116) => 0.999988
+(0, 112) ~ (3, 117) => 0.999959
+(0, 113) ~ (3, 118) => 0.999852
+(0, 114) ~ (3, 119) => 0.99902
+(0, 115) ~ (3, 120) => 0.992036
+(0, 116) ~ (3, 121) => 0.986692
+(0, 117) ~ (3, 121) => 0.0103366
+(0, 117) ~ (3, 122) => 0.981732
+(0, 118) ~ (3, 122) => 0.0152999
+(0, 118) ~ (3, 123) => 0.981632
+(0, 119) ~ (3, 124) => 0.988605
+(0, 120) ~ (3, 125) => 0.989909
+(0, 121) ~ (3, 126) => 0.989303
+(0, 122) ~ (3, 127) => 0.990573
+(0, 123) ~ (3, 128) => 0.998255
+(0, 124) ~ (3, 129) => 0.999882
+(0, 125) ~ (3, 130) => 0.999947
+(0, 126) ~ (3, 131) => 0.999967
+(0, 127) ~ (3, 132) => 0.999982
+(0, 128) ~ (3, 133) => 0.999925
+(0, 129) ~ (3, 134) => 0.999744
+(0, 130) ~ (3, 135) => 0.999566
+(0, 131) ~ (3, 136) => 0.998649
+(0, 132) ~ (3, 137) => 0.997995
+(0, 133) ~ (3, 138) => 0.998048
+(0, 134) ~ (3, 139) => 0.999437
+(0, 135) ~ (3, 140) => 0.998906
+(0, 136) ~ (3, 141) => 0.999
+(0, 137) ~ (3, 142) => 0.999824
+(0, 138) ~ (3, 143) => 0.999966
+(0, 139) ~ (3, 144) => 0.999985
+(0, 140) ~ (3, 145) => 0.999963
+(0, 141) ~ (3, 146) => 0.999949
+(0, 142) ~ (3, 147) => 0.999965
+(0, 143) ~ (3, 148) => 0.999979
+(0, 144) ~ (3, 149) => 0.999996
+(0, 145) ~ (3, 150) => 0.999993
+(0, 146) ~ (3, 151) => 0.999965
+(0, 147) ~ (3, 152) => 0.999752
+(0, 148) ~ (3, 153) => 0.999428
+(0, 149) ~ (3, 154) => 0.999456
+(0, 150) ~ (3, 155) => 0.999845
+(0, 151) ~ (3, 156) => 0.999944
+(0, 152) ~ (3, 157) => 0.99973
+(0, 153) ~ (3, 158) => 0.999514
+(0, 154) ~ (3, 159) => 0.99923
+(0, 155) ~ (3, 160) => 0.99896
+(0, 156) ~ (3, 161) => 0.996036
+(0, 157) ~ (3, 162) => 0.993818
+(0, 158) ~ (3, 163) => 0.992366
+(0, 159) ~ (3, 164) => 0.988917
+(0, 160) ~ (3, 165) => 0.988574
+(0, 161) ~ (3, 166) => 0.989602
+(0, 162) ~ (3, 167) => 0.991049
+(0, 163) ~ (3, 168) => 0.992011
+(0, 164) ~ (3, 169) => 0.991864
+(0, 165) ~ (3, 170) => 0.992366
+(0, 166) ~ (3, 171) => 0.992853
+(0, 167) ~ (3, 172) => 0.992473
+(0, 168) ~ (3, 173) => 0.99269
+(0, 169) ~ (3, 174) => 0.993218
+(0, 170) ~ (3, 175) => 0.994006
+(0, 171) ~ (3, 176) => 0.995384
+(0, 172) ~ (3, 177) => 0.996321
+(0, 173) ~ (3, 178) => 0.99567
+(0, 174) ~ (3, 179) => 0.996102
+(0, 175) ~ (3, 180) => 0.99605
+(0, 176) ~ (3, 181) => 0.997943
+(0, 177) ~ (3, 182) => 0.999641
+(0, 178) ~ (3, 183) => 0.999857
+(0, 179) ~ (3, 184) => 0.995955
+(0, 180) ~ (3, 185) => 0.992007
+(0, 181) ~ (3, 186) => 0.891649
+(0, 182) ~ (3, 186) => 0.105279
+(0, 182) ~ (3, 187) => 0.816319
+(0, 183) ~ (3, 187) => 0.171694
+(0, 183) ~ (3, 188) => 0.713917
+(0, 183) ~ (3, 189) => 0.0109857
+(0, 184) ~ (3, 188) => 0.270236
+(0, 184) ~ (3, 189) => 0.463727
+(0, 184) ~ (3, 190) => 0.0377497
+(0, 185) ~ (3, 189) => 0.48348
+(0, 185) ~ (3, 190) => 0.386296
+(0, 185) ~ (3, 191) => 0.0613418
+(0, 185) ~ (3, 192) => 0.0237557
+(0, 186) ~ (3, 190) => 0.506434
+(0, 186) ~ (3, 191) => 0.267725
+(0, 186) ~ (3, 192) => 0.102257
+(0, 186) ~ (3, 193) => 0.0759969
+(0, 187) ~ (3, 191) => 0.525267
+(0, 187) ~ (3, 192) => 0.131927
+(0, 187) ~ (3, 193) => 0.192942
+(0, 187) ~ (3, 194) => 0.124363
+(0, 188) ~ (3, 192) => 0.298726
+(0, 188) ~ (3, 193) => 0.0744224
+(0, 188) ~ (3, 194) => 0.218894
+(0, 188) ~ (3, 195) => 0.372883
+(0, 189) ~ (3, 192) => 0.0212
+(0, 189) ~ (3, 193) => 0.232901
+(0, 189) ~ (3, 194) => 0.0367877
+(0, 189) ~ (3, 195) => 0.307823
+(0, 189) ~ (3, 196) => 0.361461
+(0, 190) ~ (3, 193) => 0.0264794
+(0, 190) ~ (3, 194) => 0.0499937
+(0, 190) ~ (3, 195) => 0.0105654
+(0, 190) ~ (3, 196) => 0.533805
+(0, 190) ~ (3, 197) => 0.33825
+(0, 191) ~ (3, 194) => 0.0315484
+(0, 191) ~ (3, 195) => 0.0355312
+(0, 191) ~ (3, 197) => 0.571763
+(0, 191) ~ (3, 198) => 0.283779
+(0, 192) ~ (3, 195) => 0.0295944
+(0, 192) ~ (3, 196) => 0.0287529
+(0, 192) ~ (3, 198) => 0.632966
+(0, 192) ~ (3, 199) => 0.19588
+(0, 193) ~ (3, 196) => 0.0303312
+(0, 193) ~ (3, 197) => 0.0247499
+(0, 193) ~ (3, 199) => 0.728508
+(0, 193) ~ (3, 200) => 0.166706
+(0, 194) ~ (3, 197) => 0.0227545
+(0, 194) ~ (3, 198) => 0.0173771
+(0, 194) ~ (3, 200) => 0.779059
+(0, 194) ~ (3, 201) => 0.10118
+(0, 195) ~ (3, 198) => 0.0113913
+(0, 195) ~ (3, 199) => 0.0104827
+(0, 195) ~ (3, 201) => 0.868535
+(0, 195) ~ (3, 202) => 0.0226979
+(0, 196) ~ (3, 202) => 0.963224
+(0, 196) ~ (3, 203) => 0.0116733
+(0, 197) ~ (3, 203) => 0.9825
+(0, 198) ~ (3, 204) => 0.996081
+(0, 199) ~ (3, 205) => 0.998199
+(0, 200) ~ (3, 206) => 0.9988
+(0, 201) ~ (3, 207) => 0.998619
+(0, 202) ~ (3, 208) => 0.998287
+(0, 203) ~ (3, 209) => 0.997418
+(0, 204) ~ (3, 210) => 0.997371
+(0, 205) ~ (3, 211) => 0.998104
+(0, 206) ~ (3, 212) => 0.999518
+(0, 207) ~ (3, 213) => 0.998676
+(0, 208) ~ (3, 214) => 0.991467
+(0, 209) ~ (3, 215) => 0.982737
+(0, 210) ~ (3, 215) => 0.0162395
+(0, 210) ~ (3, 216) => 0.975531
+(0, 211) ~ (3, 216) => 0.0233495
+(0, 211) ~ (3, 217) => 0.975447
+(0, 212) ~ (3, 217) => 0.01827
+(0, 212) ~ (3, 218) => 0.981042
+(0, 213) ~ (3, 218) => 0.0132324
+(0, 213) ~ (3, 219) => 0.986376
+(0, 214) ~ (3, 220) => 0.991385
+(0, 215) ~ (3, 221) => 0.994184
+(0, 216) ~ (3, 222) => 0.993976
+(0, 217) ~ (3, 223) => 0.994804
+(0, 218) ~ (3, 224) => 0.995643
+(0, 219) ~ (3, 225) => 0.997593
+(0, 220) ~ (3, 226) => 0.999293
+(0, 221) ~ (3, 227) => 0.999359
+(0, 222) ~ (3, 228) => 0.999674
+(0, 223) ~ (3, 229) => 0.99986
+(0, 224) ~ (3, 230) => 0.999988
+(0, 225) ~ (3, 231) => 0.999991
+(0, 226) ~ (3, 232) => 0.999982
+(0, 227) ~ (3, 233) => 0.999898
+(0, 228) ~ (3, 234) => 0.998763
+(0, 229) ~ (3, 235) => 0.995801
+(0, 230) ~ (3, 236) => 0.995812
+(0, 231) ~ (3, 237) => 0.998729
+(0, 232) ~ (3, 238) => 0.999385
+
+; gap posteriors
+(0, 0) ~ (3, -1) => 0.299911
+(0, 1) ~ (3, -1) => 0.0335389
+(0, 2) ~ (3, -1) => 0.045219
+(0, 3) ~ (3, -1) => 0.0523184
+(0, 4) ~ (3, -1) => 0.0999478
+(0, 5) ~ (3, -1) => 0.0672246
+(0, 6) ~ (3, -1) => 0.0887307
+(0, 7) ~ (3, -1) => 0.0256978
+(0, 8) ~ (3, -1) => 0.0225036
+(0, 9) ~ (3, -1) => 0.0226464
+(0, 10) ~ (3, -1) => 0.021748
+(0, 11) ~ (3, -1) => 0.0180745
+(0, 12) ~ (3, -1) => 0.0321702
+(0, 13) ~ (3, -1) => 0.0409312
+(0, 14) ~ (3, -1) => 0.0338302
+(0, 15) ~ (3, -1) => 0.0289053
+(0, 16) ~ (3, -1) => 0.25431
+(0, 17) ~ (3, -1) => 0.317749
+(0, 18) ~ (3, -1) => 0.0670201
+(0, 19) ~ (3, -1) => 0.0407566
+(0, 20) ~ (3, -1) => 0.00518495
+(0, 21) ~ (3, -1) => 0.0001
+(0, 22) ~ (3, -1) => 0.0001
+(0, 23) ~ (3, -1) => 0.0001
+(0, 24) ~ (3, -1) => 0.0001
+(0, 25) ~ (3, -1) => 0.000247002
+(0, 26) ~ (3, -1) => 0.000283778
+(0, 27) ~ (3, -1) => 0.00025177
+(0, 28) ~ (3, -1) => 0.000852585
+(0, 29) ~ (3, -1) => 0.00230551
+(0, 30) ~ (3, -1) => 0.00289476
+(0, 31) ~ (3, -1) => 0.00440848
+(0, 32) ~ (3, -1) => 0.00446504
+(0, 33) ~ (3, -1) => 0.0034337
+(0, 34) ~ (3, -1) => 0.00314951
+(0, 35) ~ (3, -1) => 0.0034703
+(0, 36) ~ (3, -1) => 0.00477743
+(0, 37) ~ (3, -1) => 0.0062775
+(0, 38) ~ (3, -1) => 0.0123917
+(0, 39) ~ (3, -1) => 0.0140868
+(0, 40) ~ (3, -1) => 0.0128109
+(0, 41) ~ (3, -1) => 0.00809103
+(0, 42) ~ (3, -1) => 0.00375515
+(0, 43) ~ (3, -1) => 0.00955874
+(0, 44) ~ (3, -1) => 0.0162743
+(0, 45) ~ (3, -1) => 0.0172939
+(0, 46) ~ (3, -1) => 0.031479
+(0, 47) ~ (3, -1) => 0.0182534
+(0, 48) ~ (3, -1) => 0.0251459
+(0, 49) ~ (3, -1) => 0.0230238
+(0, 50) ~ (3, -1) => 0.0101058
+(0, 51) ~ (3, -1) => 0.00109684
+(0, 52) ~ (3, -1) => 0.000108957
+(0, 53) ~ (3, -1) => 0.0001
+(0, 54) ~ (3, -1) => 0.0001
+(0, 55) ~ (3, -1) => 0.000271738
+(0, 56) ~ (3, -1) => 0.00114018
+(0, 57) ~ (3, -1) => 0.000335172
+(0, 58) ~ (3, -1) => 0.000481941
+(0, 59) ~ (3, -1) => 0.00109492
+(0, 60) ~ (3, -1) => 0.00170398
+(0, 61) ~ (3, -1) => 0.00180039
+(0, 62) ~ (3, -1) => 0.00170177
+(0, 63) ~ (3, -1) => 0.00160569
+(0, 64) ~ (3, -1) => 0.000319839
+(0, 65) ~ (3, -1) => 0.000231981
+(0, 66) ~ (3, -1) => 0.000241816
+(0, 67) ~ (3, -1) => 0.00136942
+(0, 68) ~ (3, -1) => 0.00139678
+(0, 69) ~ (3, -1) => 0.00114995
+(0, 70) ~ (3, -1) => 0.000196815
+(0, 71) ~ (3, -1) => 0.0001
+(0, 72) ~ (3, -1) => 0.0001
+(0, 73) ~ (3, -1) => 0.000138104
+(0, 74) ~ (3, -1) => 0.000207782
+(0, 75) ~ (3, -1) => 0.000612855
+(0, 76) ~ (3, -1) => 0.00862223
+(0, 77) ~ (3, -1) => 0.00250255
+(0, 78) ~ (3, -1) => 0.00471883
+(0, 79) ~ (3, -1) => 0.00711954
+(0, 80) ~ (3, -1) => 0.0065129
+(0, 81) ~ (3, -1) => 0.00552634
+(0, 82) ~ (3, -1) => 0.0192668
+(0, 83) ~ (3, -1) => 0.0102357
+(0, 84) ~ (3, -1) => 0.00525498
+(0, 85) ~ (3, -1) => 0.000969648
+(0, 86) ~ (3, -1) => 0.000715375
+(0, 87) ~ (3, -1) => 0.000139475
+(0, 88) ~ (3, -1) => 0.000125647
+(0, 89) ~ (3, -1) => 0.000176549
+(0, 90) ~ (3, -1) => 0.000603199
+(0, 91) ~ (3, -1) => 0.00101727
+(0, 92) ~ (3, -1) => 0.00288451
+(0, 93) ~ (3, -1) => 0.00406379
+(0, 94) ~ (3, -1) => 0.00527382
+(0, 95) ~ (3, -1) => 0.0159079
+(0, 96) ~ (3, -1) => 0.0125526
+(0, 97) ~ (3, -1) => 0.0194059
+(0, 98) ~ (3, -1) => 0.0250372
+(0, 99) ~ (3, -1) => 0.0274304
+(0, 100) ~ (3, -1) => 0.0197054
+(0, 101) ~ (3, -1) => 0.0132006
+(0, 102) ~ (3, -1) => 0.0212355
+(0, 103) ~ (3, -1) => 0.0104192
+(0, 104) ~ (3, -1) => 0.000597477
+(0, 105) ~ (3, -1) => 0.000286162
+(0, 106) ~ (3, -1) => 0.000180185
+(0, 107) ~ (3, -1) => 0.0001
+(0, 108) ~ (3, -1) => 0.0001
+(0, 109) ~ (3, -1) => 0.0001
+(0, 110) ~ (3, -1) => 0.0001
+(0, 111) ~ (3, -1) => 0.0001
+(0, 112) ~ (3, -1) => 0.0001
+(0, 113) ~ (3, -1) => 0.000148177
+(0, 114) ~ (3, -1) => 0.000979722
+(0, 115) ~ (3, -1) => 0.00796402
+(0, 116) ~ (3, -1) => 0.0133081
+(0, 117) ~ (3, -1) => 0.00793123
+(0, 118) ~ (3, -1) => 0.00306761
+(0, 119) ~ (3, -1) => 0.0113949
+(0, 120) ~ (3, -1) => 0.0100909
+(0, 121) ~ (3, -1) => 0.0106972
+(0, 122) ~ (3, -1) => 0.00942659
+(0, 123) ~ (3, -1) => 0.00174463
+(0, 124) ~ (3, -1) => 0.00011754
+(0, 125) ~ (3, -1) => 0.0001
+(0, 126) ~ (3, -1) => 0.0001
+(0, 127) ~ (3, -1) => 0.0001
+(0, 128) ~ (3, -1) => 0.0001
+(0, 129) ~ (3, -1) => 0.000256002
+(0, 130) ~ (3, -1) => 0.000433981
+(0, 131) ~ (3, -1) => 0.00135058
+(0, 132) ~ (3, -1) => 0.00200474
+(0, 133) ~ (3, -1) => 0.00195152
+(0, 134) ~ (3, -1) => 0.000562847
+(0, 135) ~ (3, -1) => 0.00109446
+(0, 136) ~ (3, -1) => 0.000999689
+(0, 137) ~ (3, -1) => 0.000176072
+(0, 138) ~ (3, -1) => 0.0001
+(0, 139) ~ (3, -1) => 0.0001
+(0, 140) ~ (3, -1) => 0.0001
+(0, 141) ~ (3, -1) => 0.0001
+(0, 142) ~ (3, -1) => 0.0001
+(0, 143) ~ (3, -1) => 0.0001
+(0, 144) ~ (3, -1) => 0.0001
+(0, 145) ~ (3, -1) => 0.0001
+(0, 146) ~ (3, -1) => 0.0001
+(0, 147) ~ (3, -1) => 0.000247717
+(0, 148) ~ (3, -1) => 0.000572026
+(0, 149) ~ (3, -1) => 0.000543773
+(0, 150) ~ (3, -1) => 0.000154614
+(0, 151) ~ (3, -1) => 0.0001
+(0, 152) ~ (3, -1) => 0.000269771
+(0, 153) ~ (3, -1) => 0.000485778
+(0, 154) ~ (3, -1) => 0.00077045
+(0, 155) ~ (3, -1) => 0.00104022
+(0, 156) ~ (3, -1) => 0.00396353
+(0, 157) ~ (3, -1) => 0.00618249
+(0, 158) ~ (3, -1) => 0.0076341
+(0, 159) ~ (3, -1) => 0.0110826
+(0, 160) ~ (3, -1) => 0.0114257
+(0, 161) ~ (3, -1) => 0.0103984
+(0, 162) ~ (3, -1) => 0.00895095
+(0, 163) ~ (3, -1) => 0.00798911
+(0, 164) ~ (3, -1) => 0.00813627
+(0, 165) ~ (3, -1) => 0.00763363
+(0, 166) ~ (3, -1) => 0.00714725
+(0, 167) ~ (3, -1) => 0.00752735
+(0, 168) ~ (3, -1) => 0.00730968
+(0, 169) ~ (3, -1) => 0.00678241
+(0, 170) ~ (3, -1) => 0.0059936
+(0, 171) ~ (3, -1) => 0.0046162
+(0, 172) ~ (3, -1) => 0.00367928
+(0, 173) ~ (3, -1) => 0.00432962
+(0, 174) ~ (3, -1) => 0.00389832
+(0, 175) ~ (3, -1) => 0.0039497
+(0, 176) ~ (3, -1) => 0.00205708
+(0, 177) ~ (3, -1) => 0.000359237
+(0, 178) ~ (3, -1) => 0.000143349
+(0, 179) ~ (3, -1) => 0.00404489
+(0, 180) ~ (3, -1) => 0.00799346
+(0, 181) ~ (3, -1) => 0.108351
+(0, 182) ~ (3, -1) => 0.0784019
+(0, 183) ~ (3, -1) => 0.103403
+(0, 184) ~ (3, -1) => 0.228287
+(0, 185) ~ (3, -1) => 0.0451264
+(0, 186) ~ (3, -1) => 0.0475877
+(0, 187) ~ (3, -1) => 0.0255018
+(0, 188) ~ (3, -1) => 0.0350746
+(0, 189) ~ (3, -1) => 0.039827
+(0, 190) ~ (3, -1) => 0.0409064
+(0, 191) ~ (3, -1) => 0.0773785
+(0, 192) ~ (3, -1) => 0.112807
+(0, 193) ~ (3, -1) => 0.0497052
+(0, 194) ~ (3, -1) => 0.0796297
+(0, 195) ~ (3, -1) => 0.0868927
+(0, 196) ~ (3, -1) => 0.0251031
+(0, 197) ~ (3, -1) => 0.0175004
+(0, 198) ~ (3, -1) => 0.00391871
+(0, 199) ~ (3, -1) => 0.00180066
+(0, 200) ~ (3, -1) => 0.00120038
+(0, 201) ~ (3, -1) => 0.00138146
+(0, 202) ~ (3, -1) => 0.0017128
+(0, 203) ~ (3, -1) => 0.00258249
+(0, 204) ~ (3, -1) => 0.00262886
+(0, 205) ~ (3, -1) => 0.00189644
+(0, 206) ~ (3, -1) => 0.000482321
+(0, 207) ~ (3, -1) => 0.00132352
+(0, 208) ~ (3, -1) => 0.0085327
+(0, 209) ~ (3, -1) => 0.0172632
+(0, 210) ~ (3, -1) => 0.00822937
+(0, 211) ~ (3, -1) => 0.00120306
+(0, 212) ~ (3, -1) => 0.000687659
+(0, 213) ~ (3, -1) => 0.000391662
+(0, 214) ~ (3, -1) => 0.00861484
+(0, 215) ~ (3, -1) => 0.00581557
+(0, 216) ~ (3, -1) => 0.00602382
+(0, 217) ~ (3, -1) => 0.00519574
+(0, 218) ~ (3, -1) => 0.00435698
+(0, 219) ~ (3, -1) => 0.00240713
+(0, 220) ~ (3, -1) => 0.000707388
+(0, 221) ~ (3, -1) => 0.000640929
+(0, 222) ~ (3, -1) => 0.000326097
+(0, 223) ~ (3, -1) => 0.000139892
+(0, 224) ~ (3, -1) => 0.0001
+(0, 225) ~ (3, -1) => 0.0001
+(0, 226) ~ (3, -1) => 0.0001
+(0, 227) ~ (3, -1) => 0.000102341
+(0, 228) ~ (3, -1) => 0.00123703
+(0, 229) ~ (3, -1) => 0.00419861
+(0, 230) ~ (3, -1) => 0.00418806
+(0, 231) ~ (3, -1) => 0.00127113
+(0, 232) ~ (3, -1) => 0.00061518
+
+(0, -1) ~ (3, 0) => 0.191442
+(0, -1) ~ (3, 1) => 0.281631
+(0, -1) ~ (3, 2) => 0.140715
+(0, -1) ~ (3, 3) => 0.0729202
+(0, -1) ~ (3, 4) => 0.0751782
+(0, -1) ~ (3, 5) => 0.0893828
+(0, -1) ~ (3, 6) => 0.171209
+(0, -1) ~ (3, 7) => 0.219727
+(0, -1) ~ (3, 8) => 0.0794379
+(0, -1) ~ (3, 9) => 0.0901879
+(0, -1) ~ (3, 10) => 0.102788
+(0, -1) ~ (3, 11) => 0.159004
+(0, -1) ~ (3, 12) => 0.206263
+(0, -1) ~ (3, 13) => 0.329238
+(0, -1) ~ (3, 14) => 0.51682
+(0, -1) ~ (3, 15) => 0.433667
+(0, -1) ~ (3, 16) => 0.145169
+(0, -1) ~ (3, 17) => 0.130263
+(0, -1) ~ (3, 18) => 0.0881311
+(0, -1) ~ (3, 19) => 0.0641164
+(0, -1) ~ (3, 20) => 0.0175695
+(0, -1) ~ (3, 21) => 0.00837344
+(0, -1) ~ (3, 22) => 0.00518495
+(0, -1) ~ (3, 23) => 0.0001
+(0, -1) ~ (3, 24) => 0.0001
+(0, -1) ~ (3, 25) => 0.0001
+(0, -1) ~ (3, 26) => 0.0001
+(0, -1) ~ (3, 27) => 0.000247002
+(0, -1) ~ (3, 28) => 0.000283778
+(0, -1) ~ (3, 29) => 0.00025177
+(0, -1) ~ (3, 30) => 0.000852585
+(0, -1) ~ (3, 31) => 0.00230551
+(0, -1) ~ (3, 32) => 0.00289476
+(0, -1) ~ (3, 33) => 0.00440848
+(0, -1) ~ (3, 34) => 0.00446504
+(0, -1) ~ (3, 35) => 0.0034337
+(0, -1) ~ (3, 36) => 0.00314951
+(0, -1) ~ (3, 37) => 0.0034703
+(0, -1) ~ (3, 38) => 0.00477743
+(0, -1) ~ (3, 39) => 0.0062775
+(0, -1) ~ (3, 40) => 0.0123917
+(0, -1) ~ (3, 41) => 0.0140868
+(0, -1) ~ (3, 42) => 0.0128109
+(0, -1) ~ (3, 43) => 0.00809103
+(0, -1) ~ (3, 44) => 0.00375515
+(0, -1) ~ (3, 45) => 0.00955874
+(0, -1) ~ (3, 46) => 0.0162743
+(0, -1) ~ (3, 47) => 0.079915
+(0, -1) ~ (3, 48) => 0.273866
+(0, -1) ~ (3, 49) => 0.612558
+(0, -1) ~ (3, 50) => 0.537183
+(0, -1) ~ (3, 51) => 0.275333
+(0, -1) ~ (3, 52) => 0.230956
+(0, -1) ~ (3, 53) => 0.105386
+(0, -1) ~ (3, 54) => 0.0101058
+(0, -1) ~ (3, 55) => 0.00109684
+(0, -1) ~ (3, 56) => 0.000108957
+(0, -1) ~ (3, 57) => 0.0001
+(0, -1) ~ (3, 58) => 0.0001
+(0, -1) ~ (3, 59) => 0.000271738
+(0, -1) ~ (3, 60) => 0.00114018
+(0, -1) ~ (3, 61) => 0.026114
+(0, -1) ~ (3, 62) => 0.00847322
+(0, -1) ~ (3, 63) => 0.103332
+(0, -1) ~ (3, 64) => 0.103793
+(0, -1) ~ (3, 65) => 0.104057
+(0, -1) ~ (3, 66) => 0.490931
+(0, -1) ~ (3, 67) => 0.0792408
+(0, -1) ~ (3, 68) => 0.0757917
+(0, -1) ~ (3, 69) => 0.0173117
+(0, -1) ~ (3, 70) => 0.000231981
+(0, -1) ~ (3, 71) => 0.000241816
+(0, -1) ~ (3, 72) => 0.00136942
+(0, -1) ~ (3, 73) => 0.00139678
+(0, -1) ~ (3, 74) => 0.00114995
+(0, -1) ~ (3, 75) => 0.000196815
+(0, -1) ~ (3, 76) => 0.0001
+(0, -1) ~ (3, 77) => 0.0001
+(0, -1) ~ (3, 78) => 0.000138104
+(0, -1) ~ (3, 79) => 0.000207782
+(0, -1) ~ (3, 80) => 0.000612855
+(0, -1) ~ (3, 81) => 0.00862223
+(0, -1) ~ (3, 82) => 0.0193379
+(0, -1) ~ (3, 83) => 0.00474697
+(0, -1) ~ (3, 84) => 0.006073
+(0, -1) ~ (3, 85) => 0.00747716
+(0, -1) ~ (3, 86) => 0.00442553
+(0, -1) ~ (3, 87) => 0.00358641
+(0, -1) ~ (3, 88) => 0.0102357
+(0, -1) ~ (3, 89) => 0.00525498
+(0, -1) ~ (3, 90) => 0.000969648
+(0, -1) ~ (3, 91) => 0.000715375
+(0, -1) ~ (3, 92) => 0.000139475
+(0, -1) ~ (3, 93) => 0.000125647
+(0, -1) ~ (3, 94) => 0.000176549
+(0, -1) ~ (3, 95) => 0.000603199
+(0, -1) ~ (3, 96) => 0.00101727
+(0, -1) ~ (3, 97) => 0.00288451
+(0, -1) ~ (3, 98) => 0.00406379
+(0, -1) ~ (3, 99) => 0.00527382
+(0, -1) ~ (3, 100) => 0.0159079
+(0, -1) ~ (3, 101) => 0.0249399
+(0, -1) ~ (3, 102) => 0.0243845
+(0, -1) ~ (3, 103) => 0.0297008
+(0, -1) ~ (3, 104) => 0.0200363
+(0, -1) ~ (3, 105) => 0.0160283
+(0, -1) ~ (3, 106) => 0.0170091
+(0, -1) ~ (3, 107) => 0.00646871
+(0, -1) ~ (3, 108) => 0.0104192
+(0, -1) ~ (3, 109) => 0.000597477
+(0, -1) ~ (3, 110) => 0.000286162
+(0, -1) ~ (3, 111) => 0.000180185
+(0, -1) ~ (3, 112) => 0.0001
+(0, -1) ~ (3, 113) => 0.0001
+(0, -1) ~ (3, 114) => 0.0001
+(0, -1) ~ (3, 115) => 0.0001
+(0, -1) ~ (3, 116) => 0.0001
+(0, -1) ~ (3, 117) => 0.0001
+(0, -1) ~ (3, 118) => 0.000148177
+(0, -1) ~ (3, 119) => 0.000979722
+(0, -1) ~ (3, 120) => 0.00796402
+(0, -1) ~ (3, 121) => 0.00297155
+(0, -1) ~ (3, 122) => 0.00296788
+(0, -1) ~ (3, 123) => 0.0183675
+(0, -1) ~ (3, 124) => 0.0113949
+(0, -1) ~ (3, 125) => 0.0100909
+(0, -1) ~ (3, 126) => 0.0106972
+(0, -1) ~ (3, 127) => 0.00942659
+(0, -1) ~ (3, 128) => 0.00174463
+(0, -1) ~ (3, 129) => 0.00011754
+(0, -1) ~ (3, 130) => 0.0001
+(0, -1) ~ (3, 131) => 0.0001
+(0, -1) ~ (3, 132) => 0.0001
+(0, -1) ~ (3, 133) => 0.0001
+(0, -1) ~ (3, 134) => 0.000256002
+(0, -1) ~ (3, 135) => 0.000433981
+(0, -1) ~ (3, 136) => 0.00135058
+(0, -1) ~ (3, 137) => 0.00200474
+(0, -1) ~ (3, 138) => 0.00195152
+(0, -1) ~ (3, 139) => 0.000562847
+(0, -1) ~ (3, 140) => 0.00109446
+(0, -1) ~ (3, 141) => 0.000999689
+(0, -1) ~ (3, 142) => 0.000176072
+(0, -1) ~ (3, 143) => 0.0001
+(0, -1) ~ (3, 144) => 0.0001
+(0, -1) ~ (3, 145) => 0.0001
+(0, -1) ~ (3, 146) => 0.0001
+(0, -1) ~ (3, 147) => 0.0001
+(0, -1) ~ (3, 148) => 0.0001
+(0, -1) ~ (3, 149) => 0.0001
+(0, -1) ~ (3, 150) => 0.0001
+(0, -1) ~ (3, 151) => 0.0001
+(0, -1) ~ (3, 152) => 0.000247717
+(0, -1) ~ (3, 153) => 0.000572026
+(0, -1) ~ (3, 154) => 0.000543773
+(0, -1) ~ (3, 155) => 0.000154614
+(0, -1) ~ (3, 156) => 0.0001
+(0, -1) ~ (3, 157) => 0.000269771
+(0, -1) ~ (3, 158) => 0.000485778
+(0, -1) ~ (3, 159) => 0.00077045
+(0, -1) ~ (3, 160) => 0.00104022
+(0, -1) ~ (3, 161) => 0.00396353
+(0, -1) ~ (3, 162) => 0.00618249
+(0, -1) ~ (3, 163) => 0.0076341
+(0, -1) ~ (3, 164) => 0.0110826
+(0, -1) ~ (3, 165) => 0.0114257
+(0, -1) ~ (3, 166) => 0.0103984
+(0, -1) ~ (3, 167) => 0.00895095
+(0, -1) ~ (3, 168) => 0.00798911
+(0, -1) ~ (3, 169) => 0.00813627
+(0, -1) ~ (3, 170) => 0.00763363
+(0, -1) ~ (3, 171) => 0.00714725
+(0, -1) ~ (3, 172) => 0.00752735
+(0, -1) ~ (3, 173) => 0.00730968
+(0, -1) ~ (3, 174) => 0.00678241
+(0, -1) ~ (3, 175) => 0.0059936
+(0, -1) ~ (3, 176) => 0.0046162
+(0, -1) ~ (3, 177) => 0.00367928
+(0, -1) ~ (3, 178) => 0.00432962
+(0, -1) ~ (3, 179) => 0.00389832
+(0, -1) ~ (3, 180) => 0.0039497
+(0, -1) ~ (3, 181) => 0.00205708
+(0, -1) ~ (3, 182) => 0.000359237
+(0, -1) ~ (3, 183) => 0.000143349
+(0, -1) ~ (3, 184) => 0.00404489
+(0, -1) ~ (3, 185) => 0.00799346
+(0, -1) ~ (3, 186) => 0.00307188
+(0, -1) ~ (3, 187) => 0.0119864
+(0, -1) ~ (3, 188) => 0.0158472
+(0, -1) ~ (3, 189) => 0.0418065
+(0, -1) ~ (3, 190) => 0.0695207
+(0, -1) ~ (3, 191) => 0.145666
+(0, -1) ~ (3, 192) => 0.422135
+(0, -1) ~ (3, 193) => 0.397259
+(0, -1) ~ (3, 194) => 0.538414
+(0, -1) ~ (3, 195) => 0.243603
+(0, -1) ~ (3, 196) => 0.0456492
+(0, -1) ~ (3, 197) => 0.0424827
+(0, -1) ~ (3, 198) => 0.0544871
+(0, -1) ~ (3, 199) => 0.0651293
+(0, -1) ~ (3, 200) => 0.0542351
+(0, -1) ~ (3, 201) => 0.0302851
+(0, -1) ~ (3, 202) => 0.0140786
+(0, -1) ~ (3, 203) => 0.00582707
+(0, -1) ~ (3, 204) => 0.00391871
+(0, -1) ~ (3, 205) => 0.00180066
+(0, -1) ~ (3, 206) => 0.00120038
+(0, -1) ~ (3, 207) => 0.00138146
+(0, -1) ~ (3, 208) => 0.0017128
+(0, -1) ~ (3, 209) => 0.00258249
+(0, -1) ~ (3, 210) => 0.00262886
+(0, -1) ~ (3, 211) => 0.00189644
+(0, -1) ~ (3, 212) => 0.000482321
+(0, -1) ~ (3, 213) => 0.00132352
+(0, -1) ~ (3, 214) => 0.0085327
+(0, -1) ~ (3, 215) => 0.00102372
+(0, -1) ~ (3, 216) => 0.00111929
+(0, -1) ~ (3, 217) => 0.00628258
+(0, -1) ~ (3, 218) => 0.00572532
+(0, -1) ~ (3, 219) => 0.013624
+(0, -1) ~ (3, 220) => 0.00861484
+(0, -1) ~ (3, 221) => 0.00581557
+(0, -1) ~ (3, 222) => 0.00602382
+(0, -1) ~ (3, 223) => 0.00519574
+(0, -1) ~ (3, 224) => 0.00435698
+(0, -1) ~ (3, 225) => 0.00240713
+(0, -1) ~ (3, 226) => 0.000707388
+(0, -1) ~ (3, 227) => 0.000640929
+(0, -1) ~ (3, 228) => 0.000326097
+(0, -1) ~ (3, 229) => 0.000139892
+(0, -1) ~ (3, 230) => 0.0001
+(0, -1) ~ (3, 231) => 0.0001
+(0, -1) ~ (3, 232) => 0.0001
+(0, -1) ~ (3, 233) => 0.000102341
+(0, -1) ~ (3, 234) => 0.00123703
+(0, -1) ~ (3, 235) => 0.00419861
+(0, -1) ~ (3, 236) => 0.00418806
+(0, -1) ~ (3, 237) => 0.00127113
+(0, -1) ~ (3, 238) => 0.00061518
+
+; Sparse posterior probability matrix for sequences 0 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (4, 0) => 0.354707
+(0, 0) ~ (4, 1) => 0.629218
+(0, 1) ~ (4, 1) => 0.256812
+(0, 1) ~ (4, 2) => 0.718143
+(0, 2) ~ (4, 2) => 0.163972
+(0, 2) ~ (4, 3) => 0.806587
+(0, 3) ~ (4, 3) => 0.133315
+(0, 3) ~ (4, 4) => 0.833635
+(0, 4) ~ (4, 3) => 0.0111244
+(0, 4) ~ (4, 4) => 0.113585
+(0, 4) ~ (4, 5) => 0.824777
+(0, 4) ~ (4, 7) => 0.0180062
+(0, 5) ~ (4, 4) => 0.0210531
+(0, 5) ~ (4, 5) => 0.113333
+(0, 5) ~ (4, 6) => 0.782572
+(0, 5) ~ (4, 8) => 0.049947
+(0, 6) ~ (4, 5) => 0.0304084
+(0, 6) ~ (4, 6) => 0.0973225
+(0, 6) ~ (4, 7) => 0.761439
+(0, 6) ~ (4, 9) => 0.0802125
+(0, 7) ~ (4, 6) => 0.047
+(0, 7) ~ (4, 7) => 0.0740586
+(0, 7) ~ (4, 8) => 0.736611
+(0, 7) ~ (4, 10) => 0.129892
+(0, 8) ~ (4, 7) => 0.0404603
+(0, 8) ~ (4, 8) => 0.06842
+(0, 8) ~ (4, 9) => 0.747139
+(0, 8) ~ (4, 11) => 0.12982
+(0, 9) ~ (4, 8) => 0.0290991
+(0, 9) ~ (4, 9) => 0.0502129
+(0, 9) ~ (4, 10) => 0.737374
+(0, 9) ~ (4, 11) => 0.0432329
+(0, 9) ~ (4, 12) => 0.119025
+(0, 10) ~ (4, 9) => 0.0177761
+(0, 10) ~ (4, 10) => 0.0314942
+(0, 10) ~ (4, 11) => 0.724339
+(0, 10) ~ (4, 12) => 0.0951032
+(0, 10) ~ (4, 13) => 0.0913556
+(0, 11) ~ (4, 10) => 0.0108091
+(0, 11) ~ (4, 11) => 0.0129869
+(0, 11) ~ (4, 12) => 0.691418
+(0, 11) ~ (4, 13) => 0.184418
+(0, 11) ~ (4, 14) => 0.0819864
+(0, 12) ~ (4, 13) => 0.451135
+(0, 12) ~ (4, 14) => 0.446391
+(0, 12) ~ (4, 15) => 0.081854
+(0, 13) ~ (4, 14) => 0.265206
+(0, 13) ~ (4, 15) => 0.642639
+(0, 13) ~ (4, 16) => 0.0484948
+(0, 14) ~ (4, 15) => 0.145788
+(0, 14) ~ (4, 16) => 0.798659
+(0, 15) ~ (4, 16) => 0.0136699
+(0, 15) ~ (4, 17) => 0.979698
+(0, 16) ~ (4, 18) => 0.994347
+(0, 17) ~ (4, 19) => 0.996042
+(0, 18) ~ (4, 20) => 0.998719
+(0, 19) ~ (4, 21) => 0.999326
+(0, 20) ~ (4, 22) => 0.999889
+(0, 21) ~ (4, 23) => 0.99998
+(0, 22) ~ (4, 24) => 0.999935
+(0, 23) ~ (4, 25) => 0.998635
+(0, 24) ~ (4, 26) => 0.993509
+(0, 25) ~ (4, 27) => 0.980705
+(0, 25) ~ (4, 28) => 0.0157649
+(0, 26) ~ (4, 28) => 0.971262
+(0, 26) ~ (4, 29) => 0.0238278
+(0, 27) ~ (4, 29) => 0.942026
+(0, 27) ~ (4, 30) => 0.0504982
+(0, 28) ~ (4, 30) => 0.931229
+(0, 28) ~ (4, 31) => 0.0595547
+(0, 29) ~ (4, 31) => 0.930442
+(0, 29) ~ (4, 32) => 0.0538183
+(0, 30) ~ (4, 32) => 0.936814
+(0, 30) ~ (4, 33) => 0.0473468
+(0, 31) ~ (4, 33) => 0.942758
+(0, 31) ~ (4, 34) => 0.0407755
+(0, 32) ~ (4, 34) => 0.948934
+(0, 32) ~ (4, 35) => 0.0366851
+(0, 33) ~ (4, 35) => 0.951926
+(0, 33) ~ (4, 36) => 0.0339196
+(0, 34) ~ (4, 36) => 0.957529
+(0, 34) ~ (4, 37) => 0.0160545
+(0, 35) ~ (4, 37) => 0.979373
+(0, 36) ~ (4, 38) => 0.992057
+(0, 37) ~ (4, 39) => 0.992238
+(0, 38) ~ (4, 40) => 0.993692
+(0, 39) ~ (4, 41) => 0.99697
+(0, 40) ~ (4, 42) => 0.998066
+(0, 41) ~ (4, 43) => 0.998598
+(0, 42) ~ (4, 44) => 0.999513
+(0, 43) ~ (4, 45) => 0.998858
+(0, 44) ~ (4, 46) => 0.998823
+(0, 45) ~ (4, 47) => 0.998865
+(0, 46) ~ (4, 48) => 0.998958
+(0, 47) ~ (4, 49) => 0.999047
+(0, 48) ~ (4, 50) => 0.999194
+(0, 49) ~ (4, 51) => 0.999636
+(0, 50) ~ (4, 52) => 0.999967
+(0, 51) ~ (4, 53) => 0.999999
+(0, 52) ~ (4, 54) => 0.999996
+(0, 53) ~ (4, 55) => 0.999952
+(0, 54) ~ (4, 56) => 0.999647
+(0, 55) ~ (4, 57) => 0.993112
+(0, 56) ~ (4, 58) => 0.985969
+(0, 56) ~ (4, 59) => 0.0113468
+(0, 57) ~ (4, 59) => 0.94107
+(0, 57) ~ (4, 60) => 0.0552703
+(0, 58) ~ (4, 60) => 0.934184
+(0, 58) ~ (4, 61) => 0.0600308
+(0, 59) ~ (4, 61) => 0.877643
+(0, 59) ~ (4, 62) => 0.103937
+(0, 60) ~ (4, 61) => 0.0175604
+(0, 60) ~ (4, 62) => 0.820564
+(0, 60) ~ (4, 63) => 0.147513
+(0, 61) ~ (4, 62) => 0.0299267
+(0, 61) ~ (4, 63) => 0.577562
+(0, 61) ~ (4, 64) => 0.37645
+(0, 62) ~ (4, 63) => 0.0375248
+(0, 62) ~ (4, 64) => 0.274215
+(0, 62) ~ (4, 65) => 0.669317
+(0, 63) ~ (4, 64) => 0.048323
+(0, 63) ~ (4, 65) => 0.169105
+(0, 63) ~ (4, 66) => 0.776689
+(0, 64) ~ (4, 65) => 0.0273583
+(0, 64) ~ (4, 66) => 0.0767054
+(0, 64) ~ (4, 67) => 0.893058
+(0, 65) ~ (4, 68) => 0.9933
+(0, 66) ~ (4, 69) => 0.99874
+(0, 67) ~ (4, 70) => 0.998802
+(0, 68) ~ (4, 71) => 0.999447
+(0, 69) ~ (4, 72) => 0.999942
+(0, 70) ~ (4, 73) => 0.999989
+(0, 71) ~ (4, 74) => 0.99998
+(0, 72) ~ (4, 75) => 0.999927
+(0, 73) ~ (4, 76) => 0.999331
+(0, 74) ~ (4, 77) => 0.998704
+(0, 75) ~ (4, 78) => 0.996007
+(0, 76) ~ (4, 79) => 0.91435
+(0, 77) ~ (4, 80) => 0.775753
+(0, 78) ~ (4, 80) => 0.0122599
+(0, 78) ~ (4, 81) => 0.564706
+(0, 79) ~ (4, 79) => 0.0636952
+(0, 79) ~ (4, 80) => 0.0129337
+(0, 79) ~ (4, 81) => 0.020785
+(0, 79) ~ (4, 82) => 0.354809
+(0, 80) ~ (4, 80) => 0.188461
+(0, 80) ~ (4, 81) => 0.0119514
+(0, 80) ~ (4, 82) => 0.012775
+(0, 80) ~ (4, 83) => 0.195949
+(0, 81) ~ (4, 81) => 0.390785
+(0, 81) ~ (4, 82) => 0.0108336
+(0, 81) ~ (4, 84) => 0.109923
+(0, 82) ~ (4, 82) => 0.600286
+(0, 82) ~ (4, 83) => 0.0118349
+(0, 82) ~ (4, 85) => 0.0324213
+(0, 83) ~ (4, 83) => 0.763221
+(0, 84) ~ (4, 84) => 0.866735
+(0, 85) ~ (4, 85) => 0.955159
+(0, 86) ~ (4, 86) => 0.985982
+(0, 87) ~ (4, 87) => 0.987828
+(0, 88) ~ (4, 88) => 0.988695
+(0, 89) ~ (4, 89) => 0.988984
+(0, 90) ~ (4, 90) => 0.986859
+(0, 91) ~ (4, 91) => 0.983696
+(0, 92) ~ (4, 92) => 0.930817
+(0, 92) ~ (4, 96) => 0.0294705
+(0, 93) ~ (4, 93) => 0.865977
+(0, 93) ~ (4, 97) => 0.0773831
+(0, 93) ~ (4, 98) => 0.0214042
+(0, 94) ~ (4, 94) => 0.830071
+(0, 94) ~ (4, 98) => 0.101393
+(0, 94) ~ (4, 99) => 0.0359639
+(0, 95) ~ (4, 95) => 0.671641
+(0, 95) ~ (4, 99) => 0.110074
+(0, 95) ~ (4, 100) => 0.184659
+(0, 95) ~ (4, 101) => 0.0136525
+(0, 96) ~ (4, 96) => 0.658944
+(0, 96) ~ (4, 100) => 0.0864994
+(0, 96) ~ (4, 101) => 0.19955
+(0, 96) ~ (4, 102) => 0.0223239
+(0, 96) ~ (4, 103) => 0.0195866
+(0, 97) ~ (4, 97) => 0.650024
+(0, 97) ~ (4, 101) => 0.0805842
+(0, 97) ~ (4, 102) => 0.21043
+(0, 97) ~ (4, 103) => 0.0244918
+(0, 97) ~ (4, 104) => 0.0191353
+(0, 98) ~ (4, 98) => 0.498083
+(0, 98) ~ (4, 102) => 0.0756801
+(0, 98) ~ (4, 103) => 0.29691
+(0, 98) ~ (4, 104) => 0.0566669
+(0, 98) ~ (4, 105) => 0.0310399
+(0, 99) ~ (4, 98) => 0.0191128
+(0, 99) ~ (4, 99) => 0.321096
+(0, 99) ~ (4, 102) => 0.0153483
+(0, 99) ~ (4, 103) => 0.0508688
+(0, 99) ~ (4, 104) => 0.466185
+(0, 99) ~ (4, 105) => 0.0602934
+(0, 99) ~ (4, 106) => 0.0116941
+(0, 100) ~ (4, 99) => 0.0156632
+(0, 100) ~ (4, 100) => 0.221321
+(0, 100) ~ (4, 101) => 0.0125015
+(0, 100) ~ (4, 102) => 0.0107059
+(0, 100) ~ (4, 103) => 0.0211461
+(0, 100) ~ (4, 104) => 0.0340524
+(0, 100) ~ (4, 105) => 0.582069
+(0, 100) ~ (4, 106) => 0.0552365
+(0, 101) ~ (4, 101) => 0.0721322
+(0, 101) ~ (4, 102) => 0.010731
+(0, 101) ~ (4, 104) => 0.0141961
+(0, 101) ~ (4, 105) => 0.0193284
+(0, 101) ~ (4, 106) => 0.798507
+(0, 101) ~ (4, 107) => 0.0398774
+(0, 102) ~ (4, 102) => 0.0200074
+(0, 102) ~ (4, 107) => 0.920313
+(0, 102) ~ (4, 108) => 0.0205614
+(0, 103) ~ (4, 108) => 0.968586
+(0, 104) ~ (4, 109) => 0.998705
+(0, 105) ~ (4, 110) => 0.999803
+(0, 106) ~ (4, 111) => 0.999968
+(0, 107) ~ (4, 112) => 0.99999
+(0, 108) ~ (4, 113) => 0.999988
+(0, 109) ~ (4, 114) => 0.999972
+(0, 110) ~ (4, 115) => 0.999964
+(0, 111) ~ (4, 116) => 0.999901
+(0, 112) ~ (4, 117) => 0.999844
+(0, 113) ~ (4, 118) => 0.99985
+(0, 114) ~ (4, 119) => 0.99993
+(0, 115) ~ (4, 120) => 0.999991
+(0, 116) ~ (4, 121) => 0.999968
+(0, 117) ~ (4, 122) => 0.999706
+(0, 118) ~ (4, 123) => 0.999647
+(0, 119) ~ (4, 124) => 0.999787
+(0, 120) ~ (4, 125) => 0.999593
+(0, 121) ~ (4, 126) => 0.999366
+(0, 122) ~ (4, 127) => 0.999405
+(0, 123) ~ (4, 128) => 0.999025
+(0, 124) ~ (4, 129) => 0.997704
+(0, 125) ~ (4, 130) => 0.977299
+(0, 126) ~ (4, 131) => 0.958921
+(0, 126) ~ (4, 133) => 0.0167028
+(0, 127) ~ (4, 132) => 0.930713
+(0, 127) ~ (4, 134) => 0.0368153
+(0, 128) ~ (4, 133) => 0.92254
+(0, 128) ~ (4, 135) => 0.0367939
+(0, 129) ~ (4, 134) => 0.912811
+(0, 129) ~ (4, 136) => 0.0372567
+(0, 130) ~ (4, 135) => 0.90547
+(0, 130) ~ (4, 137) => 0.0350622
+(0, 131) ~ (4, 131) => 0.0154992
+(0, 131) ~ (4, 136) => 0.890265
+(0, 131) ~ (4, 138) => 0.03291
+(0, 132) ~ (4, 132) => 0.0198253
+(0, 132) ~ (4, 136) => 0.0169624
+(0, 132) ~ (4, 137) => 0.842209
+(0, 132) ~ (4, 139) => 0.029257
+(0, 133) ~ (4, 133) => 0.0207697
+(0, 133) ~ (4, 137) => 0.0606403
+(0, 133) ~ (4, 138) => 0.793511
+(0, 133) ~ (4, 140) => 0.0227596
+(0, 134) ~ (4, 134) => 0.0209826
+(0, 134) ~ (4, 135) => 0.0126298
+(0, 134) ~ (4, 138) => 0.106325
+(0, 134) ~ (4, 139) => 0.752801
+(0, 134) ~ (4, 141) => 0.0139538
+(0, 135) ~ (4, 136) => 0.0208468
+(0, 135) ~ (4, 138) => 0.0113268
+(0, 135) ~ (4, 139) => 0.159509
+(0, 135) ~ (4, 140) => 0.673104
+(0, 135) ~ (4, 142) => 0.010867
+(0, 136) ~ (4, 137) => 0.0125595
+(0, 136) ~ (4, 140) => 0.263672
+(0, 136) ~ (4, 141) => 0.594236
+(0, 137) ~ (4, 141) => 0.3743
+(0, 137) ~ (4, 142) => 0.212308
+(0, 138) ~ (4, 142) => 0.76754
+(0, 138) ~ (4, 143) => 0.0815242
+(0, 139) ~ (4, 143) => 0.906928
+(0, 140) ~ (4, 144) => 0.99733
+(0, 141) ~ (4, 145) => 0.998185
+(0, 142) ~ (4, 146) => 0.998506
+(0, 143) ~ (4, 147) => 0.999606
+(0, 144) ~ (4, 148) => 0.999979
+(0, 145) ~ (4, 149) => 0.999994
+(0, 146) ~ (4, 150) => 0.999983
+(0, 147) ~ (4, 151) => 0.999923
+(0, 148) ~ (4, 152) => 0.999919
+(0, 149) ~ (4, 153) => 0.999982
+(0, 150) ~ (4, 154) => 0.999991
+(0, 151) ~ (4, 155) => 0.999991
+(0, 152) ~ (4, 156) => 0.999944
+(0, 153) ~ (4, 157) => 0.99968
+(0, 154) ~ (4, 158) => 0.998694
+(0, 155) ~ (4, 159) => 0.997013
+(0, 156) ~ (4, 160) => 0.99447
+(0, 157) ~ (4, 161) => 0.990829
+(0, 158) ~ (4, 162) => 0.989638
+(0, 159) ~ (4, 163) => 0.988182
+(0, 160) ~ (4, 164) => 0.988005
+(0, 161) ~ (4, 165) => 0.988211
+(0, 162) ~ (4, 166) => 0.989651
+(0, 163) ~ (4, 167) => 0.989557
+(0, 164) ~ (4, 168) => 0.990485
+(0, 165) ~ (4, 169) => 0.993264
+(0, 166) ~ (4, 170) => 0.994604
+(0, 167) ~ (4, 171) => 0.993256
+(0, 168) ~ (4, 172) => 0.993328
+(0, 169) ~ (4, 173) => 0.993929
+(0, 170) ~ (4, 174) => 0.996268
+(0, 171) ~ (4, 175) => 0.998114
+(0, 172) ~ (4, 176) => 0.998047
+(0, 173) ~ (4, 177) => 0.997531
+(0, 174) ~ (4, 178) => 0.99809
+(0, 175) ~ (4, 179) => 0.998782
+(0, 176) ~ (4, 180) => 0.999556
+(0, 177) ~ (4, 181) => 0.999933
+(0, 178) ~ (4, 182) => 0.999976
+(0, 179) ~ (4, 183) => 0.999972
+(0, 180) ~ (4, 184) => 0.999965
+(0, 181) ~ (4, 185) => 0.999715
+(0, 182) ~ (4, 186) => 0.999505
+(0, 183) ~ (4, 187) => 0.999226
+(0, 184) ~ (4, 188) => 0.998127
+(0, 185) ~ (4, 189) => 0.995163
+(0, 186) ~ (4, 190) => 0.988568
+(0, 187) ~ (4, 191) => 0.975911
+(0, 187) ~ (4, 194) => 0.0186323
+(0, 188) ~ (4, 192) => 0.972092
+(0, 188) ~ (4, 195) => 0.0200044
+(0, 189) ~ (4, 193) => 0.969961
+(0, 189) ~ (4, 196) => 0.0210085
+(0, 190) ~ (4, 194) => 0.970959
+(0, 190) ~ (4, 197) => 0.018539
+(0, 191) ~ (4, 195) => 0.972131
+(0, 191) ~ (4, 198) => 0.01543
+(0, 192) ~ (4, 196) => 0.972235
+(0, 192) ~ (4, 199) => 0.0144208
+(0, 193) ~ (4, 197) => 0.976311
+(0, 193) ~ (4, 200) => 0.0139808
+(0, 194) ~ (4, 198) => 0.978401
+(0, 194) ~ (4, 201) => 0.0127553
+(0, 195) ~ (4, 199) => 0.978723
+(0, 196) ~ (4, 200) => 0.978795
+(0, 197) ~ (4, 201) => 0.980948
+(0, 198) ~ (4, 202) => 0.989939
+(0, 199) ~ (4, 203) => 0.992226
+(0, 200) ~ (4, 204) => 0.994785
+(0, 201) ~ (4, 205) => 0.994913
+(0, 202) ~ (4, 206) => 0.995607
+(0, 203) ~ (4, 207) => 0.993698
+(0, 204) ~ (4, 208) => 0.992856
+(0, 205) ~ (4, 209) => 0.993044
+(0, 206) ~ (4, 210) => 0.994342
+(0, 207) ~ (4, 211) => 0.985456
+(0, 208) ~ (4, 212) => 0.979197
+(0, 209) ~ (4, 212) => 0.0125869
+(0, 209) ~ (4, 213) => 0.974895
+(0, 210) ~ (4, 213) => 0.0158078
+(0, 210) ~ (4, 214) => 0.971333
+(0, 211) ~ (4, 214) => 0.0150241
+(0, 211) ~ (4, 215) => 0.970893
+(0, 212) ~ (4, 215) => 0.0126545
+(0, 212) ~ (4, 216) => 0.973379
+(0, 213) ~ (4, 217) => 0.97544
+(0, 214) ~ (4, 218) => 0.970342
+(0, 214) ~ (4, 219) => 0.015412
+(0, 215) ~ (4, 219) => 0.960623
+(0, 215) ~ (4, 220) => 0.0263461
+(0, 216) ~ (4, 220) => 0.821666
+(0, 216) ~ (4, 221) => 0.165677
+(0, 217) ~ (4, 221) => 0.277747
+(0, 217) ~ (4, 222) => 0.704585
+(0, 218) ~ (4, 222) => 0.229325
+(0, 218) ~ (4, 223) => 0.751362
+(0, 219) ~ (4, 223) => 0.166657
+(0, 219) ~ (4, 224) => 0.813925
+(0, 220) ~ (4, 224) => 0.10476
+(0, 220) ~ (4, 225) => 0.883187
+(0, 221) ~ (4, 225) => 0.0587038
+(0, 221) ~ (4, 226) => 0.934513
+(0, 222) ~ (4, 227) => 0.995447
+(0, 223) ~ (4, 228) => 0.999285
+(0, 224) ~ (4, 229) => 0.999911
+(0, 225) ~ (4, 230) => 0.999557
+(0, 226) ~ (4, 231) => 0.998202
+(0, 227) ~ (4, 232) => 0.997516
+(0, 228) ~ (4, 233) => 0.98851
+(0, 228) ~ (4, 234) => 0.0102478
+(0, 229) ~ (4, 234) => 0.98152
+(0, 229) ~ (4, 235) => 0.0167049
+(0, 230) ~ (4, 235) => 0.981232
+(0, 230) ~ (4, 236) => 0.0129216
+(0, 231) ~ (4, 236) => 0.985454
+(0, 231) ~ (4, 237) => 0.0114117
+(0, 232) ~ (4, 237) => 0.987806
+
+; gap posteriors
+(0, 0) ~ (4, -1) => 0.0160754
+(0, 1) ~ (4, -1) => 0.0250445
+(0, 2) ~ (4, -1) => 0.0294403
+(0, 3) ~ (4, -1) => 0.03305
+(0, 4) ~ (4, -1) => 0.0325083
+(0, 5) ~ (4, -1) => 0.0330957
+(0, 6) ~ (4, -1) => 0.0306173
+(0, 7) ~ (4, -1) => 0.0124388
+(0, 8) ~ (4, -1) => 0.0141609
+(0, 9) ~ (4, -1) => 0.0210556
+(0, 10) ~ (4, -1) => 0.0399323
+(0, 11) ~ (4, -1) => 0.0183816
+(0, 12) ~ (4, -1) => 0.02062
+(0, 13) ~ (4, -1) => 0.0436606
+(0, 14) ~ (4, -1) => 0.0555535
+(0, 15) ~ (4, -1) => 0.00663173
+(0, 16) ~ (4, -1) => 0.00565344
+(0, 17) ~ (4, -1) => 0.00395775
+(0, 18) ~ (4, -1) => 0.00128055
+(0, 19) ~ (4, -1) => 0.000674188
+(0, 20) ~ (4, -1) => 0.000110507
+(0, 21) ~ (4, -1) => 0.0001
+(0, 22) ~ (4, -1) => 0.0001
+(0, 23) ~ (4, -1) => 0.00136548
+(0, 24) ~ (4, -1) => 0.0064913
+(0, 25) ~ (4, -1) => 0.00352961
+(0, 26) ~ (4, -1) => 0.00491052
+(0, 27) ~ (4, -1) => 0.00747562
+(0, 28) ~ (4, -1) => 0.00921609
+(0, 29) ~ (4, -1) => 0.0157399
+(0, 30) ~ (4, -1) => 0.0158393
+(0, 31) ~ (4, -1) => 0.0164661
+(0, 32) ~ (4, -1) => 0.0143806
+(0, 33) ~ (4, -1) => 0.0141544
+(0, 34) ~ (4, -1) => 0.0264163
+(0, 35) ~ (4, -1) => 0.0206273
+(0, 36) ~ (4, -1) => 0.00794303
+(0, 37) ~ (4, -1) => 0.00776219
+(0, 38) ~ (4, -1) => 0.0063082
+(0, 39) ~ (4, -1) => 0.00302976
+(0, 40) ~ (4, -1) => 0.00193411
+(0, 41) ~ (4, -1) => 0.00140154
+(0, 42) ~ (4, -1) => 0.000486851
+(0, 43) ~ (4, -1) => 0.0011422
+(0, 44) ~ (4, -1) => 0.00117666
+(0, 45) ~ (4, -1) => 0.00113469
+(0, 46) ~ (4, -1) => 0.00104165
+(0, 47) ~ (4, -1) => 0.00095284
+(0, 48) ~ (4, -1) => 0.000806451
+(0, 49) ~ (4, -1) => 0.000363767
+(0, 50) ~ (4, -1) => 0.0001
+(0, 51) ~ (4, -1) => 0.0001
+(0, 52) ~ (4, -1) => 0.0001
+(0, 53) ~ (4, -1) => 0.0001
+(0, 54) ~ (4, -1) => 0.000353396
+(0, 55) ~ (4, -1) => 0.00688815
+(0, 56) ~ (4, -1) => 0.00268397
+(0, 57) ~ (4, -1) => 0.00365977
+(0, 58) ~ (4, -1) => 0.00578496
+(0, 59) ~ (4, -1) => 0.01842
+(0, 60) ~ (4, -1) => 0.0143628
+(0, 61) ~ (4, -1) => 0.0160607
+(0, 62) ~ (4, -1) => 0.0189435
+(0, 63) ~ (4, -1) => 0.00588328
+(0, 64) ~ (4, -1) => 0.00287867
+(0, 65) ~ (4, -1) => 0.00670028
+(0, 66) ~ (4, -1) => 0.0012604
+(0, 67) ~ (4, -1) => 0.0011977
+(0, 68) ~ (4, -1) => 0.000553012
+(0, 69) ~ (4, -1) => 0.0001
+(0, 70) ~ (4, -1) => 0.0001
+(0, 71) ~ (4, -1) => 0.0001
+(0, 72) ~ (4, -1) => 0.0001
+(0, 73) ~ (4, -1) => 0.000669003
+(0, 74) ~ (4, -1) => 0.00129616
+(0, 75) ~ (4, -1) => 0.00399309
+(0, 76) ~ (4, -1) => 0.0856501
+(0, 77) ~ (4, -1) => 0.224247
+(0, 78) ~ (4, -1) => 0.423034
+(0, 79) ~ (4, -1) => 0.547777
+(0, 80) ~ (4, -1) => 0.590863
+(0, 81) ~ (4, -1) => 0.488458
+(0, 82) ~ (4, -1) => 0.355458
+(0, 83) ~ (4, -1) => 0.236779
+(0, 84) ~ (4, -1) => 0.133265
+(0, 85) ~ (4, -1) => 0.0448415
+(0, 86) ~ (4, -1) => 0.0140181
+(0, 87) ~ (4, -1) => 0.0121716
+(0, 88) ~ (4, -1) => 0.011305
+(0, 89) ~ (4, -1) => 0.0110158
+(0, 90) ~ (4, -1) => 0.0131413
+(0, 91) ~ (4, -1) => 0.0163044
+(0, 92) ~ (4, -1) => 0.0397121
+(0, 93) ~ (4, -1) => 0.0352361
+(0, 94) ~ (4, -1) => 0.0325723
+(0, 95) ~ (4, -1) => 0.0199742
+(0, 96) ~ (4, -1) => 0.013097
+(0, 97) ~ (4, -1) => 0.0153352
+(0, 98) ~ (4, -1) => 0.0416196
+(0, 99) ~ (4, -1) => 0.0554018
+(0, 100) ~ (4, -1) => 0.0473047
+(0, 101) ~ (4, -1) => 0.0452282
+(0, 102) ~ (4, -1) => 0.0391182
+(0, 103) ~ (4, -1) => 0.0314136
+(0, 104) ~ (4, -1) => 0.00129521
+(0, 105) ~ (4, -1) => 0.000197172
+(0, 106) ~ (4, -1) => 0.0001
+(0, 107) ~ (4, -1) => 0.0001
+(0, 108) ~ (4, -1) => 0.0001
+(0, 109) ~ (4, -1) => 0.0001
+(0, 110) ~ (4, -1) => 0.0001
+(0, 111) ~ (4, -1) => 0.0001
+(0, 112) ~ (4, -1) => 0.000155985
+(0, 113) ~ (4, -1) => 0.000149667
+(0, 114) ~ (4, -1) => 0.0001
+(0, 115) ~ (4, -1) => 0.0001
+(0, 116) ~ (4, -1) => 0.0001
+(0, 117) ~ (4, -1) => 0.000293672
+(0, 118) ~ (4, -1) => 0.000352561
+(0, 119) ~ (4, -1) => 0.000213325
+(0, 120) ~ (4, -1) => 0.000407279
+(0, 121) ~ (4, -1) => 0.000633597
+(0, 122) ~ (4, -1) => 0.000595212
+(0, 123) ~ (4, -1) => 0.000975251
+(0, 124) ~ (4, -1) => 0.00229573
+(0, 125) ~ (4, -1) => 0.0227012
+(0, 126) ~ (4, -1) => 0.0243762
+(0, 127) ~ (4, -1) => 0.0324719
+(0, 128) ~ (4, -1) => 0.0406665
+(0, 129) ~ (4, -1) => 0.0499325
+(0, 130) ~ (4, -1) => 0.0594681
+(0, 131) ~ (4, -1) => 0.0613254
+(0, 132) ~ (4, -1) => 0.0917463
+(0, 133) ~ (4, -1) => 0.10232
+(0, 134) ~ (4, -1) => 0.0933086
+(0, 135) ~ (4, -1) => 0.124346
+(0, 136) ~ (4, -1) => 0.129533
+(0, 137) ~ (4, -1) => 0.413392
+(0, 138) ~ (4, -1) => 0.150936
+(0, 139) ~ (4, -1) => 0.0930717
+(0, 140) ~ (4, -1) => 0.00266963
+(0, 141) ~ (4, -1) => 0.00181472
+(0, 142) ~ (4, -1) => 0.00149387
+(0, 143) ~ (4, -1) => 0.00039351
+(0, 144) ~ (4, -1) => 0.0001
+(0, 145) ~ (4, -1) => 0.0001
+(0, 146) ~ (4, -1) => 0.0001
+(0, 147) ~ (4, -1) => 0.0001
+(0, 148) ~ (4, -1) => 0.0001
+(0, 149) ~ (4, -1) => 0.0001
+(0, 150) ~ (4, -1) => 0.0001
+(0, 151) ~ (4, -1) => 0.0001
+(0, 152) ~ (4, -1) => 0.0001
+(0, 153) ~ (4, -1) => 0.000319719
+(0, 154) ~ (4, -1) => 0.0013063
+(0, 155) ~ (4, -1) => 0.00298697
+(0, 156) ~ (4, -1) => 0.00552952
+(0, 157) ~ (4, -1) => 0.00917131
+(0, 158) ~ (4, -1) => 0.0103619
+(0, 159) ~ (4, -1) => 0.0118175
+(0, 160) ~ (4, -1) => 0.0119948
+(0, 161) ~ (4, -1) => 0.0117887
+(0, 162) ~ (4, -1) => 0.0103491
+(0, 163) ~ (4, -1) => 0.0104428
+(0, 164) ~ (4, -1) => 0.00951463
+(0, 165) ~ (4, -1) => 0.00673634
+(0, 166) ~ (4, -1) => 0.00539619
+(0, 167) ~ (4, -1) => 0.00674355
+(0, 168) ~ (4, -1) => 0.00667179
+(0, 169) ~ (4, -1) => 0.00607073
+(0, 170) ~ (4, -1) => 0.00373232
+(0, 171) ~ (4, -1) => 0.00188553
+(0, 172) ~ (4, -1) => 0.00195307
+(0, 173) ~ (4, -1) => 0.002469
+(0, 174) ~ (4, -1) => 0.00190991
+(0, 175) ~ (4, -1) => 0.00121814
+(0, 176) ~ (4, -1) => 0.000444174
+(0, 177) ~ (4, -1) => 0.0001
+(0, 178) ~ (4, -1) => 0.0001
+(0, 179) ~ (4, -1) => 0.0001
+(0, 180) ~ (4, -1) => 0.0001
+(0, 181) ~ (4, -1) => 0.000285149
+(0, 182) ~ (4, -1) => 0.000494838
+(0, 183) ~ (4, -1) => 0.000773668
+(0, 184) ~ (4, -1) => 0.00187337
+(0, 185) ~ (4, -1) => 0.00483721
+(0, 186) ~ (4, -1) => 0.0114324
+(0, 187) ~ (4, -1) => 0.00545685
+(0, 188) ~ (4, -1) => 0.00790314
+(0, 189) ~ (4, -1) => 0.00903091
+(0, 190) ~ (4, -1) => 0.0105018
+(0, 191) ~ (4, -1) => 0.0124387
+(0, 192) ~ (4, -1) => 0.0133445
+(0, 193) ~ (4, -1) => 0.00970776
+(0, 194) ~ (4, -1) => 0.008844
+(0, 195) ~ (4, -1) => 0.0212765
+(0, 196) ~ (4, -1) => 0.021205
+(0, 197) ~ (4, -1) => 0.019052
+(0, 198) ~ (4, -1) => 0.0100607
+(0, 199) ~ (4, -1) => 0.00777411
+(0, 200) ~ (4, -1) => 0.00521457
+(0, 201) ~ (4, -1) => 0.00508708
+(0, 202) ~ (4, -1) => 0.00439292
+(0, 203) ~ (4, -1) => 0.00630236
+(0, 204) ~ (4, -1) => 0.00714415
+(0, 205) ~ (4, -1) => 0.0069564
+(0, 206) ~ (4, -1) => 0.00565755
+(0, 207) ~ (4, -1) => 0.0145437
+(0, 208) ~ (4, -1) => 0.0208026
+(0, 209) ~ (4, -1) => 0.0125183
+(0, 210) ~ (4, -1) => 0.0128592
+(0, 211) ~ (4, -1) => 0.0140827
+(0, 212) ~ (4, -1) => 0.0139662
+(0, 213) ~ (4, -1) => 0.0245598
+(0, 214) ~ (4, -1) => 0.0142461
+(0, 215) ~ (4, -1) => 0.0130305
+(0, 216) ~ (4, -1) => 0.0126568
+(0, 217) ~ (4, -1) => 0.0176681
+(0, 218) ~ (4, -1) => 0.0193133
+(0, 219) ~ (4, -1) => 0.0194183
+(0, 220) ~ (4, -1) => 0.012053
+(0, 221) ~ (4, -1) => 0.00678289
+(0, 222) ~ (4, -1) => 0.00455266
+(0, 223) ~ (4, -1) => 0.000714719
+(0, 224) ~ (4, -1) => 0.0001
+(0, 225) ~ (4, -1) => 0.000442564
+(0, 226) ~ (4, -1) => 0.00179833
+(0, 227) ~ (4, -1) => 0.00248355
+(0, 228) ~ (4, -1) => 0.0012424
+(0, 229) ~ (4, -1) => 0.00177518
+(0, 230) ~ (4, -1) => 0.00584641
+(0, 231) ~ (4, -1) => 0.00313416
+(0, 232) ~ (4, -1) => 0.0121936
+
+(0, -1) ~ (4, 0) => 0.645293
+(0, -1) ~ (4, 1) => 0.11397
+(0, -1) ~ (4, 2) => 0.117884
+(0, -1) ~ (4, 3) => 0.0489734
+(0, -1) ~ (4, 4) => 0.0317273
+(0, -1) ~ (4, 5) => 0.0314825
+(0, -1) ~ (4, 6) => 0.0731058
+(0, -1) ~ (4, 7) => 0.106036
+(0, -1) ~ (4, 8) => 0.115923
+(0, -1) ~ (4, 9) => 0.104659
+(0, -1) ~ (4, 10) => 0.0904308
+(0, -1) ~ (4, 11) => 0.0896218
+(0, -1) ~ (4, 12) => 0.094453
+(0, -1) ~ (4, 13) => 0.273092
+(0, -1) ~ (4, 14) => 0.206417
+(0, -1) ~ (4, 15) => 0.129719
+(0, -1) ~ (4, 16) => 0.139176
+(0, -1) ~ (4, 17) => 0.0203016
+(0, -1) ~ (4, 18) => 0.00565344
+(0, -1) ~ (4, 19) => 0.00395775
+(0, -1) ~ (4, 20) => 0.00128055
+(0, -1) ~ (4, 21) => 0.000674188
+(0, -1) ~ (4, 22) => 0.000110507
+(0, -1) ~ (4, 23) => 0.0001
+(0, -1) ~ (4, 24) => 0.0001
+(0, -1) ~ (4, 25) => 0.00136548
+(0, -1) ~ (4, 26) => 0.0064913
+(0, -1) ~ (4, 27) => 0.0192945
+(0, -1) ~ (4, 28) => 0.0129734
+(0, -1) ~ (4, 29) => 0.0341461
+(0, -1) ~ (4, 30) => 0.0182726
+(0, -1) ~ (4, 31) => 0.0100034
+(0, -1) ~ (4, 32) => 0.00936776
+(0, -1) ~ (4, 33) => 0.00989491
+(0, -1) ~ (4, 34) => 0.0102901
+(0, -1) ~ (4, 35) => 0.0113889
+(0, -1) ~ (4, 36) => 0.00855112
+(0, -1) ~ (4, 37) => 0.00457281
+(0, -1) ~ (4, 38) => 0.00794303
+(0, -1) ~ (4, 39) => 0.00776219
+(0, -1) ~ (4, 40) => 0.0063082
+(0, -1) ~ (4, 41) => 0.00302976
+(0, -1) ~ (4, 42) => 0.00193411
+(0, -1) ~ (4, 43) => 0.00140154
+(0, -1) ~ (4, 44) => 0.000486851
+(0, -1) ~ (4, 45) => 0.0011422
+(0, -1) ~ (4, 46) => 0.00117666
+(0, -1) ~ (4, 47) => 0.00113469
+(0, -1) ~ (4, 48) => 0.00104165
+(0, -1) ~ (4, 49) => 0.00095284
+(0, -1) ~ (4, 50) => 0.000806451
+(0, -1) ~ (4, 51) => 0.000363767
+(0, -1) ~ (4, 52) => 0.0001
+(0, -1) ~ (4, 53) => 0.0001
+(0, -1) ~ (4, 54) => 0.0001
+(0, -1) ~ (4, 55) => 0.0001
+(0, -1) ~ (4, 56) => 0.000353396
+(0, -1) ~ (4, 57) => 0.00688815
+(0, -1) ~ (4, 58) => 0.0140308
+(0, -1) ~ (4, 59) => 0.0475833
+(0, -1) ~ (4, 60) => 0.0105454
+(0, -1) ~ (4, 61) => 0.0447659
+(0, -1) ~ (4, 62) => 0.045572
+(0, -1) ~ (4, 63) => 0.2374
+(0, -1) ~ (4, 64) => 0.301012
+(0, -1) ~ (4, 65) => 0.13422
+(0, -1) ~ (4, 66) => 0.146606
+(0, -1) ~ (4, 67) => 0.106942
+(0, -1) ~ (4, 68) => 0.00670028
+(0, -1) ~ (4, 69) => 0.0012604
+(0, -1) ~ (4, 70) => 0.0011977
+(0, -1) ~ (4, 71) => 0.000553012
+(0, -1) ~ (4, 72) => 0.0001
+(0, -1) ~ (4, 73) => 0.0001
+(0, -1) ~ (4, 74) => 0.0001
+(0, -1) ~ (4, 75) => 0.0001
+(0, -1) ~ (4, 76) => 0.000669003
+(0, -1) ~ (4, 77) => 0.00129616
+(0, -1) ~ (4, 78) => 0.00399309
+(0, -1) ~ (4, 79) => 0.0219549
+(0, -1) ~ (4, 80) => 0.0105922
+(0, -1) ~ (4, 81) => 0.0117723
+(0, -1) ~ (4, 82) => 0.0212967
+(0, -1) ~ (4, 83) => 0.0289944
+(0, -1) ~ (4, 84) => 0.0233412
+(0, -1) ~ (4, 85) => 0.0124202
+(0, -1) ~ (4, 86) => 0.0140181
+(0, -1) ~ (4, 87) => 0.0121716
+(0, -1) ~ (4, 88) => 0.011305
+(0, -1) ~ (4, 89) => 0.0110158
+(0, -1) ~ (4, 90) => 0.0131413
+(0, -1) ~ (4, 91) => 0.0163044
+(0, -1) ~ (4, 92) => 0.0691826
+(0, -1) ~ (4, 93) => 0.134023
+(0, -1) ~ (4, 94) => 0.169929
+(0, -1) ~ (4, 95) => 0.328359
+(0, -1) ~ (4, 96) => 0.311586
+(0, -1) ~ (4, 97) => 0.272593
+(0, -1) ~ (4, 98) => 0.360006
+(0, -1) ~ (4, 99) => 0.517203
+(0, -1) ~ (4, 100) => 0.507521
+(0, -1) ~ (4, 101) => 0.62158
+(0, -1) ~ (4, 102) => 0.634773
+(0, -1) ~ (4, 103) => 0.586997
+(0, -1) ~ (4, 104) => 0.409765
+(0, -1) ~ (4, 105) => 0.307269
+(0, -1) ~ (4, 106) => 0.134563
+(0, -1) ~ (4, 107) => 0.0398096
+(0, -1) ~ (4, 108) => 0.0108522
+(0, -1) ~ (4, 109) => 0.00129521
+(0, -1) ~ (4, 110) => 0.000197172
+(0, -1) ~ (4, 111) => 0.0001
+(0, -1) ~ (4, 112) => 0.0001
+(0, -1) ~ (4, 113) => 0.0001
+(0, -1) ~ (4, 114) => 0.0001
+(0, -1) ~ (4, 115) => 0.0001
+(0, -1) ~ (4, 116) => 0.0001
+(0, -1) ~ (4, 117) => 0.000155985
+(0, -1) ~ (4, 118) => 0.000149667
+(0, -1) ~ (4, 119) => 0.0001
+(0, -1) ~ (4, 120) => 0.0001
+(0, -1) ~ (4, 121) => 0.0001
+(0, -1) ~ (4, 122) => 0.000293672
+(0, -1) ~ (4, 123) => 0.000352561
+(0, -1) ~ (4, 124) => 0.000213325
+(0, -1) ~ (4, 125) => 0.000407279
+(0, -1) ~ (4, 126) => 0.000633597
+(0, -1) ~ (4, 127) => 0.000595212
+(0, -1) ~ (4, 128) => 0.000975251
+(0, -1) ~ (4, 129) => 0.00229573
+(0, -1) ~ (4, 130) => 0.0227012
+(0, -1) ~ (4, 131) => 0.0255798
+(0, -1) ~ (4, 132) => 0.0494619
+(0, -1) ~ (4, 133) => 0.039988
+(0, -1) ~ (4, 134) => 0.0293914
+(0, -1) ~ (4, 135) => 0.0451066
+(0, -1) ~ (4, 136) => 0.0346686
+(0, -1) ~ (4, 137) => 0.049529
+(0, -1) ~ (4, 138) => 0.0559277
+(0, -1) ~ (4, 139) => 0.0584328
+(0, -1) ~ (4, 140) => 0.0404646
+(0, -1) ~ (4, 141) => 0.0175101
+(0, -1) ~ (4, 142) => 0.00928527
+(0, -1) ~ (4, 143) => 0.0115475
+(0, -1) ~ (4, 144) => 0.00266963
+(0, -1) ~ (4, 145) => 0.00181472
+(0, -1) ~ (4, 146) => 0.00149387
+(0, -1) ~ (4, 147) => 0.00039351
+(0, -1) ~ (4, 148) => 0.0001
+(0, -1) ~ (4, 149) => 0.0001
+(0, -1) ~ (4, 150) => 0.0001
+(0, -1) ~ (4, 151) => 0.0001
+(0, -1) ~ (4, 152) => 0.0001
+(0, -1) ~ (4, 153) => 0.0001
+(0, -1) ~ (4, 154) => 0.0001
+(0, -1) ~ (4, 155) => 0.0001
+(0, -1) ~ (4, 156) => 0.0001
+(0, -1) ~ (4, 157) => 0.000319719
+(0, -1) ~ (4, 158) => 0.0013063
+(0, -1) ~ (4, 159) => 0.00298697
+(0, -1) ~ (4, 160) => 0.00552952
+(0, -1) ~ (4, 161) => 0.00917131
+(0, -1) ~ (4, 162) => 0.0103619
+(0, -1) ~ (4, 163) => 0.0118175
+(0, -1) ~ (4, 164) => 0.0119948
+(0, -1) ~ (4, 165) => 0.0117887
+(0, -1) ~ (4, 166) => 0.0103491
+(0, -1) ~ (4, 167) => 0.0104428
+(0, -1) ~ (4, 168) => 0.00951463
+(0, -1) ~ (4, 169) => 0.00673634
+(0, -1) ~ (4, 170) => 0.00539619
+(0, -1) ~ (4, 171) => 0.00674355
+(0, -1) ~ (4, 172) => 0.00667179
+(0, -1) ~ (4, 173) => 0.00607073
+(0, -1) ~ (4, 174) => 0.00373232
+(0, -1) ~ (4, 175) => 0.00188553
+(0, -1) ~ (4, 176) => 0.00195307
+(0, -1) ~ (4, 177) => 0.002469
+(0, -1) ~ (4, 178) => 0.00190991
+(0, -1) ~ (4, 179) => 0.00121814
+(0, -1) ~ (4, 180) => 0.000444174
+(0, -1) ~ (4, 181) => 0.0001
+(0, -1) ~ (4, 182) => 0.0001
+(0, -1) ~ (4, 183) => 0.0001
+(0, -1) ~ (4, 184) => 0.0001
+(0, -1) ~ (4, 185) => 0.000285149
+(0, -1) ~ (4, 186) => 0.000494838
+(0, -1) ~ (4, 187) => 0.000773668
+(0, -1) ~ (4, 188) => 0.00187337
+(0, -1) ~ (4, 189) => 0.00483721
+(0, -1) ~ (4, 190) => 0.0114324
+(0, -1) ~ (4, 191) => 0.0240892
+(0, -1) ~ (4, 192) => 0.0279076
+(0, -1) ~ (4, 193) => 0.0300394
+(0, -1) ~ (4, 194) => 0.0104085
+(0, -1) ~ (4, 195) => 0.00786436
+(0, -1) ~ (4, 196) => 0.00675684
+(0, -1) ~ (4, 197) => 0.00514954
+(0, -1) ~ (4, 198) => 0.00616926
+(0, -1) ~ (4, 199) => 0.00685573
+(0, -1) ~ (4, 200) => 0.0072242
+(0, -1) ~ (4, 201) => 0.00629675
+(0, -1) ~ (4, 202) => 0.0100607
+(0, -1) ~ (4, 203) => 0.00777411
+(0, -1) ~ (4, 204) => 0.00521457
+(0, -1) ~ (4, 205) => 0.00508708
+(0, -1) ~ (4, 206) => 0.00439292
+(0, -1) ~ (4, 207) => 0.00630236
+(0, -1) ~ (4, 208) => 0.00714415
+(0, -1) ~ (4, 209) => 0.0069564
+(0, -1) ~ (4, 210) => 0.00565755
+(0, -1) ~ (4, 211) => 0.0145437
+(0, -1) ~ (4, 212) => 0.00821571
+(0, -1) ~ (4, 213) => 0.00929741
+(0, -1) ~ (4, 214) => 0.0136429
+(0, -1) ~ (4, 215) => 0.0164522
+(0, -1) ~ (4, 216) => 0.0266207
+(0, -1) ~ (4, 217) => 0.0245598
+(0, -1) ~ (4, 218) => 0.0296581
+(0, -1) ~ (4, 219) => 0.0239646
+(0, -1) ~ (4, 220) => 0.151988
+(0, -1) ~ (4, 221) => 0.556576
+(0, -1) ~ (4, 222) => 0.0660902
+(0, -1) ~ (4, 223) => 0.0819809
+(0, -1) ~ (4, 224) => 0.0813152
+(0, -1) ~ (4, 225) => 0.0581095
+(0, -1) ~ (4, 226) => 0.0654867
+(0, -1) ~ (4, 227) => 0.00455266
+(0, -1) ~ (4, 228) => 0.000714719
+(0, -1) ~ (4, 229) => 0.0001
+(0, -1) ~ (4, 230) => 0.000442564
+(0, -1) ~ (4, 231) => 0.00179833
+(0, -1) ~ (4, 232) => 0.00248355
+(0, -1) ~ (4, 233) => 0.0114902
+(0, -1) ~ (4, 234) => 0.00823236
+(0, -1) ~ (4, 235) => 0.0020631
+(0, -1) ~ (4, 236) => 0.00162429
+(0, -1) ~ (4, 237) => 0.000781894
+
+; Sparse posterior probability matrix for sequences 0 and 5
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (5, 0) => 0.99998
+(0, 1) ~ (5, 1) => 0.99997
+(0, 2) ~ (5, 2) => 0.999967
+(0, 3) ~ (5, 3) => 0.99997
+(0, 4) ~ (5, 4) => 0.999972
+(0, 5) ~ (5, 5) => 0.99998
+(0, 6) ~ (5, 6) => 0.999984
+(0, 7) ~ (5, 7) => 0.999995
+(0, 8) ~ (5, 8) => 0.999993
+(0, 9) ~ (5, 9) => 0.999963
+(0, 10) ~ (5, 10) => 0.999885
+(0, 11) ~ (5, 11) => 0.992982
+(0, 12) ~ (5, 12) => 0.956823
+(0, 12) ~ (5, 13) => 0.042909
+(0, 13) ~ (5, 13) => 0.92784
+(0, 13) ~ (5, 14) => 0.0718188
+(0, 14) ~ (5, 14) => 0.536412
+(0, 14) ~ (5, 15) => 0.46326
+(0, 15) ~ (5, 15) => 0.0416179
+(0, 15) ~ (5, 16) => 0.958288
+(0, 16) ~ (5, 17) => 0.995469
+(0, 17) ~ (5, 18) => 0.999854
+(0, 18) ~ (5, 19) => 0.999974
+(0, 19) ~ (5, 20) => 1
+(0, 20) ~ (5, 21) => 1
+(0, 21) ~ (5, 22) => 1
+(0, 22) ~ (5, 23) => 1
+(0, 23) ~ (5, 24) => 0.999999
+(0, 24) ~ (5, 25) => 0.999995
+(0, 25) ~ (5, 26) => 0.999993
+(0, 26) ~ (5, 27) => 0.999993
+(0, 27) ~ (5, 28) => 0.999998
+(0, 28) ~ (5, 29) => 0.999998
+(0, 29) ~ (5, 30) => 0.999995
+(0, 30) ~ (5, 31) => 0.999993
+(0, 31) ~ (5, 32) => 0.999992
+(0, 32) ~ (5, 33) => 0.999994
+(0, 33) ~ (5, 34) => 0.999997
+(0, 34) ~ (5, 35) => 0.999999
+(0, 35) ~ (5, 36) => 0.999999
+(0, 36) ~ (5, 37) => 0.999996
+(0, 37) ~ (5, 38) => 0.999994
+(0, 38) ~ (5, 39) => 0.999994
+(0, 39) ~ (5, 40) => 0.999996
+(0, 40) ~ (5, 41) => 0.999996
+(0, 41) ~ (5, 42) => 0.999996
+(0, 42) ~ (5, 43) => 1
+(0, 43) ~ (5, 44) => 1
+(0, 44) ~ (5, 45) => 0.999997
+(0, 45) ~ (5, 46) => 0.999978
+(0, 46) ~ (5, 47) => 0.999975
+(0, 47) ~ (5, 48) => 0.999979
+(0, 48) ~ (5, 49) => 0.999976
+(0, 49) ~ (5, 50) => 0.999991
+(0, 50) ~ (5, 51) => 0.999994
+(0, 51) ~ (5, 52) => 1
+(0, 52) ~ (5, 53) => 1
+(0, 53) ~ (5, 54) => 1
+(0, 54) ~ (5, 55) => 1
+(0, 55) ~ (5, 56) => 1
+(0, 56) ~ (5, 57) => 1
+(0, 57) ~ (5, 58) => 1
+(0, 58) ~ (5, 59) => 0.999999
+(0, 59) ~ (5, 60) => 0.999998
+(0, 60) ~ (5, 61) => 0.999997
+(0, 61) ~ (5, 62) => 0.999997
+(0, 62) ~ (5, 63) => 0.999999
+(0, 63) ~ (5, 64) => 1
+(0, 64) ~ (5, 65) => 1
+(0, 65) ~ (5, 66) => 1
+(0, 66) ~ (5, 67) => 1
+(0, 67) ~ (5, 68) => 1
+(0, 68) ~ (5, 69) => 1
+(0, 69) ~ (5, 70) => 1
+(0, 70) ~ (5, 71) => 1
+(0, 71) ~ (5, 72) => 1
+(0, 72) ~ (5, 73) => 1
+(0, 73) ~ (5, 74) => 1
+(0, 74) ~ (5, 75) => 1
+(0, 75) ~ (5, 76) => 1
+(0, 76) ~ (5, 77) => 0.999999
+(0, 77) ~ (5, 78) => 0.999997
+(0, 78) ~ (5, 79) => 0.999995
+(0, 79) ~ (5, 80) => 0.999994
+(0, 80) ~ (5, 81) => 0.999992
+(0, 81) ~ (5, 82) => 0.999995
+(0, 82) ~ (5, 83) => 0.999999
+(0, 83) ~ (5, 84) => 0.999999
+(0, 84) ~ (5, 85) => 0.999999
+(0, 85) ~ (5, 86) => 0.999998
+(0, 86) ~ (5, 87) => 0.999993
+(0, 87) ~ (5, 88) => 0.99999
+(0, 88) ~ (5, 89) => 0.999929
+(0, 89) ~ (5, 90) => 0.99991
+(0, 90) ~ (5, 91) => 0.999857
+(0, 91) ~ (5, 92) => 0.999844
+(0, 92) ~ (5, 93) => 0.999851
+(0, 93) ~ (5, 94) => 0.999971
+(0, 94) ~ (5, 95) => 0.999994
+(0, 95) ~ (5, 96) => 0.999999
+(0, 96) ~ (5, 97) => 1
+(0, 97) ~ (5, 98) => 0.999999
+(0, 98) ~ (5, 99) => 0.999991
+(0, 99) ~ (5, 100) => 0.999944
+(0, 100) ~ (5, 101) => 0.999938
+(0, 101) ~ (5, 102) => 0.999957
+(0, 102) ~ (5, 103) => 0.999976
+(0, 103) ~ (5, 104) => 0.999988
+(0, 104) ~ (5, 105) => 1
+(0, 105) ~ (5, 106) => 1
+(0, 106) ~ (5, 107) => 1
+(0, 107) ~ (5, 108) => 1
+(0, 108) ~ (5, 109) => 1
+(0, 109) ~ (5, 110) => 1
+(0, 110) ~ (5, 111) => 1
+(0, 111) ~ (5, 112) => 1
+(0, 112) ~ (5, 113) => 1
+(0, 113) ~ (5, 114) => 1
+(0, 114) ~ (5, 115) => 0.999999
+(0, 115) ~ (5, 116) => 0.999988
+(0, 116) ~ (5, 117) => 0.999983
+(0, 117) ~ (5, 118) => 0.999982
+(0, 118) ~ (5, 119) => 0.999984
+(0, 119) ~ (5, 120) => 0.99998
+(0, 120) ~ (5, 121) => 0.999979
+(0, 121) ~ (5, 122) => 0.999982
+(0, 122) ~ (5, 123) => 0.999999
+(0, 123) ~ (5, 124) => 1
+(0, 124) ~ (5, 125) => 1
+(0, 125) ~ (5, 126) => 1
+(0, 126) ~ (5, 127) => 1
+(0, 127) ~ (5, 128) => 1
+(0, 128) ~ (5, 129) => 1
+(0, 129) ~ (5, 130) => 0.999999
+(0, 130) ~ (5, 131) => 0.999999
+(0, 131) ~ (5, 132) => 0.999997
+(0, 132) ~ (5, 133) => 0.999998
+(0, 133) ~ (5, 134) => 0.999998
+(0, 134) ~ (5, 135) => 1
+(0, 135) ~ (5, 136) => 0.999999
+(0, 136) ~ (5, 137) => 0.999999
+(0, 137) ~ (5, 138) => 1
+(0, 138) ~ (5, 139) => 1
+(0, 139) ~ (5, 140) => 1
+(0, 140) ~ (5, 141) => 1
+(0, 141) ~ (5, 142) => 1
+(0, 142) ~ (5, 143) => 1
+(0, 143) ~ (5, 144) => 1
+(0, 144) ~ (5, 145) => 1
+(0, 145) ~ (5, 146) => 1
+(0, 146) ~ (5, 147) => 1
+(0, 147) ~ (5, 148) => 1
+(0, 148) ~ (5, 149) => 0.999999
+(0, 149) ~ (5, 150) => 0.999999
+(0, 150) ~ (5, 151) => 1
+(0, 151) ~ (5, 152) => 1
+(0, 152) ~ (5, 153) => 1
+(0, 153) ~ (5, 154) => 1
+(0, 154) ~ (5, 155) => 1
+(0, 155) ~ (5, 156) => 0.999997
+(0, 156) ~ (5, 157) => 0.999985
+(0, 157) ~ (5, 158) => 0.999981
+(0, 158) ~ (5, 159) => 0.999983
+(0, 159) ~ (5, 160) => 0.999982
+(0, 160) ~ (5, 161) => 0.999983
+(0, 161) ~ (5, 162) => 0.999985
+(0, 162) ~ (5, 163) => 0.999989
+(0, 163) ~ (5, 164) => 0.999989
+(0, 164) ~ (5, 165) => 0.999986
+(0, 165) ~ (5, 166) => 0.999986
+(0, 166) ~ (5, 167) => 0.999986
+(0, 167) ~ (5, 168) => 0.999965
+(0, 168) ~ (5, 169) => 0.999959
+(0, 169) ~ (5, 170) => 0.99996
+(0, 170) ~ (5, 171) => 0.999968
+(0, 171) ~ (5, 172) => 0.999976
+(0, 172) ~ (5, 173) => 0.999985
+(0, 173) ~ (5, 174) => 0.999988
+(0, 174) ~ (5, 175) => 0.99999
+(0, 175) ~ (5, 176) => 0.999996
+(0, 176) ~ (5, 177) => 1
+(0, 177) ~ (5, 178) => 1
+(0, 178) ~ (5, 179) => 1
+(0, 179) ~ (5, 180) => 1
+(0, 180) ~ (5, 181) => 1
+(0, 181) ~ (5, 182) => 0.999992
+(0, 182) ~ (5, 183) => 0.999986
+(0, 183) ~ (5, 184) => 0.999966
+(0, 184) ~ (5, 185) => 0.99989
+(0, 185) ~ (5, 186) => 0.999658
+(0, 186) ~ (5, 187) => 0.999182
+(0, 187) ~ (5, 188) => 0.998765
+(0, 188) ~ (5, 189) => 0.998509
+(0, 189) ~ (5, 190) => 0.998451
+(0, 190) ~ (5, 191) => 0.998407
+(0, 191) ~ (5, 192) => 0.998461
+(0, 192) ~ (5, 193) => 0.998468
+(0, 193) ~ (5, 194) => 0.998691
+(0, 194) ~ (5, 195) => 0.99909
+(0, 195) ~ (5, 196) => 0.999236
+(0, 196) ~ (5, 197) => 0.99956
+(0, 197) ~ (5, 198) => 0.999645
+(0, 198) ~ (5, 199) => 0.999706
+(0, 199) ~ (5, 200) => 0.999724
+(0, 200) ~ (5, 201) => 0.999772
+(0, 201) ~ (5, 202) => 0.999817
+(0, 202) ~ (5, 203) => 0.999875
+(0, 203) ~ (5, 204) => 0.999887
+(0, 204) ~ (5, 205) => 0.999913
+(0, 205) ~ (5, 206) => 0.999982
+(0, 206) ~ (5, 207) => 0.999997
+(0, 207) ~ (5, 208) => 0.999998
+(0, 208) ~ (5, 209) => 0.999999
+(0, 209) ~ (5, 210) => 0.999999
+(0, 210) ~ (5, 211) => 1
+(0, 211) ~ (5, 212) => 1
+(0, 212) ~ (5, 213) => 1
+(0, 213) ~ (5, 214) => 1
+(0, 214) ~ (5, 215) => 0.999999
+(0, 215) ~ (5, 216) => 0.999992
+(0, 216) ~ (5, 217) => 0.999918
+(0, 217) ~ (5, 218) => 0.999897
+(0, 218) ~ (5, 219) => 0.999875
+(0, 219) ~ (5, 220) => 0.999875
+(0, 220) ~ (5, 221) => 0.999937
+(0, 221) ~ (5, 222) => 0.99996
+(0, 222) ~ (5, 223) => 0.999996
+(0, 223) ~ (5, 224) => 1
+(0, 224) ~ (5, 225) => 1
+(0, 225) ~ (5, 226) => 1
+(0, 226) ~ (5, 227) => 0.999998
+(0, 227) ~ (5, 228) => 0.999994
+(0, 228) ~ (5, 229) => 0.999937
+(0, 229) ~ (5, 230) => 0.99993
+(0, 230) ~ (5, 231) => 0.999934
+(0, 231) ~ (5, 232) => 0.999949
+(0, 232) ~ (5, 233) => 0.999979
+
+; gap posteriors
+(0, 0) ~ (5, -1) => 0.0001
+(0, 1) ~ (5, -1) => 0.0001
+(0, 2) ~ (5, -1) => 0.0001
+(0, 3) ~ (5, -1) => 0.0001
+(0, 4) ~ (5, -1) => 0.0001
+(0, 5) ~ (5, -1) => 0.0001
+(0, 6) ~ (5, -1) => 0.0001
+(0, 7) ~ (5, -1) => 0.0001
+(0, 8) ~ (5, -1) => 0.0001
+(0, 9) ~ (5, -1) => 0.0001
+(0, 10) ~ (5, -1) => 0.000115097
+(0, 11) ~ (5, -1) => 0.00701809
+(0, 12) ~ (5, -1) => 0.000268403
+(0, 13) ~ (5, -1) => 0.00034149
+(0, 14) ~ (5, -1) => 0.000327647
+(0, 15) ~ (5, -1) => 0.0001
+(0, 16) ~ (5, -1) => 0.00453055
+(0, 17) ~ (5, -1) => 0.000145555
+(0, 18) ~ (5, -1) => 0.0001
+(0, 19) ~ (5, -1) => 0.0001
+(0, 20) ~ (5, -1) => 0.0001
+(0, 21) ~ (5, -1) => 0.0001
+(0, 22) ~ (5, -1) => 0.0001
+(0, 23) ~ (5, -1) => 0.0001
+(0, 24) ~ (5, -1) => 0.0001
+(0, 25) ~ (5, -1) => 0.0001
+(0, 26) ~ (5, -1) => 0.0001
+(0, 27) ~ (5, -1) => 0.0001
+(0, 28) ~ (5, -1) => 0.0001
+(0, 29) ~ (5, -1) => 0.0001
+(0, 30) ~ (5, -1) => 0.0001
+(0, 31) ~ (5, -1) => 0.0001
+(0, 32) ~ (5, -1) => 0.0001
+(0, 33) ~ (5, -1) => 0.0001
+(0, 34) ~ (5, -1) => 0.0001
+(0, 35) ~ (5, -1) => 0.0001
+(0, 36) ~ (5, -1) => 0.0001
+(0, 37) ~ (5, -1) => 0.0001
+(0, 38) ~ (5, -1) => 0.0001
+(0, 39) ~ (5, -1) => 0.0001
+(0, 40) ~ (5, -1) => 0.0001
+(0, 41) ~ (5, -1) => 0.0001
+(0, 42) ~ (5, -1) => 0.0001
+(0, 43) ~ (5, -1) => 0.0001
+(0, 44) ~ (5, -1) => 0.0001
+(0, 45) ~ (5, -1) => 0.0001
+(0, 46) ~ (5, -1) => 0.0001
+(0, 47) ~ (5, -1) => 0.0001
+(0, 48) ~ (5, -1) => 0.0001
+(0, 49) ~ (5, -1) => 0.0001
+(0, 50) ~ (5, -1) => 0.0001
+(0, 51) ~ (5, -1) => 0.0001
+(0, 52) ~ (5, -1) => 0.0001
+(0, 53) ~ (5, -1) => 0.0001
+(0, 54) ~ (5, -1) => 0.0001
+(0, 55) ~ (5, -1) => 0.0001
+(0, 56) ~ (5, -1) => 0.0001
+(0, 57) ~ (5, -1) => 0.0001
+(0, 58) ~ (5, -1) => 0.0001
+(0, 59) ~ (5, -1) => 0.0001
+(0, 60) ~ (5, -1) => 0.0001
+(0, 61) ~ (5, -1) => 0.0001
+(0, 62) ~ (5, -1) => 0.0001
+(0, 63) ~ (5, -1) => 0.0001
+(0, 64) ~ (5, -1) => 0.0001
+(0, 65) ~ (5, -1) => 0.0001
+(0, 66) ~ (5, -1) => 0.0001
+(0, 67) ~ (5, -1) => 0.0001
+(0, 68) ~ (5, -1) => 0.0001
+(0, 69) ~ (5, -1) => 0.0001
+(0, 70) ~ (5, -1) => 0.0001
+(0, 71) ~ (5, -1) => 0.0001
+(0, 72) ~ (5, -1) => 0.0001
+(0, 73) ~ (5, -1) => 0.0001
+(0, 74) ~ (5, -1) => 0.0001
+(0, 75) ~ (5, -1) => 0.0001
+(0, 76) ~ (5, -1) => 0.0001
+(0, 77) ~ (5, -1) => 0.0001
+(0, 78) ~ (5, -1) => 0.0001
+(0, 79) ~ (5, -1) => 0.0001
+(0, 80) ~ (5, -1) => 0.0001
+(0, 81) ~ (5, -1) => 0.0001
+(0, 82) ~ (5, -1) => 0.0001
+(0, 83) ~ (5, -1) => 0.0001
+(0, 84) ~ (5, -1) => 0.0001
+(0, 85) ~ (5, -1) => 0.0001
+(0, 86) ~ (5, -1) => 0.0001
+(0, 87) ~ (5, -1) => 0.0001
+(0, 88) ~ (5, -1) => 0.0001
+(0, 89) ~ (5, -1) => 0.0001
+(0, 90) ~ (5, -1) => 0.000143111
+(0, 91) ~ (5, -1) => 0.000156403
+(0, 92) ~ (5, -1) => 0.00014931
+(0, 93) ~ (5, -1) => 0.0001
+(0, 94) ~ (5, -1) => 0.0001
+(0, 95) ~ (5, -1) => 0.0001
+(0, 96) ~ (5, -1) => 0.0001
+(0, 97) ~ (5, -1) => 0.0001
+(0, 98) ~ (5, -1) => 0.0001
+(0, 99) ~ (5, -1) => 0.0001
+(0, 100) ~ (5, -1) => 0.0001
+(0, 101) ~ (5, -1) => 0.0001
+(0, 102) ~ (5, -1) => 0.0001
+(0, 103) ~ (5, -1) => 0.0001
+(0, 104) ~ (5, -1) => 0.0001
+(0, 105) ~ (5, -1) => 0.0001
+(0, 106) ~ (5, -1) => 0.0001
+(0, 107) ~ (5, -1) => 0.0001
+(0, 108) ~ (5, -1) => 0.0001
+(0, 109) ~ (5, -1) => 0.0001
+(0, 110) ~ (5, -1) => 0.0001
+(0, 111) ~ (5, -1) => 0.0001
+(0, 112) ~ (5, -1) => 0.0001
+(0, 113) ~ (5, -1) => 0.0001
+(0, 114) ~ (5, -1) => 0.0001
+(0, 115) ~ (5, -1) => 0.0001
+(0, 116) ~ (5, -1) => 0.0001
+(0, 117) ~ (5, -1) => 0.0001
+(0, 118) ~ (5, -1) => 0.0001
+(0, 119) ~ (5, -1) => 0.0001
+(0, 120) ~ (5, -1) => 0.0001
+(0, 121) ~ (5, -1) => 0.0001
+(0, 122) ~ (5, -1) => 0.0001
+(0, 123) ~ (5, -1) => 0.0001
+(0, 124) ~ (5, -1) => 0.0001
+(0, 125) ~ (5, -1) => 0.0001
+(0, 126) ~ (5, -1) => 0.0001
+(0, 127) ~ (5, -1) => 0.0001
+(0, 128) ~ (5, -1) => 0.0001
+(0, 129) ~ (5, -1) => 0.0001
+(0, 130) ~ (5, -1) => 0.0001
+(0, 131) ~ (5, -1) => 0.0001
+(0, 132) ~ (5, -1) => 0.0001
+(0, 133) ~ (5, -1) => 0.0001
+(0, 134) ~ (5, -1) => 0.0001
+(0, 135) ~ (5, -1) => 0.0001
+(0, 136) ~ (5, -1) => 0.0001
+(0, 137) ~ (5, -1) => 0.0001
+(0, 138) ~ (5, -1) => 0.0001
+(0, 139) ~ (5, -1) => 0.0001
+(0, 140) ~ (5, -1) => 0.0001
+(0, 141) ~ (5, -1) => 0.0001
+(0, 142) ~ (5, -1) => 0.0001
+(0, 143) ~ (5, -1) => 0.0001
+(0, 144) ~ (5, -1) => 0.0001
+(0, 145) ~ (5, -1) => 0.0001
+(0, 146) ~ (5, -1) => 0.0001
+(0, 147) ~ (5, -1) => 0.0001
+(0, 148) ~ (5, -1) => 0.0001
+(0, 149) ~ (5, -1) => 0.0001
+(0, 150) ~ (5, -1) => 0.0001
+(0, 151) ~ (5, -1) => 0.0001
+(0, 152) ~ (5, -1) => 0.0001
+(0, 153) ~ (5, -1) => 0.0001
+(0, 154) ~ (5, -1) => 0.0001
+(0, 155) ~ (5, -1) => 0.0001
+(0, 156) ~ (5, -1) => 0.0001
+(0, 157) ~ (5, -1) => 0.0001
+(0, 158) ~ (5, -1) => 0.0001
+(0, 159) ~ (5, -1) => 0.0001
+(0, 160) ~ (5, -1) => 0.0001
+(0, 161) ~ (5, -1) => 0.0001
+(0, 162) ~ (5, -1) => 0.0001
+(0, 163) ~ (5, -1) => 0.0001
+(0, 164) ~ (5, -1) => 0.0001
+(0, 165) ~ (5, -1) => 0.0001
+(0, 166) ~ (5, -1) => 0.0001
+(0, 167) ~ (5, -1) => 0.0001
+(0, 168) ~ (5, -1) => 0.0001
+(0, 169) ~ (5, -1) => 0.0001
+(0, 170) ~ (5, -1) => 0.0001
+(0, 171) ~ (5, -1) => 0.0001
+(0, 172) ~ (5, -1) => 0.0001
+(0, 173) ~ (5, -1) => 0.0001
+(0, 174) ~ (5, -1) => 0.0001
+(0, 175) ~ (5, -1) => 0.0001
+(0, 176) ~ (5, -1) => 0.0001
+(0, 177) ~ (5, -1) => 0.0001
+(0, 178) ~ (5, -1) => 0.0001
+(0, 179) ~ (5, -1) => 0.0001
+(0, 180) ~ (5, -1) => 0.0001
+(0, 181) ~ (5, -1) => 0.0001
+(0, 182) ~ (5, -1) => 0.0001
+(0, 183) ~ (5, -1) => 0.0001
+(0, 184) ~ (5, -1) => 0.00011009
+(0, 185) ~ (5, -1) => 0.000341892
+(0, 186) ~ (5, -1) => 0.000817537
+(0, 187) ~ (5, -1) => 0.00123513
+(0, 188) ~ (5, -1) => 0.00149065
+(0, 189) ~ (5, -1) => 0.00154889
+(0, 190) ~ (5, -1) => 0.00159281
+(0, 191) ~ (5, -1) => 0.00153947
+(0, 192) ~ (5, -1) => 0.00153232
+(0, 193) ~ (5, -1) => 0.00130916
+(0, 194) ~ (5, -1) => 0.000910282
+(0, 195) ~ (5, -1) => 0.00076437
+(0, 196) ~ (5, -1) => 0.0004403
+(0, 197) ~ (5, -1) => 0.000355244
+(0, 198) ~ (5, -1) => 0.000293911
+(0, 199) ~ (5, -1) => 0.000276268
+(0, 200) ~ (5, -1) => 0.000228465
+(0, 201) ~ (5, -1) => 0.000182867
+(0, 202) ~ (5, -1) => 0.000124633
+(0, 203) ~ (5, -1) => 0.000113487
+(0, 204) ~ (5, -1) => 0.0001
+(0, 205) ~ (5, -1) => 0.0001
+(0, 206) ~ (5, -1) => 0.0001
+(0, 207) ~ (5, -1) => 0.0001
+(0, 208) ~ (5, -1) => 0.0001
+(0, 209) ~ (5, -1) => 0.0001
+(0, 210) ~ (5, -1) => 0.0001
+(0, 211) ~ (5, -1) => 0.0001
+(0, 212) ~ (5, -1) => 0.0001
+(0, 213) ~ (5, -1) => 0.0001
+(0, 214) ~ (5, -1) => 0.0001
+(0, 215) ~ (5, -1) => 0.0001
+(0, 216) ~ (5, -1) => 0.0001
+(0, 217) ~ (5, -1) => 0.000102758
+(0, 218) ~ (5, -1) => 0.00012511
+(0, 219) ~ (5, -1) => 0.000124693
+(0, 220) ~ (5, -1) => 0.0001
+(0, 221) ~ (5, -1) => 0.0001
+(0, 222) ~ (5, -1) => 0.0001
+(0, 223) ~ (5, -1) => 0.0001
+(0, 224) ~ (5, -1) => 0.0001
+(0, 225) ~ (5, -1) => 0.0001
+(0, 226) ~ (5, -1) => 0.0001
+(0, 227) ~ (5, -1) => 0.0001
+(0, 228) ~ (5, -1) => 0.0001
+(0, 229) ~ (5, -1) => 0.0001
+(0, 230) ~ (5, -1) => 0.0001
+(0, 231) ~ (5, -1) => 0.0001
+(0, 232) ~ (5, -1) => 0.0001
+
+(0, -1) ~ (5, 0) => 0.0001
+(0, -1) ~ (5, 1) => 0.0001
+(0, -1) ~ (5, 2) => 0.0001
+(0, -1) ~ (5, 3) => 0.0001
+(0, -1) ~ (5, 4) => 0.0001
+(0, -1) ~ (5, 5) => 0.0001
+(0, -1) ~ (5, 6) => 0.0001
+(0, -1) ~ (5, 7) => 0.0001
+(0, -1) ~ (5, 8) => 0.0001
+(0, -1) ~ (5, 9) => 0.0001
+(0, -1) ~ (5, 10) => 0.000115097
+(0, -1) ~ (5, 11) => 0.00701809
+(0, -1) ~ (5, 12) => 0.0431774
+(0, -1) ~ (5, 13) => 0.0292513
+(0, -1) ~ (5, 14) => 0.391769
+(0, -1) ~ (5, 15) => 0.495122
+(0, -1) ~ (5, 16) => 0.0417121
+(0, -1) ~ (5, 17) => 0.00453055
+(0, -1) ~ (5, 18) => 0.000145555
+(0, -1) ~ (5, 19) => 0.0001
+(0, -1) ~ (5, 20) => 0.0001
+(0, -1) ~ (5, 21) => 0.0001
+(0, -1) ~ (5, 22) => 0.0001
+(0, -1) ~ (5, 23) => 0.0001
+(0, -1) ~ (5, 24) => 0.0001
+(0, -1) ~ (5, 25) => 0.0001
+(0, -1) ~ (5, 26) => 0.0001
+(0, -1) ~ (5, 27) => 0.0001
+(0, -1) ~ (5, 28) => 0.0001
+(0, -1) ~ (5, 29) => 0.0001
+(0, -1) ~ (5, 30) => 0.0001
+(0, -1) ~ (5, 31) => 0.0001
+(0, -1) ~ (5, 32) => 0.0001
+(0, -1) ~ (5, 33) => 0.0001
+(0, -1) ~ (5, 34) => 0.0001
+(0, -1) ~ (5, 35) => 0.0001
+(0, -1) ~ (5, 36) => 0.0001
+(0, -1) ~ (5, 37) => 0.0001
+(0, -1) ~ (5, 38) => 0.0001
+(0, -1) ~ (5, 39) => 0.0001
+(0, -1) ~ (5, 40) => 0.0001
+(0, -1) ~ (5, 41) => 0.0001
+(0, -1) ~ (5, 42) => 0.0001
+(0, -1) ~ (5, 43) => 0.0001
+(0, -1) ~ (5, 44) => 0.0001
+(0, -1) ~ (5, 45) => 0.0001
+(0, -1) ~ (5, 46) => 0.0001
+(0, -1) ~ (5, 47) => 0.0001
+(0, -1) ~ (5, 48) => 0.0001
+(0, -1) ~ (5, 49) => 0.0001
+(0, -1) ~ (5, 50) => 0.0001
+(0, -1) ~ (5, 51) => 0.0001
+(0, -1) ~ (5, 52) => 0.0001
+(0, -1) ~ (5, 53) => 0.0001
+(0, -1) ~ (5, 54) => 0.0001
+(0, -1) ~ (5, 55) => 0.0001
+(0, -1) ~ (5, 56) => 0.0001
+(0, -1) ~ (5, 57) => 0.0001
+(0, -1) ~ (5, 58) => 0.0001
+(0, -1) ~ (5, 59) => 0.0001
+(0, -1) ~ (5, 60) => 0.0001
+(0, -1) ~ (5, 61) => 0.0001
+(0, -1) ~ (5, 62) => 0.0001
+(0, -1) ~ (5, 63) => 0.0001
+(0, -1) ~ (5, 64) => 0.0001
+(0, -1) ~ (5, 65) => 0.0001
+(0, -1) ~ (5, 66) => 0.0001
+(0, -1) ~ (5, 67) => 0.0001
+(0, -1) ~ (5, 68) => 0.0001
+(0, -1) ~ (5, 69) => 0.0001
+(0, -1) ~ (5, 70) => 0.0001
+(0, -1) ~ (5, 71) => 0.0001
+(0, -1) ~ (5, 72) => 0.0001
+(0, -1) ~ (5, 73) => 0.0001
+(0, -1) ~ (5, 74) => 0.0001
+(0, -1) ~ (5, 75) => 0.0001
+(0, -1) ~ (5, 76) => 0.0001
+(0, -1) ~ (5, 77) => 0.0001
+(0, -1) ~ (5, 78) => 0.0001
+(0, -1) ~ (5, 79) => 0.0001
+(0, -1) ~ (5, 80) => 0.0001
+(0, -1) ~ (5, 81) => 0.0001
+(0, -1) ~ (5, 82) => 0.0001
+(0, -1) ~ (5, 83) => 0.0001
+(0, -1) ~ (5, 84) => 0.0001
+(0, -1) ~ (5, 85) => 0.0001
+(0, -1) ~ (5, 86) => 0.0001
+(0, -1) ~ (5, 87) => 0.0001
+(0, -1) ~ (5, 88) => 0.0001
+(0, -1) ~ (5, 89) => 0.0001
+(0, -1) ~ (5, 90) => 0.0001
+(0, -1) ~ (5, 91) => 0.000143111
+(0, -1) ~ (5, 92) => 0.000156403
+(0, -1) ~ (5, 93) => 0.00014931
+(0, -1) ~ (5, 94) => 0.0001
+(0, -1) ~ (5, 95) => 0.0001
+(0, -1) ~ (5, 96) => 0.0001
+(0, -1) ~ (5, 97) => 0.0001
+(0, -1) ~ (5, 98) => 0.0001
+(0, -1) ~ (5, 99) => 0.0001
+(0, -1) ~ (5, 100) => 0.0001
+(0, -1) ~ (5, 101) => 0.0001
+(0, -1) ~ (5, 102) => 0.0001
+(0, -1) ~ (5, 103) => 0.0001
+(0, -1) ~ (5, 104) => 0.0001
+(0, -1) ~ (5, 105) => 0.0001
+(0, -1) ~ (5, 106) => 0.0001
+(0, -1) ~ (5, 107) => 0.0001
+(0, -1) ~ (5, 108) => 0.0001
+(0, -1) ~ (5, 109) => 0.0001
+(0, -1) ~ (5, 110) => 0.0001
+(0, -1) ~ (5, 111) => 0.0001
+(0, -1) ~ (5, 112) => 0.0001
+(0, -1) ~ (5, 113) => 0.0001
+(0, -1) ~ (5, 114) => 0.0001
+(0, -1) ~ (5, 115) => 0.0001
+(0, -1) ~ (5, 116) => 0.0001
+(0, -1) ~ (5, 117) => 0.0001
+(0, -1) ~ (5, 118) => 0.0001
+(0, -1) ~ (5, 119) => 0.0001
+(0, -1) ~ (5, 120) => 0.0001
+(0, -1) ~ (5, 121) => 0.0001
+(0, -1) ~ (5, 122) => 0.0001
+(0, -1) ~ (5, 123) => 0.0001
+(0, -1) ~ (5, 124) => 0.0001
+(0, -1) ~ (5, 125) => 0.0001
+(0, -1) ~ (5, 126) => 0.0001
+(0, -1) ~ (5, 127) => 0.0001
+(0, -1) ~ (5, 128) => 0.0001
+(0, -1) ~ (5, 129) => 0.0001
+(0, -1) ~ (5, 130) => 0.0001
+(0, -1) ~ (5, 131) => 0.0001
+(0, -1) ~ (5, 132) => 0.0001
+(0, -1) ~ (5, 133) => 0.0001
+(0, -1) ~ (5, 134) => 0.0001
+(0, -1) ~ (5, 135) => 0.0001
+(0, -1) ~ (5, 136) => 0.0001
+(0, -1) ~ (5, 137) => 0.0001
+(0, -1) ~ (5, 138) => 0.0001
+(0, -1) ~ (5, 139) => 0.0001
+(0, -1) ~ (5, 140) => 0.0001
+(0, -1) ~ (5, 141) => 0.0001
+(0, -1) ~ (5, 142) => 0.0001
+(0, -1) ~ (5, 143) => 0.0001
+(0, -1) ~ (5, 144) => 0.0001
+(0, -1) ~ (5, 145) => 0.0001
+(0, -1) ~ (5, 146) => 0.0001
+(0, -1) ~ (5, 147) => 0.0001
+(0, -1) ~ (5, 148) => 0.0001
+(0, -1) ~ (5, 149) => 0.0001
+(0, -1) ~ (5, 150) => 0.0001
+(0, -1) ~ (5, 151) => 0.0001
+(0, -1) ~ (5, 152) => 0.0001
+(0, -1) ~ (5, 153) => 0.0001
+(0, -1) ~ (5, 154) => 0.0001
+(0, -1) ~ (5, 155) => 0.0001
+(0, -1) ~ (5, 156) => 0.0001
+(0, -1) ~ (5, 157) => 0.0001
+(0, -1) ~ (5, 158) => 0.0001
+(0, -1) ~ (5, 159) => 0.0001
+(0, -1) ~ (5, 160) => 0.0001
+(0, -1) ~ (5, 161) => 0.0001
+(0, -1) ~ (5, 162) => 0.0001
+(0, -1) ~ (5, 163) => 0.0001
+(0, -1) ~ (5, 164) => 0.0001
+(0, -1) ~ (5, 165) => 0.0001
+(0, -1) ~ (5, 166) => 0.0001
+(0, -1) ~ (5, 167) => 0.0001
+(0, -1) ~ (5, 168) => 0.0001
+(0, -1) ~ (5, 169) => 0.0001
+(0, -1) ~ (5, 170) => 0.0001
+(0, -1) ~ (5, 171) => 0.0001
+(0, -1) ~ (5, 172) => 0.0001
+(0, -1) ~ (5, 173) => 0.0001
+(0, -1) ~ (5, 174) => 0.0001
+(0, -1) ~ (5, 175) => 0.0001
+(0, -1) ~ (5, 176) => 0.0001
+(0, -1) ~ (5, 177) => 0.0001
+(0, -1) ~ (5, 178) => 0.0001
+(0, -1) ~ (5, 179) => 0.0001
+(0, -1) ~ (5, 180) => 0.0001
+(0, -1) ~ (5, 181) => 0.0001
+(0, -1) ~ (5, 182) => 0.0001
+(0, -1) ~ (5, 183) => 0.0001
+(0, -1) ~ (5, 184) => 0.0001
+(0, -1) ~ (5, 185) => 0.00011009
+(0, -1) ~ (5, 186) => 0.000341892
+(0, -1) ~ (5, 187) => 0.000817537
+(0, -1) ~ (5, 188) => 0.00123513
+(0, -1) ~ (5, 189) => 0.00149065
+(0, -1) ~ (5, 190) => 0.00154889
+(0, -1) ~ (5, 191) => 0.00159281
+(0, -1) ~ (5, 192) => 0.00153947
+(0, -1) ~ (5, 193) => 0.00153232
+(0, -1) ~ (5, 194) => 0.00130916
+(0, -1) ~ (5, 195) => 0.000910282
+(0, -1) ~ (5, 196) => 0.00076437
+(0, -1) ~ (5, 197) => 0.0004403
+(0, -1) ~ (5, 198) => 0.000355244
+(0, -1) ~ (5, 199) => 0.000293911
+(0, -1) ~ (5, 200) => 0.000276268
+(0, -1) ~ (5, 201) => 0.000228465
+(0, -1) ~ (5, 202) => 0.000182867
+(0, -1) ~ (5, 203) => 0.000124633
+(0, -1) ~ (5, 204) => 0.000113487
+(0, -1) ~ (5, 205) => 0.0001
+(0, -1) ~ (5, 206) => 0.0001
+(0, -1) ~ (5, 207) => 0.0001
+(0, -1) ~ (5, 208) => 0.0001
+(0, -1) ~ (5, 209) => 0.0001
+(0, -1) ~ (5, 210) => 0.0001
+(0, -1) ~ (5, 211) => 0.0001
+(0, -1) ~ (5, 212) => 0.0001
+(0, -1) ~ (5, 213) => 0.0001
+(0, -1) ~ (5, 214) => 0.0001
+(0, -1) ~ (5, 215) => 0.0001
+(0, -1) ~ (5, 216) => 0.0001
+(0, -1) ~ (5, 217) => 0.0001
+(0, -1) ~ (5, 218) => 0.000102758
+(0, -1) ~ (5, 219) => 0.00012511
+(0, -1) ~ (5, 220) => 0.000124693
+(0, -1) ~ (5, 221) => 0.0001
+(0, -1) ~ (5, 222) => 0.0001
+(0, -1) ~ (5, 223) => 0.0001
+(0, -1) ~ (5, 224) => 0.0001
+(0, -1) ~ (5, 225) => 0.0001
+(0, -1) ~ (5, 226) => 0.0001
+(0, -1) ~ (5, 227) => 0.0001
+(0, -1) ~ (5, 228) => 0.0001
+(0, -1) ~ (5, 229) => 0.0001
+(0, -1) ~ (5, 230) => 0.0001
+(0, -1) ~ (5, 231) => 0.0001
+(0, -1) ~ (5, 232) => 0.0001
+(0, -1) ~ (5, 233) => 0.0001
+
+; Sparse posterior probability matrix for sequences 1 and 2
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (2, 0) => 0.993019
+(1, 1) ~ (2, 1) => 0.989517
+(1, 2) ~ (2, 2) => 0.986456
+(1, 3) ~ (2, 3) => 0.964716
+(1, 3) ~ (2, 4) => 0.0164795
+(1, 3) ~ (2, 6) => 0.0165713
+(1, 4) ~ (2, 4) => 0.877497
+(1, 4) ~ (2, 5) => 0.0320993
+(1, 4) ~ (2, 7) => 0.0837111
+(1, 5) ~ (2, 5) => 0.857003
+(1, 5) ~ (2, 6) => 0.0329866
+(1, 5) ~ (2, 8) => 0.0974208
+(1, 6) ~ (2, 6) => 0.848276
+(1, 6) ~ (2, 7) => 0.0323247
+(1, 6) ~ (2, 9) => 0.106028
+(1, 7) ~ (2, 7) => 0.700335
+(1, 7) ~ (2, 8) => 0.0584836
+(1, 7) ~ (2, 10) => 0.21943
+(1, 8) ~ (2, 6) => 0.010108
+(1, 8) ~ (2, 8) => 0.418577
+(1, 8) ~ (2, 9) => 0.190819
+(1, 8) ~ (2, 11) => 0.341595
+(1, 9) ~ (2, 8) => 0.0316858
+(1, 9) ~ (2, 9) => 0.0806953
+(1, 9) ~ (2, 10) => 0.352615
+(1, 9) ~ (2, 12) => 0.495367
+(1, 10) ~ (2, 9) => 0.0579283
+(1, 10) ~ (2, 10) => 0.0226107
+(1, 10) ~ (2, 11) => 0.357558
+(1, 10) ~ (2, 13) => 0.549378
+(1, 11) ~ (2, 10) => 0.059208
+(1, 11) ~ (2, 11) => 0.016685
+(1, 11) ~ (2, 12) => 0.3456
+(1, 11) ~ (2, 14) => 0.56271
+(1, 12) ~ (2, 11) => 0.0493718
+(1, 12) ~ (2, 12) => 0.0129237
+(1, 12) ~ (2, 13) => 0.304786
+(1, 12) ~ (2, 14) => 0.0237175
+(1, 12) ~ (2, 15) => 0.602548
+(1, 13) ~ (2, 12) => 0.0173648
+(1, 13) ~ (2, 14) => 0.162943
+(1, 13) ~ (2, 15) => 0.0521418
+(1, 13) ~ (2, 16) => 0.752493
+(1, 14) ~ (2, 15) => 0.0748135
+(1, 14) ~ (2, 16) => 0.0295865
+(1, 14) ~ (2, 17) => 0.875726
+(1, 15) ~ (2, 18) => 0.9812
+(1, 16) ~ (2, 19) => 0.996636
+(1, 17) ~ (2, 20) => 0.998422
+(1, 18) ~ (2, 21) => 0.999791
+(1, 19) ~ (2, 22) => 0.999956
+(1, 20) ~ (2, 23) => 0.999992
+(1, 21) ~ (2, 24) => 0.999999
+(1, 22) ~ (2, 25) => 0.999999
+(1, 23) ~ (2, 26) => 0.999996
+(1, 24) ~ (2, 27) => 0.999979
+(1, 25) ~ (2, 28) => 0.999933
+(1, 26) ~ (2, 29) => 0.999937
+(1, 27) ~ (2, 30) => 0.999954
+(1, 28) ~ (2, 31) => 0.999923
+(1, 29) ~ (2, 32) => 0.999899
+(1, 30) ~ (2, 33) => 0.999922
+(1, 31) ~ (2, 34) => 0.99996
+(1, 32) ~ (2, 35) => 0.999958
+(1, 33) ~ (2, 36) => 0.999974
+(1, 34) ~ (2, 37) => 0.99987
+(1, 35) ~ (2, 38) => 0.999719
+(1, 36) ~ (2, 39) => 0.998912
+(1, 37) ~ (2, 40) => 0.998887
+(1, 38) ~ (2, 41) => 0.999479
+(1, 39) ~ (2, 42) => 0.999483
+(1, 40) ~ (2, 43) => 0.999599
+(1, 41) ~ (2, 44) => 0.999779
+(1, 42) ~ (2, 45) => 0.999968
+(1, 43) ~ (2, 46) => 0.99995
+(1, 44) ~ (2, 47) => 0.999757
+(1, 45) ~ (2, 48) => 0.998242
+(1, 46) ~ (2, 49) => 0.997388
+(1, 47) ~ (2, 50) => 0.995968
+(1, 48) ~ (2, 51) => 0.988918
+(1, 49) ~ (2, 52) => 0.980472
+(1, 49) ~ (2, 54) => 0.0153142
+(1, 50) ~ (2, 53) => 0.980386
+(1, 50) ~ (2, 55) => 0.0108652
+(1, 51) ~ (2, 54) => 0.980876
+(1, 52) ~ (2, 55) => 0.986462
+(1, 53) ~ (2, 56) => 0.993295
+(1, 54) ~ (2, 57) => 0.999768
+(1, 55) ~ (2, 58) => 0.999953
+(1, 56) ~ (2, 59) => 0.99999
+(1, 57) ~ (2, 60) => 0.999931
+(1, 58) ~ (2, 61) => 0.999724
+(1, 59) ~ (2, 62) => 0.995682
+(1, 60) ~ (2, 63) => 0.988752
+(1, 61) ~ (2, 63) => 0.0109703
+(1, 61) ~ (2, 64) => 0.931966
+(1, 62) ~ (2, 64) => 0.0670032
+(1, 62) ~ (2, 65) => 0.875257
+(1, 63) ~ (2, 65) => 0.122964
+(1, 63) ~ (2, 66) => 0.818801
+(1, 64) ~ (2, 66) => 0.178986
+(1, 64) ~ (2, 67) => 0.244021
+(1, 65) ~ (2, 67) => 0.753306
+(1, 65) ~ (2, 68) => 0.0259534
+(1, 66) ~ (2, 68) => 0.971919
+(1, 67) ~ (2, 69) => 0.992485
+(1, 68) ~ (2, 70) => 0.999919
+(1, 69) ~ (2, 71) => 0.999984
+(1, 70) ~ (2, 72) => 0.999991
+(1, 71) ~ (2, 73) => 0.999976
+(1, 72) ~ (2, 74) => 0.999978
+(1, 73) ~ (2, 75) => 0.999999
+(1, 74) ~ (2, 76) => 0.999999
+(1, 75) ~ (2, 77) => 0.999999
+(1, 76) ~ (2, 78) => 0.999998
+(1, 77) ~ (2, 79) => 0.999998
+(1, 78) ~ (2, 80) => 0.999994
+(1, 79) ~ (2, 81) => 0.999917
+(1, 80) ~ (2, 82) => 0.999562
+(1, 81) ~ (2, 83) => 0.999403
+(1, 82) ~ (2, 84) => 0.998313
+(1, 83) ~ (2, 85) => 0.997856
+(1, 84) ~ (2, 86) => 0.997466
+(1, 85) ~ (2, 87) => 0.997779
+(1, 86) ~ (2, 88) => 0.998361
+(1, 87) ~ (2, 89) => 0.998163
+(1, 88) ~ (2, 90) => 0.998516
+(1, 89) ~ (2, 91) => 0.999058
+(1, 90) ~ (2, 92) => 0.999901
+(1, 91) ~ (2, 93) => 0.999983
+(1, 92) ~ (2, 94) => 0.999993
+(1, 93) ~ (2, 95) => 0.999967
+(1, 94) ~ (2, 96) => 0.999852
+(1, 95) ~ (2, 97) => 0.999784
+(1, 96) ~ (2, 98) => 0.999846
+(1, 97) ~ (2, 99) => 0.99988
+(1, 98) ~ (2, 100) => 0.999436
+(1, 99) ~ (2, 101) => 0.999324
+(1, 100) ~ (2, 102) => 0.999353
+(1, 101) ~ (2, 103) => 0.999683
+(1, 102) ~ (2, 104) => 0.999953
+(1, 103) ~ (2, 105) => 0.999964
+(1, 104) ~ (2, 106) => 0.999958
+(1, 105) ~ (2, 107) => 0.999912
+(1, 106) ~ (2, 108) => 0.999928
+(1, 107) ~ (2, 109) => 0.999994
+(1, 108) ~ (2, 110) => 0.999989
+(1, 109) ~ (2, 111) => 0.999982
+(1, 110) ~ (2, 112) => 0.999991
+(1, 111) ~ (2, 113) => 0.999997
+(1, 112) ~ (2, 114) => 0.999997
+(1, 113) ~ (2, 115) => 0.999997
+(1, 114) ~ (2, 116) => 0.999998
+(1, 115) ~ (2, 117) => 0.999998
+(1, 116) ~ (2, 118) => 0.999999
+(1, 117) ~ (2, 119) => 0.99999
+(1, 118) ~ (2, 120) => 0.999973
+(1, 119) ~ (2, 121) => 0.999962
+(1, 120) ~ (2, 122) => 0.999961
+(1, 121) ~ (2, 123) => 0.999986
+(1, 122) ~ (2, 124) => 0.999988
+(1, 123) ~ (2, 125) => 0.999983
+(1, 124) ~ (2, 126) => 0.999988
+(1, 125) ~ (2, 127) => 0.999989
+(1, 126) ~ (2, 128) => 0.999988
+(1, 127) ~ (2, 129) => 0.999989
+(1, 128) ~ (2, 130) => 0.999927
+(1, 129) ~ (2, 131) => 0.999727
+(1, 130) ~ (2, 132) => 0.999564
+(1, 131) ~ (2, 133) => 0.999019
+(1, 132) ~ (2, 134) => 0.999027
+(1, 133) ~ (2, 135) => 0.999662
+(1, 134) ~ (2, 136) => 0.999625
+(1, 135) ~ (2, 137) => 0.999772
+(1, 136) ~ (2, 138) => 0.99997
+(1, 137) ~ (2, 139) => 0.999991
+(1, 138) ~ (2, 140) => 0.99998
+(1, 139) ~ (2, 141) => 0.999978
+(1, 140) ~ (2, 142) => 0.999985
+(1, 141) ~ (2, 143) => 0.999933
+(1, 142) ~ (2, 144) => 0.999919
+(1, 143) ~ (2, 145) => 0.99998
+(1, 144) ~ (2, 146) => 0.999986
+(1, 145) ~ (2, 147) => 0.999989
+(1, 146) ~ (2, 148) => 0.999994
+(1, 147) ~ (2, 149) => 1
+(1, 148) ~ (2, 150) => 1
+(1, 149) ~ (2, 151) => 1
+(1, 150) ~ (2, 152) => 0.999994
+(1, 151) ~ (2, 153) => 0.999707
+(1, 152) ~ (2, 154) => 0.999692
+(1, 153) ~ (2, 155) => 0.999924
+(1, 154) ~ (2, 156) => 0.99998
+(1, 155) ~ (2, 157) => 0.999973
+(1, 156) ~ (2, 158) => 0.999982
+(1, 157) ~ (2, 159) => 0.999996
+(1, 158) ~ (2, 160) => 0.999986
+(1, 159) ~ (2, 161) => 0.999879
+(1, 160) ~ (2, 162) => 0.999854
+(1, 161) ~ (2, 163) => 0.999879
+(1, 162) ~ (2, 164) => 0.999942
+(1, 163) ~ (2, 165) => 0.999944
+(1, 164) ~ (2, 166) => 0.999955
+(1, 165) ~ (2, 167) => 0.999948
+(1, 166) ~ (2, 168) => 0.999852
+(1, 167) ~ (2, 169) => 0.999395
+(1, 168) ~ (2, 170) => 0.998255
+(1, 169) ~ (2, 171) => 0.998097
+(1, 170) ~ (2, 172) => 0.998565
+(1, 171) ~ (2, 173) => 0.999131
+(1, 172) ~ (2, 174) => 0.999917
+(1, 173) ~ (2, 175) => 0.999981
+(1, 174) ~ (2, 176) => 0.999867
+(1, 175) ~ (2, 177) => 0.999505
+(1, 176) ~ (2, 178) => 0.998645
+(1, 177) ~ (2, 179) => 0.99776
+(1, 178) ~ (2, 180) => 0.997528
+(1, 179) ~ (2, 181) => 0.998172
+(1, 180) ~ (2, 182) => 0.999586
+(1, 181) ~ (2, 183) => 0.999974
+(1, 182) ~ (2, 184) => 0.999991
+(1, 183) ~ (2, 185) => 0.999986
+(1, 184) ~ (2, 186) => 0.999894
+(1, 185) ~ (2, 187) => 0.999849
+(1, 186) ~ (2, 188) => 0.999857
+(1, 187) ~ (2, 189) => 0.999261
+(1, 188) ~ (2, 190) => 0.990245
+(1, 189) ~ (2, 191) => 0.852272
+(1, 189) ~ (2, 193) => 0.13708
+(1, 190) ~ (2, 192) => 0.69463
+(1, 190) ~ (2, 194) => 0.28594
+(1, 191) ~ (2, 193) => 0.529572
+(1, 191) ~ (2, 195) => 0.450467
+(1, 192) ~ (2, 194) => 0.145408
+(1, 192) ~ (2, 196) => 0.837076
+(1, 193) ~ (2, 195) => 0.0520482
+(1, 193) ~ (2, 197) => 0.944347
+(1, 194) ~ (2, 196) => 0.0426213
+(1, 194) ~ (2, 198) => 0.95507
+(1, 195) ~ (2, 197) => 0.0219896
+(1, 195) ~ (2, 199) => 0.976453
+(1, 196) ~ (2, 200) => 0.995105
+(1, 197) ~ (2, 201) => 0.998556
+(1, 198) ~ (2, 202) => 0.99887
+(1, 199) ~ (2, 203) => 0.99898
+(1, 200) ~ (2, 204) => 0.999019
+(1, 201) ~ (2, 205) => 0.998817
+(1, 202) ~ (2, 206) => 0.998788
+(1, 203) ~ (2, 207) => 0.999054
+(1, 204) ~ (2, 208) => 0.999465
+(1, 205) ~ (2, 209) => 0.999668
+(1, 206) ~ (2, 210) => 0.999791
+(1, 207) ~ (2, 211) => 0.999927
+(1, 208) ~ (2, 212) => 0.999997
+(1, 209) ~ (2, 213) => 0.999988
+(1, 210) ~ (2, 214) => 0.999661
+(1, 211) ~ (2, 215) => 0.999566
+(1, 212) ~ (2, 216) => 0.999735
+(1, 213) ~ (2, 217) => 0.998825
+(1, 214) ~ (2, 218) => 0.997984
+(1, 215) ~ (2, 219) => 0.994981
+(1, 216) ~ (2, 220) => 0.987192
+(1, 216) ~ (2, 221) => 0.0100263
+(1, 217) ~ (2, 221) => 0.975322
+(1, 217) ~ (2, 222) => 0.0207732
+(1, 218) ~ (2, 222) => 0.916296
+(1, 218) ~ (2, 223) => 0.0741965
+(1, 219) ~ (2, 223) => 0.796245
+(1, 219) ~ (2, 224) => 0.188055
+(1, 220) ~ (2, 224) => 0.56354
+(1, 220) ~ (2, 225) => 0.420347
+(1, 221) ~ (2, 225) => 0.246711
+(1, 221) ~ (2, 226) => 0.742792
+(1, 222) ~ (2, 226) => 0.0362951
+(1, 222) ~ (2, 227) => 0.961443
+(1, 223) ~ (2, 228) => 0.999426
+(1, 224) ~ (2, 229) => 0.999884
+(1, 225) ~ (2, 230) => 0.999996
+(1, 226) ~ (2, 231) => 1
+(1, 227) ~ (2, 232) => 0.999998
+(1, 228) ~ (2, 233) => 0.999988
+(1, 229) ~ (2, 234) => 0.999976
+(1, 230) ~ (2, 235) => 0.999978
+(1, 231) ~ (2, 236) => 0.999938
+(1, 232) ~ (2, 237) => 0.999944
+(1, 233) ~ (2, 238) => 0.999999
+
+; gap posteriors
+(1, 0) ~ (2, -1) => 0.00698137
+(1, 1) ~ (2, -1) => 0.0104825
+(1, 2) ~ (2, -1) => 0.013544
+(1, 3) ~ (2, -1) => 0.00223297
+(1, 4) ~ (2, -1) => 0.00669251
+(1, 5) ~ (2, -1) => 0.0125901
+(1, 6) ~ (2, -1) => 0.0133718
+(1, 7) ~ (2, -1) => 0.0217519
+(1, 8) ~ (2, -1) => 0.0389011
+(1, 9) ~ (2, -1) => 0.039637
+(1, 10) ~ (2, -1) => 0.0125243
+(1, 11) ~ (2, -1) => 0.0157968
+(1, 12) ~ (2, -1) => 0.00665337
+(1, 13) ~ (2, -1) => 0.0150576
+(1, 14) ~ (2, -1) => 0.0198743
+(1, 15) ~ (2, -1) => 0.0187997
+(1, 16) ~ (2, -1) => 0.00336367
+(1, 17) ~ (2, -1) => 0.00157768
+(1, 18) ~ (2, -1) => 0.000208676
+(1, 19) ~ (2, -1) => 0.0001
+(1, 20) ~ (2, -1) => 0.0001
+(1, 21) ~ (2, -1) => 0.0001
+(1, 22) ~ (2, -1) => 0.0001
+(1, 23) ~ (2, -1) => 0.0001
+(1, 24) ~ (2, -1) => 0.0001
+(1, 25) ~ (2, -1) => 0.0001
+(1, 26) ~ (2, -1) => 0.0001
+(1, 27) ~ (2, -1) => 0.0001
+(1, 28) ~ (2, -1) => 0.0001
+(1, 29) ~ (2, -1) => 0.000100553
+(1, 30) ~ (2, -1) => 0.0001
+(1, 31) ~ (2, -1) => 0.0001
+(1, 32) ~ (2, -1) => 0.0001
+(1, 33) ~ (2, -1) => 0.0001
+(1, 34) ~ (2, -1) => 0.000129819
+(1, 35) ~ (2, -1) => 0.000280559
+(1, 36) ~ (2, -1) => 0.00108784
+(1, 37) ~ (2, -1) => 0.00111258
+(1, 38) ~ (2, -1) => 0.000520706
+(1, 39) ~ (2, -1) => 0.000517428
+(1, 40) ~ (2, -1) => 0.000401497
+(1, 41) ~ (2, -1) => 0.000220537
+(1, 42) ~ (2, -1) => 0.0001
+(1, 43) ~ (2, -1) => 0.0001
+(1, 44) ~ (2, -1) => 0.000243306
+(1, 45) ~ (2, -1) => 0.00175804
+(1, 46) ~ (2, -1) => 0.00261241
+(1, 47) ~ (2, -1) => 0.00403243
+(1, 48) ~ (2, -1) => 0.011082
+(1, 49) ~ (2, -1) => 0.00421365
+(1, 50) ~ (2, -1) => 0.008749
+(1, 51) ~ (2, -1) => 0.0191239
+(1, 52) ~ (2, -1) => 0.0135378
+(1, 53) ~ (2, -1) => 0.00670534
+(1, 54) ~ (2, -1) => 0.000231802
+(1, 55) ~ (2, -1) => 0.0001
+(1, 56) ~ (2, -1) => 0.0001
+(1, 57) ~ (2, -1) => 0.0001
+(1, 58) ~ (2, -1) => 0.00027585
+(1, 59) ~ (2, -1) => 0.00431806
+(1, 60) ~ (2, -1) => 0.0112481
+(1, 61) ~ (2, -1) => 0.0570636
+(1, 62) ~ (2, -1) => 0.0577396
+(1, 63) ~ (2, -1) => 0.0582351
+(1, 64) ~ (2, -1) => 0.576994
+(1, 65) ~ (2, -1) => 0.220741
+(1, 66) ~ (2, -1) => 0.0280811
+(1, 67) ~ (2, -1) => 0.00751543
+(1, 68) ~ (2, -1) => 0.0001
+(1, 69) ~ (2, -1) => 0.0001
+(1, 70) ~ (2, -1) => 0.0001
+(1, 71) ~ (2, -1) => 0.0001
+(1, 72) ~ (2, -1) => 0.0001
+(1, 73) ~ (2, -1) => 0.0001
+(1, 74) ~ (2, -1) => 0.0001
+(1, 75) ~ (2, -1) => 0.0001
+(1, 76) ~ (2, -1) => 0.0001
+(1, 77) ~ (2, -1) => 0.0001
+(1, 78) ~ (2, -1) => 0.0001
+(1, 79) ~ (2, -1) => 0.0001
+(1, 80) ~ (2, -1) => 0.000437737
+(1, 81) ~ (2, -1) => 0.000597179
+(1, 82) ~ (2, -1) => 0.00168735
+(1, 83) ~ (2, -1) => 0.00214356
+(1, 84) ~ (2, -1) => 0.00253403
+(1, 85) ~ (2, -1) => 0.00222147
+(1, 86) ~ (2, -1) => 0.00163895
+(1, 87) ~ (2, -1) => 0.00183743
+(1, 88) ~ (2, -1) => 0.00148404
+(1, 89) ~ (2, -1) => 0.000941992
+(1, 90) ~ (2, -1) => 0.0001
+(1, 91) ~ (2, -1) => 0.0001
+(1, 92) ~ (2, -1) => 0.0001
+(1, 93) ~ (2, -1) => 0.0001
+(1, 94) ~ (2, -1) => 0.0001477
+(1, 95) ~ (2, -1) => 0.000215888
+(1, 96) ~ (2, -1) => 0.000154197
+(1, 97) ~ (2, -1) => 0.000120282
+(1, 98) ~ (2, -1) => 0.000563562
+(1, 99) ~ (2, -1) => 0.000676334
+(1, 100) ~ (2, -1) => 0.000646591
+(1, 101) ~ (2, -1) => 0.000317156
+(1, 102) ~ (2, -1) => 0.0001
+(1, 103) ~ (2, -1) => 0.0001
+(1, 104) ~ (2, -1) => 0.0001
+(1, 105) ~ (2, -1) => 0.0001
+(1, 106) ~ (2, -1) => 0.0001
+(1, 107) ~ (2, -1) => 0.0001
+(1, 108) ~ (2, -1) => 0.0001
+(1, 109) ~ (2, -1) => 0.0001
+(1, 110) ~ (2, -1) => 0.0001
+(1, 111) ~ (2, -1) => 0.0001
+(1, 112) ~ (2, -1) => 0.0001
+(1, 113) ~ (2, -1) => 0.0001
+(1, 114) ~ (2, -1) => 0.0001
+(1, 115) ~ (2, -1) => 0.0001
+(1, 116) ~ (2, -1) => 0.0001
+(1, 117) ~ (2, -1) => 0.0001
+(1, 118) ~ (2, -1) => 0.0001
+(1, 119) ~ (2, -1) => 0.0001
+(1, 120) ~ (2, -1) => 0.0001
+(1, 121) ~ (2, -1) => 0.0001
+(1, 122) ~ (2, -1) => 0.0001
+(1, 123) ~ (2, -1) => 0.0001
+(1, 124) ~ (2, -1) => 0.0001
+(1, 125) ~ (2, -1) => 0.0001
+(1, 126) ~ (2, -1) => 0.0001
+(1, 127) ~ (2, -1) => 0.0001
+(1, 128) ~ (2, -1) => 0.0001
+(1, 129) ~ (2, -1) => 0.000272691
+(1, 130) ~ (2, -1) => 0.000435531
+(1, 131) ~ (2, -1) => 0.000981212
+(1, 132) ~ (2, -1) => 0.000972807
+(1, 133) ~ (2, -1) => 0.000337601
+(1, 134) ~ (2, -1) => 0.000375092
+(1, 135) ~ (2, -1) => 0.000227869
+(1, 136) ~ (2, -1) => 0.0001
+(1, 137) ~ (2, -1) => 0.0001
+(1, 138) ~ (2, -1) => 0.0001
+(1, 139) ~ (2, -1) => 0.0001
+(1, 140) ~ (2, -1) => 0.0001
+(1, 141) ~ (2, -1) => 0.0001
+(1, 142) ~ (2, -1) => 0.0001
+(1, 143) ~ (2, -1) => 0.0001
+(1, 144) ~ (2, -1) => 0.0001
+(1, 145) ~ (2, -1) => 0.0001
+(1, 146) ~ (2, -1) => 0.0001
+(1, 147) ~ (2, -1) => 0.0001
+(1, 148) ~ (2, -1) => 0.0001
+(1, 149) ~ (2, -1) => 0.0001
+(1, 150) ~ (2, -1) => 0.0001
+(1, 151) ~ (2, -1) => 0.000293076
+(1, 152) ~ (2, -1) => 0.000307739
+(1, 153) ~ (2, -1) => 0.0001
+(1, 154) ~ (2, -1) => 0.0001
+(1, 155) ~ (2, -1) => 0.0001
+(1, 156) ~ (2, -1) => 0.0001
+(1, 157) ~ (2, -1) => 0.0001
+(1, 158) ~ (2, -1) => 0.0001
+(1, 159) ~ (2, -1) => 0.000121117
+(1, 160) ~ (2, -1) => 0.000145912
+(1, 161) ~ (2, -1) => 0.000121474
+(1, 162) ~ (2, -1) => 0.0001
+(1, 163) ~ (2, -1) => 0.0001
+(1, 164) ~ (2, -1) => 0.0001
+(1, 165) ~ (2, -1) => 0.0001
+(1, 166) ~ (2, -1) => 0.000148177
+(1, 167) ~ (2, -1) => 0.000605285
+(1, 168) ~ (2, -1) => 0.00174481
+(1, 169) ~ (2, -1) => 0.00190264
+(1, 170) ~ (2, -1) => 0.00143516
+(1, 171) ~ (2, -1) => 0.000869155
+(1, 172) ~ (2, -1) => 0.0001
+(1, 173) ~ (2, -1) => 0.0001
+(1, 174) ~ (2, -1) => 0.000133157
+(1, 175) ~ (2, -1) => 0.000494659
+(1, 176) ~ (2, -1) => 0.00135493
+(1, 177) ~ (2, -1) => 0.00224036
+(1, 178) ~ (2, -1) => 0.00247151
+(1, 179) ~ (2, -1) => 0.00182831
+(1, 180) ~ (2, -1) => 0.000414133
+(1, 181) ~ (2, -1) => 0.0001
+(1, 182) ~ (2, -1) => 0.0001
+(1, 183) ~ (2, -1) => 0.0001
+(1, 184) ~ (2, -1) => 0.0001055
+(1, 185) ~ (2, -1) => 0.000151217
+(1, 186) ~ (2, -1) => 0.000142753
+(1, 187) ~ (2, -1) => 0.00073874
+(1, 188) ~ (2, -1) => 0.00975513
+(1, 189) ~ (2, -1) => 0.0106484
+(1, 190) ~ (2, -1) => 0.0194294
+(1, 191) ~ (2, -1) => 0.0199612
+(1, 192) ~ (2, -1) => 0.0175157
+(1, 193) ~ (2, -1) => 0.00360459
+(1, 194) ~ (2, -1) => 0.00230879
+(1, 195) ~ (2, -1) => 0.00155717
+(1, 196) ~ (2, -1) => 0.00489461
+(1, 197) ~ (2, -1) => 0.00144362
+(1, 198) ~ (2, -1) => 0.00112975
+(1, 199) ~ (2, -1) => 0.00102001
+(1, 200) ~ (2, -1) => 0.00098145
+(1, 201) ~ (2, -1) => 0.00118339
+(1, 202) ~ (2, -1) => 0.00121194
+(1, 203) ~ (2, -1) => 0.000945807
+(1, 204) ~ (2, -1) => 0.000535309
+(1, 205) ~ (2, -1) => 0.000332355
+(1, 206) ~ (2, -1) => 0.000208855
+(1, 207) ~ (2, -1) => 0.0001
+(1, 208) ~ (2, -1) => 0.0001
+(1, 209) ~ (2, -1) => 0.0001
+(1, 210) ~ (2, -1) => 0.000338793
+(1, 211) ~ (2, -1) => 0.000433743
+(1, 212) ~ (2, -1) => 0.000264943
+(1, 213) ~ (2, -1) => 0.00117528
+(1, 214) ~ (2, -1) => 0.00201565
+(1, 215) ~ (2, -1) => 0.00501925
+(1, 216) ~ (2, -1) => 0.00278168
+(1, 217) ~ (2, -1) => 0.00390463
+(1, 218) ~ (2, -1) => 0.00950745
+(1, 219) ~ (2, -1) => 0.0157005
+(1, 220) ~ (2, -1) => 0.0161128
+(1, 221) ~ (2, -1) => 0.0104968
+(1, 222) ~ (2, -1) => 0.0022617
+(1, 223) ~ (2, -1) => 0.00057447
+(1, 224) ~ (2, -1) => 0.000116169
+(1, 225) ~ (2, -1) => 0.0001
+(1, 226) ~ (2, -1) => 0.0001
+(1, 227) ~ (2, -1) => 0.0001
+(1, 228) ~ (2, -1) => 0.0001
+(1, 229) ~ (2, -1) => 0.0001
+(1, 230) ~ (2, -1) => 0.0001
+(1, 231) ~ (2, -1) => 0.0001
+(1, 232) ~ (2, -1) => 0.0001
+(1, 233) ~ (2, -1) => 0.0001
+
+(1, -1) ~ (2, 0) => 0.00698137
+(1, -1) ~ (2, 1) => 0.0104825
+(1, -1) ~ (2, 2) => 0.013544
+(1, -1) ~ (2, 3) => 0.0352837
+(1, -1) ~ (2, 4) => 0.106023
+(1, -1) ~ (2, 5) => 0.110898
+(1, -1) ~ (2, 6) => 0.0920584
+(1, -1) ~ (2, 7) => 0.183629
+(1, -1) ~ (2, 8) => 0.393832
+(1, -1) ~ (2, 9) => 0.56453
+(1, -1) ~ (2, 10) => 0.346137
+(1, -1) ~ (2, 11) => 0.23479
+(1, -1) ~ (2, 12) => 0.128745
+(1, -1) ~ (2, 13) => 0.145836
+(1, -1) ~ (2, 14) => 0.250629
+(1, -1) ~ (2, 15) => 0.270497
+(1, -1) ~ (2, 16) => 0.21792
+(1, -1) ~ (2, 17) => 0.124274
+(1, -1) ~ (2, 18) => 0.0187997
+(1, -1) ~ (2, 19) => 0.00336367
+(1, -1) ~ (2, 20) => 0.00157768
+(1, -1) ~ (2, 21) => 0.000208676
+(1, -1) ~ (2, 22) => 0.0001
+(1, -1) ~ (2, 23) => 0.0001
+(1, -1) ~ (2, 24) => 0.0001
+(1, -1) ~ (2, 25) => 0.0001
+(1, -1) ~ (2, 26) => 0.0001
+(1, -1) ~ (2, 27) => 0.0001
+(1, -1) ~ (2, 28) => 0.0001
+(1, -1) ~ (2, 29) => 0.0001
+(1, -1) ~ (2, 30) => 0.0001
+(1, -1) ~ (2, 31) => 0.0001
+(1, -1) ~ (2, 32) => 0.000100553
+(1, -1) ~ (2, 33) => 0.0001
+(1, -1) ~ (2, 34) => 0.0001
+(1, -1) ~ (2, 35) => 0.0001
+(1, -1) ~ (2, 36) => 0.0001
+(1, -1) ~ (2, 37) => 0.000129819
+(1, -1) ~ (2, 38) => 0.000280559
+(1, -1) ~ (2, 39) => 0.00108784
+(1, -1) ~ (2, 40) => 0.00111258
+(1, -1) ~ (2, 41) => 0.000520706
+(1, -1) ~ (2, 42) => 0.000517428
+(1, -1) ~ (2, 43) => 0.000401497
+(1, -1) ~ (2, 44) => 0.000220537
+(1, -1) ~ (2, 45) => 0.0001
+(1, -1) ~ (2, 46) => 0.0001
+(1, -1) ~ (2, 47) => 0.000243306
+(1, -1) ~ (2, 48) => 0.00175804
+(1, -1) ~ (2, 49) => 0.00261241
+(1, -1) ~ (2, 50) => 0.00403243
+(1, -1) ~ (2, 51) => 0.011082
+(1, -1) ~ (2, 52) => 0.0195279
+(1, -1) ~ (2, 53) => 0.0196142
+(1, -1) ~ (2, 54) => 0.00380969
+(1, -1) ~ (2, 55) => 0.00267261
+(1, -1) ~ (2, 56) => 0.00670534
+(1, -1) ~ (2, 57) => 0.000231802
+(1, -1) ~ (2, 58) => 0.0001
+(1, -1) ~ (2, 59) => 0.0001
+(1, -1) ~ (2, 60) => 0.0001
+(1, -1) ~ (2, 61) => 0.00027585
+(1, -1) ~ (2, 62) => 0.00431806
+(1, -1) ~ (2, 63) => 0.000277753
+(1, -1) ~ (2, 64) => 0.00103068
+(1, -1) ~ (2, 65) => 0.00177842
+(1, -1) ~ (2, 66) => 0.00221382
+(1, -1) ~ (2, 67) => 0.00267327
+(1, -1) ~ (2, 68) => 0.00212765
+(1, -1) ~ (2, 69) => 0.00751543
+(1, -1) ~ (2, 70) => 0.0001
+(1, -1) ~ (2, 71) => 0.0001
+(1, -1) ~ (2, 72) => 0.0001
+(1, -1) ~ (2, 73) => 0.0001
+(1, -1) ~ (2, 74) => 0.0001
+(1, -1) ~ (2, 75) => 0.0001
+(1, -1) ~ (2, 76) => 0.0001
+(1, -1) ~ (2, 77) => 0.0001
+(1, -1) ~ (2, 78) => 0.0001
+(1, -1) ~ (2, 79) => 0.0001
+(1, -1) ~ (2, 80) => 0.0001
+(1, -1) ~ (2, 81) => 0.0001
+(1, -1) ~ (2, 82) => 0.000437737
+(1, -1) ~ (2, 83) => 0.000597179
+(1, -1) ~ (2, 84) => 0.00168735
+(1, -1) ~ (2, 85) => 0.00214356
+(1, -1) ~ (2, 86) => 0.00253403
+(1, -1) ~ (2, 87) => 0.00222147
+(1, -1) ~ (2, 88) => 0.00163895
+(1, -1) ~ (2, 89) => 0.00183743
+(1, -1) ~ (2, 90) => 0.00148404
+(1, -1) ~ (2, 91) => 0.000941992
+(1, -1) ~ (2, 92) => 0.0001
+(1, -1) ~ (2, 93) => 0.0001
+(1, -1) ~ (2, 94) => 0.0001
+(1, -1) ~ (2, 95) => 0.0001
+(1, -1) ~ (2, 96) => 0.0001477
+(1, -1) ~ (2, 97) => 0.000215888
+(1, -1) ~ (2, 98) => 0.000154197
+(1, -1) ~ (2, 99) => 0.000120282
+(1, -1) ~ (2, 100) => 0.000563562
+(1, -1) ~ (2, 101) => 0.000676334
+(1, -1) ~ (2, 102) => 0.000646591
+(1, -1) ~ (2, 103) => 0.000317156
+(1, -1) ~ (2, 104) => 0.0001
+(1, -1) ~ (2, 105) => 0.0001
+(1, -1) ~ (2, 106) => 0.0001
+(1, -1) ~ (2, 107) => 0.0001
+(1, -1) ~ (2, 108) => 0.0001
+(1, -1) ~ (2, 109) => 0.0001
+(1, -1) ~ (2, 110) => 0.0001
+(1, -1) ~ (2, 111) => 0.0001
+(1, -1) ~ (2, 112) => 0.0001
+(1, -1) ~ (2, 113) => 0.0001
+(1, -1) ~ (2, 114) => 0.0001
+(1, -1) ~ (2, 115) => 0.0001
+(1, -1) ~ (2, 116) => 0.0001
+(1, -1) ~ (2, 117) => 0.0001
+(1, -1) ~ (2, 118) => 0.0001
+(1, -1) ~ (2, 119) => 0.0001
+(1, -1) ~ (2, 120) => 0.0001
+(1, -1) ~ (2, 121) => 0.0001
+(1, -1) ~ (2, 122) => 0.0001
+(1, -1) ~ (2, 123) => 0.0001
+(1, -1) ~ (2, 124) => 0.0001
+(1, -1) ~ (2, 125) => 0.0001
+(1, -1) ~ (2, 126) => 0.0001
+(1, -1) ~ (2, 127) => 0.0001
+(1, -1) ~ (2, 128) => 0.0001
+(1, -1) ~ (2, 129) => 0.0001
+(1, -1) ~ (2, 130) => 0.0001
+(1, -1) ~ (2, 131) => 0.000272691
+(1, -1) ~ (2, 132) => 0.000435531
+(1, -1) ~ (2, 133) => 0.000981212
+(1, -1) ~ (2, 134) => 0.000972807
+(1, -1) ~ (2, 135) => 0.000337601
+(1, -1) ~ (2, 136) => 0.000375092
+(1, -1) ~ (2, 137) => 0.000227869
+(1, -1) ~ (2, 138) => 0.0001
+(1, -1) ~ (2, 139) => 0.0001
+(1, -1) ~ (2, 140) => 0.0001
+(1, -1) ~ (2, 141) => 0.0001
+(1, -1) ~ (2, 142) => 0.0001
+(1, -1) ~ (2, 143) => 0.0001
+(1, -1) ~ (2, 144) => 0.0001
+(1, -1) ~ (2, 145) => 0.0001
+(1, -1) ~ (2, 146) => 0.0001
+(1, -1) ~ (2, 147) => 0.0001
+(1, -1) ~ (2, 148) => 0.0001
+(1, -1) ~ (2, 149) => 0.0001
+(1, -1) ~ (2, 150) => 0.0001
+(1, -1) ~ (2, 151) => 0.0001
+(1, -1) ~ (2, 152) => 0.0001
+(1, -1) ~ (2, 153) => 0.000293076
+(1, -1) ~ (2, 154) => 0.000307739
+(1, -1) ~ (2, 155) => 0.0001
+(1, -1) ~ (2, 156) => 0.0001
+(1, -1) ~ (2, 157) => 0.0001
+(1, -1) ~ (2, 158) => 0.0001
+(1, -1) ~ (2, 159) => 0.0001
+(1, -1) ~ (2, 160) => 0.0001
+(1, -1) ~ (2, 161) => 0.000121117
+(1, -1) ~ (2, 162) => 0.000145912
+(1, -1) ~ (2, 163) => 0.000121474
+(1, -1) ~ (2, 164) => 0.0001
+(1, -1) ~ (2, 165) => 0.0001
+(1, -1) ~ (2, 166) => 0.0001
+(1, -1) ~ (2, 167) => 0.0001
+(1, -1) ~ (2, 168) => 0.000148177
+(1, -1) ~ (2, 169) => 0.000605285
+(1, -1) ~ (2, 170) => 0.00174481
+(1, -1) ~ (2, 171) => 0.00190264
+(1, -1) ~ (2, 172) => 0.00143516
+(1, -1) ~ (2, 173) => 0.000869155
+(1, -1) ~ (2, 174) => 0.0001
+(1, -1) ~ (2, 175) => 0.0001
+(1, -1) ~ (2, 176) => 0.000133157
+(1, -1) ~ (2, 177) => 0.000494659
+(1, -1) ~ (2, 178) => 0.00135493
+(1, -1) ~ (2, 179) => 0.00224036
+(1, -1) ~ (2, 180) => 0.00247151
+(1, -1) ~ (2, 181) => 0.00182831
+(1, -1) ~ (2, 182) => 0.000414133
+(1, -1) ~ (2, 183) => 0.0001
+(1, -1) ~ (2, 184) => 0.0001
+(1, -1) ~ (2, 185) => 0.0001
+(1, -1) ~ (2, 186) => 0.0001055
+(1, -1) ~ (2, 187) => 0.000151217
+(1, -1) ~ (2, 188) => 0.000142753
+(1, -1) ~ (2, 189) => 0.00073874
+(1, -1) ~ (2, 190) => 0.00975513
+(1, -1) ~ (2, 191) => 0.147728
+(1, -1) ~ (2, 192) => 0.30537
+(1, -1) ~ (2, 193) => 0.333348
+(1, -1) ~ (2, 194) => 0.568652
+(1, -1) ~ (2, 195) => 0.497485
+(1, -1) ~ (2, 196) => 0.120302
+(1, -1) ~ (2, 197) => 0.0336632
+(1, -1) ~ (2, 198) => 0.0449301
+(1, -1) ~ (2, 199) => 0.0235468
+(1, -1) ~ (2, 200) => 0.00489461
+(1, -1) ~ (2, 201) => 0.00144362
+(1, -1) ~ (2, 202) => 0.00112975
+(1, -1) ~ (2, 203) => 0.00102001
+(1, -1) ~ (2, 204) => 0.00098145
+(1, -1) ~ (2, 205) => 0.00118339
+(1, -1) ~ (2, 206) => 0.00121194
+(1, -1) ~ (2, 207) => 0.000945807
+(1, -1) ~ (2, 208) => 0.000535309
+(1, -1) ~ (2, 209) => 0.000332355
+(1, -1) ~ (2, 210) => 0.000208855
+(1, -1) ~ (2, 211) => 0.0001
+(1, -1) ~ (2, 212) => 0.0001
+(1, -1) ~ (2, 213) => 0.0001
+(1, -1) ~ (2, 214) => 0.000338793
+(1, -1) ~ (2, 215) => 0.000433743
+(1, -1) ~ (2, 216) => 0.000264943
+(1, -1) ~ (2, 217) => 0.00117528
+(1, -1) ~ (2, 218) => 0.00201565
+(1, -1) ~ (2, 219) => 0.00501925
+(1, -1) ~ (2, 220) => 0.012808
+(1, -1) ~ (2, 221) => 0.0146515
+(1, -1) ~ (2, 222) => 0.0629308
+(1, -1) ~ (2, 223) => 0.129559
+(1, -1) ~ (2, 224) => 0.248405
+(1, -1) ~ (2, 225) => 0.332942
+(1, -1) ~ (2, 226) => 0.220913
+(1, -1) ~ (2, 227) => 0.0385568
+(1, -1) ~ (2, 228) => 0.00057447
+(1, -1) ~ (2, 229) => 0.000116169
+(1, -1) ~ (2, 230) => 0.0001
+(1, -1) ~ (2, 231) => 0.0001
+(1, -1) ~ (2, 232) => 0.0001
+(1, -1) ~ (2, 233) => 0.0001
+(1, -1) ~ (2, 234) => 0.0001
+(1, -1) ~ (2, 235) => 0.0001
+(1, -1) ~ (2, 236) => 0.0001
+(1, -1) ~ (2, 237) => 0.0001
+(1, -1) ~ (2, 238) => 0.0001
+
+; Sparse posterior probability matrix for sequences 1 and 3
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (3, 0) => 0.999726
+(1, 1) ~ (3, 1) => 0.99956
+(1, 2) ~ (3, 2) => 0.999525
+(1, 3) ~ (3, 3) => 0.999581
+(1, 4) ~ (3, 4) => 0.999677
+(1, 5) ~ (3, 5) => 0.999442
+(1, 6) ~ (3, 6) => 0.996046
+(1, 7) ~ (3, 7) => 0.995789
+(1, 8) ~ (3, 8) => 0.995553
+(1, 9) ~ (3, 9) => 0.991269
+(1, 10) ~ (3, 10) => 0.977453
+(1, 10) ~ (3, 12) => 0.0213676
+(1, 11) ~ (3, 11) => 0.955851
+(1, 11) ~ (3, 13) => 0.0341568
+(1, 12) ~ (3, 12) => 0.894457
+(1, 12) ~ (3, 13) => 0.0155478
+(1, 12) ~ (3, 14) => 0.0691138
+(1, 13) ~ (3, 12) => 0.0175064
+(1, 13) ~ (3, 13) => 0.683704
+(1, 13) ~ (3, 14) => 0.051098
+(1, 13) ~ (3, 15) => 0.205208
+(1, 14) ~ (3, 13) => 0.0535947
+(1, 14) ~ (3, 14) => 0.324391
+(1, 14) ~ (3, 15) => 0.0166838
+(1, 14) ~ (3, 16) => 0.598949
+(1, 15) ~ (3, 14) => 0.0284845
+(1, 15) ~ (3, 17) => 0.957961
+(1, 16) ~ (3, 18) => 0.996514
+(1, 17) ~ (3, 19) => 0.999199
+(1, 18) ~ (3, 20) => 0.999588
+(1, 19) ~ (3, 21) => 0.999624
+(1, 20) ~ (3, 22) => 0.999948
+(1, 21) ~ (3, 23) => 0.999999
+(1, 22) ~ (3, 24) => 1
+(1, 23) ~ (3, 25) => 0.999998
+(1, 24) ~ (3, 26) => 0.999992
+(1, 25) ~ (3, 27) => 0.999971
+(1, 26) ~ (3, 28) => 0.999971
+(1, 27) ~ (3, 29) => 0.999967
+(1, 28) ~ (3, 30) => 0.999943
+(1, 29) ~ (3, 31) => 0.999945
+(1, 30) ~ (3, 32) => 0.999968
+(1, 31) ~ (3, 33) => 0.999965
+(1, 32) ~ (3, 34) => 0.999956
+(1, 33) ~ (3, 35) => 0.999976
+(1, 34) ~ (3, 36) => 0.999975
+(1, 35) ~ (3, 37) => 0.999963
+(1, 36) ~ (3, 38) => 0.999938
+(1, 37) ~ (3, 39) => 0.999919
+(1, 38) ~ (3, 40) => 0.999855
+(1, 39) ~ (3, 41) => 0.999792
+(1, 40) ~ (3, 42) => 0.999836
+(1, 41) ~ (3, 43) => 0.999946
+(1, 42) ~ (3, 44) => 0.999994
+(1, 43) ~ (3, 45) => 0.999997
+(1, 44) ~ (3, 46) => 0.999997
+(1, 45) ~ (3, 47) => 0.99999
+(1, 46) ~ (3, 48) => 0.999947
+(1, 47) ~ (3, 49) => 0.999882
+(1, 48) ~ (3, 50) => 0.999857
+(1, 49) ~ (3, 51) => 0.999871
+(1, 50) ~ (3, 52) => 0.999944
+(1, 51) ~ (3, 53) => 0.999995
+(1, 52) ~ (3, 54) => 0.999999
+(1, 53) ~ (3, 55) => 0.999999
+(1, 54) ~ (3, 56) => 0.999999
+(1, 55) ~ (3, 57) => 0.999999
+(1, 56) ~ (3, 58) => 0.999999
+(1, 57) ~ (3, 59) => 0.999998
+(1, 58) ~ (3, 60) => 0.999997
+(1, 59) ~ (3, 61) => 0.999981
+(1, 60) ~ (3, 62) => 0.99998
+(1, 61) ~ (3, 63) => 0.999962
+(1, 62) ~ (3, 64) => 0.999939
+(1, 63) ~ (3, 65) => 0.999921
+(1, 64) ~ (3, 66) => 0.999852
+(1, 65) ~ (3, 67) => 0.999831
+(1, 66) ~ (3, 68) => 0.999842
+(1, 67) ~ (3, 69) => 0.99995
+(1, 68) ~ (3, 70) => 0.999999
+(1, 69) ~ (3, 71) => 0.999994
+(1, 70) ~ (3, 72) => 0.999976
+(1, 71) ~ (3, 73) => 0.999976
+(1, 72) ~ (3, 74) => 0.999987
+(1, 73) ~ (3, 75) => 0.999999
+(1, 74) ~ (3, 76) => 0.999999
+(1, 75) ~ (3, 77) => 0.999999
+(1, 76) ~ (3, 78) => 0.999998
+(1, 77) ~ (3, 79) => 0.999996
+(1, 78) ~ (3, 80) => 0.999993
+(1, 79) ~ (3, 81) => 0.999905
+(1, 80) ~ (3, 82) => 0.999037
+(1, 81) ~ (3, 83) => 0.998709
+(1, 82) ~ (3, 84) => 0.996773
+(1, 83) ~ (3, 85) => 0.99658
+(1, 84) ~ (3, 86) => 0.996474
+(1, 85) ~ (3, 87) => 0.996559
+(1, 86) ~ (3, 88) => 0.997084
+(1, 87) ~ (3, 89) => 0.997171
+(1, 88) ~ (3, 90) => 0.998425
+(1, 89) ~ (3, 91) => 0.99908
+(1, 90) ~ (3, 92) => 0.999952
+(1, 91) ~ (3, 93) => 0.999982
+(1, 92) ~ (3, 94) => 0.999995
+(1, 93) ~ (3, 95) => 0.999991
+(1, 94) ~ (3, 96) => 0.999969
+(1, 95) ~ (3, 97) => 0.999964
+(1, 96) ~ (3, 98) => 0.999987
+(1, 97) ~ (3, 99) => 0.999987
+(1, 98) ~ (3, 100) => 0.999923
+(1, 99) ~ (3, 101) => 0.999845
+(1, 100) ~ (3, 102) => 0.999782
+(1, 101) ~ (3, 103) => 0.999811
+(1, 102) ~ (3, 104) => 0.999856
+(1, 103) ~ (3, 105) => 0.999941
+(1, 104) ~ (3, 106) => 0.999972
+(1, 105) ~ (3, 107) => 0.999972
+(1, 106) ~ (3, 108) => 0.999983
+(1, 107) ~ (3, 109) => 0.999997
+(1, 108) ~ (3, 110) => 0.999994
+(1, 109) ~ (3, 111) => 0.999992
+(1, 110) ~ (3, 112) => 0.999996
+(1, 111) ~ (3, 113) => 0.999998
+(1, 112) ~ (3, 114) => 0.999998
+(1, 113) ~ (3, 115) => 0.999998
+(1, 114) ~ (3, 116) => 0.999996
+(1, 115) ~ (3, 117) => 0.999996
+(1, 116) ~ (3, 118) => 0.999998
+(1, 117) ~ (3, 119) => 0.999994
+(1, 118) ~ (3, 120) => 0.999986
+(1, 119) ~ (3, 121) => 0.999989
+(1, 120) ~ (3, 122) => 0.999996
+(1, 121) ~ (3, 123) => 0.999999
+(1, 122) ~ (3, 124) => 0.999995
+(1, 123) ~ (3, 125) => 0.999993
+(1, 124) ~ (3, 126) => 0.999996
+(1, 125) ~ (3, 127) => 0.999997
+(1, 126) ~ (3, 128) => 0.999997
+(1, 127) ~ (3, 129) => 0.999996
+(1, 128) ~ (3, 130) => 0.99992
+(1, 129) ~ (3, 131) => 0.999727
+(1, 130) ~ (3, 132) => 0.99955
+(1, 131) ~ (3, 133) => 0.999577
+(1, 132) ~ (3, 134) => 0.99993
+(1, 133) ~ (3, 135) => 0.999983
+(1, 134) ~ (3, 136) => 0.999977
+(1, 135) ~ (3, 137) => 0.999978
+(1, 136) ~ (3, 138) => 0.999937
+(1, 137) ~ (3, 139) => 0.999915
+(1, 138) ~ (3, 140) => 0.999504
+(1, 139) ~ (3, 141) => 0.999518
+(1, 140) ~ (3, 142) => 0.999947
+(1, 141) ~ (3, 143) => 0.999991
+(1, 142) ~ (3, 144) => 0.999998
+(1, 143) ~ (3, 145) => 0.999998
+(1, 144) ~ (3, 146) => 0.999999
+(1, 145) ~ (3, 147) => 0.999998
+(1, 146) ~ (3, 148) => 0.999997
+(1, 147) ~ (3, 149) => 0.999999
+(1, 148) ~ (3, 150) => 0.999999
+(1, 149) ~ (3, 151) => 0.999999
+(1, 150) ~ (3, 152) => 0.999997
+(1, 151) ~ (3, 153) => 0.99997
+(1, 152) ~ (3, 154) => 0.999967
+(1, 153) ~ (3, 155) => 0.999989
+(1, 154) ~ (3, 156) => 0.999997
+(1, 155) ~ (3, 157) => 0.999997
+(1, 156) ~ (3, 158) => 0.999997
+(1, 157) ~ (3, 159) => 0.999996
+(1, 158) ~ (3, 160) => 0.999987
+(1, 159) ~ (3, 161) => 0.999924
+(1, 160) ~ (3, 162) => 0.99987
+(1, 161) ~ (3, 163) => 0.999826
+(1, 162) ~ (3, 164) => 0.999844
+(1, 163) ~ (3, 165) => 0.999956
+(1, 164) ~ (3, 166) => 0.999982
+(1, 165) ~ (3, 167) => 0.999984
+(1, 166) ~ (3, 168) => 0.999984
+(1, 167) ~ (3, 169) => 0.999967
+(1, 168) ~ (3, 170) => 0.99997
+(1, 169) ~ (3, 171) => 0.999975
+(1, 170) ~ (3, 172) => 0.999974
+(1, 171) ~ (3, 173) => 0.999966
+(1, 172) ~ (3, 174) => 0.999975
+(1, 173) ~ (3, 175) => 0.999997
+(1, 174) ~ (3, 176) => 0.999998
+(1, 175) ~ (3, 177) => 0.999978
+(1, 176) ~ (3, 178) => 0.999971
+(1, 177) ~ (3, 179) => 0.99998
+(1, 178) ~ (3, 180) => 0.999996
+(1, 179) ~ (3, 181) => 0.999998
+(1, 180) ~ (3, 182) => 0.999998
+(1, 181) ~ (3, 183) => 0.999998
+(1, 182) ~ (3, 184) => 0.99999
+(1, 183) ~ (3, 185) => 0.999953
+(1, 184) ~ (3, 186) => 0.999887
+(1, 185) ~ (3, 187) => 0.999807
+(1, 186) ~ (3, 188) => 0.999693
+(1, 187) ~ (3, 189) => 0.999107
+(1, 188) ~ (3, 190) => 0.990967
+(1, 189) ~ (3, 191) => 0.863111
+(1, 189) ~ (3, 193) => 0.128317
+(1, 190) ~ (3, 192) => 0.719686
+(1, 190) ~ (3, 194) => 0.267641
+(1, 191) ~ (3, 193) => 0.565654
+(1, 191) ~ (3, 195) => 0.420557
+(1, 192) ~ (3, 194) => 0.118254
+(1, 192) ~ (3, 196) => 0.869737
+(1, 193) ~ (3, 195) => 0.0355752
+(1, 193) ~ (3, 197) => 0.959279
+(1, 194) ~ (3, 196) => 0.029588
+(1, 194) ~ (3, 198) => 0.965522
+(1, 195) ~ (3, 197) => 0.0260377
+(1, 195) ~ (3, 199) => 0.969083
+(1, 196) ~ (3, 198) => 0.0201736
+(1, 196) ~ (3, 200) => 0.975441
+(1, 197) ~ (3, 201) => 0.991701
+(1, 198) ~ (3, 202) => 0.99658
+(1, 199) ~ (3, 203) => 0.999517
+(1, 200) ~ (3, 204) => 0.999853
+(1, 201) ~ (3, 205) => 0.999938
+(1, 202) ~ (3, 206) => 0.999896
+(1, 203) ~ (3, 207) => 0.999869
+(1, 204) ~ (3, 208) => 0.999841
+(1, 205) ~ (3, 209) => 0.999795
+(1, 206) ~ (3, 210) => 0.999867
+(1, 207) ~ (3, 211) => 0.999958
+(1, 208) ~ (3, 212) => 0.999988
+(1, 209) ~ (3, 213) => 0.999981
+(1, 210) ~ (3, 214) => 0.999969
+(1, 211) ~ (3, 215) => 0.999975
+(1, 212) ~ (3, 216) => 0.999972
+(1, 213) ~ (3, 217) => 0.999713
+(1, 214) ~ (3, 218) => 0.9965
+(1, 215) ~ (3, 219) => 0.993385
+(1, 216) ~ (3, 220) => 0.977851
+(1, 216) ~ (3, 221) => 0.0211596
+(1, 217) ~ (3, 221) => 0.950753
+(1, 217) ~ (3, 222) => 0.0480003
+(1, 218) ~ (3, 222) => 0.816315
+(1, 218) ~ (3, 223) => 0.181398
+(1, 219) ~ (3, 223) => 0.778348
+(1, 219) ~ (3, 224) => 0.218191
+(1, 220) ~ (3, 224) => 0.540422
+(1, 220) ~ (3, 225) => 0.44963
+(1, 221) ~ (3, 225) => 0.305196
+(1, 221) ~ (3, 226) => 0.681579
+(1, 222) ~ (3, 226) => 0.100878
+(1, 222) ~ (3, 227) => 0.887649
+(1, 223) ~ (3, 228) => 0.995746
+(1, 224) ~ (3, 229) => 0.998132
+(1, 225) ~ (3, 230) => 0.999924
+(1, 226) ~ (3, 231) => 0.999984
+(1, 227) ~ (3, 232) => 0.999995
+(1, 228) ~ (3, 233) => 0.999993
+(1, 229) ~ (3, 234) => 0.99999
+(1, 230) ~ (3, 235) => 0.999992
+(1, 231) ~ (3, 236) => 0.999982
+(1, 232) ~ (3, 237) => 0.999985
+(1, 233) ~ (3, 238) => 0.999998
+
+; gap posteriors
+(1, 0) ~ (3, -1) => 0.000273585
+(1, 1) ~ (3, -1) => 0.000439703
+(1, 2) ~ (3, -1) => 0.000475466
+(1, 3) ~ (3, -1) => 0.000418901
+(1, 4) ~ (3, -1) => 0.000323057
+(1, 5) ~ (3, -1) => 0.000558197
+(1, 6) ~ (3, -1) => 0.00395393
+(1, 7) ~ (3, -1) => 0.00421083
+(1, 8) ~ (3, -1) => 0.00444686
+(1, 9) ~ (3, -1) => 0.00873119
+(1, 10) ~ (3, -1) => 0.00117948
+(1, 11) ~ (3, -1) => 0.00999258
+(1, 12) ~ (3, -1) => 0.020881
+(1, 13) ~ (3, -1) => 0.0424837
+(1, 14) ~ (3, -1) => 0.00638145
+(1, 15) ~ (3, -1) => 0.0135546
+(1, 16) ~ (3, -1) => 0.0034861
+(1, 17) ~ (3, -1) => 0.000800967
+(1, 18) ~ (3, -1) => 0.000411808
+(1, 19) ~ (3, -1) => 0.000376225
+(1, 20) ~ (3, -1) => 0.0001
+(1, 21) ~ (3, -1) => 0.0001
+(1, 22) ~ (3, -1) => 0.0001
+(1, 23) ~ (3, -1) => 0.0001
+(1, 24) ~ (3, -1) => 0.0001
+(1, 25) ~ (3, -1) => 0.0001
+(1, 26) ~ (3, -1) => 0.0001
+(1, 27) ~ (3, -1) => 0.0001
+(1, 28) ~ (3, -1) => 0.0001
+(1, 29) ~ (3, -1) => 0.0001
+(1, 30) ~ (3, -1) => 0.0001
+(1, 31) ~ (3, -1) => 0.0001
+(1, 32) ~ (3, -1) => 0.0001
+(1, 33) ~ (3, -1) => 0.0001
+(1, 34) ~ (3, -1) => 0.0001
+(1, 35) ~ (3, -1) => 0.0001
+(1, 36) ~ (3, -1) => 0.0001
+(1, 37) ~ (3, -1) => 0.0001
+(1, 38) ~ (3, -1) => 0.000145018
+(1, 39) ~ (3, -1) => 0.00020802
+(1, 40) ~ (3, -1) => 0.000163794
+(1, 41) ~ (3, -1) => 0.0001
+(1, 42) ~ (3, -1) => 0.0001
+(1, 43) ~ (3, -1) => 0.0001
+(1, 44) ~ (3, -1) => 0.0001
+(1, 45) ~ (3, -1) => 0.0001
+(1, 46) ~ (3, -1) => 0.0001
+(1, 47) ~ (3, -1) => 0.000118256
+(1, 48) ~ (3, -1) => 0.000143111
+(1, 49) ~ (3, -1) => 0.000129104
+(1, 50) ~ (3, -1) => 0.0001
+(1, 51) ~ (3, -1) => 0.0001
+(1, 52) ~ (3, -1) => 0.0001
+(1, 53) ~ (3, -1) => 0.0001
+(1, 54) ~ (3, -1) => 0.0001
+(1, 55) ~ (3, -1) => 0.0001
+(1, 56) ~ (3, -1) => 0.0001
+(1, 57) ~ (3, -1) => 0.0001
+(1, 58) ~ (3, -1) => 0.0001
+(1, 59) ~ (3, -1) => 0.0001
+(1, 60) ~ (3, -1) => 0.0001
+(1, 61) ~ (3, -1) => 0.0001
+(1, 62) ~ (3, -1) => 0.0001
+(1, 63) ~ (3, -1) => 0.0001
+(1, 64) ~ (3, -1) => 0.000147581
+(1, 65) ~ (3, -1) => 0.0001688
+(1, 66) ~ (3, -1) => 0.00015825
+(1, 67) ~ (3, -1) => 0.0001
+(1, 68) ~ (3, -1) => 0.0001
+(1, 69) ~ (3, -1) => 0.0001
+(1, 70) ~ (3, -1) => 0.0001
+(1, 71) ~ (3, -1) => 0.0001
+(1, 72) ~ (3, -1) => 0.0001
+(1, 73) ~ (3, -1) => 0.0001
+(1, 74) ~ (3, -1) => 0.0001
+(1, 75) ~ (3, -1) => 0.0001
+(1, 76) ~ (3, -1) => 0.0001
+(1, 77) ~ (3, -1) => 0.0001
+(1, 78) ~ (3, -1) => 0.0001
+(1, 79) ~ (3, -1) => 0.0001
+(1, 80) ~ (3, -1) => 0.000962973
+(1, 81) ~ (3, -1) => 0.00129086
+(1, 82) ~ (3, -1) => 0.00322717
+(1, 83) ~ (3, -1) => 0.00342023
+(1, 84) ~ (3, -1) => 0.00352556
+(1, 85) ~ (3, -1) => 0.00344127
+(1, 86) ~ (3, -1) => 0.00291592
+(1, 87) ~ (3, -1) => 0.00282913
+(1, 88) ~ (3, -1) => 0.00157523
+(1, 89) ~ (3, -1) => 0.000919878
+(1, 90) ~ (3, -1) => 0.0001
+(1, 91) ~ (3, -1) => 0.0001
+(1, 92) ~ (3, -1) => 0.0001
+(1, 93) ~ (3, -1) => 0.0001
+(1, 94) ~ (3, -1) => 0.0001
+(1, 95) ~ (3, -1) => 0.0001
+(1, 96) ~ (3, -1) => 0.0001
+(1, 97) ~ (3, -1) => 0.0001
+(1, 98) ~ (3, -1) => 0.0001
+(1, 99) ~ (3, -1) => 0.000154793
+(1, 100) ~ (3, -1) => 0.000217736
+(1, 101) ~ (3, -1) => 0.000189364
+(1, 102) ~ (3, -1) => 0.000143766
+(1, 103) ~ (3, -1) => 0.0001
+(1, 104) ~ (3, -1) => 0.0001
+(1, 105) ~ (3, -1) => 0.0001
+(1, 106) ~ (3, -1) => 0.0001
+(1, 107) ~ (3, -1) => 0.0001
+(1, 108) ~ (3, -1) => 0.0001
+(1, 109) ~ (3, -1) => 0.0001
+(1, 110) ~ (3, -1) => 0.0001
+(1, 111) ~ (3, -1) => 0.0001
+(1, 112) ~ (3, -1) => 0.0001
+(1, 113) ~ (3, -1) => 0.0001
+(1, 114) ~ (3, -1) => 0.0001
+(1, 115) ~ (3, -1) => 0.0001
+(1, 116) ~ (3, -1) => 0.0001
+(1, 117) ~ (3, -1) => 0.0001
+(1, 118) ~ (3, -1) => 0.0001
+(1, 119) ~ (3, -1) => 0.0001
+(1, 120) ~ (3, -1) => 0.0001
+(1, 121) ~ (3, -1) => 0.0001
+(1, 122) ~ (3, -1) => 0.0001
+(1, 123) ~ (3, -1) => 0.0001
+(1, 124) ~ (3, -1) => 0.0001
+(1, 125) ~ (3, -1) => 0.0001
+(1, 126) ~ (3, -1) => 0.0001
+(1, 127) ~ (3, -1) => 0.0001
+(1, 128) ~ (3, -1) => 0.0001
+(1, 129) ~ (3, -1) => 0.000272691
+(1, 130) ~ (3, -1) => 0.000450253
+(1, 131) ~ (3, -1) => 0.000423312
+(1, 132) ~ (3, -1) => 0.0001
+(1, 133) ~ (3, -1) => 0.0001
+(1, 134) ~ (3, -1) => 0.0001
+(1, 135) ~ (3, -1) => 0.0001
+(1, 136) ~ (3, -1) => 0.0001
+(1, 137) ~ (3, -1) => 0.0001
+(1, 138) ~ (3, -1) => 0.000496149
+(1, 139) ~ (3, -1) => 0.000481963
+(1, 140) ~ (3, -1) => 0.0001
+(1, 141) ~ (3, -1) => 0.0001
+(1, 142) ~ (3, -1) => 0.0001
+(1, 143) ~ (3, -1) => 0.0001
+(1, 144) ~ (3, -1) => 0.0001
+(1, 145) ~ (3, -1) => 0.0001
+(1, 146) ~ (3, -1) => 0.0001
+(1, 147) ~ (3, -1) => 0.0001
+(1, 148) ~ (3, -1) => 0.0001
+(1, 149) ~ (3, -1) => 0.0001
+(1, 150) ~ (3, -1) => 0.0001
+(1, 151) ~ (3, -1) => 0.0001
+(1, 152) ~ (3, -1) => 0.0001
+(1, 153) ~ (3, -1) => 0.0001
+(1, 154) ~ (3, -1) => 0.0001
+(1, 155) ~ (3, -1) => 0.0001
+(1, 156) ~ (3, -1) => 0.0001
+(1, 157) ~ (3, -1) => 0.0001
+(1, 158) ~ (3, -1) => 0.0001
+(1, 159) ~ (3, -1) => 0.0001
+(1, 160) ~ (3, -1) => 0.000130057
+(1, 161) ~ (3, -1) => 0.000174046
+(1, 162) ~ (3, -1) => 0.000155568
+(1, 163) ~ (3, -1) => 0.0001
+(1, 164) ~ (3, -1) => 0.0001
+(1, 165) ~ (3, -1) => 0.0001
+(1, 166) ~ (3, -1) => 0.0001
+(1, 167) ~ (3, -1) => 0.0001
+(1, 168) ~ (3, -1) => 0.0001
+(1, 169) ~ (3, -1) => 0.0001
+(1, 170) ~ (3, -1) => 0.0001
+(1, 171) ~ (3, -1) => 0.0001
+(1, 172) ~ (3, -1) => 0.0001
+(1, 173) ~ (3, -1) => 0.0001
+(1, 174) ~ (3, -1) => 0.0001
+(1, 175) ~ (3, -1) => 0.0001
+(1, 176) ~ (3, -1) => 0.0001
+(1, 177) ~ (3, -1) => 0.0001
+(1, 178) ~ (3, -1) => 0.0001
+(1, 179) ~ (3, -1) => 0.0001
+(1, 180) ~ (3, -1) => 0.0001
+(1, 181) ~ (3, -1) => 0.0001
+(1, 182) ~ (3, -1) => 0.0001
+(1, 183) ~ (3, -1) => 0.0001
+(1, 184) ~ (3, -1) => 0.000113487
+(1, 185) ~ (3, -1) => 0.000193119
+(1, 186) ~ (3, -1) => 0.000307083
+(1, 187) ~ (3, -1) => 0.000892937
+(1, 188) ~ (3, -1) => 0.00903308
+(1, 189) ~ (3, -1) => 0.00857249
+(1, 190) ~ (3, -1) => 0.0126731
+(1, 191) ~ (3, -1) => 0.0137887
+(1, 192) ~ (3, -1) => 0.0120088
+(1, 193) ~ (3, -1) => 0.00514621
+(1, 194) ~ (3, -1) => 0.00488979
+(1, 195) ~ (3, -1) => 0.00487965
+(1, 196) ~ (3, -1) => 0.00438541
+(1, 197) ~ (3, -1) => 0.00829947
+(1, 198) ~ (3, -1) => 0.00341988
+(1, 199) ~ (3, -1) => 0.000483453
+(1, 200) ~ (3, -1) => 0.000147283
+(1, 201) ~ (3, -1) => 0.0001
+(1, 202) ~ (3, -1) => 0.000104189
+(1, 203) ~ (3, -1) => 0.000131011
+(1, 204) ~ (3, -1) => 0.000158548
+(1, 205) ~ (3, -1) => 0.000204682
+(1, 206) ~ (3, -1) => 0.000133097
+(1, 207) ~ (3, -1) => 0.0001
+(1, 208) ~ (3, -1) => 0.0001
+(1, 209) ~ (3, -1) => 0.0001
+(1, 210) ~ (3, -1) => 0.0001
+(1, 211) ~ (3, -1) => 0.0001
+(1, 212) ~ (3, -1) => 0.0001
+(1, 213) ~ (3, -1) => 0.000287354
+(1, 214) ~ (3, -1) => 0.00350016
+(1, 215) ~ (3, -1) => 0.00661546
+(1, 216) ~ (3, -1) => 0.000989355
+(1, 217) ~ (3, -1) => 0.00124667
+(1, 218) ~ (3, -1) => 0.00228733
+(1, 219) ~ (3, -1) => 0.00346093
+(1, 220) ~ (3, -1) => 0.00994769
+(1, 221) ~ (3, -1) => 0.0132247
+(1, 222) ~ (3, -1) => 0.0114732
+(1, 223) ~ (3, -1) => 0.00425428
+(1, 224) ~ (3, -1) => 0.00186837
+(1, 225) ~ (3, -1) => 0.0001
+(1, 226) ~ (3, -1) => 0.0001
+(1, 227) ~ (3, -1) => 0.0001
+(1, 228) ~ (3, -1) => 0.0001
+(1, 229) ~ (3, -1) => 0.0001
+(1, 230) ~ (3, -1) => 0.0001
+(1, 231) ~ (3, -1) => 0.0001
+(1, 232) ~ (3, -1) => 0.0001
+(1, 233) ~ (3, -1) => 0.0001
+
+(1, -1) ~ (3, 0) => 0.000273585
+(1, -1) ~ (3, 1) => 0.000439703
+(1, -1) ~ (3, 2) => 0.000475466
+(1, -1) ~ (3, 3) => 0.000418901
+(1, -1) ~ (3, 4) => 0.000323057
+(1, -1) ~ (3, 5) => 0.000558197
+(1, -1) ~ (3, 6) => 0.00395393
+(1, -1) ~ (3, 7) => 0.00421083
+(1, -1) ~ (3, 8) => 0.00444686
+(1, -1) ~ (3, 9) => 0.00873119
+(1, -1) ~ (3, 10) => 0.0225471
+(1, -1) ~ (3, 11) => 0.0441494
+(1, -1) ~ (3, 12) => 0.0666685
+(1, -1) ~ (3, 13) => 0.212997
+(1, -1) ~ (3, 14) => 0.526913
+(1, -1) ~ (3, 15) => 0.778108
+(1, -1) ~ (3, 16) => 0.401051
+(1, -1) ~ (3, 17) => 0.0420391
+(1, -1) ~ (3, 18) => 0.0034861
+(1, -1) ~ (3, 19) => 0.000800967
+(1, -1) ~ (3, 20) => 0.000411808
+(1, -1) ~ (3, 21) => 0.000376225
+(1, -1) ~ (3, 22) => 0.0001
+(1, -1) ~ (3, 23) => 0.0001
+(1, -1) ~ (3, 24) => 0.0001
+(1, -1) ~ (3, 25) => 0.0001
+(1, -1) ~ (3, 26) => 0.0001
+(1, -1) ~ (3, 27) => 0.0001
+(1, -1) ~ (3, 28) => 0.0001
+(1, -1) ~ (3, 29) => 0.0001
+(1, -1) ~ (3, 30) => 0.0001
+(1, -1) ~ (3, 31) => 0.0001
+(1, -1) ~ (3, 32) => 0.0001
+(1, -1) ~ (3, 33) => 0.0001
+(1, -1) ~ (3, 34) => 0.0001
+(1, -1) ~ (3, 35) => 0.0001
+(1, -1) ~ (3, 36) => 0.0001
+(1, -1) ~ (3, 37) => 0.0001
+(1, -1) ~ (3, 38) => 0.0001
+(1, -1) ~ (3, 39) => 0.0001
+(1, -1) ~ (3, 40) => 0.000145018
+(1, -1) ~ (3, 41) => 0.00020802
+(1, -1) ~ (3, 42) => 0.000163794
+(1, -1) ~ (3, 43) => 0.0001
+(1, -1) ~ (3, 44) => 0.0001
+(1, -1) ~ (3, 45) => 0.0001
+(1, -1) ~ (3, 46) => 0.0001
+(1, -1) ~ (3, 47) => 0.0001
+(1, -1) ~ (3, 48) => 0.0001
+(1, -1) ~ (3, 49) => 0.000118256
+(1, -1) ~ (3, 50) => 0.000143111
+(1, -1) ~ (3, 51) => 0.000129104
+(1, -1) ~ (3, 52) => 0.0001
+(1, -1) ~ (3, 53) => 0.0001
+(1, -1) ~ (3, 54) => 0.0001
+(1, -1) ~ (3, 55) => 0.0001
+(1, -1) ~ (3, 56) => 0.0001
+(1, -1) ~ (3, 57) => 0.0001
+(1, -1) ~ (3, 58) => 0.0001
+(1, -1) ~ (3, 59) => 0.0001
+(1, -1) ~ (3, 60) => 0.0001
+(1, -1) ~ (3, 61) => 0.0001
+(1, -1) ~ (3, 62) => 0.0001
+(1, -1) ~ (3, 63) => 0.0001
+(1, -1) ~ (3, 64) => 0.0001
+(1, -1) ~ (3, 65) => 0.0001
+(1, -1) ~ (3, 66) => 0.000147581
+(1, -1) ~ (3, 67) => 0.0001688
+(1, -1) ~ (3, 68) => 0.00015825
+(1, -1) ~ (3, 69) => 0.0001
+(1, -1) ~ (3, 70) => 0.0001
+(1, -1) ~ (3, 71) => 0.0001
+(1, -1) ~ (3, 72) => 0.0001
+(1, -1) ~ (3, 73) => 0.0001
+(1, -1) ~ (3, 74) => 0.0001
+(1, -1) ~ (3, 75) => 0.0001
+(1, -1) ~ (3, 76) => 0.0001
+(1, -1) ~ (3, 77) => 0.0001
+(1, -1) ~ (3, 78) => 0.0001
+(1, -1) ~ (3, 79) => 0.0001
+(1, -1) ~ (3, 80) => 0.0001
+(1, -1) ~ (3, 81) => 0.0001
+(1, -1) ~ (3, 82) => 0.000962973
+(1, -1) ~ (3, 83) => 0.00129086
+(1, -1) ~ (3, 84) => 0.00322717
+(1, -1) ~ (3, 85) => 0.00342023
+(1, -1) ~ (3, 86) => 0.00352556
+(1, -1) ~ (3, 87) => 0.00344127
+(1, -1) ~ (3, 88) => 0.00291592
+(1, -1) ~ (3, 89) => 0.00282913
+(1, -1) ~ (3, 90) => 0.00157523
+(1, -1) ~ (3, 91) => 0.000919878
+(1, -1) ~ (3, 92) => 0.0001
+(1, -1) ~ (3, 93) => 0.0001
+(1, -1) ~ (3, 94) => 0.0001
+(1, -1) ~ (3, 95) => 0.0001
+(1, -1) ~ (3, 96) => 0.0001
+(1, -1) ~ (3, 97) => 0.0001
+(1, -1) ~ (3, 98) => 0.0001
+(1, -1) ~ (3, 99) => 0.0001
+(1, -1) ~ (3, 100) => 0.0001
+(1, -1) ~ (3, 101) => 0.000154793
+(1, -1) ~ (3, 102) => 0.000217736
+(1, -1) ~ (3, 103) => 0.000189364
+(1, -1) ~ (3, 104) => 0.000143766
+(1, -1) ~ (3, 105) => 0.0001
+(1, -1) ~ (3, 106) => 0.0001
+(1, -1) ~ (3, 107) => 0.0001
+(1, -1) ~ (3, 108) => 0.0001
+(1, -1) ~ (3, 109) => 0.0001
+(1, -1) ~ (3, 110) => 0.0001
+(1, -1) ~ (3, 111) => 0.0001
+(1, -1) ~ (3, 112) => 0.0001
+(1, -1) ~ (3, 113) => 0.0001
+(1, -1) ~ (3, 114) => 0.0001
+(1, -1) ~ (3, 115) => 0.0001
+(1, -1) ~ (3, 116) => 0.0001
+(1, -1) ~ (3, 117) => 0.0001
+(1, -1) ~ (3, 118) => 0.0001
+(1, -1) ~ (3, 119) => 0.0001
+(1, -1) ~ (3, 120) => 0.0001
+(1, -1) ~ (3, 121) => 0.0001
+(1, -1) ~ (3, 122) => 0.0001
+(1, -1) ~ (3, 123) => 0.0001
+(1, -1) ~ (3, 124) => 0.0001
+(1, -1) ~ (3, 125) => 0.0001
+(1, -1) ~ (3, 126) => 0.0001
+(1, -1) ~ (3, 127) => 0.0001
+(1, -1) ~ (3, 128) => 0.0001
+(1, -1) ~ (3, 129) => 0.0001
+(1, -1) ~ (3, 130) => 0.0001
+(1, -1) ~ (3, 131) => 0.000272691
+(1, -1) ~ (3, 132) => 0.000450253
+(1, -1) ~ (3, 133) => 0.000423312
+(1, -1) ~ (3, 134) => 0.0001
+(1, -1) ~ (3, 135) => 0.0001
+(1, -1) ~ (3, 136) => 0.0001
+(1, -1) ~ (3, 137) => 0.0001
+(1, -1) ~ (3, 138) => 0.0001
+(1, -1) ~ (3, 139) => 0.0001
+(1, -1) ~ (3, 140) => 0.000496149
+(1, -1) ~ (3, 141) => 0.000481963
+(1, -1) ~ (3, 142) => 0.0001
+(1, -1) ~ (3, 143) => 0.0001
+(1, -1) ~ (3, 144) => 0.0001
+(1, -1) ~ (3, 145) => 0.0001
+(1, -1) ~ (3, 146) => 0.0001
+(1, -1) ~ (3, 147) => 0.0001
+(1, -1) ~ (3, 148) => 0.0001
+(1, -1) ~ (3, 149) => 0.0001
+(1, -1) ~ (3, 150) => 0.0001
+(1, -1) ~ (3, 151) => 0.0001
+(1, -1) ~ (3, 152) => 0.0001
+(1, -1) ~ (3, 153) => 0.0001
+(1, -1) ~ (3, 154) => 0.0001
+(1, -1) ~ (3, 155) => 0.0001
+(1, -1) ~ (3, 156) => 0.0001
+(1, -1) ~ (3, 157) => 0.0001
+(1, -1) ~ (3, 158) => 0.0001
+(1, -1) ~ (3, 159) => 0.0001
+(1, -1) ~ (3, 160) => 0.0001
+(1, -1) ~ (3, 161) => 0.0001
+(1, -1) ~ (3, 162) => 0.000130057
+(1, -1) ~ (3, 163) => 0.000174046
+(1, -1) ~ (3, 164) => 0.000155568
+(1, -1) ~ (3, 165) => 0.0001
+(1, -1) ~ (3, 166) => 0.0001
+(1, -1) ~ (3, 167) => 0.0001
+(1, -1) ~ (3, 168) => 0.0001
+(1, -1) ~ (3, 169) => 0.0001
+(1, -1) ~ (3, 170) => 0.0001
+(1, -1) ~ (3, 171) => 0.0001
+(1, -1) ~ (3, 172) => 0.0001
+(1, -1) ~ (3, 173) => 0.0001
+(1, -1) ~ (3, 174) => 0.0001
+(1, -1) ~ (3, 175) => 0.0001
+(1, -1) ~ (3, 176) => 0.0001
+(1, -1) ~ (3, 177) => 0.0001
+(1, -1) ~ (3, 178) => 0.0001
+(1, -1) ~ (3, 179) => 0.0001
+(1, -1) ~ (3, 180) => 0.0001
+(1, -1) ~ (3, 181) => 0.0001
+(1, -1) ~ (3, 182) => 0.0001
+(1, -1) ~ (3, 183) => 0.0001
+(1, -1) ~ (3, 184) => 0.0001
+(1, -1) ~ (3, 185) => 0.0001
+(1, -1) ~ (3, 186) => 0.000113487
+(1, -1) ~ (3, 187) => 0.000193119
+(1, -1) ~ (3, 188) => 0.000307083
+(1, -1) ~ (3, 189) => 0.000892937
+(1, -1) ~ (3, 190) => 0.00903308
+(1, -1) ~ (3, 191) => 0.136889
+(1, -1) ~ (3, 192) => 0.280314
+(1, -1) ~ (3, 193) => 0.306029
+(1, -1) ~ (3, 194) => 0.614105
+(1, -1) ~ (3, 195) => 0.543868
+(1, -1) ~ (3, 196) => 0.100675
+(1, -1) ~ (3, 197) => 0.0146837
+(1, -1) ~ (3, 198) => 0.0143042
+(1, -1) ~ (3, 199) => 0.0309173
+(1, -1) ~ (3, 200) => 0.024559
+(1, -1) ~ (3, 201) => 0.00829947
+(1, -1) ~ (3, 202) => 0.00341988
+(1, -1) ~ (3, 203) => 0.000483453
+(1, -1) ~ (3, 204) => 0.000147283
+(1, -1) ~ (3, 205) => 0.0001
+(1, -1) ~ (3, 206) => 0.000104189
+(1, -1) ~ (3, 207) => 0.000131011
+(1, -1) ~ (3, 208) => 0.000158548
+(1, -1) ~ (3, 209) => 0.000204682
+(1, -1) ~ (3, 210) => 0.000133097
+(1, -1) ~ (3, 211) => 0.0001
+(1, -1) ~ (3, 212) => 0.0001
+(1, -1) ~ (3, 213) => 0.0001
+(1, -1) ~ (3, 214) => 0.0001
+(1, -1) ~ (3, 215) => 0.0001
+(1, -1) ~ (3, 216) => 0.0001
+(1, -1) ~ (3, 217) => 0.000287354
+(1, -1) ~ (3, 218) => 0.00350016
+(1, -1) ~ (3, 219) => 0.00661546
+(1, -1) ~ (3, 220) => 0.022149
+(1, -1) ~ (3, 221) => 0.0280874
+(1, -1) ~ (3, 222) => 0.135685
+(1, -1) ~ (3, 223) => 0.0402537
+(1, -1) ~ (3, 224) => 0.241387
+(1, -1) ~ (3, 225) => 0.245174
+(1, -1) ~ (3, 226) => 0.217543
+(1, -1) ~ (3, 227) => 0.112351
+(1, -1) ~ (3, 228) => 0.00425428
+(1, -1) ~ (3, 229) => 0.00186837
+(1, -1) ~ (3, 230) => 0.0001
+(1, -1) ~ (3, 231) => 0.0001
+(1, -1) ~ (3, 232) => 0.0001
+(1, -1) ~ (3, 233) => 0.0001
+(1, -1) ~ (3, 234) => 0.0001
+(1, -1) ~ (3, 235) => 0.0001
+(1, -1) ~ (3, 236) => 0.0001
+(1, -1) ~ (3, 237) => 0.0001
+(1, -1) ~ (3, 238) => 0.0001
+
+; Sparse posterior probability matrix for sequences 1 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (4, 0) => 0.994944
+(1, 1) ~ (4, 1) => 0.991771
+(1, 2) ~ (4, 2) => 0.98873
+(1, 3) ~ (4, 3) => 0.989058
+(1, 4) ~ (4, 4) => 0.987711
+(1, 5) ~ (4, 5) => 0.98873
+(1, 6) ~ (4, 6) => 0.986876
+(1, 7) ~ (4, 7) => 0.904069
+(1, 7) ~ (4, 9) => 0.0912081
+(1, 8) ~ (4, 8) => 0.694731
+(1, 8) ~ (4, 10) => 0.300541
+(1, 9) ~ (4, 9) => 0.685606
+(1, 9) ~ (4, 11) => 0.308914
+(1, 10) ~ (4, 10) => 0.66876
+(1, 10) ~ (4, 12) => 0.323109
+(1, 11) ~ (4, 11) => 0.663041
+(1, 11) ~ (4, 13) => 0.318723
+(1, 12) ~ (4, 12) => 0.647839
+(1, 12) ~ (4, 13) => 0.0156041
+(1, 12) ~ (4, 14) => 0.316004
+(1, 13) ~ (4, 13) => 0.610506
+(1, 13) ~ (4, 14) => 0.0372699
+(1, 13) ~ (4, 15) => 0.326203
+(1, 13) ~ (4, 16) => 0.0138145
+(1, 14) ~ (4, 14) => 0.535987
+(1, 14) ~ (4, 15) => 0.0720464
+(1, 14) ~ (4, 16) => 0.351931
+(1, 14) ~ (4, 17) => 0.0231614
+(1, 15) ~ (4, 15) => 0.483853
+(1, 15) ~ (4, 16) => 0.0924835
+(1, 15) ~ (4, 17) => 0.380851
+(1, 15) ~ (4, 18) => 0.0116282
+(1, 16) ~ (4, 16) => 0.420016
+(1, 16) ~ (4, 17) => 0.109448
+(1, 16) ~ (4, 18) => 0.439277
+(1, 17) ~ (4, 17) => 0.366106
+(1, 17) ~ (4, 18) => 0.0397265
+(1, 17) ~ (4, 19) => 0.565994
+(1, 18) ~ (4, 18) => 0.314945
+(1, 18) ~ (4, 20) => 0.662332
+(1, 19) ~ (4, 19) => 0.212978
+(1, 19) ~ (4, 21) => 0.770101
+(1, 20) ~ (4, 20) => 0.015187
+(1, 20) ~ (4, 22) => 0.981819
+(1, 21) ~ (4, 23) => 0.998723
+(1, 22) ~ (4, 24) => 0.99984
+(1, 23) ~ (4, 25) => 0.999651
+(1, 24) ~ (4, 26) => 0.999059
+(1, 25) ~ (4, 27) => 0.997627
+(1, 26) ~ (4, 28) => 0.996177
+(1, 27) ~ (4, 29) => 0.99038
+(1, 28) ~ (4, 30) => 0.987969
+(1, 29) ~ (4, 31) => 0.988904
+(1, 30) ~ (4, 32) => 0.993893
+(1, 31) ~ (4, 33) => 0.997115
+(1, 32) ~ (4, 34) => 0.998662
+(1, 33) ~ (4, 35) => 0.998147
+(1, 34) ~ (4, 36) => 0.997766
+(1, 35) ~ (4, 37) => 0.997975
+(1, 36) ~ (4, 38) => 0.997947
+(1, 37) ~ (4, 39) => 0.997963
+(1, 38) ~ (4, 40) => 0.998964
+(1, 39) ~ (4, 41) => 0.998773
+(1, 40) ~ (4, 42) => 0.997276
+(1, 41) ~ (4, 43) => 0.996895
+(1, 42) ~ (4, 44) => 0.995949
+(1, 43) ~ (4, 45) => 0.975381
+(1, 44) ~ (4, 45) => 0.0107168
+(1, 44) ~ (4, 46) => 0.955988
+(1, 45) ~ (4, 47) => 0.856988
+(1, 46) ~ (4, 46) => 0.0259819
+(1, 46) ~ (4, 47) => 0.011334
+(1, 46) ~ (4, 48) => 0.804507
+(1, 47) ~ (4, 47) => 0.113058
+(1, 47) ~ (4, 48) => 0.0170685
+(1, 47) ~ (4, 49) => 0.738338
+(1, 48) ~ (4, 48) => 0.15722
+(1, 48) ~ (4, 49) => 0.0236114
+(1, 48) ~ (4, 50) => 0.404766
+(1, 49) ~ (4, 49) => 0.21716
+(1, 49) ~ (4, 50) => 0.0104614
+(1, 49) ~ (4, 51) => 0.0997237
+(1, 50) ~ (4, 50) => 0.565035
+(1, 50) ~ (4, 51) => 0.0101291
+(1, 51) ~ (4, 51) => 0.876251
+(1, 52) ~ (4, 52) => 0.987023
+(1, 53) ~ (4, 53) => 0.996116
+(1, 54) ~ (4, 54) => 0.999647
+(1, 55) ~ (4, 55) => 0.999876
+(1, 56) ~ (4, 56) => 0.999851
+(1, 57) ~ (4, 57) => 0.999299
+(1, 58) ~ (4, 58) => 0.998963
+(1, 59) ~ (4, 59) => 0.998714
+(1, 60) ~ (4, 60) => 0.999196
+(1, 61) ~ (4, 61) => 0.999609
+(1, 62) ~ (4, 62) => 0.999533
+(1, 63) ~ (4, 63) => 0.99957
+(1, 64) ~ (4, 64) => 0.999883
+(1, 65) ~ (4, 65) => 0.999829
+(1, 66) ~ (4, 66) => 0.999434
+(1, 67) ~ (4, 67) => 0.999398
+(1, 68) ~ (4, 68) => 0.999831
+(1, 69) ~ (4, 69) => 0.999845
+(1, 70) ~ (4, 70) => 0.999077
+(1, 71) ~ (4, 71) => 0.998851
+(1, 72) ~ (4, 72) => 0.999237
+(1, 73) ~ (4, 73) => 0.999878
+(1, 74) ~ (4, 74) => 0.999906
+(1, 75) ~ (4, 75) => 0.99992
+(1, 76) ~ (4, 76) => 0.999714
+(1, 77) ~ (4, 77) => 0.998657
+(1, 78) ~ (4, 78) => 0.997165
+(1, 79) ~ (4, 79) => 0.967135
+(1, 80) ~ (4, 80) => 0.756688
+(1, 80) ~ (4, 81) => 0.0204138
+(1, 80) ~ (4, 84) => 0.0151265
+(1, 80) ~ (4, 86) => 0.0215564
+(1, 81) ~ (4, 80) => 0.0726278
+(1, 81) ~ (4, 81) => 0.571302
+(1, 81) ~ (4, 82) => 0.0104147
+(1, 81) ~ (4, 86) => 0.0105766
+(1, 81) ~ (4, 87) => 0.091539
+(1, 81) ~ (4, 88) => 0.0141562
+(1, 82) ~ (4, 81) => 0.144421
+(1, 82) ~ (4, 82) => 0.372116
+(1, 82) ~ (4, 84) => 0.023865
+(1, 82) ~ (4, 85) => 0.0137208
+(1, 82) ~ (4, 87) => 0.0166608
+(1, 82) ~ (4, 88) => 0.103474
+(1, 82) ~ (4, 89) => 0.0218947
+(1, 83) ~ (4, 80) => 0.0836311
+(1, 83) ~ (4, 82) => 0.136143
+(1, 83) ~ (4, 83) => 0.311751
+(1, 83) ~ (4, 85) => 0.0229525
+(1, 83) ~ (4, 86) => 0.0179798
+(1, 83) ~ (4, 88) => 0.0220569
+(1, 83) ~ (4, 89) => 0.090457
+(1, 83) ~ (4, 90) => 0.0370508
+(1, 84) ~ (4, 81) => 0.110818
+(1, 84) ~ (4, 83) => 0.12491
+(1, 84) ~ (4, 84) => 0.249541
+(1, 84) ~ (4, 85) => 0.0110579
+(1, 84) ~ (4, 86) => 0.0201665
+(1, 84) ~ (4, 87) => 0.0209943
+(1, 84) ~ (4, 89) => 0.0407234
+(1, 84) ~ (4, 90) => 0.0731161
+(1, 84) ~ (4, 91) => 0.0550254
+(1, 85) ~ (4, 82) => 0.265756
+(1, 85) ~ (4, 83) => 0.0111229
+(1, 85) ~ (4, 84) => 0.125586
+(1, 85) ~ (4, 85) => 0.233608
+(1, 85) ~ (4, 86) => 0.011643
+(1, 85) ~ (4, 87) => 0.0147802
+(1, 85) ~ (4, 88) => 0.0194274
+(1, 85) ~ (4, 90) => 0.0560704
+(1, 85) ~ (4, 91) => 0.0408148
+(1, 85) ~ (4, 92) => 0.0759568
+(1, 86) ~ (4, 83) => 0.312889
+(1, 86) ~ (4, 84) => 0.0100508
+(1, 86) ~ (4, 85) => 0.124365
+(1, 86) ~ (4, 86) => 0.19157
+(1, 86) ~ (4, 87) => 0.0157939
+(1, 86) ~ (4, 89) => 0.0202675
+(1, 86) ~ (4, 91) => 0.0815018
+(1, 86) ~ (4, 92) => 0.0220477
+(1, 86) ~ (4, 93) => 0.0987517
+(1, 87) ~ (4, 84) => 0.344397
+(1, 87) ~ (4, 86) => 0.125319
+(1, 87) ~ (4, 87) => 0.117103
+(1, 87) ~ (4, 88) => 0.0209876
+(1, 87) ~ (4, 90) => 0.0189649
+(1, 87) ~ (4, 92) => 0.0978522
+(1, 87) ~ (4, 93) => 0.013058
+(1, 87) ~ (4, 94) => 0.126188
+(1, 87) ~ (4, 95) => 0.0106016
+(1, 88) ~ (4, 85) => 0.353723
+(1, 88) ~ (4, 86) => 0.0131415
+(1, 88) ~ (4, 87) => 0.163172
+(1, 88) ~ (4, 88) => 0.0870018
+(1, 88) ~ (4, 89) => 0.0239416
+(1, 88) ~ (4, 91) => 0.0180844
+(1, 88) ~ (4, 93) => 0.0911661
+(1, 88) ~ (4, 95) => 0.144103
+(1, 88) ~ (4, 96) => 0.0102504
+(1, 89) ~ (4, 86) => 0.367954
+(1, 89) ~ (4, 87) => 0.0157616
+(1, 89) ~ (4, 88) => 0.171932
+(1, 89) ~ (4, 89) => 0.0651024
+(1, 89) ~ (4, 90) => 0.0255847
+(1, 89) ~ (4, 92) => 0.0159161
+(1, 89) ~ (4, 94) => 0.0662331
+(1, 89) ~ (4, 96) => 0.189146
+(1, 90) ~ (4, 87) => 0.384164
+(1, 90) ~ (4, 89) => 0.178715
+(1, 90) ~ (4, 90) => 0.0500917
+(1, 90) ~ (4, 91) => 0.0285306
+(1, 90) ~ (4, 93) => 0.0180759
+(1, 90) ~ (4, 95) => 0.0587357
+(1, 90) ~ (4, 97) => 0.207322
+(1, 91) ~ (4, 88) => 0.402651
+(1, 91) ~ (4, 90) => 0.188699
+(1, 91) ~ (4, 92) => 0.0351395
+(1, 91) ~ (4, 94) => 0.0188186
+(1, 91) ~ (4, 96) => 0.0605687
+(1, 91) ~ (4, 98) => 0.198561
+(1, 92) ~ (4, 89) => 0.39923
+(1, 92) ~ (4, 91) => 0.234962
+(1, 92) ~ (4, 93) => 0.0390534
+(1, 92) ~ (4, 95) => 0.0104074
+(1, 92) ~ (4, 97) => 0.0706072
+(1, 92) ~ (4, 99) => 0.158063
+(1, 93) ~ (4, 90) => 0.354564
+(1, 93) ~ (4, 92) => 0.231229
+(1, 93) ~ (4, 94) => 0.0787084
+(1, 93) ~ (4, 98) => 0.0995316
+(1, 93) ~ (4, 100) => 0.0509368
+(1, 94) ~ (4, 91) => 0.343578
+(1, 94) ~ (4, 93) => 0.100987
+(1, 94) ~ (4, 95) => 0.182099
+(1, 94) ~ (4, 99) => 0.169112
+(1, 94) ~ (4, 100) => 0.0302867
+(1, 94) ~ (4, 101) => 0.0344248
+(1, 95) ~ (4, 92) => 0.151725
+(1, 95) ~ (4, 94) => 0.0302835
+(1, 95) ~ (4, 96) => 0.439087
+(1, 95) ~ (4, 99) => 0.0103353
+(1, 95) ~ (4, 100) => 0.204526
+(1, 95) ~ (4, 101) => 0.0226278
+(1, 95) ~ (4, 102) => 0.0120776
+(1, 96) ~ (4, 93) => 0.118836
+(1, 96) ~ (4, 97) => 0.509981
+(1, 96) ~ (4, 101) => 0.163545
+(1, 96) ~ (4, 102) => 0.0110317
+(1, 97) ~ (4, 94) => 0.109462
+(1, 97) ~ (4, 98) => 0.510742
+(1, 97) ~ (4, 99) => 0.0197235
+(1, 97) ~ (4, 102) => 0.118364
+(1, 98) ~ (4, 95) => 0.0693256
+(1, 98) ~ (4, 99) => 0.451715
+(1, 98) ~ (4, 100) => 0.158207
+(1, 98) ~ (4, 103) => 0.0726801
+(1, 99) ~ (4, 96) => 0.049504
+(1, 99) ~ (4, 100) => 0.392911
+(1, 99) ~ (4, 101) => 0.297157
+(1, 99) ~ (4, 104) => 0.0331294
+(1, 100) ~ (4, 97) => 0.0314265
+(1, 100) ~ (4, 101) => 0.323625
+(1, 100) ~ (4, 102) => 0.460553
+(1, 100) ~ (4, 105) => 0.0228735
+(1, 101) ~ (4, 98) => 0.0117964
+(1, 101) ~ (4, 101) => 0.0163475
+(1, 101) ~ (4, 102) => 0.204806
+(1, 101) ~ (4, 103) => 0.659237
+(1, 102) ~ (4, 102) => 0.0265446
+(1, 102) ~ (4, 103) => 0.139869
+(1, 102) ~ (4, 104) => 0.779827
+(1, 103) ~ (4, 104) => 0.0686504
+(1, 103) ~ (4, 105) => 0.887088
+(1, 104) ~ (4, 106) => 0.980378
+(1, 105) ~ (4, 107) => 0.989012
+(1, 106) ~ (4, 108) => 0.994685
+(1, 107) ~ (4, 109) => 0.999768
+(1, 108) ~ (4, 110) => 0.999934
+(1, 109) ~ (4, 111) => 0.99998
+(1, 110) ~ (4, 112) => 0.999988
+(1, 111) ~ (4, 113) => 0.999962
+(1, 112) ~ (4, 114) => 0.999857
+(1, 113) ~ (4, 115) => 0.999829
+(1, 114) ~ (4, 116) => 0.999655
+(1, 115) ~ (4, 117) => 0.99962
+(1, 116) ~ (4, 118) => 0.999656
+(1, 117) ~ (4, 119) => 0.999818
+(1, 118) ~ (4, 120) => 0.999846
+(1, 119) ~ (4, 121) => 0.998998
+(1, 120) ~ (4, 122) => 0.998401
+(1, 121) ~ (4, 123) => 0.998428
+(1, 122) ~ (4, 124) => 0.999184
+(1, 123) ~ (4, 125) => 0.999443
+(1, 124) ~ (4, 126) => 0.996138
+(1, 125) ~ (4, 127) => 0.992652
+(1, 126) ~ (4, 128) => 0.993218
+(1, 127) ~ (4, 129) => 0.99101
+(1, 128) ~ (4, 130) => 0.906329
+(1, 128) ~ (4, 131) => 0.0147104
+(1, 129) ~ (4, 130) => 0.0135658
+(1, 129) ~ (4, 131) => 0.799308
+(1, 129) ~ (4, 132) => 0.0333574
+(1, 130) ~ (4, 130) => 0.0149936
+(1, 130) ~ (4, 131) => 0.0315317
+(1, 130) ~ (4, 132) => 0.6575
+(1, 130) ~ (4, 133) => 0.0439649
+(1, 130) ~ (4, 134) => 0.0233695
+(1, 130) ~ (4, 136) => 0.0106776
+(1, 131) ~ (4, 131) => 0.0282151
+(1, 131) ~ (4, 132) => 0.04486
+(1, 131) ~ (4, 133) => 0.515255
+(1, 131) ~ (4, 134) => 0.0977739
+(1, 131) ~ (4, 135) => 0.0421064
+(1, 131) ~ (4, 137) => 0.0116969
+(1, 132) ~ (4, 130) => 0.0267767
+(1, 132) ~ (4, 132) => 0.0742505
+(1, 132) ~ (4, 133) => 0.0609106
+(1, 132) ~ (4, 134) => 0.409821
+(1, 132) ~ (4, 135) => 0.0631348
+(1, 132) ~ (4, 136) => 0.0620993
+(1, 132) ~ (4, 138) => 0.0150662
+(1, 133) ~ (4, 131) => 0.0674515
+(1, 133) ~ (4, 133) => 0.120302
+(1, 133) ~ (4, 134) => 0.125145
+(1, 133) ~ (4, 135) => 0.314001
+(1, 133) ~ (4, 136) => 0.045285
+(1, 133) ~ (4, 137) => 0.0659222
+(1, 133) ~ (4, 139) => 0.0133682
+(1, 134) ~ (4, 132) => 0.117461
+(1, 134) ~ (4, 134) => 0.137658
+(1, 134) ~ (4, 135) => 0.214616
+(1, 134) ~ (4, 136) => 0.189129
+(1, 134) ~ (4, 137) => 0.0155879
+(1, 134) ~ (4, 138) => 0.0771059
+(1, 135) ~ (4, 133) => 0.106526
+(1, 135) ~ (4, 135) => 0.171764
+(1, 135) ~ (4, 136) => 0.354566
+(1, 135) ~ (4, 137) => 0.0695191
+(1, 135) ~ (4, 138) => 0.0123262
+(1, 135) ~ (4, 139) => 0.0879259
+(1, 136) ~ (4, 134) => 0.071584
+(1, 136) ~ (4, 136) => 0.104525
+(1, 136) ~ (4, 137) => 0.601234
+(1, 136) ~ (4, 138) => 0.0468989
+(1, 136) ~ (4, 139) => 0.0114798
+(1, 136) ~ (4, 140) => 0.0991672
+(1, 137) ~ (4, 135) => 0.0675154
+(1, 137) ~ (4, 137) => 0.110424
+(1, 137) ~ (4, 138) => 0.610069
+(1, 137) ~ (4, 139) => 0.04448
+(1, 137) ~ (4, 141) => 0.0650784
+(1, 138) ~ (4, 136) => 0.0619842
+(1, 138) ~ (4, 138) => 0.124434
+(1, 138) ~ (4, 139) => 0.627822
+(1, 138) ~ (4, 140) => 0.0253922
+(1, 138) ~ (4, 142) => 0.0511871
+(1, 139) ~ (4, 137) => 0.0375905
+(1, 139) ~ (4, 139) => 0.0739111
+(1, 139) ~ (4, 140) => 0.736601
+(1, 139) ~ (4, 141) => 0.0187119
+(1, 139) ~ (4, 143) => 0.0215202
+(1, 140) ~ (4, 138) => 0.01357
+(1, 140) ~ (4, 140) => 0.0185252
+(1, 140) ~ (4, 141) => 0.869013
+(1, 141) ~ (4, 142) => 0.925201
+(1, 142) ~ (4, 143) => 0.966595
+(1, 143) ~ (4, 144) => 0.998669
+(1, 144) ~ (4, 145) => 0.998798
+(1, 145) ~ (4, 146) => 0.999012
+(1, 146) ~ (4, 147) => 0.999761
+(1, 147) ~ (4, 148) => 0.999983
+(1, 148) ~ (4, 149) => 0.999992
+(1, 149) ~ (4, 150) => 0.999958
+(1, 150) ~ (4, 151) => 0.999549
+(1, 151) ~ (4, 152) => 0.999144
+(1, 152) ~ (4, 153) => 0.999207
+(1, 153) ~ (4, 154) => 0.999756
+(1, 154) ~ (4, 155) => 0.999914
+(1, 155) ~ (4, 156) => 0.999751
+(1, 156) ~ (4, 157) => 0.999685
+(1, 157) ~ (4, 158) => 0.999433
+(1, 158) ~ (4, 159) => 0.997397
+(1, 159) ~ (4, 160) => 0.995658
+(1, 160) ~ (4, 161) => 0.995048
+(1, 161) ~ (4, 162) => 0.994523
+(1, 162) ~ (4, 163) => 0.994902
+(1, 163) ~ (4, 164) => 0.994897
+(1, 164) ~ (4, 165) => 0.994414
+(1, 165) ~ (4, 166) => 0.995912
+(1, 166) ~ (4, 167) => 0.997012
+(1, 167) ~ (4, 168) => 0.997407
+(1, 168) ~ (4, 169) => 0.997563
+(1, 169) ~ (4, 170) => 0.997727
+(1, 170) ~ (4, 171) => 0.997693
+(1, 171) ~ (4, 172) => 0.998681
+(1, 172) ~ (4, 173) => 0.999854
+(1, 173) ~ (4, 174) => 0.999986
+(1, 174) ~ (4, 175) => 0.999981
+(1, 175) ~ (4, 176) => 0.999385
+(1, 176) ~ (4, 177) => 0.999157
+(1, 177) ~ (4, 178) => 0.999241
+(1, 178) ~ (4, 179) => 0.999388
+(1, 179) ~ (4, 180) => 0.999915
+(1, 180) ~ (4, 181) => 0.999972
+(1, 181) ~ (4, 182) => 0.999927
+(1, 182) ~ (4, 183) => 0.999227
+(1, 183) ~ (4, 184) => 0.99855
+(1, 184) ~ (4, 185) => 0.967167
+(1, 184) ~ (4, 186) => 0.0319884
+(1, 185) ~ (4, 186) => 0.9359
+(1, 185) ~ (4, 187) => 0.0625334
+(1, 186) ~ (4, 187) => 0.90218
+(1, 186) ~ (4, 188) => 0.0929544
+(1, 187) ~ (4, 188) => 0.782807
+(1, 187) ~ (4, 189) => 0.201041
+(1, 187) ~ (4, 190) => 0.0139164
+(1, 188) ~ (4, 189) => 0.653543
+(1, 188) ~ (4, 190) => 0.308075
+(1, 188) ~ (4, 191) => 0.0338042
+(1, 189) ~ (4, 190) => 0.559118
+(1, 189) ~ (4, 191) => 0.392585
+(1, 189) ~ (4, 192) => 0.0358691
+(1, 190) ~ (4, 191) => 0.496492
+(1, 190) ~ (4, 192) => 0.447633
+(1, 190) ~ (4, 193) => 0.0346356
+(1, 191) ~ (4, 192) => 0.443553
+(1, 191) ~ (4, 193) => 0.502776
+(1, 191) ~ (4, 194) => 0.0243296
+(1, 192) ~ (4, 193) => 0.0208528
+(1, 192) ~ (4, 194) => 0.945434
+(1, 193) ~ (4, 194) => 0.0114323
+(1, 193) ~ (4, 195) => 0.970704
+(1, 194) ~ (4, 196) => 0.979842
+(1, 195) ~ (4, 197) => 0.984163
+(1, 196) ~ (4, 198) => 0.984022
+(1, 197) ~ (4, 199) => 0.986753
+(1, 198) ~ (4, 200) => 0.989447
+(1, 199) ~ (4, 201) => 0.991588
+(1, 200) ~ (4, 202) => 0.992196
+(1, 201) ~ (4, 203) => 0.991872
+(1, 202) ~ (4, 204) => 0.99389
+(1, 203) ~ (4, 205) => 0.996707
+(1, 204) ~ (4, 206) => 0.998942
+(1, 205) ~ (4, 207) => 0.99975
+(1, 206) ~ (4, 208) => 0.999508
+(1, 207) ~ (4, 209) => 0.999192
+(1, 208) ~ (4, 210) => 0.999208
+(1, 209) ~ (4, 211) => 0.997871
+(1, 210) ~ (4, 212) => 0.984271
+(1, 210) ~ (4, 214) => 0.0113453
+(1, 211) ~ (4, 213) => 0.952313
+(1, 211) ~ (4, 215) => 0.0355963
+(1, 212) ~ (4, 214) => 0.920626
+(1, 212) ~ (4, 216) => 0.0605931
+(1, 213) ~ (4, 215) => 0.866341
+(1, 213) ~ (4, 217) => 0.10942
+(1, 214) ~ (4, 216) => 0.829978
+(1, 214) ~ (4, 218) => 0.146675
+(1, 215) ~ (4, 217) => 0.795447
+(1, 215) ~ (4, 219) => 0.184237
+(1, 216) ~ (4, 218) => 0.659993
+(1, 216) ~ (4, 220) => 0.313407
+(1, 216) ~ (4, 221) => 0.0186496
+(1, 217) ~ (4, 219) => 0.613031
+(1, 217) ~ (4, 221) => 0.353923
+(1, 217) ~ (4, 222) => 0.0241244
+(1, 218) ~ (4, 220) => 0.146149
+(1, 218) ~ (4, 222) => 0.816324
+(1, 218) ~ (4, 223) => 0.0208099
+(1, 219) ~ (4, 221) => 0.0285838
+(1, 219) ~ (4, 223) => 0.939567
+(1, 219) ~ (4, 224) => 0.0122971
+(1, 220) ~ (4, 222) => 0.0149912
+(1, 220) ~ (4, 224) => 0.966694
+(1, 221) ~ (4, 225) => 0.99623
+(1, 222) ~ (4, 226) => 0.999296
+(1, 223) ~ (4, 227) => 0.999893
+(1, 224) ~ (4, 228) => 0.999964
+(1, 225) ~ (4, 229) => 0.999972
+(1, 226) ~ (4, 230) => 0.999717
+(1, 227) ~ (4, 231) => 0.998467
+(1, 228) ~ (4, 232) => 0.998261
+(1, 229) ~ (4, 233) => 0.995957
+(1, 230) ~ (4, 234) => 0.994618
+(1, 231) ~ (4, 235) => 0.993542
+(1, 232) ~ (4, 236) => 0.994169
+(1, 233) ~ (4, 237) => 0.995455
+
+; gap posteriors
+(1, 0) ~ (4, -1) => 0.00505596
+(1, 1) ~ (4, -1) => 0.0082289
+(1, 2) ~ (4, -1) => 0.0112702
+(1, 3) ~ (4, -1) => 0.0109421
+(1, 4) ~ (4, -1) => 0.0122889
+(1, 5) ~ (4, -1) => 0.0112699
+(1, 6) ~ (4, -1) => 0.013124
+(1, 7) ~ (4, -1) => 0.0047228
+(1, 8) ~ (4, -1) => 0.00472772
+(1, 9) ~ (4, -1) => 0.00547948
+(1, 10) ~ (4, -1) => 0.00813046
+(1, 11) ~ (4, -1) => 0.0182358
+(1, 12) ~ (4, -1) => 0.0205531
+(1, 13) ~ (4, -1) => 0.0122073
+(1, 14) ~ (4, -1) => 0.0168737
+(1, 15) ~ (4, -1) => 0.0311842
+(1, 16) ~ (4, -1) => 0.0312586
+(1, 17) ~ (4, -1) => 0.0281737
+(1, 18) ~ (4, -1) => 0.0227236
+(1, 19) ~ (4, -1) => 0.016921
+(1, 20) ~ (4, -1) => 0.00299442
+(1, 21) ~ (4, -1) => 0.00127733
+(1, 22) ~ (4, -1) => 0.000160456
+(1, 23) ~ (4, -1) => 0.000348747
+(1, 24) ~ (4, -1) => 0.000940979
+(1, 25) ~ (4, -1) => 0.0023731
+(1, 26) ~ (4, -1) => 0.00382298
+(1, 27) ~ (4, -1) => 0.00962013
+(1, 28) ~ (4, -1) => 0.0120308
+(1, 29) ~ (4, -1) => 0.0110959
+(1, 30) ~ (4, -1) => 0.00610745
+(1, 31) ~ (4, -1) => 0.00288498
+(1, 32) ~ (4, -1) => 0.00133806
+(1, 33) ~ (4, -1) => 0.00185341
+(1, 34) ~ (4, -1) => 0.00223428
+(1, 35) ~ (4, -1) => 0.00202477
+(1, 36) ~ (4, -1) => 0.00205302
+(1, 37) ~ (4, -1) => 0.00203729
+(1, 38) ~ (4, -1) => 0.00103605
+(1, 39) ~ (4, -1) => 0.00122696
+(1, 40) ~ (4, -1) => 0.00272393
+(1, 41) ~ (4, -1) => 0.00310528
+(1, 42) ~ (4, -1) => 0.00405145
+(1, 43) ~ (4, -1) => 0.0246195
+(1, 44) ~ (4, -1) => 0.0332953
+(1, 45) ~ (4, -1) => 0.143012
+(1, 46) ~ (4, -1) => 0.158177
+(1, 47) ~ (4, -1) => 0.131536
+(1, 48) ~ (4, -1) => 0.414403
+(1, 49) ~ (4, -1) => 0.672655
+(1, 50) ~ (4, -1) => 0.424835
+(1, 51) ~ (4, -1) => 0.123749
+(1, 52) ~ (4, -1) => 0.0129771
+(1, 53) ~ (4, -1) => 0.00388378
+(1, 54) ~ (4, -1) => 0.000353277
+(1, 55) ~ (4, -1) => 0.000124097
+(1, 56) ~ (4, -1) => 0.000149369
+(1, 57) ~ (4, -1) => 0.000700772
+(1, 58) ~ (4, -1) => 0.00103742
+(1, 59) ~ (4, -1) => 0.00128621
+(1, 60) ~ (4, -1) => 0.000804067
+(1, 61) ~ (4, -1) => 0.000391304
+(1, 62) ~ (4, -1) => 0.000467181
+(1, 63) ~ (4, -1) => 0.000430107
+(1, 64) ~ (4, -1) => 0.000117242
+(1, 65) ~ (4, -1) => 0.000171423
+(1, 66) ~ (4, -1) => 0.000565886
+(1, 67) ~ (4, -1) => 0.000602186
+(1, 68) ~ (4, -1) => 0.000169039
+(1, 69) ~ (4, -1) => 0.000154674
+(1, 70) ~ (4, -1) => 0.000923455
+(1, 71) ~ (4, -1) => 0.00114882
+(1, 72) ~ (4, -1) => 0.000763237
+(1, 73) ~ (4, -1) => 0.00012207
+(1, 74) ~ (4, -1) => 0.0001
+(1, 75) ~ (4, -1) => 0.0001
+(1, 76) ~ (4, -1) => 0.000285804
+(1, 77) ~ (4, -1) => 0.00134259
+(1, 78) ~ (4, -1) => 0.00283498
+(1, 79) ~ (4, -1) => 0.0328649
+(1, 80) ~ (4, -1) => 0.186215
+(1, 81) ~ (4, -1) => 0.229384
+(1, 82) ~ (4, -1) => 0.303848
+(1, 83) ~ (4, -1) => 0.277978
+(1, 84) ~ (4, -1) => 0.293647
+(1, 85) ~ (4, -1) => 0.145235
+(1, 86) ~ (4, -1) => 0.122763
+(1, 87) ~ (4, -1) => 0.125528
+(1, 88) ~ (4, -1) => 0.0954174
+(1, 89) ~ (4, -1) => 0.0823698
+(1, 90) ~ (4, -1) => 0.0743653
+(1, 91) ~ (4, -1) => 0.0955611
+(1, 92) ~ (4, -1) => 0.0876763
+(1, 93) ~ (4, -1) => 0.18503
+(1, 94) ~ (4, -1) => 0.139513
+(1, 95) ~ (4, -1) => 0.129337
+(1, 96) ~ (4, -1) => 0.196606
+(1, 97) ~ (4, -1) => 0.241708
+(1, 98) ~ (4, -1) => 0.248072
+(1, 99) ~ (4, -1) => 0.227298
+(1, 100) ~ (4, -1) => 0.161523
+(1, 101) ~ (4, -1) => 0.107813
+(1, 102) ~ (4, -1) => 0.0537594
+(1, 103) ~ (4, -1) => 0.0442619
+(1, 104) ~ (4, -1) => 0.0196223
+(1, 105) ~ (4, -1) => 0.0109875
+(1, 106) ~ (4, -1) => 0.00531483
+(1, 107) ~ (4, -1) => 0.00023222
+(1, 108) ~ (4, -1) => 0.0001
+(1, 109) ~ (4, -1) => 0.0001
+(1, 110) ~ (4, -1) => 0.0001
+(1, 111) ~ (4, -1) => 0.0001
+(1, 112) ~ (4, -1) => 0.00014323
+(1, 113) ~ (4, -1) => 0.000171304
+(1, 114) ~ (4, -1) => 0.000344515
+(1, 115) ~ (4, -1) => 0.000379741
+(1, 116) ~ (4, -1) => 0.0003438
+(1, 117) ~ (4, -1) => 0.000181675
+(1, 118) ~ (4, -1) => 0.000153899
+(1, 119) ~ (4, -1) => 0.00100213
+(1, 120) ~ (4, -1) => 0.00159895
+(1, 121) ~ (4, -1) => 0.00157166
+(1, 122) ~ (4, -1) => 0.000816047
+(1, 123) ~ (4, -1) => 0.000556588
+(1, 124) ~ (4, -1) => 0.00386232
+(1, 125) ~ (4, -1) => 0.0073477
+(1, 126) ~ (4, -1) => 0.00678247
+(1, 127) ~ (4, -1) => 0.00898993
+(1, 128) ~ (4, -1) => 0.0789605
+(1, 129) ~ (4, -1) => 0.153769
+(1, 130) ~ (4, -1) => 0.217962
+(1, 131) ~ (4, -1) => 0.260093
+(1, 132) ~ (4, -1) => 0.287941
+(1, 133) ~ (4, -1) => 0.248525
+(1, 134) ~ (4, -1) => 0.248442
+(1, 135) ~ (4, -1) => 0.197373
+(1, 136) ~ (4, -1) => 0.0651105
+(1, 137) ~ (4, -1) => 0.102433
+(1, 138) ~ (4, -1) => 0.109181
+(1, 139) ~ (4, -1) => 0.111665
+(1, 140) ~ (4, -1) => 0.0988922
+(1, 141) ~ (4, -1) => 0.0747992
+(1, 142) ~ (4, -1) => 0.0334051
+(1, 143) ~ (4, -1) => 0.00133097
+(1, 144) ~ (4, -1) => 0.00120211
+(1, 145) ~ (4, -1) => 0.000988066
+(1, 146) ~ (4, -1) => 0.000238538
+(1, 147) ~ (4, -1) => 0.0001
+(1, 148) ~ (4, -1) => 0.0001
+(1, 149) ~ (4, -1) => 0.0001
+(1, 150) ~ (4, -1) => 0.000451267
+(1, 151) ~ (4, -1) => 0.000855923
+(1, 152) ~ (4, -1) => 0.000792801
+(1, 153) ~ (4, -1) => 0.000243545
+(1, 154) ~ (4, -1) => 0.0001
+(1, 155) ~ (4, -1) => 0.000248611
+(1, 156) ~ (4, -1) => 0.000314891
+(1, 157) ~ (4, -1) => 0.000566661
+(1, 158) ~ (4, -1) => 0.00260347
+(1, 159) ~ (4, -1) => 0.0043416
+(1, 160) ~ (4, -1) => 0.00495237
+(1, 161) ~ (4, -1) => 0.00547743
+(1, 162) ~ (4, -1) => 0.00509775
+(1, 163) ~ (4, -1) => 0.00510311
+(1, 164) ~ (4, -1) => 0.00558627
+(1, 165) ~ (4, -1) => 0.00408834
+(1, 166) ~ (4, -1) => 0.00298822
+(1, 167) ~ (4, -1) => 0.00259256
+(1, 168) ~ (4, -1) => 0.002437
+(1, 169) ~ (4, -1) => 0.0022735
+(1, 170) ~ (4, -1) => 0.0023067
+(1, 171) ~ (4, -1) => 0.00131947
+(1, 172) ~ (4, -1) => 0.000145912
+(1, 173) ~ (4, -1) => 0.0001
+(1, 174) ~ (4, -1) => 0.0001
+(1, 175) ~ (4, -1) => 0.000614524
+(1, 176) ~ (4, -1) => 0.00084269
+(1, 177) ~ (4, -1) => 0.000758886
+(1, 178) ~ (4, -1) => 0.000611544
+(1, 179) ~ (4, -1) => 0.0001
+(1, 180) ~ (4, -1) => 0.0001
+(1, 181) ~ (4, -1) => 0.0001
+(1, 182) ~ (4, -1) => 0.00077343
+(1, 183) ~ (4, -1) => 0.00145036
+(1, 184) ~ (4, -1) => 0.00084468
+(1, 185) ~ (4, -1) => 0.0015666
+(1, 186) ~ (4, -1) => 0.00486531
+(1, 187) ~ (4, -1) => 0.0022357
+(1, 188) ~ (4, -1) => 0.00457769
+(1, 189) ~ (4, -1) => 0.0124275
+(1, 190) ~ (4, -1) => 0.021239
+(1, 191) ~ (4, -1) => 0.0293408
+(1, 192) ~ (4, -1) => 0.0337133
+(1, 193) ~ (4, -1) => 0.017864
+(1, 194) ~ (4, -1) => 0.0201579
+(1, 195) ~ (4, -1) => 0.0158369
+(1, 196) ~ (4, -1) => 0.0159778
+(1, 197) ~ (4, -1) => 0.0132467
+(1, 198) ~ (4, -1) => 0.010553
+(1, 199) ~ (4, -1) => 0.00841218
+(1, 200) ~ (4, -1) => 0.00780421
+(1, 201) ~ (4, -1) => 0.0081284
+(1, 202) ~ (4, -1) => 0.0061096
+(1, 203) ~ (4, -1) => 0.00329334
+(1, 204) ~ (4, -1) => 0.00105816
+(1, 205) ~ (4, -1) => 0.000249743
+(1, 206) ~ (4, -1) => 0.000492454
+(1, 207) ~ (4, -1) => 0.000807583
+(1, 208) ~ (4, -1) => 0.000791788
+(1, 209) ~ (4, -1) => 0.00212926
+(1, 210) ~ (4, -1) => 0.00438351
+(1, 211) ~ (4, -1) => 0.0120902
+(1, 212) ~ (4, -1) => 0.0187811
+(1, 213) ~ (4, -1) => 0.0242385
+(1, 214) ~ (4, -1) => 0.0233469
+(1, 215) ~ (4, -1) => 0.0203169
+(1, 216) ~ (4, -1) => 0.00795005
+(1, 217) ~ (4, -1) => 0.00892122
+(1, 218) ~ (4, -1) => 0.0167171
+(1, 219) ~ (4, -1) => 0.0195522
+(1, 220) ~ (4, -1) => 0.0183151
+(1, 221) ~ (4, -1) => 0.00376999
+(1, 222) ~ (4, -1) => 0.000703633
+(1, 223) ~ (4, -1) => 0.000107408
+(1, 224) ~ (4, -1) => 0.0001
+(1, 225) ~ (4, -1) => 0.0001
+(1, 226) ~ (4, -1) => 0.000282764
+(1, 227) ~ (4, -1) => 0.00153261
+(1, 228) ~ (4, -1) => 0.00173867
+(1, 229) ~ (4, -1) => 0.00404304
+(1, 230) ~ (4, -1) => 0.00538242
+(1, 231) ~ (4, -1) => 0.00645834
+(1, 232) ~ (4, -1) => 0.00583088
+(1, 233) ~ (4, -1) => 0.00454479
+
+(1, -1) ~ (4, 0) => 0.00505596
+(1, -1) ~ (4, 1) => 0.0082289
+(1, -1) ~ (4, 2) => 0.0112702
+(1, -1) ~ (4, 3) => 0.0109421
+(1, -1) ~ (4, 4) => 0.0122889
+(1, -1) ~ (4, 5) => 0.0112699
+(1, -1) ~ (4, 6) => 0.013124
+(1, -1) ~ (4, 7) => 0.0959309
+(1, -1) ~ (4, 8) => 0.305269
+(1, -1) ~ (4, 9) => 0.223186
+(1, -1) ~ (4, 10) => 0.0306985
+(1, -1) ~ (4, 11) => 0.0280448
+(1, -1) ~ (4, 12) => 0.0290524
+(1, -1) ~ (4, 13) => 0.0551672
+(1, -1) ~ (4, 14) => 0.110738
+(1, -1) ~ (4, 15) => 0.117898
+(1, -1) ~ (4, 16) => 0.121754
+(1, -1) ~ (4, 17) => 0.120434
+(1, -1) ~ (4, 18) => 0.194424
+(1, -1) ~ (4, 19) => 0.221028
+(1, -1) ~ (4, 20) => 0.322481
+(1, -1) ~ (4, 21) => 0.229899
+(1, -1) ~ (4, 22) => 0.0181814
+(1, -1) ~ (4, 23) => 0.00127733
+(1, -1) ~ (4, 24) => 0.000160456
+(1, -1) ~ (4, 25) => 0.000348747
+(1, -1) ~ (4, 26) => 0.000940979
+(1, -1) ~ (4, 27) => 0.0023731
+(1, -1) ~ (4, 28) => 0.00382298
+(1, -1) ~ (4, 29) => 0.00962013
+(1, -1) ~ (4, 30) => 0.0120308
+(1, -1) ~ (4, 31) => 0.0110959
+(1, -1) ~ (4, 32) => 0.00610745
+(1, -1) ~ (4, 33) => 0.00288498
+(1, -1) ~ (4, 34) => 0.00133806
+(1, -1) ~ (4, 35) => 0.00185341
+(1, -1) ~ (4, 36) => 0.00223428
+(1, -1) ~ (4, 37) => 0.00202477
+(1, -1) ~ (4, 38) => 0.00205302
+(1, -1) ~ (4, 39) => 0.00203729
+(1, -1) ~ (4, 40) => 0.00103605
+(1, -1) ~ (4, 41) => 0.00122696
+(1, -1) ~ (4, 42) => 0.00272393
+(1, -1) ~ (4, 43) => 0.00310528
+(1, -1) ~ (4, 44) => 0.00405145
+(1, -1) ~ (4, 45) => 0.0139027
+(1, -1) ~ (4, 46) => 0.0180301
+(1, -1) ~ (4, 47) => 0.0186207
+(1, -1) ~ (4, 48) => 0.0212045
+(1, -1) ~ (4, 49) => 0.0208905
+(1, -1) ~ (4, 50) => 0.0197368
+(1, -1) ~ (4, 51) => 0.0138966
+(1, -1) ~ (4, 52) => 0.0129771
+(1, -1) ~ (4, 53) => 0.00388378
+(1, -1) ~ (4, 54) => 0.000353277
+(1, -1) ~ (4, 55) => 0.000124097
+(1, -1) ~ (4, 56) => 0.000149369
+(1, -1) ~ (4, 57) => 0.000700772
+(1, -1) ~ (4, 58) => 0.00103742
+(1, -1) ~ (4, 59) => 0.00128621
+(1, -1) ~ (4, 60) => 0.000804067
+(1, -1) ~ (4, 61) => 0.000391304
+(1, -1) ~ (4, 62) => 0.000467181
+(1, -1) ~ (4, 63) => 0.000430107
+(1, -1) ~ (4, 64) => 0.000117242
+(1, -1) ~ (4, 65) => 0.000171423
+(1, -1) ~ (4, 66) => 0.000565886
+(1, -1) ~ (4, 67) => 0.000602186
+(1, -1) ~ (4, 68) => 0.000169039
+(1, -1) ~ (4, 69) => 0.000154674
+(1, -1) ~ (4, 70) => 0.000923455
+(1, -1) ~ (4, 71) => 0.00114882
+(1, -1) ~ (4, 72) => 0.000763237
+(1, -1) ~ (4, 73) => 0.00012207
+(1, -1) ~ (4, 74) => 0.0001
+(1, -1) ~ (4, 75) => 0.0001
+(1, -1) ~ (4, 76) => 0.000285804
+(1, -1) ~ (4, 77) => 0.00134259
+(1, -1) ~ (4, 78) => 0.00283498
+(1, -1) ~ (4, 79) => 0.0328649
+(1, -1) ~ (4, 80) => 0.0870527
+(1, -1) ~ (4, 81) => 0.153046
+(1, -1) ~ (4, 82) => 0.21557
+(1, -1) ~ (4, 83) => 0.239327
+(1, -1) ~ (4, 84) => 0.231433
+(1, -1) ~ (4, 85) => 0.240573
+(1, -1) ~ (4, 86) => 0.220093
+(1, -1) ~ (4, 87) => 0.160031
+(1, -1) ~ (4, 88) => 0.158313
+(1, -1) ~ (4, 89) => 0.159668
+(1, -1) ~ (4, 90) => 0.195858
+(1, -1) ~ (4, 91) => 0.197503
+(1, -1) ~ (4, 92) => 0.370134
+(1, -1) ~ (4, 93) => 0.520072
+(1, -1) ~ (4, 94) => 0.570306
+(1, -1) ~ (4, 95) => 0.524728
+(1, -1) ~ (4, 96) => 0.251443
+(1, -1) ~ (4, 97) => 0.180663
+(1, -1) ~ (4, 98) => 0.179368
+(1, -1) ~ (4, 99) => 0.191051
+(1, -1) ~ (4, 100) => 0.163131
+(1, -1) ~ (4, 101) => 0.142273
+(1, -1) ~ (4, 102) => 0.166624
+(1, -1) ~ (4, 103) => 0.128214
+(1, -1) ~ (4, 104) => 0.118393
+(1, -1) ~ (4, 105) => 0.0900389
+(1, -1) ~ (4, 106) => 0.0196223
+(1, -1) ~ (4, 107) => 0.0109875
+(1, -1) ~ (4, 108) => 0.00531483
+(1, -1) ~ (4, 109) => 0.00023222
+(1, -1) ~ (4, 110) => 0.0001
+(1, -1) ~ (4, 111) => 0.0001
+(1, -1) ~ (4, 112) => 0.0001
+(1, -1) ~ (4, 113) => 0.0001
+(1, -1) ~ (4, 114) => 0.00014323
+(1, -1) ~ (4, 115) => 0.000171304
+(1, -1) ~ (4, 116) => 0.000344515
+(1, -1) ~ (4, 117) => 0.000379741
+(1, -1) ~ (4, 118) => 0.0003438
+(1, -1) ~ (4, 119) => 0.000181675
+(1, -1) ~ (4, 120) => 0.000153899
+(1, -1) ~ (4, 121) => 0.00100213
+(1, -1) ~ (4, 122) => 0.00159895
+(1, -1) ~ (4, 123) => 0.00157166
+(1, -1) ~ (4, 124) => 0.000816047
+(1, -1) ~ (4, 125) => 0.000556588
+(1, -1) ~ (4, 126) => 0.00386232
+(1, -1) ~ (4, 127) => 0.0073477
+(1, -1) ~ (4, 128) => 0.00678247
+(1, -1) ~ (4, 129) => 0.00898993
+(1, -1) ~ (4, 130) => 0.0383348
+(1, -1) ~ (4, 131) => 0.0587833
+(1, -1) ~ (4, 132) => 0.0725711
+(1, -1) ~ (4, 133) => 0.153042
+(1, -1) ~ (4, 134) => 0.134649
+(1, -1) ~ (4, 135) => 0.126863
+(1, -1) ~ (4, 136) => 0.171733
+(1, -1) ~ (4, 137) => 0.0880252
+(1, -1) ~ (4, 138) => 0.10053
+(1, -1) ~ (4, 139) => 0.141013
+(1, -1) ~ (4, 140) => 0.120314
+(1, -1) ~ (4, 141) => 0.047197
+(1, -1) ~ (4, 142) => 0.0236121
+(1, -1) ~ (4, 143) => 0.011885
+(1, -1) ~ (4, 144) => 0.00133097
+(1, -1) ~ (4, 145) => 0.00120211
+(1, -1) ~ (4, 146) => 0.000988066
+(1, -1) ~ (4, 147) => 0.000238538
+(1, -1) ~ (4, 148) => 0.0001
+(1, -1) ~ (4, 149) => 0.0001
+(1, -1) ~ (4, 150) => 0.0001
+(1, -1) ~ (4, 151) => 0.000451267
+(1, -1) ~ (4, 152) => 0.000855923
+(1, -1) ~ (4, 153) => 0.000792801
+(1, -1) ~ (4, 154) => 0.000243545
+(1, -1) ~ (4, 155) => 0.0001
+(1, -1) ~ (4, 156) => 0.000248611
+(1, -1) ~ (4, 157) => 0.000314891
+(1, -1) ~ (4, 158) => 0.000566661
+(1, -1) ~ (4, 159) => 0.00260347
+(1, -1) ~ (4, 160) => 0.0043416
+(1, -1) ~ (4, 161) => 0.00495237
+(1, -1) ~ (4, 162) => 0.00547743
+(1, -1) ~ (4, 163) => 0.00509775
+(1, -1) ~ (4, 164) => 0.00510311
+(1, -1) ~ (4, 165) => 0.00558627
+(1, -1) ~ (4, 166) => 0.00408834
+(1, -1) ~ (4, 167) => 0.00298822
+(1, -1) ~ (4, 168) => 0.00259256
+(1, -1) ~ (4, 169) => 0.002437
+(1, -1) ~ (4, 170) => 0.0022735
+(1, -1) ~ (4, 171) => 0.0023067
+(1, -1) ~ (4, 172) => 0.00131947
+(1, -1) ~ (4, 173) => 0.000145912
+(1, -1) ~ (4, 174) => 0.0001
+(1, -1) ~ (4, 175) => 0.0001
+(1, -1) ~ (4, 176) => 0.000614524
+(1, -1) ~ (4, 177) => 0.00084269
+(1, -1) ~ (4, 178) => 0.000758886
+(1, -1) ~ (4, 179) => 0.000611544
+(1, -1) ~ (4, 180) => 0.0001
+(1, -1) ~ (4, 181) => 0.0001
+(1, -1) ~ (4, 182) => 0.0001
+(1, -1) ~ (4, 183) => 0.00077343
+(1, -1) ~ (4, 184) => 0.00145036
+(1, -1) ~ (4, 185) => 0.032833
+(1, -1) ~ (4, 186) => 0.0321116
+(1, -1) ~ (4, 187) => 0.0352863
+(1, -1) ~ (4, 188) => 0.124239
+(1, -1) ~ (4, 189) => 0.145416
+(1, -1) ~ (4, 190) => 0.11889
+(1, -1) ~ (4, 191) => 0.0771186
+(1, -1) ~ (4, 192) => 0.0729445
+(1, -1) ~ (4, 193) => 0.441735
+(1, -1) ~ (4, 194) => 0.0188042
+(1, -1) ~ (4, 195) => 0.0292963
+(1, -1) ~ (4, 196) => 0.0201579
+(1, -1) ~ (4, 197) => 0.0158369
+(1, -1) ~ (4, 198) => 0.0159778
+(1, -1) ~ (4, 199) => 0.0132467
+(1, -1) ~ (4, 200) => 0.010553
+(1, -1) ~ (4, 201) => 0.00841218
+(1, -1) ~ (4, 202) => 0.00780421
+(1, -1) ~ (4, 203) => 0.0081284
+(1, -1) ~ (4, 204) => 0.0061096
+(1, -1) ~ (4, 205) => 0.00329334
+(1, -1) ~ (4, 206) => 0.00105816
+(1, -1) ~ (4, 207) => 0.000249743
+(1, -1) ~ (4, 208) => 0.000492454
+(1, -1) ~ (4, 209) => 0.000807583
+(1, -1) ~ (4, 210) => 0.000791788
+(1, -1) ~ (4, 211) => 0.00212926
+(1, -1) ~ (4, 212) => 0.0157288
+(1, -1) ~ (4, 213) => 0.0476865
+(1, -1) ~ (4, 214) => 0.0680289
+(1, -1) ~ (4, 215) => 0.0980626
+(1, -1) ~ (4, 216) => 0.109429
+(1, -1) ~ (4, 217) => 0.0951331
+(1, -1) ~ (4, 218) => 0.193332
+(1, -1) ~ (4, 219) => 0.202732
+(1, -1) ~ (4, 220) => 0.540444
+(1, -1) ~ (4, 221) => 0.598844
+(1, -1) ~ (4, 222) => 0.14456
+(1, -1) ~ (4, 223) => 0.0396232
+(1, -1) ~ (4, 224) => 0.0210092
+(1, -1) ~ (4, 225) => 0.00376999
+(1, -1) ~ (4, 226) => 0.000703633
+(1, -1) ~ (4, 227) => 0.000107408
+(1, -1) ~ (4, 228) => 0.0001
+(1, -1) ~ (4, 229) => 0.0001
+(1, -1) ~ (4, 230) => 0.000282764
+(1, -1) ~ (4, 231) => 0.00153261
+(1, -1) ~ (4, 232) => 0.00173867
+(1, -1) ~ (4, 233) => 0.00404304
+(1, -1) ~ (4, 234) => 0.00538242
+(1, -1) ~ (4, 235) => 0.00645834
+(1, -1) ~ (4, 236) => 0.00583088
+(1, -1) ~ (4, 237) => 0.00454479
+
+; Sparse posterior probability matrix for sequences 1 and 5
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (5, 0) => 0.958042
+(1, 0) ~ (5, 1) => 0.0173021
+(1, 1) ~ (5, 0) => 0.0203377
+(1, 1) ~ (5, 1) => 0.930597
+(1, 1) ~ (5, 2) => 0.0295409
+(1, 2) ~ (5, 1) => 0.0326152
+(1, 2) ~ (5, 2) => 0.892226
+(1, 2) ~ (5, 3) => 0.0548518
+(1, 3) ~ (5, 2) => 0.0412895
+(1, 3) ~ (5, 3) => 0.866271
+(1, 3) ~ (5, 4) => 0.0694495
+(1, 4) ~ (5, 3) => 0.0509149
+(1, 4) ~ (5, 4) => 0.82409
+(1, 4) ~ (5, 5) => 0.100239
+(1, 5) ~ (5, 4) => 0.0616242
+(1, 5) ~ (5, 5) => 0.658293
+(1, 5) ~ (5, 6) => 0.208087
+(1, 6) ~ (5, 5) => 0.12117
+(1, 6) ~ (5, 6) => 0.0636501
+(1, 6) ~ (5, 7) => 0.647546
+(1, 7) ~ (5, 6) => 0.285665
+(1, 7) ~ (5, 8) => 0.665554
+(1, 8) ~ (5, 7) => 0.325503
+(1, 8) ~ (5, 9) => 0.664932
+(1, 9) ~ (5, 8) => 0.325003
+(1, 9) ~ (5, 10) => 0.66719
+(1, 10) ~ (5, 9) => 0.320155
+(1, 10) ~ (5, 11) => 0.673119
+(1, 11) ~ (5, 10) => 0.308026
+(1, 11) ~ (5, 12) => 0.671974
+(1, 12) ~ (5, 11) => 0.291398
+(1, 12) ~ (5, 12) => 0.0128356
+(1, 12) ~ (5, 13) => 0.667022
+(1, 12) ~ (5, 14) => 0.0138242
+(1, 13) ~ (5, 12) => 0.245891
+(1, 13) ~ (5, 13) => 0.0276437
+(1, 13) ~ (5, 14) => 0.678459
+(1, 13) ~ (5, 15) => 0.0209167
+(1, 14) ~ (5, 12) => 0.0187756
+(1, 14) ~ (5, 13) => 0.211915
+(1, 14) ~ (5, 14) => 0.0420879
+(1, 14) ~ (5, 15) => 0.691725
+(1, 14) ~ (5, 16) => 0.0245672
+(1, 15) ~ (5, 13) => 0.0123515
+(1, 15) ~ (5, 14) => 0.174471
+(1, 15) ~ (5, 15) => 0.0710718
+(1, 15) ~ (5, 16) => 0.70819
+(1, 16) ~ (5, 15) => 0.147012
+(1, 16) ~ (5, 16) => 0.0875313
+(1, 16) ~ (5, 17) => 0.743498
+(1, 17) ~ (5, 16) => 0.128166
+(1, 17) ~ (5, 17) => 0.0487452
+(1, 17) ~ (5, 18) => 0.808772
+(1, 18) ~ (5, 17) => 0.0914237
+(1, 18) ~ (5, 18) => 0.013469
+(1, 18) ~ (5, 19) => 0.889166
+(1, 19) ~ (5, 18) => 0.0201669
+(1, 19) ~ (5, 20) => 0.968641
+(1, 20) ~ (5, 21) => 0.996883
+(1, 21) ~ (5, 22) => 0.999786
+(1, 22) ~ (5, 23) => 0.999967
+(1, 23) ~ (5, 24) => 0.999774
+(1, 24) ~ (5, 25) => 0.998439
+(1, 25) ~ (5, 26) => 0.997551
+(1, 26) ~ (5, 27) => 0.997625
+(1, 27) ~ (5, 28) => 0.999211
+(1, 28) ~ (5, 29) => 0.999313
+(1, 29) ~ (5, 30) => 0.999367
+(1, 30) ~ (5, 31) => 0.999746
+(1, 31) ~ (5, 32) => 0.999852
+(1, 32) ~ (5, 33) => 0.999407
+(1, 33) ~ (5, 34) => 0.999112
+(1, 34) ~ (5, 35) => 0.998312
+(1, 35) ~ (5, 36) => 0.997356
+(1, 36) ~ (5, 37) => 0.988463
+(1, 36) ~ (5, 38) => 0.0103803
+(1, 37) ~ (5, 38) => 0.985966
+(1, 37) ~ (5, 39) => 0.0113672
+(1, 38) ~ (5, 39) => 0.985408
+(1, 39) ~ (5, 40) => 0.988553
+(1, 40) ~ (5, 41) => 0.989917
+(1, 41) ~ (5, 42) => 0.990312
+(1, 42) ~ (5, 43) => 0.991787
+(1, 43) ~ (5, 44) => 0.97602
+(1, 44) ~ (5, 44) => 0.0125915
+(1, 44) ~ (5, 45) => 0.959794
+(1, 45) ~ (5, 45) => 0.0224818
+(1, 45) ~ (5, 46) => 0.715167
+(1, 45) ~ (5, 48) => 0.0363064
+(1, 46) ~ (5, 46) => 0.189516
+(1, 46) ~ (5, 47) => 0.658868
+(1, 46) ~ (5, 49) => 0.0393317
+(1, 47) ~ (5, 46) => 0.0489734
+(1, 47) ~ (5, 47) => 0.204782
+(1, 47) ~ (5, 48) => 0.585399
+(1, 47) ~ (5, 50) => 0.0444322
+(1, 48) ~ (5, 47) => 0.0804177
+(1, 48) ~ (5, 48) => 0.225806
+(1, 48) ~ (5, 49) => 0.449177
+(1, 48) ~ (5, 51) => 0.0492481
+(1, 49) ~ (5, 48) => 0.121019
+(1, 49) ~ (5, 49) => 0.231869
+(1, 49) ~ (5, 50) => 0.121791
+(1, 49) ~ (5, 52) => 0.046658
+(1, 50) ~ (5, 49) => 0.243087
+(1, 50) ~ (5, 50) => 0.191289
+(1, 50) ~ (5, 51) => 0.0247119
+(1, 51) ~ (5, 50) => 0.618028
+(1, 51) ~ (5, 51) => 0.132888
+(1, 52) ~ (5, 51) => 0.781381
+(1, 53) ~ (5, 52) => 0.940546
+(1, 54) ~ (5, 53) => 0.994694
+(1, 55) ~ (5, 54) => 0.998765
+(1, 56) ~ (5, 55) => 0.999428
+(1, 57) ~ (5, 56) => 0.999701
+(1, 58) ~ (5, 57) => 0.998816
+(1, 59) ~ (5, 58) => 0.979491
+(1, 60) ~ (5, 58) => 0.0201474
+(1, 60) ~ (5, 59) => 0.947816
+(1, 61) ~ (5, 59) => 0.0514377
+(1, 61) ~ (5, 60) => 0.690977
+(1, 62) ~ (5, 60) => 0.307028
+(1, 62) ~ (5, 61) => 0.435119
+(1, 63) ~ (5, 61) => 0.562645
+(1, 63) ~ (5, 62) => 0.177971
+(1, 64) ~ (5, 62) => 0.81879
+(1, 64) ~ (5, 63) => 0.0566139
+(1, 65) ~ (5, 63) => 0.939508
+(1, 65) ~ (5, 64) => 0.0107864
+(1, 66) ~ (5, 64) => 0.98594
+(1, 67) ~ (5, 65) => 0.990578
+(1, 68) ~ (5, 66) => 0.998754
+(1, 69) ~ (5, 67) => 0.999692
+(1, 70) ~ (5, 68) => 0.999752
+(1, 71) ~ (5, 69) => 0.999767
+(1, 72) ~ (5, 70) => 0.999833
+(1, 73) ~ (5, 71) => 0.999972
+(1, 74) ~ (5, 72) => 0.999976
+(1, 75) ~ (5, 73) => 0.99997
+(1, 76) ~ (5, 74) => 0.999897
+(1, 77) ~ (5, 75) => 0.999775
+(1, 78) ~ (5, 76) => 0.999196
+(1, 79) ~ (5, 77) => 0.97164
+(1, 79) ~ (5, 78) => 0.0264883
+(1, 80) ~ (5, 78) => 0.965948
+(1, 80) ~ (5, 79) => 0.0290874
+(1, 81) ~ (5, 79) => 0.967097
+(1, 81) ~ (5, 80) => 0.0210659
+(1, 82) ~ (5, 80) => 0.975915
+(1, 82) ~ (5, 81) => 0.0191911
+(1, 83) ~ (5, 81) => 0.975907
+(1, 83) ~ (5, 82) => 0.0194006
+(1, 84) ~ (5, 82) => 0.970947
+(1, 84) ~ (5, 83) => 0.024186
+(1, 85) ~ (5, 83) => 0.972037
+(1, 86) ~ (5, 84) => 0.986879
+(1, 87) ~ (5, 85) => 0.992556
+(1, 88) ~ (5, 86) => 0.995864
+(1, 89) ~ (5, 87) => 0.99739
+(1, 90) ~ (5, 88) => 0.999259
+(1, 91) ~ (5, 89) => 0.999094
+(1, 92) ~ (5, 90) => 0.999338
+(1, 93) ~ (5, 91) => 0.998167
+(1, 94) ~ (5, 92) => 0.997555
+(1, 95) ~ (5, 93) => 0.998064
+(1, 96) ~ (5, 94) => 0.998761
+(1, 97) ~ (5, 95) => 0.998846
+(1, 98) ~ (5, 96) => 0.996986
+(1, 99) ~ (5, 97) => 0.995943
+(1, 100) ~ (5, 98) => 0.99505
+(1, 101) ~ (5, 99) => 0.994027
+(1, 102) ~ (5, 100) => 0.995214
+(1, 103) ~ (5, 101) => 0.998756
+(1, 104) ~ (5, 102) => 0.999094
+(1, 105) ~ (5, 103) => 0.999437
+(1, 106) ~ (5, 104) => 0.999795
+(1, 107) ~ (5, 105) => 0.999987
+(1, 108) ~ (5, 106) => 0.99999
+(1, 109) ~ (5, 107) => 0.99999
+(1, 110) ~ (5, 108) => 0.99999
+(1, 111) ~ (5, 109) => 0.999943
+(1, 112) ~ (5, 110) => 0.999904
+(1, 113) ~ (5, 111) => 0.999923
+(1, 114) ~ (5, 112) => 0.999966
+(1, 115) ~ (5, 113) => 0.999986
+(1, 116) ~ (5, 114) => 0.999985
+(1, 117) ~ (5, 115) => 0.999771
+(1, 118) ~ (5, 116) => 0.998157
+(1, 119) ~ (5, 117) => 0.996866
+(1, 120) ~ (5, 118) => 0.992417
+(1, 121) ~ (5, 119) => 0.992282
+(1, 122) ~ (5, 120) => 0.996178
+(1, 123) ~ (5, 121) => 0.993222
+(1, 124) ~ (5, 122) => 0.98925
+(1, 125) ~ (5, 123) => 0.989601
+(1, 126) ~ (5, 124) => 0.997311
+(1, 127) ~ (5, 125) => 0.999575
+(1, 128) ~ (5, 126) => 0.9991
+(1, 129) ~ (5, 127) => 0.997582
+(1, 130) ~ (5, 128) => 0.996202
+(1, 131) ~ (5, 129) => 0.996515
+(1, 132) ~ (5, 130) => 0.999657
+(1, 133) ~ (5, 131) => 0.999754
+(1, 134) ~ (5, 132) => 0.999593
+(1, 135) ~ (5, 133) => 0.999617
+(1, 136) ~ (5, 134) => 0.999762
+(1, 137) ~ (5, 135) => 0.999921
+(1, 138) ~ (5, 136) => 0.999472
+(1, 139) ~ (5, 137) => 0.999391
+(1, 140) ~ (5, 138) => 0.99969
+(1, 141) ~ (5, 139) => 0.999991
+(1, 142) ~ (5, 140) => 0.999998
+(1, 143) ~ (5, 141) => 0.999996
+(1, 144) ~ (5, 142) => 0.999978
+(1, 145) ~ (5, 143) => 0.999968
+(1, 146) ~ (5, 144) => 0.999979
+(1, 147) ~ (5, 145) => 0.999996
+(1, 148) ~ (5, 146) => 0.999996
+(1, 149) ~ (5, 147) => 0.999986
+(1, 150) ~ (5, 148) => 0.999863
+(1, 151) ~ (5, 149) => 0.999842
+(1, 152) ~ (5, 150) => 0.999961
+(1, 153) ~ (5, 151) => 0.999981
+(1, 154) ~ (5, 152) => 0.999971
+(1, 155) ~ (5, 153) => 0.999893
+(1, 156) ~ (5, 154) => 0.999875
+(1, 157) ~ (5, 155) => 0.999816
+(1, 158) ~ (5, 156) => 0.999655
+(1, 159) ~ (5, 157) => 0.997794
+(1, 160) ~ (5, 158) => 0.996845
+(1, 161) ~ (5, 159) => 0.996285
+(1, 162) ~ (5, 160) => 0.995755
+(1, 163) ~ (5, 161) => 0.99637
+(1, 164) ~ (5, 162) => 0.99899
+(1, 165) ~ (5, 163) => 0.999417
+(1, 166) ~ (5, 164) => 0.999807
+(1, 167) ~ (5, 165) => 0.999503
+(1, 168) ~ (5, 166) => 0.999254
+(1, 169) ~ (5, 167) => 0.998386
+(1, 170) ~ (5, 168) => 0.996336
+(1, 171) ~ (5, 169) => 0.996611
+(1, 172) ~ (5, 170) => 0.999602
+(1, 173) ~ (5, 171) => 0.999838
+(1, 174) ~ (5, 172) => 0.999419
+(1, 175) ~ (5, 173) => 0.996827
+(1, 176) ~ (5, 174) => 0.994525
+(1, 177) ~ (5, 175) => 0.994355
+(1, 178) ~ (5, 176) => 0.994905
+(1, 179) ~ (5, 177) => 0.997391
+(1, 180) ~ (5, 178) => 0.999801
+(1, 181) ~ (5, 179) => 0.999954
+(1, 182) ~ (5, 180) => 0.999046
+(1, 183) ~ (5, 181) => 0.998157
+(1, 184) ~ (5, 182) => 0.956869
+(1, 184) ~ (5, 183) => 0.042778
+(1, 185) ~ (5, 183) => 0.915677
+(1, 185) ~ (5, 184) => 0.0837163
+(1, 186) ~ (5, 184) => 0.874434
+(1, 186) ~ (5, 185) => 0.124662
+(1, 187) ~ (5, 185) => 0.728442
+(1, 187) ~ (5, 186) => 0.269972
+(1, 188) ~ (5, 186) => 0.581247
+(1, 188) ~ (5, 187) => 0.415024
+(1, 189) ~ (5, 187) => 0.542439
+(1, 189) ~ (5, 188) => 0.4511
+(1, 190) ~ (5, 188) => 0.503933
+(1, 190) ~ (5, 189) => 0.487182
+(1, 191) ~ (5, 189) => 0.479292
+(1, 191) ~ (5, 190) => 0.511975
+(1, 192) ~ (5, 190) => 0.478804
+(1, 192) ~ (5, 191) => 0.512168
+(1, 193) ~ (5, 191) => 0.44809
+(1, 193) ~ (5, 192) => 0.540408
+(1, 194) ~ (5, 192) => 0.406227
+(1, 194) ~ (5, 193) => 0.580883
+(1, 195) ~ (5, 193) => 0.389324
+(1, 195) ~ (5, 194) => 0.598717
+(1, 196) ~ (5, 194) => 0.328026
+(1, 196) ~ (5, 195) => 0.660339
+(1, 197) ~ (5, 195) => 0.267357
+(1, 197) ~ (5, 196) => 0.723168
+(1, 198) ~ (5, 196) => 0.107525
+(1, 198) ~ (5, 197) => 0.888106
+(1, 199) ~ (5, 197) => 0.0579782
+(1, 199) ~ (5, 198) => 0.939756
+(1, 200) ~ (5, 199) => 0.98948
+(1, 201) ~ (5, 200) => 0.992391
+(1, 202) ~ (5, 201) => 0.996934
+(1, 203) ~ (5, 202) => 0.998128
+(1, 204) ~ (5, 203) => 0.999156
+(1, 205) ~ (5, 204) => 0.998643
+(1, 206) ~ (5, 205) => 0.998373
+(1, 207) ~ (5, 206) => 0.998729
+(1, 208) ~ (5, 207) => 0.999286
+(1, 209) ~ (5, 208) => 0.995858
+(1, 210) ~ (5, 209) => 0.922396
+(1, 210) ~ (5, 210) => 0.0747813
+(1, 211) ~ (5, 210) => 0.7681
+(1, 211) ~ (5, 211) => 0.228975
+(1, 212) ~ (5, 211) => 0.721845
+(1, 212) ~ (5, 212) => 0.276736
+(1, 213) ~ (5, 212) => 0.716736
+(1, 213) ~ (5, 213) => 0.278487
+(1, 214) ~ (5, 213) => 0.720551
+(1, 214) ~ (5, 214) => 0.253163
+(1, 215) ~ (5, 214) => 0.746043
+(1, 215) ~ (5, 215) => 0.245204
+(1, 216) ~ (5, 215) => 0.749537
+(1, 216) ~ (5, 216) => 0.248929
+(1, 217) ~ (5, 216) => 0.699117
+(1, 217) ~ (5, 217) => 0.29975
+(1, 218) ~ (5, 217) => 0.5008
+(1, 218) ~ (5, 218) => 0.496616
+(1, 219) ~ (5, 218) => 0.46909
+(1, 219) ~ (5, 219) => 0.527782
+(1, 220) ~ (5, 219) => 0.271941
+(1, 220) ~ (5, 220) => 0.724587
+(1, 221) ~ (5, 220) => 0.0223489
+(1, 221) ~ (5, 221) => 0.976191
+(1, 222) ~ (5, 222) => 0.993621
+(1, 223) ~ (5, 223) => 0.999558
+(1, 224) ~ (5, 224) => 0.999913
+(1, 225) ~ (5, 225) => 0.99999
+(1, 226) ~ (5, 226) => 0.999978
+(1, 227) ~ (5, 227) => 0.999898
+(1, 228) ~ (5, 228) => 0.999662
+(1, 229) ~ (5, 229) => 0.997598
+(1, 230) ~ (5, 230) => 0.996004
+(1, 231) ~ (5, 231) => 0.994446
+(1, 232) ~ (5, 232) => 0.993179
+(1, 233) ~ (5, 233) => 0.993937
+
+; gap posteriors
+(1, 0) ~ (5, -1) => 0.0246555
+(1, 1) ~ (5, -1) => 0.0195246
+(1, 2) ~ (5, -1) => 0.0203071
+(1, 3) ~ (5, -1) => 0.0229897
+(1, 4) ~ (5, -1) => 0.0247567
+(1, 5) ~ (5, -1) => 0.0719956
+(1, 6) ~ (5, -1) => 0.167634
+(1, 7) ~ (5, -1) => 0.0487813
+(1, 8) ~ (5, -1) => 0.00956553
+(1, 9) ~ (5, -1) => 0.00780714
+(1, 10) ~ (5, -1) => 0.00672591
+(1, 11) ~ (5, -1) => 0.0199999
+(1, 12) ~ (5, -1) => 0.0149195
+(1, 13) ~ (5, -1) => 0.0270896
+(1, 14) ~ (5, -1) => 0.0109289
+(1, 15) ~ (5, -1) => 0.0339161
+(1, 16) ~ (5, -1) => 0.0219582
+(1, 17) ~ (5, -1) => 0.0143168
+(1, 18) ~ (5, -1) => 0.00594157
+(1, 19) ~ (5, -1) => 0.0111925
+(1, 20) ~ (5, -1) => 0.00311673
+(1, 21) ~ (5, -1) => 0.0002141
+(1, 22) ~ (5, -1) => 0.0001
+(1, 23) ~ (5, -1) => 0.000226319
+(1, 24) ~ (5, -1) => 0.00156051
+(1, 25) ~ (5, -1) => 0.00244898
+(1, 26) ~ (5, -1) => 0.00237465
+(1, 27) ~ (5, -1) => 0.000788629
+(1, 28) ~ (5, -1) => 0.000686765
+(1, 29) ~ (5, -1) => 0.000632882
+(1, 30) ~ (5, -1) => 0.000254035
+(1, 31) ~ (5, -1) => 0.000148296
+(1, 32) ~ (5, -1) => 0.000592768
+(1, 33) ~ (5, -1) => 0.000888169
+(1, 34) ~ (5, -1) => 0.00168848
+(1, 35) ~ (5, -1) => 0.002644
+(1, 36) ~ (5, -1) => 0.00115705
+(1, 37) ~ (5, -1) => 0.00266637
+(1, 38) ~ (5, -1) => 0.0145921
+(1, 39) ~ (5, -1) => 0.0114473
+(1, 40) ~ (5, -1) => 0.0100831
+(1, 41) ~ (5, -1) => 0.00968802
+(1, 42) ~ (5, -1) => 0.00821328
+(1, 43) ~ (5, -1) => 0.0239797
+(1, 44) ~ (5, -1) => 0.0276148
+(1, 45) ~ (5, -1) => 0.226045
+(1, 46) ~ (5, -1) => 0.112284
+(1, 47) ~ (5, -1) => 0.116414
+(1, 48) ~ (5, -1) => 0.195351
+(1, 49) ~ (5, -1) => 0.478663
+(1, 50) ~ (5, -1) => 0.540912
+(1, 51) ~ (5, -1) => 0.249085
+(1, 52) ~ (5, -1) => 0.218619
+(1, 53) ~ (5, -1) => 0.0594541
+(1, 54) ~ (5, -1) => 0.00530553
+(1, 55) ~ (5, -1) => 0.00123483
+(1, 56) ~ (5, -1) => 0.000572443
+(1, 57) ~ (5, -1) => 0.000298858
+(1, 58) ~ (5, -1) => 0.00118405
+(1, 59) ~ (5, -1) => 0.0205086
+(1, 60) ~ (5, -1) => 0.0320362
+(1, 61) ~ (5, -1) => 0.257585
+(1, 62) ~ (5, -1) => 0.257853
+(1, 63) ~ (5, -1) => 0.259384
+(1, 64) ~ (5, -1) => 0.124596
+(1, 65) ~ (5, -1) => 0.0497058
+(1, 66) ~ (5, -1) => 0.0140601
+(1, 67) ~ (5, -1) => 0.009422
+(1, 68) ~ (5, -1) => 0.00124568
+(1, 69) ~ (5, -1) => 0.0003075
+(1, 70) ~ (5, -1) => 0.000247598
+(1, 71) ~ (5, -1) => 0.000232697
+(1, 72) ~ (5, -1) => 0.000167251
+(1, 73) ~ (5, -1) => 0.0001
+(1, 74) ~ (5, -1) => 0.0001
+(1, 75) ~ (5, -1) => 0.0001
+(1, 76) ~ (5, -1) => 0.000103354
+(1, 77) ~ (5, -1) => 0.000225186
+(1, 78) ~ (5, -1) => 0.000804067
+(1, 79) ~ (5, -1) => 0.00187185
+(1, 80) ~ (5, -1) => 0.00496418
+(1, 81) ~ (5, -1) => 0.0118373
+(1, 82) ~ (5, -1) => 0.00489422
+(1, 83) ~ (5, -1) => 0.00469263
+(1, 84) ~ (5, -1) => 0.00486686
+(1, 85) ~ (5, -1) => 0.0279629
+(1, 86) ~ (5, -1) => 0.0131206
+(1, 87) ~ (5, -1) => 0.00744396
+(1, 88) ~ (5, -1) => 0.00413597
+(1, 89) ~ (5, -1) => 0.00261033
+(1, 90) ~ (5, -1) => 0.000740767
+(1, 91) ~ (5, -1) => 0.000906169
+(1, 92) ~ (5, -1) => 0.00066185
+(1, 93) ~ (5, -1) => 0.0018335
+(1, 94) ~ (5, -1) => 0.00244474
+(1, 95) ~ (5, -1) => 0.00193578
+(1, 96) ~ (5, -1) => 0.00123858
+(1, 97) ~ (5, -1) => 0.00115353
+(1, 98) ~ (5, -1) => 0.00301391
+(1, 99) ~ (5, -1) => 0.00405729
+(1, 100) ~ (5, -1) => 0.00494969
+(1, 101) ~ (5, -1) => 0.00597274
+(1, 102) ~ (5, -1) => 0.00478584
+(1, 103) ~ (5, -1) => 0.00124425
+(1, 104) ~ (5, -1) => 0.000905514
+(1, 105) ~ (5, -1) => 0.000563085
+(1, 106) ~ (5, -1) => 0.000204861
+(1, 107) ~ (5, -1) => 0.0001
+(1, 108) ~ (5, -1) => 0.0001
+(1, 109) ~ (5, -1) => 0.0001
+(1, 110) ~ (5, -1) => 0.0001
+(1, 111) ~ (5, -1) => 0.0001
+(1, 112) ~ (5, -1) => 0.0001
+(1, 113) ~ (5, -1) => 0.0001
+(1, 114) ~ (5, -1) => 0.0001
+(1, 115) ~ (5, -1) => 0.0001
+(1, 116) ~ (5, -1) => 0.0001
+(1, 117) ~ (5, -1) => 0.000228763
+(1, 118) ~ (5, -1) => 0.00184309
+(1, 119) ~ (5, -1) => 0.00313443
+(1, 120) ~ (5, -1) => 0.00758314
+(1, 121) ~ (5, -1) => 0.00771832
+(1, 122) ~ (5, -1) => 0.00382239
+(1, 123) ~ (5, -1) => 0.00677836
+(1, 124) ~ (5, -1) => 0.0107498
+(1, 125) ~ (5, -1) => 0.0103994
+(1, 126) ~ (5, -1) => 0.00268865
+(1, 127) ~ (5, -1) => 0.000424504
+(1, 128) ~ (5, -1) => 0.000899613
+(1, 129) ~ (5, -1) => 0.00241792
+(1, 130) ~ (5, -1) => 0.00379843
+(1, 131) ~ (5, -1) => 0.00348544
+(1, 132) ~ (5, -1) => 0.000343263
+(1, 133) ~ (5, -1) => 0.00024575
+(1, 134) ~ (5, -1) => 0.000406921
+(1, 135) ~ (5, -1) => 0.000383019
+(1, 136) ~ (5, -1) => 0.00023824
+(1, 137) ~ (5, -1) => 0.0001
+(1, 138) ~ (5, -1) => 0.000527859
+(1, 139) ~ (5, -1) => 0.000608504
+(1, 140) ~ (5, -1) => 0.000310481
+(1, 141) ~ (5, -1) => 0.0001
+(1, 142) ~ (5, -1) => 0.0001
+(1, 143) ~ (5, -1) => 0.0001
+(1, 144) ~ (5, -1) => 0.0001
+(1, 145) ~ (5, -1) => 0.0001
+(1, 146) ~ (5, -1) => 0.0001
+(1, 147) ~ (5, -1) => 0.0001
+(1, 148) ~ (5, -1) => 0.0001
+(1, 149) ~ (5, -1) => 0.0001
+(1, 150) ~ (5, -1) => 0.00013715
+(1, 151) ~ (5, -1) => 0.000158429
+(1, 152) ~ (5, -1) => 0.0001
+(1, 153) ~ (5, -1) => 0.0001
+(1, 154) ~ (5, -1) => 0.0001
+(1, 155) ~ (5, -1) => 0.000106573
+(1, 156) ~ (5, -1) => 0.000124812
+(1, 157) ~ (5, -1) => 0.000183761
+(1, 158) ~ (5, -1) => 0.000344872
+(1, 159) ~ (5, -1) => 0.00220561
+(1, 160) ~ (5, -1) => 0.00315464
+(1, 161) ~ (5, -1) => 0.0037151
+(1, 162) ~ (5, -1) => 0.0042448
+(1, 163) ~ (5, -1) => 0.00362962
+(1, 164) ~ (5, -1) => 0.0010103
+(1, 165) ~ (5, -1) => 0.000583291
+(1, 166) ~ (5, -1) => 0.000193179
+(1, 167) ~ (5, -1) => 0.000496745
+(1, 168) ~ (5, -1) => 0.000746429
+(1, 169) ~ (5, -1) => 0.00161403
+(1, 170) ~ (5, -1) => 0.00366408
+(1, 171) ~ (5, -1) => 0.003389
+(1, 172) ~ (5, -1) => 0.00039798
+(1, 173) ~ (5, -1) => 0.000162423
+(1, 174) ~ (5, -1) => 0.000581324
+(1, 175) ~ (5, -1) => 0.00317287
+(1, 176) ~ (5, -1) => 0.00547522
+(1, 177) ~ (5, -1) => 0.00564486
+(1, 178) ~ (5, -1) => 0.00509483
+(1, 179) ~ (5, -1) => 0.00260878
+(1, 180) ~ (5, -1) => 0.000199139
+(1, 181) ~ (5, -1) => 0.0001
+(1, 182) ~ (5, -1) => 0.000954449
+(1, 183) ~ (5, -1) => 0.0018428
+(1, 184) ~ (5, -1) => 0.000352729
+(1, 185) ~ (5, -1) => 0.000606671
+(1, 186) ~ (5, -1) => 0.000904649
+(1, 187) ~ (5, -1) => 0.00158632
+(1, 188) ~ (5, -1) => 0.00372937
+(1, 189) ~ (5, -1) => 0.00646076
+(1, 190) ~ (5, -1) => 0.00888517
+(1, 191) ~ (5, -1) => 0.00873297
+(1, 192) ~ (5, -1) => 0.00902838
+(1, 193) ~ (5, -1) => 0.0115016
+(1, 194) ~ (5, -1) => 0.0128899
+(1, 195) ~ (5, -1) => 0.0119585
+(1, 196) ~ (5, -1) => 0.0116351
+(1, 197) ~ (5, -1) => 0.00947458
+(1, 198) ~ (5, -1) => 0.00436807
+(1, 199) ~ (5, -1) => 0.00226557
+(1, 200) ~ (5, -1) => 0.0105197
+(1, 201) ~ (5, -1) => 0.00760943
+(1, 202) ~ (5, -1) => 0.0030663
+(1, 203) ~ (5, -1) => 0.00187194
+(1, 204) ~ (5, -1) => 0.000843763
+(1, 205) ~ (5, -1) => 0.0013566
+(1, 206) ~ (5, -1) => 0.00162685
+(1, 207) ~ (5, -1) => 0.00127143
+(1, 208) ~ (5, -1) => 0.000714242
+(1, 209) ~ (5, -1) => 0.00414246
+(1, 210) ~ (5, -1) => 0.00282282
+(1, 211) ~ (5, -1) => 0.00292493
+(1, 212) ~ (5, -1) => 0.0014188
+(1, 213) ~ (5, -1) => 0.00477701
+(1, 214) ~ (5, -1) => 0.0262863
+(1, 215) ~ (5, -1) => 0.00875352
+(1, 216) ~ (5, -1) => 0.00153376
+(1, 217) ~ (5, -1) => 0.00113368
+(1, 218) ~ (5, -1) => 0.00258407
+(1, 219) ~ (5, -1) => 0.00312769
+(1, 220) ~ (5, -1) => 0.00347155
+(1, 221) ~ (5, -1) => 0.0014599
+(1, 222) ~ (5, -1) => 0.00637895
+(1, 223) ~ (5, -1) => 0.000442386
+(1, 224) ~ (5, -1) => 0.0001
+(1, 225) ~ (5, -1) => 0.0001
+(1, 226) ~ (5, -1) => 0.0001
+(1, 227) ~ (5, -1) => 0.000102162
+(1, 228) ~ (5, -1) => 0.000338435
+(1, 229) ~ (5, -1) => 0.00240248
+(1, 230) ~ (5, -1) => 0.0039956
+(1, 231) ~ (5, -1) => 0.00555378
+(1, 232) ~ (5, -1) => 0.00682056
+(1, 233) ~ (5, -1) => 0.00606287
+
+(1, -1) ~ (5, 0) => 0.0216199
+(1, -1) ~ (5, 1) => 0.0194858
+(1, -1) ~ (5, 2) => 0.0369438
+(1, -1) ~ (5, 3) => 0.027962
+(1, -1) ~ (5, 4) => 0.0448365
+(1, -1) ~ (5, 5) => 0.120298
+(1, -1) ~ (5, 6) => 0.442598
+(1, -1) ~ (5, 7) => 0.0269507
+(1, -1) ~ (5, 8) => 0.00944364
+(1, -1) ~ (5, 9) => 0.0149131
+(1, -1) ~ (5, 10) => 0.0247838
+(1, -1) ~ (5, 11) => 0.035483
+(1, -1) ~ (5, 12) => 0.0505233
+(1, -1) ~ (5, 13) => 0.081067
+(1, -1) ~ (5, 14) => 0.0911587
+(1, -1) ~ (5, 15) => 0.0692741
+(1, -1) ~ (5, 16) => 0.051545
+(1, -1) ~ (5, 17) => 0.116333
+(1, -1) ~ (5, 18) => 0.157592
+(1, -1) ~ (5, 19) => 0.110834
+(1, -1) ~ (5, 20) => 0.0313594
+(1, -1) ~ (5, 21) => 0.00311673
+(1, -1) ~ (5, 22) => 0.0002141
+(1, -1) ~ (5, 23) => 0.0001
+(1, -1) ~ (5, 24) => 0.000226319
+(1, -1) ~ (5, 25) => 0.00156051
+(1, -1) ~ (5, 26) => 0.00244898
+(1, -1) ~ (5, 27) => 0.00237465
+(1, -1) ~ (5, 28) => 0.000788629
+(1, -1) ~ (5, 29) => 0.000686765
+(1, -1) ~ (5, 30) => 0.000632882
+(1, -1) ~ (5, 31) => 0.000254035
+(1, -1) ~ (5, 32) => 0.000148296
+(1, -1) ~ (5, 33) => 0.000592768
+(1, -1) ~ (5, 34) => 0.000888169
+(1, -1) ~ (5, 35) => 0.00168848
+(1, -1) ~ (5, 36) => 0.002644
+(1, -1) ~ (5, 37) => 0.0115374
+(1, -1) ~ (5, 38) => 0.00365329
+(1, -1) ~ (5, 39) => 0.00322485
+(1, -1) ~ (5, 40) => 0.0114473
+(1, -1) ~ (5, 41) => 0.0100831
+(1, -1) ~ (5, 42) => 0.00968802
+(1, -1) ~ (5, 43) => 0.00821328
+(1, -1) ~ (5, 44) => 0.0113882
+(1, -1) ~ (5, 45) => 0.0177245
+(1, -1) ~ (5, 46) => 0.0463437
+(1, -1) ~ (5, 47) => 0.055932
+(1, -1) ~ (5, 48) => 0.0314697
+(1, -1) ~ (5, 49) => 0.036535
+(1, -1) ~ (5, 50) => 0.0244603
+(1, -1) ~ (5, 51) => 0.0117717
+(1, -1) ~ (5, 52) => 0.0127962
+(1, -1) ~ (5, 53) => 0.00530553
+(1, -1) ~ (5, 54) => 0.00123483
+(1, -1) ~ (5, 55) => 0.000572443
+(1, -1) ~ (5, 56) => 0.000298858
+(1, -1) ~ (5, 57) => 0.00118405
+(1, -1) ~ (5, 58) => 0.000361212
+(1, -1) ~ (5, 59) => 0.000745911
+(1, -1) ~ (5, 60) => 0.0019944
+(1, -1) ~ (5, 61) => 0.00223583
+(1, -1) ~ (5, 62) => 0.00323868
+(1, -1) ~ (5, 63) => 0.00387836
+(1, -1) ~ (5, 64) => 0.00327373
+(1, -1) ~ (5, 65) => 0.009422
+(1, -1) ~ (5, 66) => 0.00124568
+(1, -1) ~ (5, 67) => 0.0003075
+(1, -1) ~ (5, 68) => 0.000247598
+(1, -1) ~ (5, 69) => 0.000232697
+(1, -1) ~ (5, 70) => 0.000167251
+(1, -1) ~ (5, 71) => 0.0001
+(1, -1) ~ (5, 72) => 0.0001
+(1, -1) ~ (5, 73) => 0.0001
+(1, -1) ~ (5, 74) => 0.000103354
+(1, -1) ~ (5, 75) => 0.000225186
+(1, -1) ~ (5, 76) => 0.000804067
+(1, -1) ~ (5, 77) => 0.0283601
+(1, -1) ~ (5, 78) => 0.00756329
+(1, -1) ~ (5, 79) => 0.00381583
+(1, -1) ~ (5, 80) => 0.00301933
+(1, -1) ~ (5, 81) => 0.00490212
+(1, -1) ~ (5, 82) => 0.00965226
+(1, -1) ~ (5, 83) => 0.00377685
+(1, -1) ~ (5, 84) => 0.0131206
+(1, -1) ~ (5, 85) => 0.00744396
+(1, -1) ~ (5, 86) => 0.00413597
+(1, -1) ~ (5, 87) => 0.00261033
+(1, -1) ~ (5, 88) => 0.000740767
+(1, -1) ~ (5, 89) => 0.000906169
+(1, -1) ~ (5, 90) => 0.00066185
+(1, -1) ~ (5, 91) => 0.0018335
+(1, -1) ~ (5, 92) => 0.00244474
+(1, -1) ~ (5, 93) => 0.00193578
+(1, -1) ~ (5, 94) => 0.00123858
+(1, -1) ~ (5, 95) => 0.00115353
+(1, -1) ~ (5, 96) => 0.00301391
+(1, -1) ~ (5, 97) => 0.00405729
+(1, -1) ~ (5, 98) => 0.00494969
+(1, -1) ~ (5, 99) => 0.00597274
+(1, -1) ~ (5, 100) => 0.00478584
+(1, -1) ~ (5, 101) => 0.00124425
+(1, -1) ~ (5, 102) => 0.000905514
+(1, -1) ~ (5, 103) => 0.000563085
+(1, -1) ~ (5, 104) => 0.000204861
+(1, -1) ~ (5, 105) => 0.0001
+(1, -1) ~ (5, 106) => 0.0001
+(1, -1) ~ (5, 107) => 0.0001
+(1, -1) ~ (5, 108) => 0.0001
+(1, -1) ~ (5, 109) => 0.0001
+(1, -1) ~ (5, 110) => 0.0001
+(1, -1) ~ (5, 111) => 0.0001
+(1, -1) ~ (5, 112) => 0.0001
+(1, -1) ~ (5, 113) => 0.0001
+(1, -1) ~ (5, 114) => 0.0001
+(1, -1) ~ (5, 115) => 0.000228763
+(1, -1) ~ (5, 116) => 0.00184309
+(1, -1) ~ (5, 117) => 0.00313443
+(1, -1) ~ (5, 118) => 0.00758314
+(1, -1) ~ (5, 119) => 0.00771832
+(1, -1) ~ (5, 120) => 0.00382239
+(1, -1) ~ (5, 121) => 0.00677836
+(1, -1) ~ (5, 122) => 0.0107498
+(1, -1) ~ (5, 123) => 0.0103994
+(1, -1) ~ (5, 124) => 0.00268865
+(1, -1) ~ (5, 125) => 0.000424504
+(1, -1) ~ (5, 126) => 0.000899613
+(1, -1) ~ (5, 127) => 0.00241792
+(1, -1) ~ (5, 128) => 0.00379843
+(1, -1) ~ (5, 129) => 0.00348544
+(1, -1) ~ (5, 130) => 0.000343263
+(1, -1) ~ (5, 131) => 0.00024575
+(1, -1) ~ (5, 132) => 0.000406921
+(1, -1) ~ (5, 133) => 0.000383019
+(1, -1) ~ (5, 134) => 0.00023824
+(1, -1) ~ (5, 135) => 0.0001
+(1, -1) ~ (5, 136) => 0.000527859
+(1, -1) ~ (5, 137) => 0.000608504
+(1, -1) ~ (5, 138) => 0.000310481
+(1, -1) ~ (5, 139) => 0.0001
+(1, -1) ~ (5, 140) => 0.0001
+(1, -1) ~ (5, 141) => 0.0001
+(1, -1) ~ (5, 142) => 0.0001
+(1, -1) ~ (5, 143) => 0.0001
+(1, -1) ~ (5, 144) => 0.0001
+(1, -1) ~ (5, 145) => 0.0001
+(1, -1) ~ (5, 146) => 0.0001
+(1, -1) ~ (5, 147) => 0.0001
+(1, -1) ~ (5, 148) => 0.00013715
+(1, -1) ~ (5, 149) => 0.000158429
+(1, -1) ~ (5, 150) => 0.0001
+(1, -1) ~ (5, 151) => 0.0001
+(1, -1) ~ (5, 152) => 0.0001
+(1, -1) ~ (5, 153) => 0.000106573
+(1, -1) ~ (5, 154) => 0.000124812
+(1, -1) ~ (5, 155) => 0.000183761
+(1, -1) ~ (5, 156) => 0.000344872
+(1, -1) ~ (5, 157) => 0.00220561
+(1, -1) ~ (5, 158) => 0.00315464
+(1, -1) ~ (5, 159) => 0.0037151
+(1, -1) ~ (5, 160) => 0.0042448
+(1, -1) ~ (5, 161) => 0.00362962
+(1, -1) ~ (5, 162) => 0.0010103
+(1, -1) ~ (5, 163) => 0.000583291
+(1, -1) ~ (5, 164) => 0.000193179
+(1, -1) ~ (5, 165) => 0.000496745
+(1, -1) ~ (5, 166) => 0.000746429
+(1, -1) ~ (5, 167) => 0.00161403
+(1, -1) ~ (5, 168) => 0.00366408
+(1, -1) ~ (5, 169) => 0.003389
+(1, -1) ~ (5, 170) => 0.00039798
+(1, -1) ~ (5, 171) => 0.000162423
+(1, -1) ~ (5, 172) => 0.000581324
+(1, -1) ~ (5, 173) => 0.00317287
+(1, -1) ~ (5, 174) => 0.00547522
+(1, -1) ~ (5, 175) => 0.00564486
+(1, -1) ~ (5, 176) => 0.00509483
+(1, -1) ~ (5, 177) => 0.00260878
+(1, -1) ~ (5, 178) => 0.000199139
+(1, -1) ~ (5, 179) => 0.0001
+(1, -1) ~ (5, 180) => 0.000954449
+(1, -1) ~ (5, 181) => 0.0018428
+(1, -1) ~ (5, 182) => 0.0431308
+(1, -1) ~ (5, 183) => 0.041545
+(1, -1) ~ (5, 184) => 0.04185
+(1, -1) ~ (5, 185) => 0.146896
+(1, -1) ~ (5, 186) => 0.148782
+(1, -1) ~ (5, 187) => 0.0425369
+(1, -1) ~ (5, 188) => 0.044967
+(1, -1) ~ (5, 189) => 0.0335258
+(1, -1) ~ (5, 190) => 0.0092217
+(1, -1) ~ (5, 191) => 0.0397421
+(1, -1) ~ (5, 192) => 0.0533646
+(1, -1) ~ (5, 193) => 0.0297924
+(1, -1) ~ (5, 194) => 0.0732568
+(1, -1) ~ (5, 195) => 0.0723042
+(1, -1) ~ (5, 196) => 0.169306
+(1, -1) ~ (5, 197) => 0.0539154
+(1, -1) ~ (5, 198) => 0.0602437
+(1, -1) ~ (5, 199) => 0.0105197
+(1, -1) ~ (5, 200) => 0.00760943
+(1, -1) ~ (5, 201) => 0.0030663
+(1, -1) ~ (5, 202) => 0.00187194
+(1, -1) ~ (5, 203) => 0.000843763
+(1, -1) ~ (5, 204) => 0.0013566
+(1, -1) ~ (5, 205) => 0.00162685
+(1, -1) ~ (5, 206) => 0.00127143
+(1, -1) ~ (5, 207) => 0.000714242
+(1, -1) ~ (5, 208) => 0.00414246
+(1, -1) ~ (5, 209) => 0.0776041
+(1, -1) ~ (5, 210) => 0.157119
+(1, -1) ~ (5, 211) => 0.0491796
+(1, -1) ~ (5, 212) => 0.0065279
+(1, -1) ~ (5, 213) => 0.000961781
+(1, -1) ~ (5, 214) => 0.000794649
+(1, -1) ~ (5, 215) => 0.00525928
+(1, -1) ~ (5, 216) => 0.051954
+(1, -1) ~ (5, 217) => 0.199451
+(1, -1) ~ (5, 218) => 0.0342938
+(1, -1) ~ (5, 219) => 0.200277
+(1, -1) ~ (5, 220) => 0.253064
+(1, -1) ~ (5, 221) => 0.0238088
+(1, -1) ~ (5, 222) => 0.00637895
+(1, -1) ~ (5, 223) => 0.000442386
+(1, -1) ~ (5, 224) => 0.0001
+(1, -1) ~ (5, 225) => 0.0001
+(1, -1) ~ (5, 226) => 0.0001
+(1, -1) ~ (5, 227) => 0.000102162
+(1, -1) ~ (5, 228) => 0.000338435
+(1, -1) ~ (5, 229) => 0.00240248
+(1, -1) ~ (5, 230) => 0.0039956
+(1, -1) ~ (5, 231) => 0.00555378
+(1, -1) ~ (5, 232) => 0.00682056
+(1, -1) ~ (5, 233) => 0.00606287
+
+; Sparse posterior probability matrix for sequences 2 and 3
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (3, 0) => 0.641212
+(2, 1) ~ (3, 0) => 0.336422
+(2, 1) ~ (3, 1) => 0.511558
+(2, 2) ~ (3, 1) => 0.460287
+(2, 2) ~ (3, 2) => 0.384703
+(2, 3) ~ (3, 2) => 0.586674
+(2, 3) ~ (3, 3) => 0.273605
+(2, 4) ~ (3, 3) => 0.694718
+(2, 4) ~ (3, 4) => 0.0575482
+(2, 5) ~ (3, 4) => 0.915073
+(2, 5) ~ (3, 5) => 0.0338163
+(2, 6) ~ (3, 3) => 0.0147276
+(2, 6) ~ (3, 5) => 0.938848
+(2, 6) ~ (3, 6) => 0.0286899
+(2, 7) ~ (3, 4) => 0.0145278
+(2, 7) ~ (3, 6) => 0.946004
+(2, 7) ~ (3, 7) => 0.0239216
+(2, 8) ~ (3, 5) => 0.0105281
+(2, 8) ~ (3, 7) => 0.956457
+(2, 8) ~ (3, 8) => 0.0110752
+(2, 9) ~ (3, 8) => 0.974224
+(2, 10) ~ (3, 9) => 0.991668
+(2, 11) ~ (3, 10) => 0.998154
+(2, 12) ~ (3, 11) => 0.999307
+(2, 13) ~ (3, 12) => 0.999596
+(2, 14) ~ (3, 13) => 0.999836
+(2, 15) ~ (3, 14) => 0.999976
+(2, 16) ~ (3, 15) => 0.999972
+(2, 17) ~ (3, 16) => 0.999975
+(2, 18) ~ (3, 17) => 0.999996
+(2, 19) ~ (3, 18) => 0.999998
+(2, 20) ~ (3, 19) => 0.999997
+(2, 21) ~ (3, 20) => 0.999996
+(2, 22) ~ (3, 21) => 0.999995
+(2, 23) ~ (3, 22) => 0.999998
+(2, 24) ~ (3, 23) => 1
+(2, 25) ~ (3, 24) => 0.999999
+(2, 26) ~ (3, 25) => 0.999999
+(2, 27) ~ (3, 26) => 0.999999
+(2, 28) ~ (3, 27) => 0.999998
+(2, 29) ~ (3, 28) => 0.999997
+(2, 30) ~ (3, 29) => 0.999998
+(2, 31) ~ (3, 30) => 0.999998
+(2, 32) ~ (3, 31) => 0.999998
+(2, 33) ~ (3, 32) => 0.999997
+(2, 34) ~ (3, 33) => 0.999996
+(2, 35) ~ (3, 34) => 0.999995
+(2, 36) ~ (3, 35) => 0.999996
+(2, 37) ~ (3, 36) => 0.999987
+(2, 38) ~ (3, 37) => 0.999968
+(2, 39) ~ (3, 38) => 0.999948
+(2, 40) ~ (3, 39) => 0.999941
+(2, 41) ~ (3, 40) => 0.999937
+(2, 42) ~ (3, 41) => 0.999907
+(2, 43) ~ (3, 42) => 0.999918
+(2, 44) ~ (3, 43) => 0.999976
+(2, 45) ~ (3, 44) => 0.999996
+(2, 46) ~ (3, 45) => 0.999993
+(2, 47) ~ (3, 46) => 0.999988
+(2, 48) ~ (3, 47) => 0.999979
+(2, 49) ~ (3, 48) => 0.999974
+(2, 50) ~ (3, 49) => 0.999928
+(2, 51) ~ (3, 50) => 0.999902
+(2, 52) ~ (3, 51) => 0.999916
+(2, 53) ~ (3, 52) => 0.99991
+(2, 54) ~ (3, 53) => 0.999904
+(2, 55) ~ (3, 54) => 0.999936
+(2, 56) ~ (3, 55) => 0.999966
+(2, 57) ~ (3, 56) => 0.999997
+(2, 58) ~ (3, 57) => 0.999998
+(2, 59) ~ (3, 58) => 0.999997
+(2, 60) ~ (3, 59) => 0.999973
+(2, 61) ~ (3, 60) => 0.999882
+(2, 62) ~ (3, 61) => 0.997265
+(2, 63) ~ (3, 62) => 0.988991
+(2, 63) ~ (3, 63) => 0.010956
+(2, 64) ~ (3, 63) => 0.884033
+(2, 64) ~ (3, 64) => 0.115727
+(2, 65) ~ (3, 64) => 0.779124
+(2, 65) ~ (3, 65) => 0.220488
+(2, 66) ~ (3, 65) => 0.674288
+(2, 66) ~ (3, 66) => 0.325292
+(2, 67) ~ (3, 66) => 0.173069
+(2, 67) ~ (3, 67) => 0.826524
+(2, 68) ~ (3, 67) => 0.0935608
+(2, 68) ~ (3, 68) => 0.906057
+(2, 69) ~ (3, 68) => 0.0174093
+(2, 69) ~ (3, 69) => 0.982512
+(2, 70) ~ (3, 70) => 0.999794
+(2, 71) ~ (3, 71) => 0.999988
+(2, 72) ~ (3, 72) => 0.999988
+(2, 73) ~ (3, 73) => 0.999992
+(2, 74) ~ (3, 74) => 0.999995
+(2, 75) ~ (3, 75) => 0.999999
+(2, 76) ~ (3, 76) => 1
+(2, 77) ~ (3, 77) => 0.999999
+(2, 78) ~ (3, 78) => 0.999999
+(2, 79) ~ (3, 79) => 0.999999
+(2, 80) ~ (3, 80) => 0.999999
+(2, 81) ~ (3, 81) => 0.999997
+(2, 82) ~ (3, 82) => 0.999996
+(2, 83) ~ (3, 83) => 0.999997
+(2, 84) ~ (3, 84) => 0.999996
+(2, 85) ~ (3, 85) => 0.999997
+(2, 86) ~ (3, 86) => 0.999984
+(2, 87) ~ (3, 87) => 0.99998
+(2, 88) ~ (3, 88) => 0.999993
+(2, 89) ~ (3, 89) => 0.999995
+(2, 90) ~ (3, 90) => 0.999998
+(2, 91) ~ (3, 91) => 0.999999
+(2, 92) ~ (3, 92) => 0.999999
+(2, 93) ~ (3, 93) => 0.999999
+(2, 94) ~ (3, 94) => 0.999999
+(2, 95) ~ (3, 95) => 1
+(2, 96) ~ (3, 96) => 0.999999
+(2, 97) ~ (3, 97) => 0.999997
+(2, 98) ~ (3, 98) => 0.999997
+(2, 99) ~ (3, 99) => 0.999997
+(2, 100) ~ (3, 100) => 0.999984
+(2, 101) ~ (3, 101) => 0.99998
+(2, 102) ~ (3, 102) => 0.999981
+(2, 103) ~ (3, 103) => 0.999984
+(2, 104) ~ (3, 104) => 0.999989
+(2, 105) ~ (3, 105) => 0.999997
+(2, 106) ~ (3, 106) => 0.999998
+(2, 107) ~ (3, 107) => 0.999997
+(2, 108) ~ (3, 108) => 0.999998
+(2, 109) ~ (3, 109) => 0.999999
+(2, 110) ~ (3, 110) => 0.999999
+(2, 111) ~ (3, 111) => 0.999999
+(2, 112) ~ (3, 112) => 0.999999
+(2, 113) ~ (3, 113) => 0.999999
+(2, 114) ~ (3, 114) => 0.999999
+(2, 115) ~ (3, 115) => 0.999999
+(2, 116) ~ (3, 116) => 0.999998
+(2, 117) ~ (3, 117) => 0.999998
+(2, 118) ~ (3, 118) => 0.999999
+(2, 119) ~ (3, 119) => 0.999995
+(2, 120) ~ (3, 120) => 0.999987
+(2, 121) ~ (3, 121) => 0.999988
+(2, 122) ~ (3, 122) => 0.99999
+(2, 123) ~ (3, 123) => 0.999997
+(2, 124) ~ (3, 124) => 0.999999
+(2, 125) ~ (3, 125) => 0.999999
+(2, 126) ~ (3, 126) => 0.999999
+(2, 127) ~ (3, 127) => 0.999999
+(2, 128) ~ (3, 128) => 0.999999
+(2, 129) ~ (3, 129) => 0.999999
+(2, 130) ~ (3, 130) => 0.999997
+(2, 131) ~ (3, 131) => 0.999977
+(2, 132) ~ (3, 132) => 0.999956
+(2, 133) ~ (3, 133) => 0.999966
+(2, 134) ~ (3, 134) => 0.999969
+(2, 135) ~ (3, 135) => 0.999994
+(2, 136) ~ (3, 136) => 0.999995
+(2, 137) ~ (3, 137) => 0.999984
+(2, 138) ~ (3, 138) => 0.999983
+(2, 139) ~ (3, 139) => 0.999991
+(2, 140) ~ (3, 140) => 0.99998
+(2, 141) ~ (3, 141) => 0.99998
+(2, 142) ~ (3, 142) => 0.999994
+(2, 143) ~ (3, 143) => 0.99999
+(2, 144) ~ (3, 144) => 0.99997
+(2, 145) ~ (3, 145) => 0.999975
+(2, 146) ~ (3, 146) => 0.999986
+(2, 147) ~ (3, 147) => 0.999997
+(2, 148) ~ (3, 148) => 0.999998
+(2, 149) ~ (3, 149) => 0.999999
+(2, 150) ~ (3, 150) => 0.999999
+(2, 151) ~ (3, 151) => 0.999999
+(2, 152) ~ (3, 152) => 0.999999
+(2, 153) ~ (3, 153) => 0.999995
+(2, 154) ~ (3, 154) => 0.999992
+(2, 155) ~ (3, 155) => 0.999995
+(2, 156) ~ (3, 156) => 0.999998
+(2, 157) ~ (3, 157) => 0.999997
+(2, 158) ~ (3, 158) => 0.999997
+(2, 159) ~ (3, 159) => 0.999996
+(2, 160) ~ (3, 160) => 0.999995
+(2, 161) ~ (3, 161) => 0.999987
+(2, 162) ~ (3, 162) => 0.999988
+(2, 163) ~ (3, 163) => 0.999995
+(2, 164) ~ (3, 164) => 0.999991
+(2, 165) ~ (3, 165) => 0.999992
+(2, 166) ~ (3, 166) => 0.999996
+(2, 167) ~ (3, 167) => 0.999997
+(2, 168) ~ (3, 168) => 0.999993
+(2, 169) ~ (3, 169) => 0.999982
+(2, 170) ~ (3, 170) => 0.999971
+(2, 171) ~ (3, 171) => 0.999953
+(2, 172) ~ (3, 172) => 0.999961
+(2, 173) ~ (3, 173) => 0.999982
+(2, 174) ~ (3, 174) => 0.999991
+(2, 175) ~ (3, 175) => 0.999995
+(2, 176) ~ (3, 176) => 0.999964
+(2, 177) ~ (3, 177) => 0.999867
+(2, 178) ~ (3, 178) => 0.999636
+(2, 179) ~ (3, 179) => 0.999451
+(2, 180) ~ (3, 180) => 0.999448
+(2, 181) ~ (3, 181) => 0.999625
+(2, 182) ~ (3, 182) => 0.999892
+(2, 183) ~ (3, 183) => 0.999993
+(2, 184) ~ (3, 184) => 0.999999
+(2, 185) ~ (3, 185) => 0.999999
+(2, 186) ~ (3, 186) => 0.999999
+(2, 187) ~ (3, 187) => 0.999999
+(2, 188) ~ (3, 188) => 0.999999
+(2, 189) ~ (3, 189) => 0.999999
+(2, 190) ~ (3, 190) => 0.999999
+(2, 191) ~ (3, 191) => 1
+(2, 192) ~ (3, 192) => 0.999999
+(2, 193) ~ (3, 193) => 0.999999
+(2, 194) ~ (3, 194) => 0.999998
+(2, 195) ~ (3, 195) => 0.99999
+(2, 196) ~ (3, 196) => 0.999989
+(2, 197) ~ (3, 197) => 0.999996
+(2, 198) ~ (3, 198) => 0.999989
+(2, 199) ~ (3, 199) => 0.999875
+(2, 200) ~ (3, 200) => 0.999836
+(2, 201) ~ (3, 201) => 0.999867
+(2, 202) ~ (3, 202) => 0.999916
+(2, 203) ~ (3, 203) => 0.999955
+(2, 204) ~ (3, 204) => 0.999973
+(2, 205) ~ (3, 205) => 0.999936
+(2, 206) ~ (3, 206) => 0.999923
+(2, 207) ~ (3, 207) => 0.999931
+(2, 208) ~ (3, 208) => 0.999939
+(2, 209) ~ (3, 209) => 0.999943
+(2, 210) ~ (3, 210) => 0.999978
+(2, 211) ~ (3, 211) => 0.999995
+(2, 212) ~ (3, 212) => 0.999999
+(2, 213) ~ (3, 213) => 0.999992
+(2, 214) ~ (3, 214) => 0.999981
+(2, 215) ~ (3, 215) => 0.999978
+(2, 216) ~ (3, 216) => 0.999992
+(2, 217) ~ (3, 217) => 0.99998
+(2, 218) ~ (3, 218) => 0.999971
+(2, 219) ~ (3, 219) => 0.999974
+(2, 220) ~ (3, 220) => 0.999974
+(2, 221) ~ (3, 221) => 0.999983
+(2, 222) ~ (3, 222) => 0.999978
+(2, 223) ~ (3, 223) => 0.99993
+(2, 224) ~ (3, 224) => 0.999882
+(2, 225) ~ (3, 225) => 0.999901
+(2, 226) ~ (3, 226) => 0.999901
+(2, 227) ~ (3, 227) => 0.999947
+(2, 228) ~ (3, 228) => 0.999996
+(2, 229) ~ (3, 229) => 0.999997
+(2, 230) ~ (3, 230) => 0.999999
+(2, 231) ~ (3, 231) => 0.999999
+(2, 232) ~ (3, 232) => 0.999999
+(2, 233) ~ (3, 233) => 0.999999
+(2, 234) ~ (3, 234) => 0.999999
+(2, 235) ~ (3, 235) => 0.999999
+(2, 236) ~ (3, 236) => 0.999993
+(2, 237) ~ (3, 237) => 0.999994
+(2, 238) ~ (3, 238) => 0.999999
+
+; gap posteriors
+(2, 0) ~ (3, -1) => 0.358788
+(2, 1) ~ (3, -1) => 0.15202
+(2, 2) ~ (3, -1) => 0.15501
+(2, 3) ~ (3, -1) => 0.139721
+(2, 4) ~ (3, -1) => 0.247734
+(2, 5) ~ (3, -1) => 0.0511105
+(2, 6) ~ (3, -1) => 0.0177344
+(2, 7) ~ (3, -1) => 0.0155469
+(2, 8) ~ (3, -1) => 0.0219392
+(2, 9) ~ (3, -1) => 0.025776
+(2, 10) ~ (3, -1) => 0.00833166
+(2, 11) ~ (3, -1) => 0.0018459
+(2, 12) ~ (3, -1) => 0.000692904
+(2, 13) ~ (3, -1) => 0.000403762
+(2, 14) ~ (3, -1) => 0.00016439
+(2, 15) ~ (3, -1) => 0.0001
+(2, 16) ~ (3, -1) => 0.0001
+(2, 17) ~ (3, -1) => 0.0001
+(2, 18) ~ (3, -1) => 0.0001
+(2, 19) ~ (3, -1) => 0.0001
+(2, 20) ~ (3, -1) => 0.0001
+(2, 21) ~ (3, -1) => 0.0001
+(2, 22) ~ (3, -1) => 0.0001
+(2, 23) ~ (3, -1) => 0.0001
+(2, 24) ~ (3, -1) => 0.0001
+(2, 25) ~ (3, -1) => 0.0001
+(2, 26) ~ (3, -1) => 0.0001
+(2, 27) ~ (3, -1) => 0.0001
+(2, 28) ~ (3, -1) => 0.0001
+(2, 29) ~ (3, -1) => 0.0001
+(2, 30) ~ (3, -1) => 0.0001
+(2, 31) ~ (3, -1) => 0.0001
+(2, 32) ~ (3, -1) => 0.0001
+(2, 33) ~ (3, -1) => 0.0001
+(2, 34) ~ (3, -1) => 0.0001
+(2, 35) ~ (3, -1) => 0.0001
+(2, 36) ~ (3, -1) => 0.0001
+(2, 37) ~ (3, -1) => 0.0001
+(2, 38) ~ (3, -1) => 0.0001
+(2, 39) ~ (3, -1) => 0.0001
+(2, 40) ~ (3, -1) => 0.0001
+(2, 41) ~ (3, -1) => 0.0001
+(2, 42) ~ (3, -1) => 0.0001
+(2, 43) ~ (3, -1) => 0.0001
+(2, 44) ~ (3, -1) => 0.0001
+(2, 45) ~ (3, -1) => 0.0001
+(2, 46) ~ (3, -1) => 0.0001
+(2, 47) ~ (3, -1) => 0.0001
+(2, 48) ~ (3, -1) => 0.0001
+(2, 49) ~ (3, -1) => 0.0001
+(2, 50) ~ (3, -1) => 0.0001
+(2, 51) ~ (3, -1) => 0.0001
+(2, 52) ~ (3, -1) => 0.0001
+(2, 53) ~ (3, -1) => 0.0001
+(2, 54) ~ (3, -1) => 0.0001
+(2, 55) ~ (3, -1) => 0.0001
+(2, 56) ~ (3, -1) => 0.0001
+(2, 57) ~ (3, -1) => 0.0001
+(2, 58) ~ (3, -1) => 0.0001
+(2, 59) ~ (3, -1) => 0.0001
+(2, 60) ~ (3, -1) => 0.0001
+(2, 61) ~ (3, -1) => 0.000117719
+(2, 62) ~ (3, -1) => 0.0027349
+(2, 63) ~ (3, -1) => 0.0001
+(2, 64) ~ (3, -1) => 0.000240259
+(2, 65) ~ (3, -1) => 0.000388235
+(2, 66) ~ (3, -1) => 0.000420779
+(2, 67) ~ (3, -1) => 0.000407219
+(2, 68) ~ (3, -1) => 0.000381768
+(2, 69) ~ (3, -1) => 0.0001
+(2, 70) ~ (3, -1) => 0.000206292
+(2, 71) ~ (3, -1) => 0.0001
+(2, 72) ~ (3, -1) => 0.0001
+(2, 73) ~ (3, -1) => 0.0001
+(2, 74) ~ (3, -1) => 0.0001
+(2, 75) ~ (3, -1) => 0.0001
+(2, 76) ~ (3, -1) => 0.0001
+(2, 77) ~ (3, -1) => 0.0001
+(2, 78) ~ (3, -1) => 0.0001
+(2, 79) ~ (3, -1) => 0.0001
+(2, 80) ~ (3, -1) => 0.0001
+(2, 81) ~ (3, -1) => 0.0001
+(2, 82) ~ (3, -1) => 0.0001
+(2, 83) ~ (3, -1) => 0.0001
+(2, 84) ~ (3, -1) => 0.0001
+(2, 85) ~ (3, -1) => 0.0001
+(2, 86) ~ (3, -1) => 0.0001
+(2, 87) ~ (3, -1) => 0.0001
+(2, 88) ~ (3, -1) => 0.0001
+(2, 89) ~ (3, -1) => 0.0001
+(2, 90) ~ (3, -1) => 0.0001
+(2, 91) ~ (3, -1) => 0.0001
+(2, 92) ~ (3, -1) => 0.0001
+(2, 93) ~ (3, -1) => 0.0001
+(2, 94) ~ (3, -1) => 0.0001
+(2, 95) ~ (3, -1) => 0.0001
+(2, 96) ~ (3, -1) => 0.0001
+(2, 97) ~ (3, -1) => 0.0001
+(2, 98) ~ (3, -1) => 0.0001
+(2, 99) ~ (3, -1) => 0.0001
+(2, 100) ~ (3, -1) => 0.0001
+(2, 101) ~ (3, -1) => 0.0001
+(2, 102) ~ (3, -1) => 0.0001
+(2, 103) ~ (3, -1) => 0.0001
+(2, 104) ~ (3, -1) => 0.0001
+(2, 105) ~ (3, -1) => 0.0001
+(2, 106) ~ (3, -1) => 0.0001
+(2, 107) ~ (3, -1) => 0.0001
+(2, 108) ~ (3, -1) => 0.0001
+(2, 109) ~ (3, -1) => 0.0001
+(2, 110) ~ (3, -1) => 0.0001
+(2, 111) ~ (3, -1) => 0.0001
+(2, 112) ~ (3, -1) => 0.0001
+(2, 113) ~ (3, -1) => 0.0001
+(2, 114) ~ (3, -1) => 0.0001
+(2, 115) ~ (3, -1) => 0.0001
+(2, 116) ~ (3, -1) => 0.0001
+(2, 117) ~ (3, -1) => 0.0001
+(2, 118) ~ (3, -1) => 0.0001
+(2, 119) ~ (3, -1) => 0.0001
+(2, 120) ~ (3, -1) => 0.0001
+(2, 121) ~ (3, -1) => 0.0001
+(2, 122) ~ (3, -1) => 0.0001
+(2, 123) ~ (3, -1) => 0.0001
+(2, 124) ~ (3, -1) => 0.0001
+(2, 125) ~ (3, -1) => 0.0001
+(2, 126) ~ (3, -1) => 0.0001
+(2, 127) ~ (3, -1) => 0.0001
+(2, 128) ~ (3, -1) => 0.0001
+(2, 129) ~ (3, -1) => 0.0001
+(2, 130) ~ (3, -1) => 0.0001
+(2, 131) ~ (3, -1) => 0.0001
+(2, 132) ~ (3, -1) => 0.0001
+(2, 133) ~ (3, -1) => 0.0001
+(2, 134) ~ (3, -1) => 0.0001
+(2, 135) ~ (3, -1) => 0.0001
+(2, 136) ~ (3, -1) => 0.0001
+(2, 137) ~ (3, -1) => 0.0001
+(2, 138) ~ (3, -1) => 0.0001
+(2, 139) ~ (3, -1) => 0.0001
+(2, 140) ~ (3, -1) => 0.0001
+(2, 141) ~ (3, -1) => 0.0001
+(2, 142) ~ (3, -1) => 0.0001
+(2, 143) ~ (3, -1) => 0.0001
+(2, 144) ~ (3, -1) => 0.0001
+(2, 145) ~ (3, -1) => 0.0001
+(2, 146) ~ (3, -1) => 0.0001
+(2, 147) ~ (3, -1) => 0.0001
+(2, 148) ~ (3, -1) => 0.0001
+(2, 149) ~ (3, -1) => 0.0001
+(2, 150) ~ (3, -1) => 0.0001
+(2, 151) ~ (3, -1) => 0.0001
+(2, 152) ~ (3, -1) => 0.0001
+(2, 153) ~ (3, -1) => 0.0001
+(2, 154) ~ (3, -1) => 0.0001
+(2, 155) ~ (3, -1) => 0.0001
+(2, 156) ~ (3, -1) => 0.0001
+(2, 157) ~ (3, -1) => 0.0001
+(2, 158) ~ (3, -1) => 0.0001
+(2, 159) ~ (3, -1) => 0.0001
+(2, 160) ~ (3, -1) => 0.0001
+(2, 161) ~ (3, -1) => 0.0001
+(2, 162) ~ (3, -1) => 0.0001
+(2, 163) ~ (3, -1) => 0.0001
+(2, 164) ~ (3, -1) => 0.0001
+(2, 165) ~ (3, -1) => 0.0001
+(2, 166) ~ (3, -1) => 0.0001
+(2, 167) ~ (3, -1) => 0.0001
+(2, 168) ~ (3, -1) => 0.0001
+(2, 169) ~ (3, -1) => 0.0001
+(2, 170) ~ (3, -1) => 0.0001
+(2, 171) ~ (3, -1) => 0.0001
+(2, 172) ~ (3, -1) => 0.0001
+(2, 173) ~ (3, -1) => 0.0001
+(2, 174) ~ (3, -1) => 0.0001
+(2, 175) ~ (3, -1) => 0.0001
+(2, 176) ~ (3, -1) => 0.0001
+(2, 177) ~ (3, -1) => 0.00013268
+(2, 178) ~ (3, -1) => 0.000363886
+(2, 179) ~ (3, -1) => 0.00054872
+(2, 180) ~ (3, -1) => 0.000552475
+(2, 181) ~ (3, -1) => 0.00037545
+(2, 182) ~ (3, -1) => 0.000107765
+(2, 183) ~ (3, -1) => 0.0001
+(2, 184) ~ (3, -1) => 0.0001
+(2, 185) ~ (3, -1) => 0.0001
+(2, 186) ~ (3, -1) => 0.0001
+(2, 187) ~ (3, -1) => 0.0001
+(2, 188) ~ (3, -1) => 0.0001
+(2, 189) ~ (3, -1) => 0.0001
+(2, 190) ~ (3, -1) => 0.0001
+(2, 191) ~ (3, -1) => 0.0001
+(2, 192) ~ (3, -1) => 0.0001
+(2, 193) ~ (3, -1) => 0.0001
+(2, 194) ~ (3, -1) => 0.0001
+(2, 195) ~ (3, -1) => 0.0001
+(2, 196) ~ (3, -1) => 0.0001
+(2, 197) ~ (3, -1) => 0.0001
+(2, 198) ~ (3, -1) => 0.0001
+(2, 199) ~ (3, -1) => 0.00012517
+(2, 200) ~ (3, -1) => 0.000163734
+(2, 201) ~ (3, -1) => 0.000132918
+(2, 202) ~ (3, -1) => 0.0001
+(2, 203) ~ (3, -1) => 0.0001
+(2, 204) ~ (3, -1) => 0.0001
+(2, 205) ~ (3, -1) => 0.0001
+(2, 206) ~ (3, -1) => 0.0001
+(2, 207) ~ (3, -1) => 0.0001
+(2, 208) ~ (3, -1) => 0.0001
+(2, 209) ~ (3, -1) => 0.0001
+(2, 210) ~ (3, -1) => 0.0001
+(2, 211) ~ (3, -1) => 0.0001
+(2, 212) ~ (3, -1) => 0.0001
+(2, 213) ~ (3, -1) => 0.0001
+(2, 214) ~ (3, -1) => 0.0001
+(2, 215) ~ (3, -1) => 0.0001
+(2, 216) ~ (3, -1) => 0.0001
+(2, 217) ~ (3, -1) => 0.0001
+(2, 218) ~ (3, -1) => 0.0001
+(2, 219) ~ (3, -1) => 0.0001
+(2, 220) ~ (3, -1) => 0.0001
+(2, 221) ~ (3, -1) => 0.0001
+(2, 222) ~ (3, -1) => 0.0001
+(2, 223) ~ (3, -1) => 0.0001
+(2, 224) ~ (3, -1) => 0.000117719
+(2, 225) ~ (3, -1) => 0.0001
+(2, 226) ~ (3, -1) => 0.0001
+(2, 227) ~ (3, -1) => 0.0001
+(2, 228) ~ (3, -1) => 0.0001
+(2, 229) ~ (3, -1) => 0.0001
+(2, 230) ~ (3, -1) => 0.0001
+(2, 231) ~ (3, -1) => 0.0001
+(2, 232) ~ (3, -1) => 0.0001
+(2, 233) ~ (3, -1) => 0.0001
+(2, 234) ~ (3, -1) => 0.0001
+(2, 235) ~ (3, -1) => 0.0001
+(2, 236) ~ (3, -1) => 0.0001
+(2, 237) ~ (3, -1) => 0.0001
+(2, 238) ~ (3, -1) => 0.0001
+
+(2, -1) ~ (3, 0) => 0.0223667
+(2, -1) ~ (3, 1) => 0.0281544
+(2, -1) ~ (3, 2) => 0.0286234
+(2, -1) ~ (3, 3) => 0.0169492
+(2, -1) ~ (3, 4) => 0.0128508
+(2, -1) ~ (3, 5) => 0.0168075
+(2, -1) ~ (3, 6) => 0.0253065
+(2, -1) ~ (3, 7) => 0.0196209
+(2, -1) ~ (3, 8) => 0.0147008
+(2, -1) ~ (3, 9) => 0.00833166
+(2, -1) ~ (3, 10) => 0.0018459
+(2, -1) ~ (3, 11) => 0.000692904
+(2, -1) ~ (3, 12) => 0.000403762
+(2, -1) ~ (3, 13) => 0.00016439
+(2, -1) ~ (3, 14) => 0.0001
+(2, -1) ~ (3, 15) => 0.0001
+(2, -1) ~ (3, 16) => 0.0001
+(2, -1) ~ (3, 17) => 0.0001
+(2, -1) ~ (3, 18) => 0.0001
+(2, -1) ~ (3, 19) => 0.0001
+(2, -1) ~ (3, 20) => 0.0001
+(2, -1) ~ (3, 21) => 0.0001
+(2, -1) ~ (3, 22) => 0.0001
+(2, -1) ~ (3, 23) => 0.0001
+(2, -1) ~ (3, 24) => 0.0001
+(2, -1) ~ (3, 25) => 0.0001
+(2, -1) ~ (3, 26) => 0.0001
+(2, -1) ~ (3, 27) => 0.0001
+(2, -1) ~ (3, 28) => 0.0001
+(2, -1) ~ (3, 29) => 0.0001
+(2, -1) ~ (3, 30) => 0.0001
+(2, -1) ~ (3, 31) => 0.0001
+(2, -1) ~ (3, 32) => 0.0001
+(2, -1) ~ (3, 33) => 0.0001
+(2, -1) ~ (3, 34) => 0.0001
+(2, -1) ~ (3, 35) => 0.0001
+(2, -1) ~ (3, 36) => 0.0001
+(2, -1) ~ (3, 37) => 0.0001
+(2, -1) ~ (3, 38) => 0.0001
+(2, -1) ~ (3, 39) => 0.0001
+(2, -1) ~ (3, 40) => 0.0001
+(2, -1) ~ (3, 41) => 0.0001
+(2, -1) ~ (3, 42) => 0.0001
+(2, -1) ~ (3, 43) => 0.0001
+(2, -1) ~ (3, 44) => 0.0001
+(2, -1) ~ (3, 45) => 0.0001
+(2, -1) ~ (3, 46) => 0.0001
+(2, -1) ~ (3, 47) => 0.0001
+(2, -1) ~ (3, 48) => 0.0001
+(2, -1) ~ (3, 49) => 0.0001
+(2, -1) ~ (3, 50) => 0.0001
+(2, -1) ~ (3, 51) => 0.0001
+(2, -1) ~ (3, 52) => 0.0001
+(2, -1) ~ (3, 53) => 0.0001
+(2, -1) ~ (3, 54) => 0.0001
+(2, -1) ~ (3, 55) => 0.0001
+(2, -1) ~ (3, 56) => 0.0001
+(2, -1) ~ (3, 57) => 0.0001
+(2, -1) ~ (3, 58) => 0.0001
+(2, -1) ~ (3, 59) => 0.0001
+(2, -1) ~ (3, 60) => 0.000117719
+(2, -1) ~ (3, 61) => 0.0027349
+(2, -1) ~ (3, 62) => 0.0110089
+(2, -1) ~ (3, 63) => 0.105011
+(2, -1) ~ (3, 64) => 0.10515
+(2, -1) ~ (3, 65) => 0.105224
+(2, -1) ~ (3, 66) => 0.50164
+(2, -1) ~ (3, 67) => 0.0799153
+(2, -1) ~ (3, 68) => 0.0765333
+(2, -1) ~ (3, 69) => 0.0174879
+(2, -1) ~ (3, 70) => 0.000206292
+(2, -1) ~ (3, 71) => 0.0001
+(2, -1) ~ (3, 72) => 0.0001
+(2, -1) ~ (3, 73) => 0.0001
+(2, -1) ~ (3, 74) => 0.0001
+(2, -1) ~ (3, 75) => 0.0001
+(2, -1) ~ (3, 76) => 0.0001
+(2, -1) ~ (3, 77) => 0.0001
+(2, -1) ~ (3, 78) => 0.0001
+(2, -1) ~ (3, 79) => 0.0001
+(2, -1) ~ (3, 80) => 0.0001
+(2, -1) ~ (3, 81) => 0.0001
+(2, -1) ~ (3, 82) => 0.0001
+(2, -1) ~ (3, 83) => 0.0001
+(2, -1) ~ (3, 84) => 0.0001
+(2, -1) ~ (3, 85) => 0.0001
+(2, -1) ~ (3, 86) => 0.0001
+(2, -1) ~ (3, 87) => 0.0001
+(2, -1) ~ (3, 88) => 0.0001
+(2, -1) ~ (3, 89) => 0.0001
+(2, -1) ~ (3, 90) => 0.0001
+(2, -1) ~ (3, 91) => 0.0001
+(2, -1) ~ (3, 92) => 0.0001
+(2, -1) ~ (3, 93) => 0.0001
+(2, -1) ~ (3, 94) => 0.0001
+(2, -1) ~ (3, 95) => 0.0001
+(2, -1) ~ (3, 96) => 0.0001
+(2, -1) ~ (3, 97) => 0.0001
+(2, -1) ~ (3, 98) => 0.0001
+(2, -1) ~ (3, 99) => 0.0001
+(2, -1) ~ (3, 100) => 0.0001
+(2, -1) ~ (3, 101) => 0.0001
+(2, -1) ~ (3, 102) => 0.0001
+(2, -1) ~ (3, 103) => 0.0001
+(2, -1) ~ (3, 104) => 0.0001
+(2, -1) ~ (3, 105) => 0.0001
+(2, -1) ~ (3, 106) => 0.0001
+(2, -1) ~ (3, 107) => 0.0001
+(2, -1) ~ (3, 108) => 0.0001
+(2, -1) ~ (3, 109) => 0.0001
+(2, -1) ~ (3, 110) => 0.0001
+(2, -1) ~ (3, 111) => 0.0001
+(2, -1) ~ (3, 112) => 0.0001
+(2, -1) ~ (3, 113) => 0.0001
+(2, -1) ~ (3, 114) => 0.0001
+(2, -1) ~ (3, 115) => 0.0001
+(2, -1) ~ (3, 116) => 0.0001
+(2, -1) ~ (3, 117) => 0.0001
+(2, -1) ~ (3, 118) => 0.0001
+(2, -1) ~ (3, 119) => 0.0001
+(2, -1) ~ (3, 120) => 0.0001
+(2, -1) ~ (3, 121) => 0.0001
+(2, -1) ~ (3, 122) => 0.0001
+(2, -1) ~ (3, 123) => 0.0001
+(2, -1) ~ (3, 124) => 0.0001
+(2, -1) ~ (3, 125) => 0.0001
+(2, -1) ~ (3, 126) => 0.0001
+(2, -1) ~ (3, 127) => 0.0001
+(2, -1) ~ (3, 128) => 0.0001
+(2, -1) ~ (3, 129) => 0.0001
+(2, -1) ~ (3, 130) => 0.0001
+(2, -1) ~ (3, 131) => 0.0001
+(2, -1) ~ (3, 132) => 0.0001
+(2, -1) ~ (3, 133) => 0.0001
+(2, -1) ~ (3, 134) => 0.0001
+(2, -1) ~ (3, 135) => 0.0001
+(2, -1) ~ (3, 136) => 0.0001
+(2, -1) ~ (3, 137) => 0.0001
+(2, -1) ~ (3, 138) => 0.0001
+(2, -1) ~ (3, 139) => 0.0001
+(2, -1) ~ (3, 140) => 0.0001
+(2, -1) ~ (3, 141) => 0.0001
+(2, -1) ~ (3, 142) => 0.0001
+(2, -1) ~ (3, 143) => 0.0001
+(2, -1) ~ (3, 144) => 0.0001
+(2, -1) ~ (3, 145) => 0.0001
+(2, -1) ~ (3, 146) => 0.0001
+(2, -1) ~ (3, 147) => 0.0001
+(2, -1) ~ (3, 148) => 0.0001
+(2, -1) ~ (3, 149) => 0.0001
+(2, -1) ~ (3, 150) => 0.0001
+(2, -1) ~ (3, 151) => 0.0001
+(2, -1) ~ (3, 152) => 0.0001
+(2, -1) ~ (3, 153) => 0.0001
+(2, -1) ~ (3, 154) => 0.0001
+(2, -1) ~ (3, 155) => 0.0001
+(2, -1) ~ (3, 156) => 0.0001
+(2, -1) ~ (3, 157) => 0.0001
+(2, -1) ~ (3, 158) => 0.0001
+(2, -1) ~ (3, 159) => 0.0001
+(2, -1) ~ (3, 160) => 0.0001
+(2, -1) ~ (3, 161) => 0.0001
+(2, -1) ~ (3, 162) => 0.0001
+(2, -1) ~ (3, 163) => 0.0001
+(2, -1) ~ (3, 164) => 0.0001
+(2, -1) ~ (3, 165) => 0.0001
+(2, -1) ~ (3, 166) => 0.0001
+(2, -1) ~ (3, 167) => 0.0001
+(2, -1) ~ (3, 168) => 0.0001
+(2, -1) ~ (3, 169) => 0.0001
+(2, -1) ~ (3, 170) => 0.0001
+(2, -1) ~ (3, 171) => 0.0001
+(2, -1) ~ (3, 172) => 0.0001
+(2, -1) ~ (3, 173) => 0.0001
+(2, -1) ~ (3, 174) => 0.0001
+(2, -1) ~ (3, 175) => 0.0001
+(2, -1) ~ (3, 176) => 0.0001
+(2, -1) ~ (3, 177) => 0.00013268
+(2, -1) ~ (3, 178) => 0.000363886
+(2, -1) ~ (3, 179) => 0.00054872
+(2, -1) ~ (3, 180) => 0.000552475
+(2, -1) ~ (3, 181) => 0.00037545
+(2, -1) ~ (3, 182) => 0.000107765
+(2, -1) ~ (3, 183) => 0.0001
+(2, -1) ~ (3, 184) => 0.0001
+(2, -1) ~ (3, 185) => 0.0001
+(2, -1) ~ (3, 186) => 0.0001
+(2, -1) ~ (3, 187) => 0.0001
+(2, -1) ~ (3, 188) => 0.0001
+(2, -1) ~ (3, 189) => 0.0001
+(2, -1) ~ (3, 190) => 0.0001
+(2, -1) ~ (3, 191) => 0.0001
+(2, -1) ~ (3, 192) => 0.0001
+(2, -1) ~ (3, 193) => 0.0001
+(2, -1) ~ (3, 194) => 0.0001
+(2, -1) ~ (3, 195) => 0.0001
+(2, -1) ~ (3, 196) => 0.0001
+(2, -1) ~ (3, 197) => 0.0001
+(2, -1) ~ (3, 198) => 0.0001
+(2, -1) ~ (3, 199) => 0.00012517
+(2, -1) ~ (3, 200) => 0.000163734
+(2, -1) ~ (3, 201) => 0.000132918
+(2, -1) ~ (3, 202) => 0.0001
+(2, -1) ~ (3, 203) => 0.0001
+(2, -1) ~ (3, 204) => 0.0001
+(2, -1) ~ (3, 205) => 0.0001
+(2, -1) ~ (3, 206) => 0.0001
+(2, -1) ~ (3, 207) => 0.0001
+(2, -1) ~ (3, 208) => 0.0001
+(2, -1) ~ (3, 209) => 0.0001
+(2, -1) ~ (3, 210) => 0.0001
+(2, -1) ~ (3, 211) => 0.0001
+(2, -1) ~ (3, 212) => 0.0001
+(2, -1) ~ (3, 213) => 0.0001
+(2, -1) ~ (3, 214) => 0.0001
+(2, -1) ~ (3, 215) => 0.0001
+(2, -1) ~ (3, 216) => 0.0001
+(2, -1) ~ (3, 217) => 0.0001
+(2, -1) ~ (3, 218) => 0.0001
+(2, -1) ~ (3, 219) => 0.0001
+(2, -1) ~ (3, 220) => 0.0001
+(2, -1) ~ (3, 221) => 0.0001
+(2, -1) ~ (3, 222) => 0.0001
+(2, -1) ~ (3, 223) => 0.0001
+(2, -1) ~ (3, 224) => 0.000117719
+(2, -1) ~ (3, 225) => 0.0001
+(2, -1) ~ (3, 226) => 0.0001
+(2, -1) ~ (3, 227) => 0.0001
+(2, -1) ~ (3, 228) => 0.0001
+(2, -1) ~ (3, 229) => 0.0001
+(2, -1) ~ (3, 230) => 0.0001
+(2, -1) ~ (3, 231) => 0.0001
+(2, -1) ~ (3, 232) => 0.0001
+(2, -1) ~ (3, 233) => 0.0001
+(2, -1) ~ (3, 234) => 0.0001
+(2, -1) ~ (3, 235) => 0.0001
+(2, -1) ~ (3, 236) => 0.0001
+(2, -1) ~ (3, 237) => 0.0001
+(2, -1) ~ (3, 238) => 0.0001
+
+; Sparse posterior probability matrix for sequences 2 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (4, 0) => 0.999377
+(2, 1) ~ (4, 1) => 0.995467
+(2, 2) ~ (4, 2) => 0.99136
+(2, 3) ~ (4, 3) => 0.988979
+(2, 4) ~ (4, 4) => 0.988076
+(2, 5) ~ (4, 5) => 0.986908
+(2, 6) ~ (4, 6) => 0.985571
+(2, 7) ~ (4, 7) => 0.903828
+(2, 7) ~ (4, 8) => 0.0131013
+(2, 8) ~ (4, 7) => 0.0742643
+(2, 8) ~ (4, 8) => 0.575007
+(2, 9) ~ (4, 8) => 0.391165
+(2, 9) ~ (4, 9) => 0.145368
+(2, 10) ~ (4, 9) => 0.825541
+(2, 10) ~ (4, 10) => 0.0575333
+(2, 11) ~ (4, 10) => 0.922638
+(2, 12) ~ (4, 11) => 0.983404
+(2, 13) ~ (4, 12) => 0.991746
+(2, 14) ~ (4, 13) => 0.991947
+(2, 15) ~ (4, 14) => 0.991395
+(2, 16) ~ (4, 15) => 0.990648
+(2, 17) ~ (4, 16) => 0.990075
+(2, 18) ~ (4, 17) => 0.981819
+(2, 19) ~ (4, 17) => 0.014132
+(2, 19) ~ (4, 18) => 0.981233
+(2, 20) ~ (4, 19) => 0.988954
+(2, 21) ~ (4, 20) => 0.995239
+(2, 22) ~ (4, 21) => 0.996894
+(2, 23) ~ (4, 22) => 0.999589
+(2, 24) ~ (4, 23) => 0.999956
+(2, 25) ~ (4, 24) => 0.999953
+(2, 26) ~ (4, 25) => 0.999184
+(2, 27) ~ (4, 26) => 0.995703
+(2, 28) ~ (4, 27) => 0.986325
+(2, 28) ~ (4, 28) => 0.0128934
+(2, 29) ~ (4, 28) => 0.983552
+(2, 29) ~ (4, 29) => 0.0152537
+(2, 30) ~ (4, 29) => 0.973276
+(2, 30) ~ (4, 30) => 0.0237234
+(2, 31) ~ (4, 30) => 0.968983
+(2, 31) ~ (4, 31) => 0.0245086
+(2, 32) ~ (4, 31) => 0.971272
+(2, 33) ~ (4, 32) => 0.996187
+(2, 34) ~ (4, 33) => 0.997889
+(2, 35) ~ (4, 34) => 0.997284
+(2, 36) ~ (4, 35) => 0.997254
+(2, 37) ~ (4, 36) => 0.997789
+(2, 38) ~ (4, 37) => 0.998596
+(2, 39) ~ (4, 38) => 0.99907
+(2, 40) ~ (4, 39) => 0.999393
+(2, 41) ~ (4, 40) => 0.999426
+(2, 42) ~ (4, 41) => 0.999196
+(2, 43) ~ (4, 42) => 0.998651
+(2, 44) ~ (4, 43) => 0.997978
+(2, 45) ~ (4, 44) => 0.995911
+(2, 46) ~ (4, 45) => 0.979815
+(2, 47) ~ (4, 46) => 0.95256
+(2, 48) ~ (4, 47) => 0.726854
+(2, 49) ~ (4, 46) => 0.0339329
+(2, 49) ~ (4, 48) => 0.687985
+(2, 49) ~ (4, 50) => 0.0108284
+(2, 50) ~ (4, 47) => 0.241888
+(2, 50) ~ (4, 49) => 0.678871
+(2, 50) ~ (4, 50) => 0.0119812
+(2, 50) ~ (4, 51) => 0.0115149
+(2, 51) ~ (4, 48) => 0.278494
+(2, 51) ~ (4, 50) => 0.657617
+(2, 51) ~ (4, 51) => 0.0225763
+(2, 51) ~ (4, 52) => 0.0124146
+(2, 52) ~ (4, 48) => 0.0104511
+(2, 52) ~ (4, 49) => 0.278148
+(2, 52) ~ (4, 51) => 0.650281
+(2, 52) ~ (4, 52) => 0.0285677
+(2, 53) ~ (4, 50) => 0.2866
+(2, 53) ~ (4, 52) => 0.64166
+(2, 53) ~ (4, 53) => 0.0164001
+(2, 54) ~ (4, 51) => 0.28829
+(2, 54) ~ (4, 53) => 0.653138
+(2, 55) ~ (4, 52) => 0.301345
+(2, 55) ~ (4, 54) => 0.0274752
+(2, 56) ~ (4, 53) => 0.32171
+(2, 57) ~ (4, 54) => 0.969225
+(2, 58) ~ (4, 55) => 0.99623
+(2, 59) ~ (4, 56) => 0.999074
+(2, 60) ~ (4, 57) => 0.996927
+(2, 61) ~ (4, 58) => 0.993348
+(2, 62) ~ (4, 59) => 0.981947
+(2, 62) ~ (4, 60) => 0.0112494
+(2, 63) ~ (4, 60) => 0.9742
+(2, 63) ~ (4, 61) => 0.0165366
+(2, 64) ~ (4, 61) => 0.91059
+(2, 64) ~ (4, 62) => 0.0616296
+(2, 65) ~ (4, 61) => 0.0261191
+(2, 65) ~ (4, 62) => 0.846318
+(2, 65) ~ (4, 63) => 0.105919
+(2, 66) ~ (4, 62) => 0.044448
+(2, 66) ~ (4, 63) => 0.59303
+(2, 66) ~ (4, 64) => 0.338282
+(2, 67) ~ (4, 63) => 0.0556393
+(2, 67) ~ (4, 64) => 0.278658
+(2, 67) ~ (4, 65) => 0.637234
+(2, 68) ~ (4, 64) => 0.07158
+(2, 68) ~ (4, 65) => 0.171687
+(2, 68) ~ (4, 66) => 0.747612
+(2, 69) ~ (4, 65) => 0.040292
+(2, 69) ~ (4, 66) => 0.0781537
+(2, 69) ~ (4, 67) => 0.876963
+(2, 70) ~ (4, 68) => 0.99133
+(2, 71) ~ (4, 69) => 0.998491
+(2, 72) ~ (4, 70) => 0.997417
+(2, 73) ~ (4, 71) => 0.997108
+(2, 74) ~ (4, 72) => 0.997789
+(2, 75) ~ (4, 73) => 0.999677
+(2, 76) ~ (4, 74) => 0.999859
+(2, 77) ~ (4, 75) => 0.999964
+(2, 78) ~ (4, 76) => 0.99997
+(2, 79) ~ (4, 77) => 0.999968
+(2, 80) ~ (4, 78) => 0.999961
+(2, 81) ~ (4, 79) => 0.999508
+(2, 82) ~ (4, 80) => 0.998251
+(2, 83) ~ (4, 81) => 0.995278
+(2, 84) ~ (4, 82) => 0.993083
+(2, 85) ~ (4, 83) => 0.97802
+(2, 86) ~ (4, 84) => 0.866778
+(2, 87) ~ (4, 84) => 0.0107565
+(2, 87) ~ (4, 85) => 0.650642
+(2, 87) ~ (4, 87) => 0.012186
+(2, 88) ~ (4, 83) => 0.0198774
+(2, 88) ~ (4, 85) => 0.0300812
+(2, 88) ~ (4, 86) => 0.547291
+(2, 89) ~ (4, 84) => 0.111326
+(2, 89) ~ (4, 86) => 0.0429003
+(2, 89) ~ (4, 87) => 0.319238
+(2, 90) ~ (4, 85) => 0.281191
+(2, 90) ~ (4, 87) => 0.0511776
+(2, 90) ~ (4, 88) => 0.10468
+(2, 90) ~ (4, 95) => 0.0102433
+(2, 91) ~ (4, 86) => 0.358175
+(2, 91) ~ (4, 88) => 0.0486361
+(2, 91) ~ (4, 89) => 0.0277334
+(2, 91) ~ (4, 92) => 0.0105276
+(2, 91) ~ (4, 96) => 0.0155106
+(2, 92) ~ (4, 87) => 0.572855
+(2, 92) ~ (4, 89) => 0.0318876
+(2, 92) ~ (4, 90) => 0.0190857
+(2, 92) ~ (4, 93) => 0.0115667
+(2, 92) ~ (4, 97) => 0.0288382
+(2, 93) ~ (4, 88) => 0.792261
+(2, 93) ~ (4, 90) => 0.0313441
+(2, 93) ~ (4, 94) => 0.0122717
+(2, 93) ~ (4, 98) => 0.0298296
+(2, 94) ~ (4, 89) => 0.881622
+(2, 94) ~ (4, 91) => 0.0365619
+(2, 94) ~ (4, 99) => 0.028593
+(2, 95) ~ (4, 90) => 0.879989
+(2, 95) ~ (4, 92) => 0.0289476
+(2, 95) ~ (4, 94) => 0.0161728
+(2, 95) ~ (4, 100) => 0.0176833
+(2, 96) ~ (4, 91) => 0.867539
+(2, 96) ~ (4, 93) => 0.0120693
+(2, 96) ~ (4, 95) => 0.0378733
+(2, 96) ~ (4, 96) => 0.0230727
+(2, 96) ~ (4, 101) => 0.0121137
+(2, 97) ~ (4, 92) => 0.616811
+(2, 97) ~ (4, 93) => 0.0180544
+(2, 97) ~ (4, 96) => 0.241248
+(2, 97) ~ (4, 97) => 0.06405
+(2, 98) ~ (4, 93) => 0.53878
+(2, 98) ~ (4, 94) => 0.0166467
+(2, 98) ~ (4, 97) => 0.328101
+(2, 98) ~ (4, 98) => 0.0620916
+(2, 99) ~ (4, 94) => 0.509288
+(2, 99) ~ (4, 95) => 0.02923
+(2, 99) ~ (4, 98) => 0.33478
+(2, 99) ~ (4, 99) => 0.0707448
+(2, 100) ~ (4, 95) => 0.382786
+(2, 100) ~ (4, 96) => 0.0339894
+(2, 100) ~ (4, 98) => 0.0331953
+(2, 100) ~ (4, 99) => 0.274706
+(2, 100) ~ (4, 100) => 0.189478
+(2, 100) ~ (4, 101) => 0.0116248
+(2, 101) ~ (4, 96) => 0.260255
+(2, 101) ~ (4, 97) => 0.024511
+(2, 101) ~ (4, 98) => 0.010949
+(2, 101) ~ (4, 99) => 0.0710273
+(2, 101) ~ (4, 100) => 0.227393
+(2, 101) ~ (4, 101) => 0.338392
+(2, 101) ~ (4, 102) => 0.013659
+(2, 102) ~ (4, 97) => 0.143728
+(2, 102) ~ (4, 98) => 0.0147181
+(2, 102) ~ (4, 99) => 0.0159791
+(2, 102) ~ (4, 100) => 0.0961335
+(2, 102) ~ (4, 101) => 0.175616
+(2, 102) ~ (4, 102) => 0.495887
+(2, 102) ~ (4, 103) => 0.0130939
+(2, 103) ~ (4, 98) => 0.0589562
+(2, 103) ~ (4, 99) => 0.0103098
+(2, 103) ~ (4, 100) => 0.0145815
+(2, 103) ~ (4, 101) => 0.112961
+(2, 103) ~ (4, 102) => 0.123724
+(2, 103) ~ (4, 103) => 0.633627
+(2, 104) ~ (4, 99) => 0.027558
+(2, 104) ~ (4, 101) => 0.0106101
+(2, 104) ~ (4, 102) => 0.123473
+(2, 104) ~ (4, 103) => 0.0866922
+(2, 104) ~ (4, 104) => 0.720739
+(2, 105) ~ (4, 100) => 0.0163262
+(2, 105) ~ (4, 103) => 0.0540578
+(2, 105) ~ (4, 104) => 0.0458309
+(2, 105) ~ (4, 105) => 0.855941
+(2, 106) ~ (4, 106) => 0.979616
+(2, 107) ~ (4, 107) => 0.993891
+(2, 108) ~ (4, 108) => 0.99869
+(2, 109) ~ (4, 109) => 0.999881
+(2, 110) ~ (4, 110) => 0.999851
+(2, 111) ~ (4, 111) => 0.999825
+(2, 112) ~ (4, 112) => 0.999916
+(2, 113) ~ (4, 113) => 0.999912
+(2, 114) ~ (4, 114) => 0.999716
+(2, 115) ~ (4, 115) => 0.999642
+(2, 116) ~ (4, 116) => 0.998768
+(2, 117) ~ (4, 117) => 0.998126
+(2, 118) ~ (4, 118) => 0.996002
+(2, 119) ~ (4, 119) => 0.994507
+(2, 120) ~ (4, 120) => 0.987494
+(2, 121) ~ (4, 121) => 0.973605
+(2, 122) ~ (4, 121) => 0.0188086
+(2, 122) ~ (4, 122) => 0.970126
+(2, 123) ~ (4, 122) => 0.0154415
+(2, 123) ~ (4, 123) => 0.972656
+(2, 124) ~ (4, 123) => 0.0104184
+(2, 124) ~ (4, 124) => 0.978272
+(2, 125) ~ (4, 125) => 0.980455
+(2, 126) ~ (4, 126) => 0.985753
+(2, 127) ~ (4, 127) => 0.988099
+(2, 128) ~ (4, 128) => 0.991889
+(2, 129) ~ (4, 129) => 0.992822
+(2, 130) ~ (4, 130) => 0.979845
+(2, 131) ~ (4, 130) => 0.0124043
+(2, 131) ~ (4, 131) => 0.958938
+(2, 132) ~ (4, 131) => 0.0314649
+(2, 132) ~ (4, 132) => 0.939069
+(2, 133) ~ (4, 132) => 0.0499393
+(2, 133) ~ (4, 133) => 0.925327
+(2, 134) ~ (4, 133) => 0.064518
+(2, 134) ~ (4, 134) => 0.904356
+(2, 135) ~ (4, 134) => 0.0874957
+(2, 135) ~ (4, 135) => 0.512627
+(2, 136) ~ (4, 135) => 0.480568
+(2, 136) ~ (4, 136) => 0.121234
+(2, 137) ~ (4, 136) => 0.872754
+(2, 138) ~ (4, 137) => 0.984749
+(2, 139) ~ (4, 138) => 0.985533
+(2, 140) ~ (4, 139) => 0.987889
+(2, 141) ~ (4, 140) => 0.99008
+(2, 142) ~ (4, 141) => 0.993738
+(2, 143) ~ (4, 142) => 0.996114
+(2, 144) ~ (4, 143) => 0.997506
+(2, 145) ~ (4, 144) => 0.99962
+(2, 146) ~ (4, 145) => 0.999148
+(2, 147) ~ (4, 146) => 0.999114
+(2, 148) ~ (4, 147) => 0.99971
+(2, 149) ~ (4, 148) => 0.99998
+(2, 150) ~ (4, 149) => 0.999991
+(2, 151) ~ (4, 150) => 0.999981
+(2, 152) ~ (4, 151) => 0.999897
+(2, 153) ~ (4, 152) => 0.999746
+(2, 154) ~ (4, 153) => 0.999565
+(2, 155) ~ (4, 154) => 0.999748
+(2, 156) ~ (4, 155) => 0.999887
+(2, 157) ~ (4, 156) => 0.99957
+(2, 158) ~ (4, 157) => 0.998851
+(2, 159) ~ (4, 158) => 0.99727
+(2, 160) ~ (4, 159) => 0.99362
+(2, 161) ~ (4, 160) => 0.990669
+(2, 162) ~ (4, 161) => 0.992353
+(2, 163) ~ (4, 162) => 0.992952
+(2, 164) ~ (4, 163) => 0.991736
+(2, 165) ~ (4, 164) => 0.990478
+(2, 166) ~ (4, 165) => 0.990937
+(2, 167) ~ (4, 166) => 0.995662
+(2, 168) ~ (4, 167) => 0.998123
+(2, 169) ~ (4, 168) => 0.999097
+(2, 170) ~ (4, 169) => 0.997298
+(2, 171) ~ (4, 170) => 0.993123
+(2, 172) ~ (4, 171) => 0.992951
+(2, 173) ~ (4, 172) => 0.99647
+(2, 174) ~ (4, 173) => 0.999397
+(2, 175) ~ (4, 174) => 0.999737
+(2, 176) ~ (4, 175) => 0.997772
+(2, 177) ~ (4, 176) => 0.992775
+(2, 178) ~ (4, 177) => 0.987076
+(2, 179) ~ (4, 178) => 0.985322
+(2, 180) ~ (4, 179) => 0.982509
+(2, 181) ~ (4, 180) => 0.985344
+(2, 182) ~ (4, 181) => 0.997318
+(2, 183) ~ (4, 182) => 0.999442
+(2, 184) ~ (4, 183) => 0.999763
+(2, 185) ~ (4, 184) => 0.999256
+(2, 186) ~ (4, 185) => 0.975951
+(2, 186) ~ (4, 187) => 0.0199874
+(2, 187) ~ (4, 186) => 0.95252
+(2, 187) ~ (4, 188) => 0.0398334
+(2, 188) ~ (4, 187) => 0.928999
+(2, 188) ~ (4, 189) => 0.0618365
+(2, 189) ~ (4, 188) => 0.847431
+(2, 189) ~ (4, 189) => 0.011111
+(2, 189) ~ (4, 190) => 0.138835
+(2, 190) ~ (4, 189) => 0.69572
+(2, 190) ~ (4, 191) => 0.292114
+(2, 191) ~ (4, 190) => 0.652804
+(2, 191) ~ (4, 192) => 0.330463
+(2, 192) ~ (4, 191) => 0.632073
+(2, 192) ~ (4, 193) => 0.351775
+(2, 193) ~ (4, 192) => 0.631342
+(2, 193) ~ (4, 194) => 0.347036
+(2, 194) ~ (4, 193) => 0.590139
+(2, 194) ~ (4, 195) => 0.320567
+(2, 194) ~ (4, 196) => 0.0670835
+(2, 195) ~ (4, 194) => 0.362596
+(2, 195) ~ (4, 196) => 0.275061
+(2, 195) ~ (4, 197) => 0.305524
+(2, 196) ~ (4, 194) => 0.034709
+(2, 196) ~ (4, 195) => 0.176677
+(2, 196) ~ (4, 196) => 0.017532
+(2, 196) ~ (4, 197) => 0.220383
+(2, 196) ~ (4, 198) => 0.505078
+(2, 197) ~ (4, 195) => 0.0611033
+(2, 197) ~ (4, 196) => 0.122727
+(2, 197) ~ (4, 197) => 0.0121927
+(2, 197) ~ (4, 198) => 0.104907
+(2, 197) ~ (4, 199) => 0.677572
+(2, 198) ~ (4, 196) => 0.0656269
+(2, 198) ~ (4, 197) => 0.0619828
+(2, 198) ~ (4, 199) => 0.0137467
+(2, 198) ~ (4, 200) => 0.841791
+(2, 199) ~ (4, 197) => 0.0718305
+(2, 199) ~ (4, 198) => 0.0487367
+(2, 199) ~ (4, 201) => 0.854984
+(2, 200) ~ (4, 198) => 0.077077
+(2, 200) ~ (4, 199) => 0.034213
+(2, 200) ~ (4, 202) => 0.859631
+(2, 201) ~ (4, 199) => 0.0903718
+(2, 201) ~ (4, 200) => 0.0215372
+(2, 201) ~ (4, 203) => 0.85827
+(2, 202) ~ (4, 200) => 0.104338
+(2, 202) ~ (4, 201) => 0.0171283
+(2, 202) ~ (4, 204) => 0.854317
+(2, 203) ~ (4, 201) => 0.110089
+(2, 203) ~ (4, 202) => 0.0104044
+(2, 203) ~ (4, 205) => 0.846628
+(2, 204) ~ (4, 202) => 0.121167
+(2, 204) ~ (4, 203) => 0.0116148
+(2, 204) ~ (4, 206) => 0.837301
+(2, 205) ~ (4, 203) => 0.123615
+(2, 205) ~ (4, 207) => 0.821621
+(2, 206) ~ (4, 204) => 0.131417
+(2, 206) ~ (4, 208) => 0.805418
+(2, 207) ~ (4, 205) => 0.142724
+(2, 207) ~ (4, 209) => 0.415746
+(2, 207) ~ (4, 211) => 0.012047
+(2, 208) ~ (4, 206) => 0.157742
+(2, 208) ~ (4, 209) => 0.0284636
+(2, 208) ~ (4, 210) => 0.0623125
+(2, 208) ~ (4, 212) => 0.012678
+(2, 209) ~ (4, 207) => 0.174063
+(2, 209) ~ (4, 210) => 0.0138652
+(2, 209) ~ (4, 211) => 0.0430311
+(2, 209) ~ (4, 213) => 0.0124547
+(2, 210) ~ (4, 208) => 0.189384
+(2, 210) ~ (4, 210) => 0.012139
+(2, 210) ~ (4, 212) => 0.0402627
+(2, 211) ~ (4, 209) => 0.530548
+(2, 211) ~ (4, 211) => 0.0161999
+(2, 211) ~ (4, 213) => 0.0321077
+(2, 212) ~ (4, 210) => 0.895381
+(2, 212) ~ (4, 212) => 0.0123611
+(2, 212) ~ (4, 213) => 0.0121803
+(2, 212) ~ (4, 214) => 0.020117
+(2, 213) ~ (4, 211) => 0.913592
+(2, 213) ~ (4, 213) => 0.0117446
+(2, 213) ~ (4, 214) => 0.0116387
+(2, 213) ~ (4, 215) => 0.0104276
+(2, 214) ~ (4, 212) => 0.912789
+(2, 214) ~ (4, 214) => 0.0141391
+(2, 214) ~ (4, 215) => 0.0128698
+(2, 215) ~ (4, 213) => 0.914548
+(2, 215) ~ (4, 215) => 0.0114202
+(2, 215) ~ (4, 216) => 0.0126945
+(2, 216) ~ (4, 214) => 0.926153
+(2, 216) ~ (4, 216) => 0.0108052
+(2, 216) ~ (4, 217) => 0.0146284
+(2, 217) ~ (4, 215) => 0.934375
+(2, 217) ~ (4, 217) => 0.0112406
+(2, 217) ~ (4, 218) => 0.0164912
+(2, 218) ~ (4, 216) => 0.935083
+(2, 218) ~ (4, 218) => 0.0112321
+(2, 218) ~ (4, 219) => 0.0177604
+(2, 219) ~ (4, 216) => 0.0110034
+(2, 219) ~ (4, 217) => 0.934005
+(2, 219) ~ (4, 219) => 0.0105349
+(2, 219) ~ (4, 220) => 0.0187231
+(2, 220) ~ (4, 217) => 0.0102687
+(2, 220) ~ (4, 218) => 0.916327
+(2, 220) ~ (4, 219) => 0.0131654
+(2, 220) ~ (4, 220) => 0.0102873
+(2, 220) ~ (4, 221) => 0.0262625
+(2, 221) ~ (4, 219) => 0.891568
+(2, 221) ~ (4, 220) => 0.0128061
+(2, 221) ~ (4, 222) => 0.0534843
+(2, 222) ~ (4, 220) => 0.820421
+(2, 222) ~ (4, 221) => 0.0384082
+(2, 222) ~ (4, 222) => 0.0212307
+(2, 222) ~ (4, 223) => 0.071595
+(2, 223) ~ (4, 220) => 0.012806
+(2, 223) ~ (4, 221) => 0.746495
+(2, 223) ~ (4, 222) => 0.0925699
+(2, 223) ~ (4, 223) => 0.0199292
+(2, 223) ~ (4, 224) => 0.0353451
+(2, 224) ~ (4, 221) => 0.0248125
+(2, 224) ~ (4, 222) => 0.594999
+(2, 224) ~ (4, 223) => 0.242043
+(2, 224) ~ (4, 224) => 0.0177007
+(2, 224) ~ (4, 225) => 0.016086
+(2, 225) ~ (4, 222) => 0.0204229
+(2, 225) ~ (4, 223) => 0.375193
+(2, 225) ~ (4, 224) => 0.514634
+(2, 226) ~ (4, 223) => 0.0114303
+(2, 226) ~ (4, 224) => 0.15883
+(2, 226) ~ (4, 225) => 0.78772
+(2, 227) ~ (4, 225) => 0.0134843
+(2, 227) ~ (4, 226) => 0.972605
+(2, 228) ~ (4, 227) => 0.997118
+(2, 229) ~ (4, 228) => 0.99953
+(2, 230) ~ (4, 229) => 0.999896
+(2, 231) ~ (4, 230) => 0.999442
+(2, 232) ~ (4, 231) => 0.997135
+(2, 233) ~ (4, 232) => 0.996669
+(2, 234) ~ (4, 233) => 0.990841
+(2, 235) ~ (4, 234) => 0.984797
+(2, 236) ~ (4, 235) => 0.978651
+(2, 236) ~ (4, 236) => 0.0147076
+(2, 237) ~ (4, 236) => 0.980051
+(2, 237) ~ (4, 237) => 0.010605
+(2, 238) ~ (4, 237) => 0.98635
+
+; gap posteriors
+(2, 0) ~ (4, -1) => 0.00062269
+(2, 1) ~ (4, -1) => 0.00453311
+(2, 2) ~ (4, -1) => 0.00863999
+(2, 3) ~ (4, -1) => 0.0110213
+(2, 4) ~ (4, -1) => 0.0119237
+(2, 5) ~ (4, -1) => 0.013092
+(2, 6) ~ (4, -1) => 0.014429
+(2, 7) ~ (4, -1) => 0.0830709
+(2, 8) ~ (4, -1) => 0.350729
+(2, 9) ~ (4, -1) => 0.463467
+(2, 10) ~ (4, -1) => 0.116926
+(2, 11) ~ (4, -1) => 0.0773618
+(2, 12) ~ (4, -1) => 0.016596
+(2, 13) ~ (4, -1) => 0.00825429
+(2, 14) ~ (4, -1) => 0.008053
+(2, 15) ~ (4, -1) => 0.0086053
+(2, 16) ~ (4, -1) => 0.00935233
+(2, 17) ~ (4, -1) => 0.00992477
+(2, 18) ~ (4, -1) => 0.0181813
+(2, 19) ~ (4, -1) => 0.00463468
+(2, 20) ~ (4, -1) => 0.0110455
+(2, 21) ~ (4, -1) => 0.00476062
+(2, 22) ~ (4, -1) => 0.00310576
+(2, 23) ~ (4, -1) => 0.000410557
+(2, 24) ~ (4, -1) => 0.0001
+(2, 25) ~ (4, -1) => 0.0001
+(2, 26) ~ (4, -1) => 0.000816047
+(2, 27) ~ (4, -1) => 0.00429708
+(2, 28) ~ (4, -1) => 0.000781747
+(2, 29) ~ (4, -1) => 0.00119404
+(2, 30) ~ (4, -1) => 0.00300038
+(2, 31) ~ (4, -1) => 0.00650832
+(2, 32) ~ (4, -1) => 0.0287281
+(2, 33) ~ (4, -1) => 0.00381321
+(2, 34) ~ (4, -1) => 0.00211066
+(2, 35) ~ (4, -1) => 0.00271636
+(2, 36) ~ (4, -1) => 0.00274605
+(2, 37) ~ (4, -1) => 0.00221103
+(2, 38) ~ (4, -1) => 0.00140423
+(2, 39) ~ (4, -1) => 0.000929892
+(2, 40) ~ (4, -1) => 0.000607491
+(2, 41) ~ (4, -1) => 0.000573993
+(2, 42) ~ (4, -1) => 0.000804245
+(2, 43) ~ (4, -1) => 0.00134856
+(2, 44) ~ (4, -1) => 0.00202239
+(2, 45) ~ (4, -1) => 0.00408912
+(2, 46) ~ (4, -1) => 0.0201854
+(2, 47) ~ (4, -1) => 0.0474404
+(2, 48) ~ (4, -1) => 0.273146
+(2, 49) ~ (4, -1) => 0.267254
+(2, 50) ~ (4, -1) => 0.0557452
+(2, 51) ~ (4, -1) => 0.0288975
+(2, 52) ~ (4, -1) => 0.0325528
+(2, 53) ~ (4, -1) => 0.055339
+(2, 54) ~ (4, -1) => 0.058572
+(2, 55) ~ (4, -1) => 0.67118
+(2, 56) ~ (4, -1) => 0.67829
+(2, 57) ~ (4, -1) => 0.0307745
+(2, 58) ~ (4, -1) => 0.00377047
+(2, 59) ~ (4, -1) => 0.000926435
+(2, 60) ~ (4, -1) => 0.00307328
+(2, 61) ~ (4, -1) => 0.00665247
+(2, 62) ~ (4, -1) => 0.00680327
+(2, 63) ~ (4, -1) => 0.00926384
+(2, 64) ~ (4, -1) => 0.0277806
+(2, 65) ~ (4, -1) => 0.0216434
+(2, 66) ~ (4, -1) => 0.0242403
+(2, 67) ~ (4, -1) => 0.0284685
+(2, 68) ~ (4, -1) => 0.00912088
+(2, 69) ~ (4, -1) => 0.00459129
+(2, 70) ~ (4, -1) => 0.00866979
+(2, 71) ~ (4, -1) => 0.00150871
+(2, 72) ~ (4, -1) => 0.00258303
+(2, 73) ~ (4, -1) => 0.00289243
+(2, 74) ~ (4, -1) => 0.00221103
+(2, 75) ~ (4, -1) => 0.000323296
+(2, 76) ~ (4, -1) => 0.000140965
+(2, 77) ~ (4, -1) => 0.0001
+(2, 78) ~ (4, -1) => 0.0001
+(2, 79) ~ (4, -1) => 0.0001
+(2, 80) ~ (4, -1) => 0.0001
+(2, 81) ~ (4, -1) => 0.000492096
+(2, 82) ~ (4, -1) => 0.00174868
+(2, 83) ~ (4, -1) => 0.00472194
+(2, 84) ~ (4, -1) => 0.00691682
+(2, 85) ~ (4, -1) => 0.0219796
+(2, 86) ~ (4, -1) => 0.133222
+(2, 87) ~ (4, -1) => 0.326416
+(2, 88) ~ (4, -1) => 0.40275
+(2, 89) ~ (4, -1) => 0.526536
+(2, 90) ~ (4, -1) => 0.552709
+(2, 91) ~ (4, -1) => 0.539417
+(2, 92) ~ (4, -1) => 0.335767
+(2, 93) ~ (4, -1) => 0.134293
+(2, 94) ~ (4, -1) => 0.0532236
+(2, 95) ~ (4, -1) => 0.0572075
+(2, 96) ~ (4, -1) => 0.0473324
+(2, 97) ~ (4, -1) => 0.0598365
+(2, 98) ~ (4, -1) => 0.0543806
+(2, 99) ~ (4, -1) => 0.0559572
+(2, 100) ~ (4, -1) => 0.0742205
+(2, 101) ~ (4, -1) => 0.0538141
+(2, 102) ~ (4, -1) => 0.0448444
+(2, 103) ~ (4, -1) => 0.0458398
+(2, 104) ~ (4, -1) => 0.0309274
+(2, 105) ~ (4, -1) => 0.027844
+(2, 106) ~ (4, -1) => 0.0203845
+(2, 107) ~ (4, -1) => 0.00610912
+(2, 108) ~ (4, -1) => 0.00131005
+(2, 109) ~ (4, -1) => 0.000118613
+(2, 110) ~ (4, -1) => 0.00014931
+(2, 111) ~ (4, -1) => 0.000175178
+(2, 112) ~ (4, -1) => 0.0001
+(2, 113) ~ (4, -1) => 0.0001
+(2, 114) ~ (4, -1) => 0.000283778
+(2, 115) ~ (4, -1) => 0.000357509
+(2, 116) ~ (4, -1) => 0.00123197
+(2, 117) ~ (4, -1) => 0.00187367
+(2, 118) ~ (4, -1) => 0.00399792
+(2, 119) ~ (4, -1) => 0.00549346
+(2, 120) ~ (4, -1) => 0.0125063
+(2, 121) ~ (4, -1) => 0.0263948
+(2, 122) ~ (4, -1) => 0.0110652
+(2, 123) ~ (4, -1) => 0.011902
+(2, 124) ~ (4, -1) => 0.01131
+(2, 125) ~ (4, -1) => 0.0195451
+(2, 126) ~ (4, -1) => 0.0142466
+(2, 127) ~ (4, -1) => 0.0119007
+(2, 128) ~ (4, -1) => 0.00811148
+(2, 129) ~ (4, -1) => 0.00717759
+(2, 130) ~ (4, -1) => 0.0201553
+(2, 131) ~ (4, -1) => 0.0286579
+(2, 132) ~ (4, -1) => 0.0294662
+(2, 133) ~ (4, -1) => 0.024734
+(2, 134) ~ (4, -1) => 0.031126
+(2, 135) ~ (4, -1) => 0.399877
+(2, 136) ~ (4, -1) => 0.398198
+(2, 137) ~ (4, -1) => 0.127246
+(2, 138) ~ (4, -1) => 0.0152509
+(2, 139) ~ (4, -1) => 0.0144674
+(2, 140) ~ (4, -1) => 0.0121113
+(2, 141) ~ (4, -1) => 0.00992012
+(2, 142) ~ (4, -1) => 0.00626224
+(2, 143) ~ (4, -1) => 0.0038864
+(2, 144) ~ (4, -1) => 0.0024935
+(2, 145) ~ (4, -1) => 0.000380337
+(2, 146) ~ (4, -1) => 0.000851691
+(2, 147) ~ (4, -1) => 0.000886083
+(2, 148) ~ (4, -1) => 0.000290334
+(2, 149) ~ (4, -1) => 0.0001
+(2, 150) ~ (4, -1) => 0.0001
+(2, 151) ~ (4, -1) => 0.0001
+(2, 152) ~ (4, -1) => 0.000103354
+(2, 153) ~ (4, -1) => 0.000254452
+(2, 154) ~ (4, -1) => 0.000435233
+(2, 155) ~ (4, -1) => 0.000251949
+(2, 156) ~ (4, -1) => 0.000113487
+(2, 157) ~ (4, -1) => 0.000429749
+(2, 158) ~ (4, -1) => 0.00114912
+(2, 159) ~ (4, -1) => 0.00273001
+(2, 160) ~ (4, -1) => 0.00637978
+(2, 161) ~ (4, -1) => 0.00933099
+(2, 162) ~ (4, -1) => 0.00764734
+(2, 163) ~ (4, -1) => 0.00704801
+(2, 164) ~ (4, -1) => 0.00826371
+(2, 165) ~ (4, -1) => 0.00952238
+(2, 166) ~ (4, -1) => 0.00906336
+(2, 167) ~ (4, -1) => 0.0043382
+(2, 168) ~ (4, -1) => 0.00187695
+(2, 169) ~ (4, -1) => 0.000902832
+(2, 170) ~ (4, -1) => 0.00270224
+(2, 171) ~ (4, -1) => 0.00687683
+(2, 172) ~ (4, -1) => 0.00704914
+(2, 173) ~ (4, -1) => 0.00353038
+(2, 174) ~ (4, -1) => 0.000602961
+(2, 175) ~ (4, -1) => 0.000262678
+(2, 176) ~ (4, -1) => 0.00222796
+(2, 177) ~ (4, -1) => 0.00722468
+(2, 178) ~ (4, -1) => 0.0129237
+(2, 179) ~ (4, -1) => 0.0146778
+(2, 180) ~ (4, -1) => 0.017491
+(2, 181) ~ (4, -1) => 0.0146556
+(2, 182) ~ (4, -1) => 0.00268197
+(2, 183) ~ (4, -1) => 0.000558078
+(2, 184) ~ (4, -1) => 0.000236571
+(2, 185) ~ (4, -1) => 0.000744045
+(2, 186) ~ (4, -1) => 0.00406203
+(2, 187) ~ (4, -1) => 0.00764645
+(2, 188) ~ (4, -1) => 0.00916406
+(2, 189) ~ (4, -1) => 0.00262232
+(2, 190) ~ (4, -1) => 0.012166
+(2, 191) ~ (4, -1) => 0.0167331
+(2, 192) ~ (4, -1) => 0.016152
+(2, 193) ~ (4, -1) => 0.0216224
+(2, 194) ~ (4, -1) => 0.0222099
+(2, 195) ~ (4, -1) => 0.056819
+(2, 196) ~ (4, -1) => 0.0456216
+(2, 197) ~ (4, -1) => 0.0214978
+(2, 198) ~ (4, -1) => 0.0168523
+(2, 199) ~ (4, -1) => 0.0244486
+(2, 200) ~ (4, -1) => 0.0290787
+(2, 201) ~ (4, -1) => 0.0298215
+(2, 202) ~ (4, -1) => 0.0242169
+(2, 203) ~ (4, -1) => 0.0328787
+(2, 204) ~ (4, -1) => 0.0299174
+(2, 205) ~ (4, -1) => 0.0547638
+(2, 206) ~ (4, -1) => 0.0631655
+(2, 207) ~ (4, -1) => 0.429483
+(2, 208) ~ (4, -1) => 0.738804
+(2, 209) ~ (4, -1) => 0.756586
+(2, 210) ~ (4, -1) => 0.758214
+(2, 211) ~ (4, -1) => 0.421144
+(2, 212) ~ (4, -1) => 0.0599611
+(2, 213) ~ (4, -1) => 0.0525968
+(2, 214) ~ (4, -1) => 0.0602022
+(2, 215) ~ (4, -1) => 0.0613375
+(2, 216) ~ (4, -1) => 0.0484139
+(2, 217) ~ (4, -1) => 0.0378929
+(2, 218) ~ (4, -1) => 0.0359247
+(2, 219) ~ (4, -1) => 0.0257336
+(2, 220) ~ (4, -1) => 0.0236891
+(2, 221) ~ (4, -1) => 0.042142
+(2, 222) ~ (4, -1) => 0.0483451
+(2, 223) ~ (4, -1) => 0.0928549
+(2, 224) ~ (4, -1) => 0.104359
+(2, 225) ~ (4, -1) => 0.0897496
+(2, 226) ~ (4, -1) => 0.0420197
+(2, 227) ~ (4, -1) => 0.0139104
+(2, 228) ~ (4, -1) => 0.00288236
+(2, 229) ~ (4, -1) => 0.000469625
+(2, 230) ~ (4, -1) => 0.000104487
+(2, 231) ~ (4, -1) => 0.000557661
+(2, 232) ~ (4, -1) => 0.00286484
+(2, 233) ~ (4, -1) => 0.00333089
+(2, 234) ~ (4, -1) => 0.00915939
+(2, 235) ~ (4, -1) => 0.0152034
+(2, 236) ~ (4, -1) => 0.00664109
+(2, 237) ~ (4, -1) => 0.0093443
+(2, 238) ~ (4, -1) => 0.0136502
+
+(2, -1) ~ (4, 0) => 0.00062269
+(2, -1) ~ (4, 1) => 0.00453311
+(2, -1) ~ (4, 2) => 0.00863999
+(2, -1) ~ (4, 3) => 0.0110213
+(2, -1) ~ (4, 4) => 0.0119237
+(2, -1) ~ (4, 5) => 0.013092
+(2, -1) ~ (4, 6) => 0.014429
+(2, -1) ~ (4, 7) => 0.0219079
+(2, -1) ~ (4, 8) => 0.0207269
+(2, -1) ~ (4, 9) => 0.0290906
+(2, -1) ~ (4, 10) => 0.0198284
+(2, -1) ~ (4, 11) => 0.016596
+(2, -1) ~ (4, 12) => 0.00825429
+(2, -1) ~ (4, 13) => 0.008053
+(2, -1) ~ (4, 14) => 0.0086053
+(2, -1) ~ (4, 15) => 0.00935233
+(2, -1) ~ (4, 16) => 0.00992477
+(2, -1) ~ (4, 17) => 0.00404928
+(2, -1) ~ (4, 18) => 0.0187666
+(2, -1) ~ (4, 19) => 0.0110455
+(2, -1) ~ (4, 20) => 0.00476062
+(2, -1) ~ (4, 21) => 0.00310576
+(2, -1) ~ (4, 22) => 0.000410557
+(2, -1) ~ (4, 23) => 0.0001
+(2, -1) ~ (4, 24) => 0.0001
+(2, -1) ~ (4, 25) => 0.000816047
+(2, -1) ~ (4, 26) => 0.00429708
+(2, -1) ~ (4, 27) => 0.0136752
+(2, -1) ~ (4, 28) => 0.0035544
+(2, -1) ~ (4, 29) => 0.01147
+(2, -1) ~ (4, 30) => 0.00729352
+(2, -1) ~ (4, 31) => 0.00421947
+(2, -1) ~ (4, 32) => 0.00381321
+(2, -1) ~ (4, 33) => 0.00211066
+(2, -1) ~ (4, 34) => 0.00271636
+(2, -1) ~ (4, 35) => 0.00274605
+(2, -1) ~ (4, 36) => 0.00221103
+(2, -1) ~ (4, 37) => 0.00140423
+(2, -1) ~ (4, 38) => 0.000929892
+(2, -1) ~ (4, 39) => 0.000607491
+(2, -1) ~ (4, 40) => 0.000573993
+(2, -1) ~ (4, 41) => 0.000804245
+(2, -1) ~ (4, 42) => 0.00134856
+(2, -1) ~ (4, 43) => 0.00202239
+(2, -1) ~ (4, 44) => 0.00408912
+(2, -1) ~ (4, 45) => 0.0201854
+(2, -1) ~ (4, 46) => 0.0135075
+(2, -1) ~ (4, 47) => 0.0312583
+(2, -1) ~ (4, 48) => 0.0230699
+(2, -1) ~ (4, 49) => 0.0429817
+(2, -1) ~ (4, 50) => 0.0329728
+(2, -1) ~ (4, 51) => 0.0273381
+(2, -1) ~ (4, 52) => 0.016012
+(2, -1) ~ (4, 53) => 0.00875157
+(2, -1) ~ (4, 54) => 0.0032993
+(2, -1) ~ (4, 55) => 0.00377047
+(2, -1) ~ (4, 56) => 0.000926435
+(2, -1) ~ (4, 57) => 0.00307328
+(2, -1) ~ (4, 58) => 0.00665247
+(2, -1) ~ (4, 59) => 0.0180526
+(2, -1) ~ (4, 60) => 0.0145511
+(2, -1) ~ (4, 61) => 0.0467543
+(2, -1) ~ (4, 62) => 0.0476042
+(2, -1) ~ (4, 63) => 0.245412
+(2, -1) ~ (4, 64) => 0.31148
+(2, -1) ~ (4, 65) => 0.150787
+(2, -1) ~ (4, 66) => 0.174234
+(2, -1) ~ (4, 67) => 0.123037
+(2, -1) ~ (4, 68) => 0.00866979
+(2, -1) ~ (4, 69) => 0.00150871
+(2, -1) ~ (4, 70) => 0.00258303
+(2, -1) ~ (4, 71) => 0.00289243
+(2, -1) ~ (4, 72) => 0.00221103
+(2, -1) ~ (4, 73) => 0.000323296
+(2, -1) ~ (4, 74) => 0.000140965
+(2, -1) ~ (4, 75) => 0.0001
+(2, -1) ~ (4, 76) => 0.0001
+(2, -1) ~ (4, 77) => 0.0001
+(2, -1) ~ (4, 78) => 0.0001
+(2, -1) ~ (4, 79) => 0.000492096
+(2, -1) ~ (4, 80) => 0.00174868
+(2, -1) ~ (4, 81) => 0.00472194
+(2, -1) ~ (4, 82) => 0.00691682
+(2, -1) ~ (4, 83) => 0.00210216
+(2, -1) ~ (4, 84) => 0.0111396
+(2, -1) ~ (4, 85) => 0.0380861
+(2, -1) ~ (4, 86) => 0.0516339
+(2, -1) ~ (4, 87) => 0.0445442
+(2, -1) ~ (4, 88) => 0.0544231
+(2, -1) ~ (4, 89) => 0.0587574
+(2, -1) ~ (4, 90) => 0.0695813
+(2, -1) ~ (4, 91) => 0.0958995
+(2, -1) ~ (4, 92) => 0.343714
+(2, -1) ~ (4, 93) => 0.41953
+(2, -1) ~ (4, 94) => 0.445621
+(2, -1) ~ (4, 95) => 0.539867
+(2, -1) ~ (4, 96) => 0.425924
+(2, -1) ~ (4, 97) => 0.410771
+(2, -1) ~ (4, 98) => 0.45548
+(2, -1) ~ (4, 99) => 0.501082
+(2, -1) ~ (4, 100) => 0.438405
+(2, -1) ~ (4, 101) => 0.338683
+(2, -1) ~ (4, 102) => 0.243256
+(2, -1) ~ (4, 103) => 0.212529
+(2, -1) ~ (4, 104) => 0.23343
+(2, -1) ~ (4, 105) => 0.144059
+(2, -1) ~ (4, 106) => 0.0203845
+(2, -1) ~ (4, 107) => 0.00610912
+(2, -1) ~ (4, 108) => 0.00131005
+(2, -1) ~ (4, 109) => 0.000118613
+(2, -1) ~ (4, 110) => 0.00014931
+(2, -1) ~ (4, 111) => 0.000175178
+(2, -1) ~ (4, 112) => 0.0001
+(2, -1) ~ (4, 113) => 0.0001
+(2, -1) ~ (4, 114) => 0.000283778
+(2, -1) ~ (4, 115) => 0.000357509
+(2, -1) ~ (4, 116) => 0.00123197
+(2, -1) ~ (4, 117) => 0.00187367
+(2, -1) ~ (4, 118) => 0.00399792
+(2, -1) ~ (4, 119) => 0.00549346
+(2, -1) ~ (4, 120) => 0.0125063
+(2, -1) ~ (4, 121) => 0.00758627
+(2, -1) ~ (4, 122) => 0.0144323
+(2, -1) ~ (4, 123) => 0.0169252
+(2, -1) ~ (4, 124) => 0.0217284
+(2, -1) ~ (4, 125) => 0.0195451
+(2, -1) ~ (4, 126) => 0.0142466
+(2, -1) ~ (4, 127) => 0.0119007
+(2, -1) ~ (4, 128) => 0.00811148
+(2, -1) ~ (4, 129) => 0.00717759
+(2, -1) ~ (4, 130) => 0.00775095
+(2, -1) ~ (4, 131) => 0.00959737
+(2, -1) ~ (4, 132) => 0.0109917
+(2, -1) ~ (4, 133) => 0.0101552
+(2, -1) ~ (4, 134) => 0.00814831
+(2, -1) ~ (4, 135) => 0.0068053
+(2, -1) ~ (4, 136) => 0.00601137
+(2, -1) ~ (4, 137) => 0.0152509
+(2, -1) ~ (4, 138) => 0.0144674
+(2, -1) ~ (4, 139) => 0.0121113
+(2, -1) ~ (4, 140) => 0.00992012
+(2, -1) ~ (4, 141) => 0.00626224
+(2, -1) ~ (4, 142) => 0.0038864
+(2, -1) ~ (4, 143) => 0.0024935
+(2, -1) ~ (4, 144) => 0.000380337
+(2, -1) ~ (4, 145) => 0.000851691
+(2, -1) ~ (4, 146) => 0.000886083
+(2, -1) ~ (4, 147) => 0.000290334
+(2, -1) ~ (4, 148) => 0.0001
+(2, -1) ~ (4, 149) => 0.0001
+(2, -1) ~ (4, 150) => 0.0001
+(2, -1) ~ (4, 151) => 0.000103354
+(2, -1) ~ (4, 152) => 0.000254452
+(2, -1) ~ (4, 153) => 0.000435233
+(2, -1) ~ (4, 154) => 0.000251949
+(2, -1) ~ (4, 155) => 0.000113487
+(2, -1) ~ (4, 156) => 0.000429749
+(2, -1) ~ (4, 157) => 0.00114912
+(2, -1) ~ (4, 158) => 0.00273001
+(2, -1) ~ (4, 159) => 0.00637978
+(2, -1) ~ (4, 160) => 0.00933099
+(2, -1) ~ (4, 161) => 0.00764734
+(2, -1) ~ (4, 162) => 0.00704801
+(2, -1) ~ (4, 163) => 0.00826371
+(2, -1) ~ (4, 164) => 0.00952238
+(2, -1) ~ (4, 165) => 0.00906336
+(2, -1) ~ (4, 166) => 0.0043382
+(2, -1) ~ (4, 167) => 0.00187695
+(2, -1) ~ (4, 168) => 0.000902832
+(2, -1) ~ (4, 169) => 0.00270224
+(2, -1) ~ (4, 170) => 0.00687683
+(2, -1) ~ (4, 171) => 0.00704914
+(2, -1) ~ (4, 172) => 0.00353038
+(2, -1) ~ (4, 173) => 0.000602961
+(2, -1) ~ (4, 174) => 0.000262678
+(2, -1) ~ (4, 175) => 0.00222796
+(2, -1) ~ (4, 176) => 0.00722468
+(2, -1) ~ (4, 177) => 0.0129237
+(2, -1) ~ (4, 178) => 0.0146778
+(2, -1) ~ (4, 179) => 0.017491
+(2, -1) ~ (4, 180) => 0.0146556
+(2, -1) ~ (4, 181) => 0.00268197
+(2, -1) ~ (4, 182) => 0.000558078
+(2, -1) ~ (4, 183) => 0.000236571
+(2, -1) ~ (4, 184) => 0.000744045
+(2, -1) ~ (4, 185) => 0.0240494
+(2, -1) ~ (4, 186) => 0.0474799
+(2, -1) ~ (4, 187) => 0.0510132
+(2, -1) ~ (4, 188) => 0.112735
+(2, -1) ~ (4, 189) => 0.231332
+(2, -1) ~ (4, 190) => 0.20836
+(2, -1) ~ (4, 191) => 0.075813
+(2, -1) ~ (4, 192) => 0.0381954
+(2, -1) ~ (4, 193) => 0.058086
+(2, -1) ~ (4, 194) => 0.255659
+(2, -1) ~ (4, 195) => 0.441653
+(2, -1) ~ (4, 196) => 0.45197
+(2, -1) ~ (4, 197) => 0.328087
+(2, -1) ~ (4, 198) => 0.264202
+(2, -1) ~ (4, 199) => 0.184096
+(2, -1) ~ (4, 200) => 0.0323336
+(2, -1) ~ (4, 201) => 0.0177981
+(2, -1) ~ (4, 202) => 0.00879744
+(2, -1) ~ (4, 203) => 0.00650025
+(2, -1) ~ (4, 204) => 0.0142664
+(2, -1) ~ (4, 205) => 0.0106484
+(2, -1) ~ (4, 206) => 0.0049572
+(2, -1) ~ (4, 207) => 0.00431652
+(2, -1) ~ (4, 208) => 0.00519815
+(2, -1) ~ (4, 209) => 0.0252416
+(2, -1) ~ (4, 210) => 0.0163028
+(2, -1) ~ (4, 211) => 0.0151296
+(2, -1) ~ (4, 212) => 0.0219094
+(2, -1) ~ (4, 213) => 0.0169649
+(2, -1) ~ (4, 214) => 0.0279526
+(2, -1) ~ (4, 215) => 0.0309072
+(2, -1) ~ (4, 216) => 0.0304141
+(2, -1) ~ (4, 217) => 0.0298573
+(2, -1) ~ (4, 218) => 0.0559497
+(2, -1) ~ (4, 219) => 0.0669718
+(2, -1) ~ (4, 220) => 0.124957
+(2, -1) ~ (4, 221) => 0.164022
+(2, -1) ~ (4, 222) => 0.217293
+(2, -1) ~ (4, 223) => 0.27981
+(2, -1) ~ (4, 224) => 0.27349
+(2, -1) ~ (4, 225) => 0.18271
+(2, -1) ~ (4, 226) => 0.0273947
+(2, -1) ~ (4, 227) => 0.00288236
+(2, -1) ~ (4, 228) => 0.000469625
+(2, -1) ~ (4, 229) => 0.000104487
+(2, -1) ~ (4, 230) => 0.000557661
+(2, -1) ~ (4, 231) => 0.00286484
+(2, -1) ~ (4, 232) => 0.00333089
+(2, -1) ~ (4, 233) => 0.00915939
+(2, -1) ~ (4, 234) => 0.0152034
+(2, -1) ~ (4, 235) => 0.0213487
+(2, -1) ~ (4, 236) => 0.00524175
+(2, -1) ~ (4, 237) => 0.00304514
+
+; Sparse posterior probability matrix for sequences 2 and 5
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (5, 0) => 0.965705
+(2, 1) ~ (5, 1) => 0.866912
+(2, 1) ~ (5, 2) => 0.0312267
+(2, 2) ~ (5, 1) => 0.04144
+(2, 2) ~ (5, 2) => 0.681972
+(2, 2) ~ (5, 3) => 0.10241
+(2, 3) ~ (5, 1) => 0.0412685
+(2, 3) ~ (5, 2) => 0.0721227
+(2, 3) ~ (5, 3) => 0.539545
+(2, 3) ~ (5, 4) => 0.142845
+(2, 4) ~ (5, 2) => 0.101023
+(2, 4) ~ (5, 3) => 0.104643
+(2, 4) ~ (5, 4) => 0.343271
+(2, 4) ~ (5, 5) => 0.227508
+(2, 5) ~ (5, 2) => 0.0250082
+(2, 5) ~ (5, 3) => 0.16432
+(2, 5) ~ (5, 4) => 0.139211
+(2, 5) ~ (5, 5) => 0.189193
+(2, 5) ~ (5, 6) => 0.295575
+(2, 6) ~ (5, 3) => 0.0258215
+(2, 6) ~ (5, 4) => 0.234175
+(2, 6) ~ (5, 5) => 0.1307
+(2, 6) ~ (5, 6) => 0.0874166
+(2, 6) ~ (5, 7) => 0.301663
+(2, 7) ~ (5, 4) => 0.0314763
+(2, 7) ~ (5, 5) => 0.331163
+(2, 7) ~ (5, 6) => 0.128676
+(2, 7) ~ (5, 7) => 0.0407108
+(2, 7) ~ (5, 8) => 0.220162
+(2, 8) ~ (5, 5) => 0.0249036
+(2, 8) ~ (5, 6) => 0.432568
+(2, 8) ~ (5, 7) => 0.0671472
+(2, 8) ~ (5, 8) => 0.0305563
+(2, 8) ~ (5, 9) => 0.0588956
+(2, 9) ~ (5, 6) => 0.0111232
+(2, 9) ~ (5, 7) => 0.564082
+(2, 9) ~ (5, 8) => 0.0184652
+(2, 9) ~ (5, 9) => 0.0315808
+(2, 9) ~ (5, 10) => 0.0298202
+(2, 10) ~ (5, 8) => 0.714369
+(2, 10) ~ (5, 10) => 0.0260196
+(2, 11) ~ (5, 9) => 0.896072
+(2, 11) ~ (5, 11) => 0.0205885
+(2, 12) ~ (5, 10) => 0.931911
+(2, 12) ~ (5, 12) => 0.0141002
+(2, 13) ~ (5, 11) => 0.964756
+(2, 13) ~ (5, 13) => 0.0117975
+(2, 14) ~ (5, 12) => 0.975583
+(2, 15) ~ (5, 13) => 0.981036
+(2, 16) ~ (5, 14) => 0.988281
+(2, 17) ~ (5, 15) => 0.994784
+(2, 18) ~ (5, 16) => 0.994695
+(2, 19) ~ (5, 17) => 0.995438
+(2, 20) ~ (5, 18) => 0.997763
+(2, 21) ~ (5, 19) => 0.99898
+(2, 22) ~ (5, 20) => 0.999323
+(2, 23) ~ (5, 21) => 0.999899
+(2, 24) ~ (5, 22) => 0.99997
+(2, 25) ~ (5, 23) => 0.999995
+(2, 26) ~ (5, 24) => 0.999981
+(2, 27) ~ (5, 25) => 0.99992
+(2, 28) ~ (5, 26) => 0.999885
+(2, 29) ~ (5, 27) => 0.999843
+(2, 30) ~ (5, 28) => 0.99989
+(2, 31) ~ (5, 29) => 0.999696
+(2, 32) ~ (5, 30) => 0.999401
+(2, 33) ~ (5, 31) => 0.999288
+(2, 34) ~ (5, 32) => 0.999081
+(2, 35) ~ (5, 33) => 0.998717
+(2, 36) ~ (5, 34) => 0.996334
+(2, 37) ~ (5, 35) => 0.993133
+(2, 38) ~ (5, 36) => 0.984039
+(2, 39) ~ (5, 37) => 0.968068
+(2, 40) ~ (5, 38) => 0.916848
+(2, 41) ~ (5, 36) => 0.0105432
+(2, 41) ~ (5, 39) => 0.749724
+(2, 42) ~ (5, 37) => 0.0251114
+(2, 42) ~ (5, 40) => 0.737548
+(2, 43) ~ (5, 38) => 0.0761803
+(2, 43) ~ (5, 41) => 0.678643
+(2, 44) ~ (5, 39) => 0.239359
+(2, 44) ~ (5, 42) => 0.610671
+(2, 45) ~ (5, 40) => 0.252951
+(2, 45) ~ (5, 43) => 0.602419
+(2, 46) ~ (5, 41) => 0.317195
+(2, 46) ~ (5, 44) => 0.58781
+(2, 47) ~ (5, 42) => 0.387866
+(2, 47) ~ (5, 45) => 0.56844
+(2, 48) ~ (5, 43) => 0.396638
+(2, 48) ~ (5, 46) => 0.517664
+(2, 49) ~ (5, 44) => 0.403306
+(2, 49) ~ (5, 45) => 0.0191756
+(2, 49) ~ (5, 47) => 0.486331
+(2, 50) ~ (5, 45) => 0.408563
+(2, 50) ~ (5, 46) => 0.0571094
+(2, 50) ~ (5, 48) => 0.483039
+(2, 51) ~ (5, 46) => 0.421247
+(2, 51) ~ (5, 47) => 0.0787423
+(2, 51) ~ (5, 49) => 0.479044
+(2, 52) ~ (5, 47) => 0.433354
+(2, 52) ~ (5, 48) => 0.0802008
+(2, 52) ~ (5, 50) => 0.476712
+(2, 53) ~ (5, 48) => 0.432135
+(2, 53) ~ (5, 49) => 0.0833132
+(2, 53) ~ (5, 51) => 0.473256
+(2, 54) ~ (5, 49) => 0.430304
+(2, 54) ~ (5, 50) => 0.0873997
+(2, 54) ~ (5, 52) => 0.468644
+(2, 55) ~ (5, 50) => 0.427978
+(2, 55) ~ (5, 51) => 0.0956219
+(2, 55) ~ (5, 53) => 0.0195892
+(2, 56) ~ (5, 51) => 0.416475
+(2, 56) ~ (5, 52) => 0.113844
+(2, 57) ~ (5, 52) => 0.0134649
+(2, 57) ~ (5, 53) => 0.966558
+(2, 58) ~ (5, 54) => 0.996983
+(2, 59) ~ (5, 55) => 0.99977
+(2, 60) ~ (5, 56) => 0.99995
+(2, 61) ~ (5, 57) => 0.999979
+(2, 62) ~ (5, 58) => 0.999917
+(2, 63) ~ (5, 59) => 0.999916
+(2, 64) ~ (5, 60) => 0.999893
+(2, 65) ~ (5, 61) => 0.999869
+(2, 66) ~ (5, 62) => 0.999876
+(2, 67) ~ (5, 63) => 0.99996
+(2, 68) ~ (5, 64) => 0.999984
+(2, 69) ~ (5, 65) => 0.999983
+(2, 70) ~ (5, 66) => 0.999992
+(2, 71) ~ (5, 67) => 0.999994
+(2, 72) ~ (5, 68) => 0.999941
+(2, 73) ~ (5, 69) => 0.999924
+(2, 74) ~ (5, 70) => 0.999934
+(2, 75) ~ (5, 71) => 0.999988
+(2, 76) ~ (5, 72) => 0.999991
+(2, 77) ~ (5, 73) => 0.999992
+(2, 78) ~ (5, 74) => 0.99998
+(2, 79) ~ (5, 75) => 0.999972
+(2, 80) ~ (5, 76) => 0.999942
+(2, 81) ~ (5, 77) => 0.998714
+(2, 82) ~ (5, 78) => 0.998271
+(2, 83) ~ (5, 79) => 0.997722
+(2, 84) ~ (5, 80) => 0.997628
+(2, 85) ~ (5, 81) => 0.998095
+(2, 86) ~ (5, 82) => 0.998589
+(2, 87) ~ (5, 83) => 0.998864
+(2, 88) ~ (5, 84) => 0.999273
+(2, 89) ~ (5, 85) => 0.999504
+(2, 90) ~ (5, 86) => 0.999718
+(2, 91) ~ (5, 87) => 0.999721
+(2, 92) ~ (5, 88) => 0.999901
+(2, 93) ~ (5, 89) => 0.999755
+(2, 94) ~ (5, 90) => 0.999724
+(2, 95) ~ (5, 91) => 0.999337
+(2, 96) ~ (5, 92) => 0.999023
+(2, 97) ~ (5, 93) => 0.999149
+(2, 98) ~ (5, 94) => 0.999351
+(2, 99) ~ (5, 95) => 0.999452
+(2, 100) ~ (5, 96) => 0.99849
+(2, 101) ~ (5, 97) => 0.998197
+(2, 102) ~ (5, 98) => 0.997855
+(2, 103) ~ (5, 99) => 0.997752
+(2, 104) ~ (5, 100) => 0.998128
+(2, 105) ~ (5, 101) => 0.999121
+(2, 106) ~ (5, 102) => 0.999536
+(2, 107) ~ (5, 103) => 0.999763
+(2, 108) ~ (5, 104) => 0.999916
+(2, 109) ~ (5, 105) => 0.999991
+(2, 110) ~ (5, 106) => 0.999983
+(2, 111) ~ (5, 107) => 0.999976
+(2, 112) ~ (5, 108) => 0.999987
+(2, 113) ~ (5, 109) => 0.999982
+(2, 114) ~ (5, 110) => 0.999975
+(2, 115) ~ (5, 111) => 0.99998
+(2, 116) ~ (5, 112) => 0.999991
+(2, 117) ~ (5, 113) => 0.999996
+(2, 118) ~ (5, 114) => 0.999997
+(2, 119) ~ (5, 115) => 0.99998
+(2, 120) ~ (5, 116) => 0.999933
+(2, 121) ~ (5, 117) => 0.999889
+(2, 122) ~ (5, 118) => 0.999768
+(2, 123) ~ (5, 119) => 0.999788
+(2, 124) ~ (5, 120) => 0.999955
+(2, 125) ~ (5, 121) => 0.999931
+(2, 126) ~ (5, 122) => 0.999759
+(2, 127) ~ (5, 123) => 0.999744
+(2, 128) ~ (5, 124) => 0.999879
+(2, 129) ~ (5, 125) => 0.99997
+(2, 130) ~ (5, 126) => 0.999981
+(2, 131) ~ (5, 127) => 0.999887
+(2, 132) ~ (5, 128) => 0.999776
+(2, 133) ~ (5, 129) => 0.999838
+(2, 134) ~ (5, 130) => 0.999854
+(2, 135) ~ (5, 131) => 0.999976
+(2, 136) ~ (5, 132) => 0.99998
+(2, 137) ~ (5, 133) => 0.999956
+(2, 138) ~ (5, 134) => 0.999964
+(2, 139) ~ (5, 135) => 0.99999
+(2, 140) ~ (5, 136) => 0.999984
+(2, 141) ~ (5, 137) => 0.999968
+(2, 142) ~ (5, 138) => 0.999971
+(2, 143) ~ (5, 139) => 0.999947
+(2, 144) ~ (5, 140) => 0.999945
+(2, 145) ~ (5, 141) => 0.999993
+(2, 146) ~ (5, 142) => 0.999998
+(2, 147) ~ (5, 143) => 0.999995
+(2, 148) ~ (5, 144) => 0.999996
+(2, 149) ~ (5, 145) => 0.999999
+(2, 150) ~ (5, 146) => 0.999998
+(2, 151) ~ (5, 147) => 0.999991
+(2, 152) ~ (5, 148) => 0.999935
+(2, 153) ~ (5, 149) => 0.999897
+(2, 154) ~ (5, 150) => 0.99989
+(2, 155) ~ (5, 151) => 0.999952
+(2, 156) ~ (5, 152) => 0.999984
+(2, 157) ~ (5, 153) => 0.999979
+(2, 158) ~ (5, 154) => 0.999973
+(2, 159) ~ (5, 155) => 0.999969
+(2, 160) ~ (5, 156) => 0.999973
+(2, 161) ~ (5, 157) => 0.999887
+(2, 162) ~ (5, 158) => 0.99977
+(2, 163) ~ (5, 159) => 0.99972
+(2, 164) ~ (5, 160) => 0.999563
+(2, 165) ~ (5, 161) => 0.999618
+(2, 166) ~ (5, 162) => 0.999864
+(2, 167) ~ (5, 163) => 0.999891
+(2, 168) ~ (5, 164) => 0.999774
+(2, 169) ~ (5, 165) => 0.999231
+(2, 170) ~ (5, 166) => 0.998038
+(2, 171) ~ (5, 167) => 0.99762
+(2, 172) ~ (5, 168) => 0.997831
+(2, 173) ~ (5, 169) => 0.999037
+(2, 174) ~ (5, 170) => 0.999859
+(2, 175) ~ (5, 171) => 0.999954
+(2, 176) ~ (5, 172) => 0.999796
+(2, 177) ~ (5, 173) => 0.999592
+(2, 178) ~ (5, 174) => 0.999159
+(2, 179) ~ (5, 175) => 0.998981
+(2, 180) ~ (5, 176) => 0.998767
+(2, 181) ~ (5, 177) => 0.999141
+(2, 182) ~ (5, 178) => 0.999867
+(2, 183) ~ (5, 179) => 0.999984
+(2, 184) ~ (5, 180) => 0.999814
+(2, 185) ~ (5, 181) => 0.999526
+(2, 186) ~ (5, 182) => 0.990456
+(2, 187) ~ (5, 183) => 0.977243
+(2, 188) ~ (5, 184) => 0.958708
+(2, 188) ~ (5, 185) => 0.0144302
+(2, 189) ~ (5, 185) => 0.907112
+(2, 189) ~ (5, 186) => 0.0310306
+(2, 189) ~ (5, 187) => 0.0153566
+(2, 190) ~ (5, 185) => 0.0196453
+(2, 190) ~ (5, 186) => 0.833072
+(2, 190) ~ (5, 187) => 0.0466816
+(2, 190) ~ (5, 188) => 0.0324746
+(2, 190) ~ (5, 190) => 0.0134044
+(2, 191) ~ (5, 186) => 0.0349315
+(2, 191) ~ (5, 187) => 0.735645
+(2, 191) ~ (5, 188) => 0.0432368
+(2, 191) ~ (5, 189) => 0.0337234
+(2, 191) ~ (5, 190) => 0.016172
+(2, 191) ~ (5, 191) => 0.0308778
+(2, 192) ~ (5, 184) => 0.0114051
+(2, 192) ~ (5, 187) => 0.0807527
+(2, 192) ~ (5, 188) => 0.491378
+(2, 192) ~ (5, 189) => 0.0321929
+(2, 192) ~ (5, 190) => 0.0388919
+(2, 192) ~ (5, 191) => 0.0103536
+(2, 192) ~ (5, 192) => 0.0750708
+(2, 193) ~ (5, 185) => 0.0177142
+(2, 193) ~ (5, 188) => 0.250015
+(2, 193) ~ (5, 189) => 0.374006
+(2, 193) ~ (5, 190) => 0.0285442
+(2, 193) ~ (5, 191) => 0.0507393
+(2, 193) ~ (5, 192) => 0.01072
+(2, 193) ~ (5, 193) => 0.0774951
+(2, 194) ~ (5, 186) => 0.0248186
+(2, 194) ~ (5, 188) => 0.0185236
+(2, 194) ~ (5, 189) => 0.337723
+(2, 194) ~ (5, 190) => 0.269262
+(2, 194) ~ (5, 191) => 0.0206403
+(2, 194) ~ (5, 192) => 0.0652409
+(2, 194) ~ (5, 193) => 0.0126337
+(2, 194) ~ (5, 194) => 0.0647064
+(2, 195) ~ (5, 187) => 0.0382183
+(2, 195) ~ (5, 189) => 0.0328929
+(2, 195) ~ (5, 190) => 0.418498
+(2, 195) ~ (5, 191) => 0.231814
+(2, 195) ~ (5, 192) => 0.0177758
+(2, 195) ~ (5, 193) => 0.0620694
+(2, 195) ~ (5, 194) => 0.0233086
+(2, 195) ~ (5, 195) => 0.0554574
+(2, 196) ~ (5, 188) => 0.0580938
+(2, 196) ~ (5, 190) => 0.0450615
+(2, 196) ~ (5, 191) => 0.452326
+(2, 196) ~ (5, 192) => 0.195094
+(2, 196) ~ (5, 193) => 0.0159937
+(2, 196) ~ (5, 194) => 0.0561963
+(2, 196) ~ (5, 195) => 0.0336236
+(2, 196) ~ (5, 196) => 0.0463523
+(2, 197) ~ (5, 189) => 0.0668408
+(2, 197) ~ (5, 191) => 0.0494649
+(2, 197) ~ (5, 192) => 0.483548
+(2, 197) ~ (5, 193) => 0.164928
+(2, 197) ~ (5, 194) => 0.0117663
+(2, 197) ~ (5, 195) => 0.0523349
+(2, 197) ~ (5, 196) => 0.0425955
+(2, 197) ~ (5, 197) => 0.031346
+(2, 198) ~ (5, 190) => 0.0569692
+(2, 198) ~ (5, 192) => 0.0541603
+(2, 198) ~ (5, 193) => 0.524153
+(2, 198) ~ (5, 194) => 0.12069
+(2, 198) ~ (5, 196) => 0.0477326
+(2, 198) ~ (5, 197) => 0.0528417
+(2, 198) ~ (5, 198) => 0.0141958
+(2, 199) ~ (5, 191) => 0.0498255
+(2, 199) ~ (5, 193) => 0.0593905
+(2, 199) ~ (5, 194) => 0.589474
+(2, 199) ~ (5, 195) => 0.100915
+(2, 199) ~ (5, 197) => 0.0441529
+(2, 199) ~ (5, 198) => 0.0655189
+(2, 200) ~ (5, 192) => 0.0472487
+(2, 200) ~ (5, 194) => 0.0541348
+(2, 200) ~ (5, 195) => 0.624488
+(2, 200) ~ (5, 196) => 0.0683398
+(2, 200) ~ (5, 198) => 0.0208322
+(2, 200) ~ (5, 199) => 0.0665327
+(2, 201) ~ (5, 193) => 0.0361204
+(2, 201) ~ (5, 195) => 0.0490096
+(2, 201) ~ (5, 196) => 0.681663
+(2, 201) ~ (5, 197) => 0.0355623
+(2, 201) ~ (5, 199) => 0.0190646
+(2, 201) ~ (5, 200) => 0.0628654
+(2, 202) ~ (5, 194) => 0.0205305
+(2, 202) ~ (5, 196) => 0.0329888
+(2, 202) ~ (5, 197) => 0.767691
+(2, 202) ~ (5, 198) => 0.0214238
+(2, 202) ~ (5, 200) => 0.0113851
+(2, 202) ~ (5, 201) => 0.052037
+(2, 203) ~ (5, 197) => 0.0215287
+(2, 203) ~ (5, 198) => 0.840567
+(2, 203) ~ (5, 199) => 0.011726
+(2, 203) ~ (5, 202) => 0.0451028
+(2, 204) ~ (5, 199) => 0.875134
+(2, 204) ~ (5, 200) => 0.0110794
+(2, 204) ~ (5, 203) => 0.0364539
+(2, 205) ~ (5, 200) => 0.892823
+(2, 205) ~ (5, 204) => 0.0233417
+(2, 206) ~ (5, 201) => 0.921598
+(2, 206) ~ (5, 205) => 0.0102242
+(2, 207) ~ (5, 202) => 0.937914
+(2, 208) ~ (5, 203) => 0.956027
+(2, 209) ~ (5, 204) => 0.972089
+(2, 210) ~ (5, 205) => 0.986962
+(2, 211) ~ (5, 206) => 0.993115
+(2, 212) ~ (5, 207) => 0.999589
+(2, 213) ~ (5, 208) => 0.999948
+(2, 214) ~ (5, 209) => 0.999918
+(2, 215) ~ (5, 210) => 0.999675
+(2, 216) ~ (5, 211) => 0.998629
+(2, 217) ~ (5, 212) => 0.998099
+(2, 218) ~ (5, 213) => 0.998057
+(2, 219) ~ (5, 214) => 0.997472
+(2, 220) ~ (5, 215) => 0.994364
+(2, 221) ~ (5, 216) => 0.994276
+(2, 222) ~ (5, 217) => 0.993498
+(2, 223) ~ (5, 218) => 0.990812
+(2, 224) ~ (5, 219) => 0.988352
+(2, 225) ~ (5, 220) => 0.988671
+(2, 226) ~ (5, 221) => 0.994057
+(2, 227) ~ (5, 222) => 0.998133
+(2, 228) ~ (5, 223) => 0.999803
+(2, 229) ~ (5, 224) => 0.999973
+(2, 230) ~ (5, 225) => 0.999995
+(2, 231) ~ (5, 226) => 0.999983
+(2, 232) ~ (5, 227) => 0.999884
+(2, 233) ~ (5, 228) => 0.99952
+(2, 234) ~ (5, 229) => 0.996575
+(2, 235) ~ (5, 230) => 0.992865
+(2, 236) ~ (5, 231) => 0.988132
+(2, 237) ~ (5, 231) => 0.0111779
+(2, 237) ~ (5, 232) => 0.987253
+(2, 238) ~ (5, 232) => 0.0113051
+(2, 238) ~ (5, 233) => 0.988109
+
+; gap posteriors
+(2, 0) ~ (5, -1) => 0.0342945
+(2, 1) ~ (5, -1) => 0.101861
+(2, 2) ~ (5, -1) => 0.174178
+(2, 3) ~ (5, -1) => 0.204219
+(2, 4) ~ (5, -1) => 0.223554
+(2, 5) ~ (5, -1) => 0.186694
+(2, 6) ~ (5, -1) => 0.220224
+(2, 7) ~ (5, -1) => 0.247811
+(2, 8) ~ (5, -1) => 0.385929
+(2, 9) ~ (5, -1) => 0.344929
+(2, 10) ~ (5, -1) => 0.259611
+(2, 11) ~ (5, -1) => 0.0833392
+(2, 12) ~ (5, -1) => 0.0539891
+(2, 13) ~ (5, -1) => 0.0234464
+(2, 14) ~ (5, -1) => 0.0244175
+(2, 15) ~ (5, -1) => 0.0189638
+(2, 16) ~ (5, -1) => 0.0117192
+(2, 17) ~ (5, -1) => 0.00521618
+(2, 18) ~ (5, -1) => 0.00530517
+(2, 19) ~ (5, -1) => 0.0045622
+(2, 20) ~ (5, -1) => 0.00223655
+(2, 21) ~ (5, -1) => 0.00101978
+(2, 22) ~ (5, -1) => 0.000677168
+(2, 23) ~ (5, -1) => 0.000100553
+(2, 24) ~ (5, -1) => 0.0001
+(2, 25) ~ (5, -1) => 0.0001
+(2, 26) ~ (5, -1) => 0.0001
+(2, 27) ~ (5, -1) => 0.0001
+(2, 28) ~ (5, -1) => 0.000114799
+(2, 29) ~ (5, -1) => 0.000157416
+(2, 30) ~ (5, -1) => 0.00011003
+(2, 31) ~ (5, -1) => 0.000304163
+(2, 32) ~ (5, -1) => 0.000599027
+(2, 33) ~ (5, -1) => 0.000712216
+(2, 34) ~ (5, -1) => 0.000918686
+(2, 35) ~ (5, -1) => 0.00128347
+(2, 36) ~ (5, -1) => 0.00366557
+(2, 37) ~ (5, -1) => 0.00686747
+(2, 38) ~ (5, -1) => 0.0159606
+(2, 39) ~ (5, -1) => 0.0319321
+(2, 40) ~ (5, -1) => 0.0831518
+(2, 41) ~ (5, -1) => 0.239733
+(2, 42) ~ (5, -1) => 0.23734
+(2, 43) ~ (5, -1) => 0.245177
+(2, 44) ~ (5, -1) => 0.14997
+(2, 45) ~ (5, -1) => 0.14463
+(2, 46) ~ (5, -1) => 0.094995
+(2, 47) ~ (5, -1) => 0.0436937
+(2, 48) ~ (5, -1) => 0.085698
+(2, 49) ~ (5, -1) => 0.0911873
+(2, 50) ~ (5, -1) => 0.0512892
+(2, 51) ~ (5, -1) => 0.0209664
+(2, 52) ~ (5, -1) => 0.00973281
+(2, 53) ~ (5, -1) => 0.0112955
+(2, 54) ~ (5, -1) => 0.0136516
+(2, 55) ~ (5, -1) => 0.456811
+(2, 56) ~ (5, -1) => 0.469681
+(2, 57) ~ (5, -1) => 0.0199767
+(2, 58) ~ (5, -1) => 0.00301701
+(2, 59) ~ (5, -1) => 0.000229597
+(2, 60) ~ (5, -1) => 0.0001
+(2, 61) ~ (5, -1) => 0.0001
+(2, 62) ~ (5, -1) => 0.0001
+(2, 63) ~ (5, -1) => 0.0001
+(2, 64) ~ (5, -1) => 0.00010711
+(2, 65) ~ (5, -1) => 0.000131011
+(2, 66) ~ (5, -1) => 0.000123978
+(2, 67) ~ (5, -1) => 0.0001
+(2, 68) ~ (5, -1) => 0.0001
+(2, 69) ~ (5, -1) => 0.0001
+(2, 70) ~ (5, -1) => 0.0001
+(2, 71) ~ (5, -1) => 0.0001
+(2, 72) ~ (5, -1) => 0.0001
+(2, 73) ~ (5, -1) => 0.0001
+(2, 74) ~ (5, -1) => 0.0001
+(2, 75) ~ (5, -1) => 0.0001
+(2, 76) ~ (5, -1) => 0.0001
+(2, 77) ~ (5, -1) => 0.0001
+(2, 78) ~ (5, -1) => 0.0001
+(2, 79) ~ (5, -1) => 0.0001
+(2, 80) ~ (5, -1) => 0.0001
+(2, 81) ~ (5, -1) => 0.00128603
+(2, 82) ~ (5, -1) => 0.00172895
+(2, 83) ~ (5, -1) => 0.00227779
+(2, 84) ~ (5, -1) => 0.00237185
+(2, 85) ~ (5, -1) => 0.00190538
+(2, 86) ~ (5, -1) => 0.00141066
+(2, 87) ~ (5, -1) => 0.00113606
+(2, 88) ~ (5, -1) => 0.000727117
+(2, 89) ~ (5, -1) => 0.000495851
+(2, 90) ~ (5, -1) => 0.000281811
+(2, 91) ~ (5, -1) => 0.000279248
+(2, 92) ~ (5, -1) => 0.0001
+(2, 93) ~ (5, -1) => 0.000245214
+(2, 94) ~ (5, -1) => 0.00027591
+(2, 95) ~ (5, -1) => 0.000662625
+(2, 96) ~ (5, -1) => 0.00097698
+(2, 97) ~ (5, -1) => 0.000851095
+(2, 98) ~ (5, -1) => 0.000649273
+(2, 99) ~ (5, -1) => 0.000548482
+(2, 100) ~ (5, -1) => 0.00150973
+(2, 101) ~ (5, -1) => 0.0018034
+(2, 102) ~ (5, -1) => 0.00214529
+(2, 103) ~ (5, -1) => 0.00224793
+(2, 104) ~ (5, -1) => 0.001872
+(2, 105) ~ (5, -1) => 0.000878751
+(2, 106) ~ (5, -1) => 0.000464499
+(2, 107) ~ (5, -1) => 0.000236988
+(2, 108) ~ (5, -1) => 0.0001
+(2, 109) ~ (5, -1) => 0.0001
+(2, 110) ~ (5, -1) => 0.0001
+(2, 111) ~ (5, -1) => 0.0001
+(2, 112) ~ (5, -1) => 0.0001
+(2, 113) ~ (5, -1) => 0.0001
+(2, 114) ~ (5, -1) => 0.0001
+(2, 115) ~ (5, -1) => 0.0001
+(2, 116) ~ (5, -1) => 0.0001
+(2, 117) ~ (5, -1) => 0.0001
+(2, 118) ~ (5, -1) => 0.0001
+(2, 119) ~ (5, -1) => 0.0001
+(2, 120) ~ (5, -1) => 0.0001
+(2, 121) ~ (5, -1) => 0.000111341
+(2, 122) ~ (5, -1) => 0.0002321
+(2, 123) ~ (5, -1) => 0.000212431
+(2, 124) ~ (5, -1) => 0.0001
+(2, 125) ~ (5, -1) => 0.0001
+(2, 126) ~ (5, -1) => 0.000240862
+(2, 127) ~ (5, -1) => 0.000255644
+(2, 128) ~ (5, -1) => 0.00012064
+(2, 129) ~ (5, -1) => 0.0001
+(2, 130) ~ (5, -1) => 0.0001
+(2, 131) ~ (5, -1) => 0.00011301
+(2, 132) ~ (5, -1) => 0.000223577
+(2, 133) ~ (5, -1) => 0.000162005
+(2, 134) ~ (5, -1) => 0.000145614
+(2, 135) ~ (5, -1) => 0.0001
+(2, 136) ~ (5, -1) => 0.0001
+(2, 137) ~ (5, -1) => 0.0001
+(2, 138) ~ (5, -1) => 0.0001
+(2, 139) ~ (5, -1) => 0.0001
+(2, 140) ~ (5, -1) => 0.0001
+(2, 141) ~ (5, -1) => 0.0001
+(2, 142) ~ (5, -1) => 0.0001
+(2, 143) ~ (5, -1) => 0.0001
+(2, 144) ~ (5, -1) => 0.0001
+(2, 145) ~ (5, -1) => 0.0001
+(2, 146) ~ (5, -1) => 0.0001
+(2, 147) ~ (5, -1) => 0.0001
+(2, 148) ~ (5, -1) => 0.0001
+(2, 149) ~ (5, -1) => 0.0001
+(2, 150) ~ (5, -1) => 0.0001
+(2, 151) ~ (5, -1) => 0.0001
+(2, 152) ~ (5, -1) => 0.0001
+(2, 153) ~ (5, -1) => 0.000103235
+(2, 154) ~ (5, -1) => 0.00011003
+(2, 155) ~ (5, -1) => 0.0001
+(2, 156) ~ (5, -1) => 0.0001
+(2, 157) ~ (5, -1) => 0.0001
+(2, 158) ~ (5, -1) => 0.0001
+(2, 159) ~ (5, -1) => 0.0001
+(2, 160) ~ (5, -1) => 0.0001
+(2, 161) ~ (5, -1) => 0.000113249
+(2, 162) ~ (5, -1) => 0.000230491
+(2, 163) ~ (5, -1) => 0.000280261
+(2, 164) ~ (5, -1) => 0.000437021
+(2, 165) ~ (5, -1) => 0.000381947
+(2, 166) ~ (5, -1) => 0.000135541
+(2, 167) ~ (5, -1) => 0.000109136
+(2, 168) ~ (5, -1) => 0.00022608
+(2, 169) ~ (5, -1) => 0.000769079
+(2, 170) ~ (5, -1) => 0.00196171
+(2, 171) ~ (5, -1) => 0.00237989
+(2, 172) ~ (5, -1) => 0.00216937
+(2, 173) ~ (5, -1) => 0.00096333
+(2, 174) ~ (5, -1) => 0.000141382
+(2, 175) ~ (5, -1) => 0.0001
+(2, 176) ~ (5, -1) => 0.000203609
+(2, 177) ~ (5, -1) => 0.000407696
+(2, 178) ~ (5, -1) => 0.00084126
+(2, 179) ~ (5, -1) => 0.00101924
+(2, 180) ~ (5, -1) => 0.00123304
+(2, 181) ~ (5, -1) => 0.000858784
+(2, 182) ~ (5, -1) => 0.000133336
+(2, 183) ~ (5, -1) => 0.0001
+(2, 184) ~ (5, -1) => 0.000186026
+(2, 185) ~ (5, -1) => 0.000473619
+(2, 186) ~ (5, -1) => 0.00954372
+(2, 187) ~ (5, -1) => 0.0227571
+(2, 188) ~ (5, -1) => 0.026862
+(2, 189) ~ (5, -1) => 0.0465005
+(2, 190) ~ (5, -1) => 0.0547221
+(2, 191) ~ (5, -1) => 0.105413
+(2, 192) ~ (5, -1) => 0.259955
+(2, 193) ~ (5, -1) => 0.190767
+(2, 194) ~ (5, -1) => 0.186452
+(2, 195) ~ (5, -1) => 0.119966
+(2, 196) ~ (5, -1) => 0.0972595
+(2, 197) ~ (5, -1) => 0.0971753
+(2, 198) ~ (5, -1) => 0.129257
+(2, 199) ~ (5, -1) => 0.0907227
+(2, 200) ~ (5, -1) => 0.118424
+(2, 201) ~ (5, -1) => 0.115715
+(2, 202) ~ (5, -1) => 0.0939433
+(2, 203) ~ (5, -1) => 0.0810754
+(2, 204) ~ (5, -1) => 0.0773327
+(2, 205) ~ (5, -1) => 0.0838352
+(2, 206) ~ (5, -1) => 0.0681779
+(2, 207) ~ (5, -1) => 0.0620858
+(2, 208) ~ (5, -1) => 0.0439728
+(2, 209) ~ (5, -1) => 0.0279111
+(2, 210) ~ (5, -1) => 0.0130379
+(2, 211) ~ (5, -1) => 0.00688547
+(2, 212) ~ (5, -1) => 0.000411034
+(2, 213) ~ (5, -1) => 0.0001
+(2, 214) ~ (5, -1) => 0.0001
+(2, 215) ~ (5, -1) => 0.000324905
+(2, 216) ~ (5, -1) => 0.00137103
+(2, 217) ~ (5, -1) => 0.00190055
+(2, 218) ~ (5, -1) => 0.00194323
+(2, 219) ~ (5, -1) => 0.00252843
+(2, 220) ~ (5, -1) => 0.00563592
+(2, 221) ~ (5, -1) => 0.00572425
+(2, 222) ~ (5, -1) => 0.00650209
+(2, 223) ~ (5, -1) => 0.00918835
+(2, 224) ~ (5, -1) => 0.0116478
+(2, 225) ~ (5, -1) => 0.0113285
+(2, 226) ~ (5, -1) => 0.00594288
+(2, 227) ~ (5, -1) => 0.00186723
+(2, 228) ~ (5, -1) => 0.000196695
+(2, 229) ~ (5, -1) => 0.0001
+(2, 230) ~ (5, -1) => 0.0001
+(2, 231) ~ (5, -1) => 0.0001
+(2, 232) ~ (5, -1) => 0.000115693
+(2, 233) ~ (5, -1) => 0.000480354
+(2, 234) ~ (5, -1) => 0.0034247
+(2, 235) ~ (5, -1) => 0.00713491
+(2, 236) ~ (5, -1) => 0.0118684
+(2, 237) ~ (5, -1) => 0.00156945
+(2, 238) ~ (5, -1) => 0.000585794
+
+(2, -1) ~ (5, 0) => 0.0342945
+(2, -1) ~ (5, 1) => 0.0503796
+(2, -1) ~ (5, 2) => 0.0886474
+(2, -1) ~ (5, 3) => 0.0632602
+(2, -1) ~ (5, 4) => 0.109022
+(2, -1) ~ (5, 5) => 0.096533
+(2, -1) ~ (5, 6) => 0.0446408
+(2, -1) ~ (5, 7) => 0.026397
+(2, -1) ~ (5, 8) => 0.016447
+(2, -1) ~ (5, 9) => 0.0134513
+(2, -1) ~ (5, 10) => 0.0122495
+(2, -1) ~ (5, 11) => 0.0146555
+(2, -1) ~ (5, 12) => 0.0103173
+(2, -1) ~ (5, 13) => 0.00716621
+(2, -1) ~ (5, 14) => 0.0117192
+(2, -1) ~ (5, 15) => 0.00521618
+(2, -1) ~ (5, 16) => 0.00530517
+(2, -1) ~ (5, 17) => 0.0045622
+(2, -1) ~ (5, 18) => 0.00223655
+(2, -1) ~ (5, 19) => 0.00101978
+(2, -1) ~ (5, 20) => 0.000677168
+(2, -1) ~ (5, 21) => 0.000100553
+(2, -1) ~ (5, 22) => 0.0001
+(2, -1) ~ (5, 23) => 0.0001
+(2, -1) ~ (5, 24) => 0.0001
+(2, -1) ~ (5, 25) => 0.0001
+(2, -1) ~ (5, 26) => 0.000114799
+(2, -1) ~ (5, 27) => 0.000157416
+(2, -1) ~ (5, 28) => 0.00011003
+(2, -1) ~ (5, 29) => 0.000304163
+(2, -1) ~ (5, 30) => 0.000599027
+(2, -1) ~ (5, 31) => 0.000712216
+(2, -1) ~ (5, 32) => 0.000918686
+(2, -1) ~ (5, 33) => 0.00128347
+(2, -1) ~ (5, 34) => 0.00366557
+(2, -1) ~ (5, 35) => 0.00686747
+(2, -1) ~ (5, 36) => 0.0054174
+(2, -1) ~ (5, 37) => 0.00682068
+(2, -1) ~ (5, 38) => 0.0069715
+(2, -1) ~ (5, 39) => 0.010917
+(2, -1) ~ (5, 40) => 0.00950098
+(2, -1) ~ (5, 41) => 0.0041627
+(2, -1) ~ (5, 42) => 0.0014632
+(2, -1) ~ (5, 43) => 0.000943005
+(2, -1) ~ (5, 44) => 0.00888366
+(2, -1) ~ (5, 45) => 0.00382149
+(2, -1) ~ (5, 46) => 0.00397953
+(2, -1) ~ (5, 47) => 0.00157201
+(2, -1) ~ (5, 48) => 0.0046255
+(2, -1) ~ (5, 49) => 0.00733832
+(2, -1) ~ (5, 50) => 0.00790992
+(2, -1) ~ (5, 51) => 0.0146466
+(2, -1) ~ (5, 52) => 0.404047
+(2, -1) ~ (5, 53) => 0.0138524
+(2, -1) ~ (5, 54) => 0.00301701
+(2, -1) ~ (5, 55) => 0.000229597
+(2, -1) ~ (5, 56) => 0.0001
+(2, -1) ~ (5, 57) => 0.0001
+(2, -1) ~ (5, 58) => 0.0001
+(2, -1) ~ (5, 59) => 0.0001
+(2, -1) ~ (5, 60) => 0.00010711
+(2, -1) ~ (5, 61) => 0.000131011
+(2, -1) ~ (5, 62) => 0.000123978
+(2, -1) ~ (5, 63) => 0.0001
+(2, -1) ~ (5, 64) => 0.0001
+(2, -1) ~ (5, 65) => 0.0001
+(2, -1) ~ (5, 66) => 0.0001
+(2, -1) ~ (5, 67) => 0.0001
+(2, -1) ~ (5, 68) => 0.0001
+(2, -1) ~ (5, 69) => 0.0001
+(2, -1) ~ (5, 70) => 0.0001
+(2, -1) ~ (5, 71) => 0.0001
+(2, -1) ~ (5, 72) => 0.0001
+(2, -1) ~ (5, 73) => 0.0001
+(2, -1) ~ (5, 74) => 0.0001
+(2, -1) ~ (5, 75) => 0.0001
+(2, -1) ~ (5, 76) => 0.0001
+(2, -1) ~ (5, 77) => 0.00128603
+(2, -1) ~ (5, 78) => 0.00172895
+(2, -1) ~ (5, 79) => 0.00227779
+(2, -1) ~ (5, 80) => 0.00237185
+(2, -1) ~ (5, 81) => 0.00190538
+(2, -1) ~ (5, 82) => 0.00141066
+(2, -1) ~ (5, 83) => 0.00113606
+(2, -1) ~ (5, 84) => 0.000727117
+(2, -1) ~ (5, 85) => 0.000495851
+(2, -1) ~ (5, 86) => 0.000281811
+(2, -1) ~ (5, 87) => 0.000279248
+(2, -1) ~ (5, 88) => 0.0001
+(2, -1) ~ (5, 89) => 0.000245214
+(2, -1) ~ (5, 90) => 0.00027591
+(2, -1) ~ (5, 91) => 0.000662625
+(2, -1) ~ (5, 92) => 0.00097698
+(2, -1) ~ (5, 93) => 0.000851095
+(2, -1) ~ (5, 94) => 0.000649273
+(2, -1) ~ (5, 95) => 0.000548482
+(2, -1) ~ (5, 96) => 0.00150973
+(2, -1) ~ (5, 97) => 0.0018034
+(2, -1) ~ (5, 98) => 0.00214529
+(2, -1) ~ (5, 99) => 0.00224793
+(2, -1) ~ (5, 100) => 0.001872
+(2, -1) ~ (5, 101) => 0.000878751
+(2, -1) ~ (5, 102) => 0.000464499
+(2, -1) ~ (5, 103) => 0.000236988
+(2, -1) ~ (5, 104) => 0.0001
+(2, -1) ~ (5, 105) => 0.0001
+(2, -1) ~ (5, 106) => 0.0001
+(2, -1) ~ (5, 107) => 0.0001
+(2, -1) ~ (5, 108) => 0.0001
+(2, -1) ~ (5, 109) => 0.0001
+(2, -1) ~ (5, 110) => 0.0001
+(2, -1) ~ (5, 111) => 0.0001
+(2, -1) ~ (5, 112) => 0.0001
+(2, -1) ~ (5, 113) => 0.0001
+(2, -1) ~ (5, 114) => 0.0001
+(2, -1) ~ (5, 115) => 0.0001
+(2, -1) ~ (5, 116) => 0.0001
+(2, -1) ~ (5, 117) => 0.000111341
+(2, -1) ~ (5, 118) => 0.0002321
+(2, -1) ~ (5, 119) => 0.000212431
+(2, -1) ~ (5, 120) => 0.0001
+(2, -1) ~ (5, 121) => 0.0001
+(2, -1) ~ (5, 122) => 0.000240862
+(2, -1) ~ (5, 123) => 0.000255644
+(2, -1) ~ (5, 124) => 0.00012064
+(2, -1) ~ (5, 125) => 0.0001
+(2, -1) ~ (5, 126) => 0.0001
+(2, -1) ~ (5, 127) => 0.00011301
+(2, -1) ~ (5, 128) => 0.000223577
+(2, -1) ~ (5, 129) => 0.000162005
+(2, -1) ~ (5, 130) => 0.000145614
+(2, -1) ~ (5, 131) => 0.0001
+(2, -1) ~ (5, 132) => 0.0001
+(2, -1) ~ (5, 133) => 0.0001
+(2, -1) ~ (5, 134) => 0.0001
+(2, -1) ~ (5, 135) => 0.0001
+(2, -1) ~ (5, 136) => 0.0001
+(2, -1) ~ (5, 137) => 0.0001
+(2, -1) ~ (5, 138) => 0.0001
+(2, -1) ~ (5, 139) => 0.0001
+(2, -1) ~ (5, 140) => 0.0001
+(2, -1) ~ (5, 141) => 0.0001
+(2, -1) ~ (5, 142) => 0.0001
+(2, -1) ~ (5, 143) => 0.0001
+(2, -1) ~ (5, 144) => 0.0001
+(2, -1) ~ (5, 145) => 0.0001
+(2, -1) ~ (5, 146) => 0.0001
+(2, -1) ~ (5, 147) => 0.0001
+(2, -1) ~ (5, 148) => 0.0001
+(2, -1) ~ (5, 149) => 0.000103235
+(2, -1) ~ (5, 150) => 0.00011003
+(2, -1) ~ (5, 151) => 0.0001
+(2, -1) ~ (5, 152) => 0.0001
+(2, -1) ~ (5, 153) => 0.0001
+(2, -1) ~ (5, 154) => 0.0001
+(2, -1) ~ (5, 155) => 0.0001
+(2, -1) ~ (5, 156) => 0.0001
+(2, -1) ~ (5, 157) => 0.000113249
+(2, -1) ~ (5, 158) => 0.000230491
+(2, -1) ~ (5, 159) => 0.000280261
+(2, -1) ~ (5, 160) => 0.000437021
+(2, -1) ~ (5, 161) => 0.000381947
+(2, -1) ~ (5, 162) => 0.000135541
+(2, -1) ~ (5, 163) => 0.000109136
+(2, -1) ~ (5, 164) => 0.00022608
+(2, -1) ~ (5, 165) => 0.000769079
+(2, -1) ~ (5, 166) => 0.00196171
+(2, -1) ~ (5, 167) => 0.00237989
+(2, -1) ~ (5, 168) => 0.00216937
+(2, -1) ~ (5, 169) => 0.00096333
+(2, -1) ~ (5, 170) => 0.000141382
+(2, -1) ~ (5, 171) => 0.0001
+(2, -1) ~ (5, 172) => 0.000203609
+(2, -1) ~ (5, 173) => 0.000407696
+(2, -1) ~ (5, 174) => 0.00084126
+(2, -1) ~ (5, 175) => 0.00101924
+(2, -1) ~ (5, 176) => 0.00123304
+(2, -1) ~ (5, 177) => 0.000858784
+(2, -1) ~ (5, 178) => 0.000133336
+(2, -1) ~ (5, 179) => 0.0001
+(2, -1) ~ (5, 180) => 0.000186026
+(2, -1) ~ (5, 181) => 0.000473619
+(2, -1) ~ (5, 182) => 0.00954372
+(2, -1) ~ (5, 183) => 0.0227571
+(2, -1) ~ (5, 184) => 0.0298872
+(2, -1) ~ (5, 185) => 0.0410979
+(2, -1) ~ (5, 186) => 0.0761473
+(2, -1) ~ (5, 187) => 0.0833455
+(2, -1) ~ (5, 188) => 0.106279
+(2, -1) ~ (5, 189) => 0.122621
+(2, -1) ~ (5, 190) => 0.113197
+(2, -1) ~ (5, 191) => 0.103958
+(2, -1) ~ (5, 192) => 0.0511415
+(2, -1) ~ (5, 193) => 0.047216
+(2, -1) ~ (5, 194) => 0.0591925
+(2, -1) ~ (5, 195) => 0.0841714
+(2, -1) ~ (5, 196) => 0.0803282
+(2, -1) ~ (5, 197) => 0.046877
+(2, -1) ~ (5, 198) => 0.0374622
+(2, -1) ~ (5, 199) => 0.0275427
+(2, -1) ~ (5, 200) => 0.021847
+(2, -1) ~ (5, 201) => 0.0263651
+(2, -1) ~ (5, 202) => 0.016983
+(2, -1) ~ (5, 203) => 0.00751895
+(2, -1) ~ (5, 204) => 0.00456941
+(2, -1) ~ (5, 205) => 0.0028137
+(2, -1) ~ (5, 206) => 0.00688547
+(2, -1) ~ (5, 207) => 0.000411034
+(2, -1) ~ (5, 208) => 0.0001
+(2, -1) ~ (5, 209) => 0.0001
+(2, -1) ~ (5, 210) => 0.000324905
+(2, -1) ~ (5, 211) => 0.00137103
+(2, -1) ~ (5, 212) => 0.00190055
+(2, -1) ~ (5, 213) => 0.00194323
+(2, -1) ~ (5, 214) => 0.00252843
+(2, -1) ~ (5, 215) => 0.00563592
+(2, -1) ~ (5, 216) => 0.00572425
+(2, -1) ~ (5, 217) => 0.00650209
+(2, -1) ~ (5, 218) => 0.00918835
+(2, -1) ~ (5, 219) => 0.0116478
+(2, -1) ~ (5, 220) => 0.0113285
+(2, -1) ~ (5, 221) => 0.00594288
+(2, -1) ~ (5, 222) => 0.00186723
+(2, -1) ~ (5, 223) => 0.000196695
+(2, -1) ~ (5, 224) => 0.0001
+(2, -1) ~ (5, 225) => 0.0001
+(2, -1) ~ (5, 226) => 0.0001
+(2, -1) ~ (5, 227) => 0.000115693
+(2, -1) ~ (5, 228) => 0.000480354
+(2, -1) ~ (5, 229) => 0.0034247
+(2, -1) ~ (5, 230) => 0.00713491
+(2, -1) ~ (5, 231) => 0.000690488
+(2, -1) ~ (5, 232) => 0.00144227
+(2, -1) ~ (5, 233) => 0.0118909
+
+; Sparse posterior probability matrix for sequences 3 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(3, 0) ~ (4, 0) => 0.951893
+(3, 1) ~ (4, 0) => 0.0231938
+(3, 1) ~ (4, 1) => 0.932358
+(3, 1) ~ (4, 4) => 0.0127117
+(3, 2) ~ (4, 1) => 0.0244733
+(3, 2) ~ (4, 2) => 0.912862
+(3, 2) ~ (4, 5) => 0.0222288
+(3, 3) ~ (4, 1) => 0.0119398
+(3, 3) ~ (4, 2) => 0.0217802
+(3, 3) ~ (4, 3) => 0.90734
+(3, 3) ~ (4, 6) => 0.0265684
+(3, 4) ~ (4, 2) => 0.0223667
+(3, 4) ~ (4, 3) => 0.0212098
+(3, 4) ~ (4, 4) => 0.905986
+(3, 4) ~ (4, 7) => 0.0230667
+(3, 5) ~ (4, 3) => 0.0237293
+(3, 5) ~ (4, 4) => 0.0191216
+(3, 5) ~ (4, 5) => 0.909188
+(3, 5) ~ (4, 8) => 0.0110996
+(3, 6) ~ (4, 4) => 0.0249142
+(3, 6) ~ (4, 5) => 0.0151907
+(3, 6) ~ (4, 6) => 0.908706
+(3, 6) ~ (4, 8) => 0.0185315
+(3, 7) ~ (4, 5) => 0.0257061
+(3, 7) ~ (4, 7) => 0.913723
+(3, 7) ~ (4, 9) => 0.027937
+(3, 8) ~ (4, 6) => 0.0280147
+(3, 8) ~ (4, 8) => 0.918358
+(3, 8) ~ (4, 10) => 0.0315939
+(3, 9) ~ (4, 7) => 0.0163768
+(3, 9) ~ (4, 9) => 0.939925
+(3, 9) ~ (4, 11) => 0.0272587
+(3, 10) ~ (4, 10) => 0.950811
+(3, 10) ~ (4, 12) => 0.0254596
+(3, 11) ~ (4, 11) => 0.961134
+(3, 11) ~ (4, 13) => 0.0202756
+(3, 12) ~ (4, 12) => 0.961028
+(3, 12) ~ (4, 14) => 0.0176634
+(3, 13) ~ (4, 13) => 0.934923
+(3, 13) ~ (4, 15) => 0.01485
+(3, 14) ~ (4, 13) => 0.035531
+(3, 14) ~ (4, 14) => 0.927083
+(3, 14) ~ (4, 16) => 0.0103539
+(3, 15) ~ (4, 14) => 0.0439306
+(3, 15) ~ (4, 15) => 0.92019
+(3, 16) ~ (4, 15) => 0.0520454
+(3, 16) ~ (4, 16) => 0.921074
+(3, 17) ~ (4, 16) => 0.0549903
+(3, 17) ~ (4, 17) => 0.923366
+(3, 18) ~ (4, 17) => 0.0569456
+(3, 18) ~ (4, 18) => 0.930576
+(3, 19) ~ (4, 18) => 0.0197629
+(3, 19) ~ (4, 19) => 0.971317
+(3, 20) ~ (4, 20) => 0.993631
+(3, 21) ~ (4, 21) => 0.998848
+(3, 22) ~ (4, 22) => 0.999863
+(3, 23) ~ (4, 23) => 0.999982
+(3, 24) ~ (4, 24) => 0.999955
+(3, 25) ~ (4, 25) => 0.999064
+(3, 26) ~ (4, 26) => 0.99499
+(3, 27) ~ (4, 27) => 0.984126
+(3, 27) ~ (4, 28) => 0.0131033
+(3, 28) ~ (4, 28) => 0.978357
+(3, 28) ~ (4, 29) => 0.0154502
+(3, 29) ~ (4, 29) => 0.948532
+(3, 29) ~ (4, 30) => 0.0239112
+(3, 30) ~ (4, 30) => 0.931993
+(3, 30) ~ (4, 31) => 0.025203
+(3, 30) ~ (4, 33) => 0.0187476
+(3, 31) ~ (4, 31) => 0.925522
+(3, 31) ~ (4, 32) => 0.0202641
+(3, 31) ~ (4, 34) => 0.0208372
+(3, 32) ~ (4, 29) => 0.0126668
+(3, 32) ~ (4, 32) => 0.928993
+(3, 32) ~ (4, 33) => 0.0168849
+(3, 32) ~ (4, 35) => 0.0187887
+(3, 33) ~ (4, 30) => 0.0144211
+(3, 33) ~ (4, 33) => 0.928378
+(3, 33) ~ (4, 34) => 0.0153462
+(3, 33) ~ (4, 36) => 0.0171802
+(3, 34) ~ (4, 31) => 0.0181115
+(3, 34) ~ (4, 34) => 0.925728
+(3, 34) ~ (4, 35) => 0.0159388
+(3, 34) ~ (4, 37) => 0.0173675
+(3, 35) ~ (4, 32) => 0.0196781
+(3, 35) ~ (4, 35) => 0.928116
+(3, 35) ~ (4, 36) => 0.016575
+(3, 35) ~ (4, 38) => 0.0152515
+(3, 36) ~ (4, 33) => 0.0216784
+(3, 36) ~ (4, 36) => 0.93021
+(3, 36) ~ (4, 37) => 0.0169814
+(3, 36) ~ (4, 39) => 0.0108988
+(3, 37) ~ (4, 34) => 0.0211019
+(3, 37) ~ (4, 37) => 0.932412
+(3, 37) ~ (4, 38) => 0.011226
+(3, 38) ~ (4, 35) => 0.0208494
+(3, 38) ~ (4, 38) => 0.940229
+(3, 38) ~ (4, 39) => 0.0103459
+(3, 39) ~ (4, 36) => 0.0206608
+(3, 39) ~ (4, 39) => 0.946248
+(3, 40) ~ (4, 37) => 0.0204607
+(3, 40) ~ (4, 40) => 0.952388
+(3, 40) ~ (4, 41) => 0.0104458
+(3, 41) ~ (4, 38) => 0.0200957
+(3, 41) ~ (4, 41) => 0.952693
+(3, 42) ~ (4, 39) => 0.0180516
+(3, 42) ~ (4, 42) => 0.956988
+(3, 43) ~ (4, 40) => 0.0127755
+(3, 43) ~ (4, 43) => 0.964088
+(3, 44) ~ (4, 41) => 0.0105742
+(3, 44) ~ (4, 44) => 0.965804
+(3, 45) ~ (4, 42) => 0.0102718
+(3, 45) ~ (4, 45) => 0.911454
+(3, 46) ~ (4, 45) => 0.0190158
+(3, 46) ~ (4, 46) => 0.842845
+(3, 47) ~ (4, 44) => 0.0102297
+(3, 47) ~ (4, 45) => 0.0375291
+(3, 47) ~ (4, 47) => 0.464687
+(3, 48) ~ (4, 45) => 0.0149172
+(3, 48) ~ (4, 46) => 0.109271
+(3, 48) ~ (4, 48) => 0.365855
+(3, 49) ~ (4, 46) => 0.0188942
+(3, 49) ~ (4, 47) => 0.489579
+(3, 49) ~ (4, 49) => 0.223851
+(3, 50) ~ (4, 47) => 0.0204364
+(3, 50) ~ (4, 48) => 0.581009
+(3, 50) ~ (4, 50) => 0.0614976
+(3, 51) ~ (4, 48) => 0.0325967
+(3, 51) ~ (4, 49) => 0.726251
+(3, 51) ~ (4, 51) => 0.0284707
+(3, 52) ~ (4, 50) => 0.921263
+(3, 53) ~ (4, 51) => 0.962878
+(3, 54) ~ (4, 52) => 0.995387
+(3, 55) ~ (4, 53) => 0.999356
+(3, 56) ~ (4, 54) => 0.999882
+(3, 57) ~ (4, 55) => 0.999973
+(3, 58) ~ (4, 56) => 0.999948
+(3, 59) ~ (4, 57) => 0.999683
+(3, 60) ~ (4, 58) => 0.999527
+(3, 61) ~ (4, 59) => 0.999483
+(3, 62) ~ (4, 60) => 0.999485
+(3, 63) ~ (4, 61) => 0.998665
+(3, 64) ~ (4, 62) => 0.997677
+(3, 65) ~ (4, 63) => 0.996255
+(3, 66) ~ (4, 64) => 0.995124
+(3, 67) ~ (4, 65) => 0.994864
+(3, 68) ~ (4, 66) => 0.995056
+(3, 69) ~ (4, 67) => 0.997423
+(3, 70) ~ (4, 68) => 0.999777
+(3, 71) ~ (4, 69) => 0.999823
+(3, 72) ~ (4, 70) => 0.999459
+(3, 73) ~ (4, 71) => 0.998829
+(3, 74) ~ (4, 72) => 0.998844
+(3, 75) ~ (4, 73) => 0.999822
+(3, 76) ~ (4, 74) => 0.999931
+(3, 77) ~ (4, 75) => 0.999985
+(3, 78) ~ (4, 76) => 0.999986
+(3, 79) ~ (4, 77) => 0.999987
+(3, 80) ~ (4, 78) => 0.999991
+(3, 81) ~ (4, 79) => 0.999901
+(3, 82) ~ (4, 80) => 0.999578
+(3, 83) ~ (4, 81) => 0.994829
+(3, 84) ~ (4, 82) => 0.988861
+(3, 85) ~ (4, 83) => 0.94144
+(3, 86) ~ (4, 84) => 0.626877
+(3, 87) ~ (4, 85) => 0.530746
+(3, 88) ~ (4, 83) => 0.0557577
+(3, 88) ~ (4, 86) => 0.436543
+(3, 89) ~ (4, 84) => 0.36384
+(3, 89) ~ (4, 86) => 0.0114535
+(3, 89) ~ (4, 87) => 0.208152
+(3, 90) ~ (4, 85) => 0.449581
+(3, 90) ~ (4, 87) => 0.0157399
+(3, 90) ~ (4, 88) => 0.0407834
+(3, 91) ~ (4, 86) => 0.529679
+(3, 91) ~ (4, 88) => 0.0120309
+(3, 92) ~ (4, 87) => 0.750092
+(3, 93) ~ (4, 88) => 0.924302
+(3, 94) ~ (4, 89) => 0.963658
+(3, 95) ~ (4, 90) => 0.960472
+(3, 95) ~ (4, 94) => 0.0111816
+(3, 96) ~ (4, 91) => 0.948523
+(3, 96) ~ (4, 95) => 0.0272433
+(3, 97) ~ (4, 92) => 0.673074
+(3, 97) ~ (4, 96) => 0.291275
+(3, 98) ~ (4, 93) => 0.557529
+(3, 98) ~ (4, 97) => 0.407077
+(3, 98) ~ (4, 98) => 0.0111709
+(3, 99) ~ (4, 94) => 0.521469
+(3, 99) ~ (4, 95) => 0.0153112
+(3, 99) ~ (4, 98) => 0.417
+(3, 99) ~ (4, 99) => 0.0254847
+(3, 100) ~ (4, 95) => 0.344876
+(3, 100) ~ (4, 96) => 0.0187242
+(3, 100) ~ (4, 97) => 0.0219287
+(3, 100) ~ (4, 99) => 0.369988
+(3, 100) ~ (4, 100) => 0.208438
+(3, 101) ~ (4, 96) => 0.255283
+(3, 101) ~ (4, 97) => 0.0152727
+(3, 101) ~ (4, 98) => 0.0317343
+(3, 101) ~ (4, 99) => 0.0120994
+(3, 101) ~ (4, 100) => 0.315736
+(3, 101) ~ (4, 101) => 0.333712
+(3, 102) ~ (4, 97) => 0.161834
+(3, 102) ~ (4, 98) => 0.0109714
+(3, 102) ~ (4, 99) => 0.0544606
+(3, 102) ~ (4, 100) => 0.0143019
+(3, 102) ~ (4, 101) => 0.259131
+(3, 102) ~ (4, 102) => 0.464089
+(3, 103) ~ (4, 98) => 0.0921556
+(3, 103) ~ (4, 100) => 0.0710826
+(3, 103) ~ (4, 101) => 0.0133129
+(3, 103) ~ (4, 102) => 0.207263
+(3, 103) ~ (4, 103) => 0.577517
+(3, 104) ~ (4, 99) => 0.0657943
+(3, 104) ~ (4, 101) => 0.0805413
+(3, 104) ~ (4, 102) => 0.0117085
+(3, 104) ~ (4, 103) => 0.168314
+(3, 104) ~ (4, 104) => 0.646102
+(3, 105) ~ (4, 100) => 0.0383338
+(3, 105) ~ (4, 102) => 0.0494249
+(3, 105) ~ (4, 104) => 0.0859605
+(3, 105) ~ (4, 105) => 0.804322
+(3, 106) ~ (4, 101) => 0.0127803
+(3, 106) ~ (4, 106) => 0.968148
+(3, 107) ~ (4, 107) => 0.994289
+(3, 108) ~ (4, 108) => 0.998947
+(3, 109) ~ (4, 109) => 0.99982
+(3, 110) ~ (4, 110) => 0.999772
+(3, 111) ~ (4, 111) => 0.999803
+(3, 112) ~ (4, 112) => 0.999926
+(3, 113) ~ (4, 113) => 0.999964
+(3, 114) ~ (4, 114) => 0.999923
+(3, 115) ~ (4, 115) => 0.999902
+(3, 116) ~ (4, 116) => 0.999457
+(3, 117) ~ (4, 117) => 0.998831
+(3, 118) ~ (4, 118) => 0.998132
+(3, 119) ~ (4, 119) => 0.998068
+(3, 120) ~ (4, 120) => 0.996016
+(3, 121) ~ (4, 121) => 0.994735
+(3, 122) ~ (4, 122) => 0.993132
+(3, 123) ~ (4, 123) => 0.991387
+(3, 124) ~ (4, 124) => 0.991214
+(3, 125) ~ (4, 125) => 0.989351
+(3, 126) ~ (4, 126) => 0.986733
+(3, 127) ~ (4, 127) => 0.982122
+(3, 128) ~ (4, 128) => 0.982583
+(3, 129) ~ (4, 127) => 0.0144105
+(3, 129) ~ (4, 129) => 0.980294
+(3, 130) ~ (4, 128) => 0.0146398
+(3, 130) ~ (4, 130) => 0.920194
+(3, 130) ~ (4, 132) => 0.0123751
+(3, 131) ~ (4, 129) => 0.0156149
+(3, 131) ~ (4, 131) => 0.862632
+(3, 131) ~ (4, 133) => 0.0226769
+(3, 132) ~ (4, 130) => 0.0333613
+(3, 132) ~ (4, 132) => 0.78465
+(3, 132) ~ (4, 134) => 0.0434339
+(3, 133) ~ (4, 130) => 0.0246839
+(3, 133) ~ (4, 131) => 0.0490238
+(3, 133) ~ (4, 133) => 0.728827
+(3, 133) ~ (4, 135) => 0.0366124
+(3, 134) ~ (4, 131) => 0.0480119
+(3, 134) ~ (4, 132) => 0.0718318
+(3, 134) ~ (4, 134) => 0.676109
+(3, 134) ~ (4, 136) => 0.0322379
+(3, 134) ~ (4, 138) => 0.0114792
+(3, 135) ~ (4, 132) => 0.0708296
+(3, 135) ~ (4, 133) => 0.0903272
+(3, 135) ~ (4, 134) => 0.0173698
+(3, 135) ~ (4, 135) => 0.662772
+(3, 135) ~ (4, 137) => 0.0173804
+(3, 135) ~ (4, 139) => 0.010855
+(3, 136) ~ (4, 133) => 0.0963955
+(3, 136) ~ (4, 134) => 0.102288
+(3, 136) ~ (4, 135) => 0.0226344
+(3, 136) ~ (4, 136) => 0.651135
+(3, 137) ~ (4, 134) => 0.114992
+(3, 137) ~ (4, 135) => 0.110412
+(3, 137) ~ (4, 136) => 0.0266924
+(3, 137) ~ (4, 137) => 0.632063
+(3, 138) ~ (4, 133) => 0.0116559
+(3, 138) ~ (4, 135) => 0.122486
+(3, 138) ~ (4, 136) => 0.0943069
+(3, 138) ~ (4, 137) => 0.0398748
+(3, 138) ~ (4, 138) => 0.631033
+(3, 139) ~ (4, 134) => 0.0178402
+(3, 139) ~ (4, 136) => 0.140234
+(3, 139) ~ (4, 137) => 0.027895
+(3, 139) ~ (4, 138) => 0.0592639
+(3, 139) ~ (4, 139) => 0.629379
+(3, 140) ~ (4, 137) => 0.223417
+(3, 140) ~ (4, 139) => 0.0884437
+(3, 140) ~ (4, 140) => 0.620247
+(3, 141) ~ (4, 138) => 0.223558
+(3, 141) ~ (4, 140) => 0.116683
+(3, 141) ~ (4, 141) => 0.234542
+(3, 141) ~ (4, 142) => 0.0160345
+(3, 142) ~ (4, 139) => 0.14744
+(3, 142) ~ (4, 141) => 0.574023
+(3, 142) ~ (4, 142) => 0.105745
+(3, 142) ~ (4, 143) => 0.011599
+(3, 143) ~ (4, 140) => 0.113797
+(3, 143) ~ (4, 142) => 0.741928
+(3, 143) ~ (4, 143) => 0.0498886
+(3, 144) ~ (4, 141) => 0.11245
+(3, 144) ~ (4, 143) => 0.815263
+(3, 144) ~ (4, 144) => 0.0111685
+(3, 145) ~ (4, 142) => 0.0558653
+(3, 145) ~ (4, 144) => 0.917619
+(3, 146) ~ (4, 143) => 0.035392
+(3, 146) ~ (4, 145) => 0.946265
+(3, 147) ~ (4, 144) => 0.0149874
+(3, 147) ~ (4, 146) => 0.974435
+(3, 148) ~ (4, 147) => 0.996608
+(3, 149) ~ (4, 148) => 0.999804
+(3, 150) ~ (4, 149) => 0.999978
+(3, 151) ~ (4, 150) => 0.99999
+(3, 152) ~ (4, 151) => 0.99998
+(3, 153) ~ (4, 152) => 0.99996
+(3, 154) ~ (4, 153) => 0.999935
+(3, 155) ~ (4, 154) => 0.999956
+(3, 156) ~ (4, 155) => 0.999969
+(3, 157) ~ (4, 156) => 0.999923
+(3, 158) ~ (4, 157) => 0.99993
+(3, 159) ~ (4, 158) => 0.99995
+(3, 160) ~ (4, 159) => 0.999214
+(3, 161) ~ (4, 160) => 0.998841
+(3, 162) ~ (4, 161) => 0.998919
+(3, 163) ~ (4, 162) => 0.998972
+(3, 164) ~ (4, 163) => 0.998588
+(3, 165) ~ (4, 164) => 0.998529
+(3, 166) ~ (4, 165) => 0.998346
+(3, 167) ~ (4, 166) => 0.999018
+(3, 168) ~ (4, 167) => 0.999278
+(3, 169) ~ (4, 168) => 0.999459
+(3, 170) ~ (4, 169) => 0.999952
+(3, 171) ~ (4, 170) => 0.999748
+(3, 172) ~ (4, 171) => 0.999672
+(3, 173) ~ (4, 172) => 0.999845
+(3, 174) ~ (4, 173) => 0.999911
+(3, 175) ~ (4, 174) => 0.999989
+(3, 176) ~ (4, 175) => 0.99999
+(3, 177) ~ (4, 176) => 0.999787
+(3, 178) ~ (4, 177) => 0.999635
+(3, 179) ~ (4, 178) => 0.999593
+(3, 180) ~ (4, 179) => 0.999686
+(3, 181) ~ (4, 180) => 0.999951
+(3, 182) ~ (4, 181) => 0.999984
+(3, 183) ~ (4, 182) => 0.999984
+(3, 184) ~ (4, 183) => 0.999901
+(3, 185) ~ (4, 184) => 0.999637
+(3, 186) ~ (4, 185) => 0.988086
+(3, 187) ~ (4, 186) => 0.976341
+(3, 187) ~ (4, 188) => 0.0182114
+(3, 188) ~ (4, 187) => 0.964269
+(3, 188) ~ (4, 189) => 0.0281274
+(3, 189) ~ (4, 188) => 0.94284
+(3, 189) ~ (4, 190) => 0.0461856
+(3, 190) ~ (4, 189) => 0.904437
+(3, 190) ~ (4, 190) => 0.0108434
+(3, 190) ~ (4, 191) => 0.0820128
+(3, 191) ~ (4, 190) => 0.891233
+(3, 191) ~ (4, 191) => 0.0118939
+(3, 191) ~ (4, 192) => 0.0901022
+(3, 192) ~ (4, 191) => 0.884499
+(3, 192) ~ (4, 192) => 0.0109084
+(3, 192) ~ (4, 193) => 0.0941961
+(3, 193) ~ (4, 192) => 0.884804
+(3, 193) ~ (4, 193) => 0.0118684
+(3, 193) ~ (4, 194) => 0.0869012
+(3, 194) ~ (4, 193) => 0.85755
+(3, 194) ~ (4, 194) => 0.0246211
+(3, 194) ~ (4, 195) => 0.0719815
+(3, 195) ~ (4, 193) => 0.0173693
+(3, 195) ~ (4, 194) => 0.623688
+(3, 195) ~ (4, 195) => 0.116664
+(3, 195) ~ (4, 196) => 0.058098
+(3, 196) ~ (4, 194) => 0.165322
+(3, 196) ~ (4, 195) => 0.502309
+(3, 196) ~ (4, 196) => 0.176028
+(3, 196) ~ (4, 197) => 0.0605164
+(3, 197) ~ (4, 195) => 0.234941
+(3, 197) ~ (4, 196) => 0.460492
+(3, 197) ~ (4, 197) => 0.172701
+(3, 197) ~ (4, 198) => 0.0428083
+(3, 197) ~ (4, 199) => 0.0123687
+(3, 198) ~ (4, 196) => 0.276441
+(3, 198) ~ (4, 197) => 0.424376
+(3, 198) ~ (4, 198) => 0.169197
+(3, 198) ~ (4, 199) => 0.0235516
+(3, 198) ~ (4, 200) => 0.0194723
+(3, 199) ~ (4, 197) => 0.312881
+(3, 199) ~ (4, 198) => 0.361075
+(3, 199) ~ (4, 199) => 0.185524
+(3, 199) ~ (4, 200) => 0.0169067
+(3, 199) ~ (4, 201) => 0.0145921
+(3, 200) ~ (4, 198) => 0.380931
+(3, 200) ~ (4, 199) => 0.312733
+(3, 200) ~ (4, 200) => 0.151794
+(3, 200) ~ (4, 201) => 0.011973
+(3, 200) ~ (4, 202) => 0.0106083
+(3, 201) ~ (4, 199) => 0.444972
+(3, 201) ~ (4, 200) => 0.242607
+(3, 201) ~ (4, 201) => 0.0607832
+(3, 201) ~ (4, 203) => 0.0109726
+(3, 202) ~ (4, 200) => 0.558135
+(3, 202) ~ (4, 201) => 0.182627
+(3, 202) ~ (4, 202) => 0.0140618
+(3, 203) ~ (4, 201) => 0.721752
+(3, 203) ~ (4, 202) => 0.11856
+(3, 204) ~ (4, 202) => 0.841197
+(3, 204) ~ (4, 203) => 0.112229
+(3, 205) ~ (4, 203) => 0.857811
+(3, 205) ~ (4, 204) => 0.0414059
+(3, 206) ~ (4, 204) => 0.940791
+(3, 206) ~ (4, 205) => 0.0248701
+(3, 207) ~ (4, 205) => 0.956596
+(3, 208) ~ (4, 206) => 0.97186
+(3, 209) ~ (4, 207) => 0.968441
+(3, 210) ~ (4, 208) => 0.973031
+(3, 211) ~ (4, 209) => 0.974679
+(3, 212) ~ (4, 210) => 0.980944
+(3, 213) ~ (4, 211) => 0.97414
+(3, 214) ~ (4, 212) => 0.964015
+(3, 214) ~ (4, 213) => 0.0133724
+(3, 214) ~ (4, 215) => 0.010426
+(3, 215) ~ (4, 213) => 0.958603
+(3, 215) ~ (4, 214) => 0.0175099
+(3, 215) ~ (4, 216) => 0.0118418
+(3, 216) ~ (4, 214) => 0.953665
+(3, 216) ~ (4, 215) => 0.0190391
+(3, 216) ~ (4, 217) => 0.0140725
+(3, 217) ~ (4, 215) => 0.94587
+(3, 217) ~ (4, 216) => 0.0225375
+(3, 217) ~ (4, 218) => 0.0180829
+(3, 218) ~ (4, 216) => 0.941038
+(3, 218) ~ (4, 217) => 0.0252731
+(3, 218) ~ (4, 219) => 0.0226745
+(3, 219) ~ (4, 217) => 0.924221
+(3, 219) ~ (4, 218) => 0.0260596
+(3, 219) ~ (4, 220) => 0.0366655
+(3, 220) ~ (4, 218) => 0.790893
+(3, 220) ~ (4, 219) => 0.0365998
+(3, 220) ~ (4, 221) => 0.155418
+(3, 221) ~ (4, 219) => 0.672164
+(3, 221) ~ (4, 220) => 0.040614
+(3, 221) ~ (4, 222) => 0.266274
+(3, 222) ~ (4, 220) => 0.410384
+(3, 222) ~ (4, 221) => 0.16392
+(3, 222) ~ (4, 222) => 0.0271422
+(3, 222) ~ (4, 223) => 0.367659
+(3, 223) ~ (4, 221) => 0.133116
+(3, 223) ~ (4, 222) => 0.419202
+(3, 223) ~ (4, 223) => 0.0318261
+(3, 223) ~ (4, 224) => 0.356393
+(3, 224) ~ (4, 222) => 0.101355
+(3, 224) ~ (4, 223) => 0.454482
+(3, 224) ~ (4, 224) => 0.0228636
+(3, 224) ~ (4, 225) => 0.298612
+(3, 225) ~ (4, 223) => 0.0707337
+(3, 225) ~ (4, 224) => 0.51742
+(3, 225) ~ (4, 225) => 0.0132039
+(3, 225) ~ (4, 226) => 0.259939
+(3, 226) ~ (4, 224) => 0.040624
+(3, 226) ~ (4, 225) => 0.620801
+(3, 226) ~ (4, 227) => 0.191959
+(3, 227) ~ (4, 225) => 0.0361708
+(3, 227) ~ (4, 226) => 0.679926
+(3, 227) ~ (4, 228) => 0.131524
+(3, 228) ~ (4, 227) => 0.802162
+(3, 229) ~ (4, 228) => 0.866635
+(3, 230) ~ (4, 229) => 0.993957
+(3, 231) ~ (4, 230) => 0.998928
+(3, 232) ~ (4, 231) => 0.998306
+(3, 233) ~ (4, 232) => 0.998542
+(3, 234) ~ (4, 233) => 0.997272
+(3, 235) ~ (4, 234) => 0.99604
+(3, 236) ~ (4, 235) => 0.995386
+(3, 237) ~ (4, 236) => 0.995915
+(3, 238) ~ (4, 237) => 0.996862
+
+; gap posteriors
+(3, 0) ~ (4, -1) => 0.0481074
+(3, 1) ~ (4, -1) => 0.0317367
+(3, 2) ~ (4, -1) => 0.0404361
+(3, 3) ~ (4, -1) => 0.0323721
+(3, 4) ~ (4, -1) => 0.0273707
+(3, 5) ~ (4, -1) => 0.0368615
+(3, 6) ~ (4, -1) => 0.0326574
+(3, 7) ~ (4, -1) => 0.0326335
+(3, 8) ~ (4, -1) => 0.0220338
+(3, 9) ~ (4, -1) => 0.0164397
+(3, 10) ~ (4, -1) => 0.0237297
+(3, 11) ~ (4, -1) => 0.0185903
+(3, 12) ~ (4, -1) => 0.0213086
+(3, 13) ~ (4, -1) => 0.0502274
+(3, 14) ~ (4, -1) => 0.027032
+(3, 15) ~ (4, -1) => 0.0358791
+(3, 16) ~ (4, -1) => 0.026881
+(3, 17) ~ (4, -1) => 0.0216439
+(3, 18) ~ (4, -1) => 0.0124786
+(3, 19) ~ (4, -1) => 0.00892037
+(3, 20) ~ (4, -1) => 0.00636941
+(3, 21) ~ (4, -1) => 0.0011521
+(3, 22) ~ (4, -1) => 0.000136971
+(3, 23) ~ (4, -1) => 0.0001
+(3, 24) ~ (4, -1) => 0.0001
+(3, 25) ~ (4, -1) => 0.000936151
+(3, 26) ~ (4, -1) => 0.00500959
+(3, 27) ~ (4, -1) => 0.00277054
+(3, 28) ~ (4, -1) => 0.00619246
+(3, 29) ~ (4, -1) => 0.0275573
+(3, 30) ~ (4, -1) => 0.0240568
+(3, 31) ~ (4, -1) => 0.0333766
+(3, 32) ~ (4, -1) => 0.0226665
+(3, 33) ~ (4, -1) => 0.0246741
+(3, 34) ~ (4, -1) => 0.022854
+(3, 35) ~ (4, -1) => 0.0203792
+(3, 36) ~ (4, -1) => 0.0202309
+(3, 37) ~ (4, -1) => 0.0352598
+(3, 38) ~ (4, -1) => 0.0285752
+(3, 39) ~ (4, -1) => 0.0330911
+(3, 40) ~ (4, -1) => 0.0167055
+(3, 41) ~ (4, -1) => 0.0272115
+(3, 42) ~ (4, -1) => 0.0249609
+(3, 43) ~ (4, -1) => 0.0231368
+(3, 44) ~ (4, -1) => 0.0236217
+(3, 45) ~ (4, -1) => 0.0782737
+(3, 46) ~ (4, -1) => 0.13814
+(3, 47) ~ (4, -1) => 0.487554
+(3, 48) ~ (4, -1) => 0.509958
+(3, 49) ~ (4, -1) => 0.267676
+(3, 50) ~ (4, -1) => 0.337057
+(3, 51) ~ (4, -1) => 0.212681
+(3, 52) ~ (4, -1) => 0.0787374
+(3, 53) ~ (4, -1) => 0.0371221
+(3, 54) ~ (4, -1) => 0.00461268
+(3, 55) ~ (4, -1) => 0.000643671
+(3, 56) ~ (4, -1) => 0.000117838
+(3, 57) ~ (4, -1) => 0.0001
+(3, 58) ~ (4, -1) => 0.0001
+(3, 59) ~ (4, -1) => 0.000317037
+(3, 60) ~ (4, -1) => 0.000473022
+(3, 61) ~ (4, -1) => 0.000517309
+(3, 62) ~ (4, -1) => 0.000514805
+(3, 63) ~ (4, -1) => 0.00133467
+(3, 64) ~ (4, -1) => 0.00232345
+(3, 65) ~ (4, -1) => 0.00374454
+(3, 66) ~ (4, -1) => 0.00487602
+(3, 67) ~ (4, -1) => 0.00513637
+(3, 68) ~ (4, -1) => 0.00494426
+(3, 69) ~ (4, -1) => 0.00257689
+(3, 70) ~ (4, -1) => 0.000223041
+(3, 71) ~ (4, -1) => 0.000176787
+(3, 72) ~ (4, -1) => 0.000541389
+(3, 73) ~ (4, -1) => 0.00117064
+(3, 74) ~ (4, -1) => 0.00115567
+(3, 75) ~ (4, -1) => 0.000177622
+(3, 76) ~ (4, -1) => 0.0001
+(3, 77) ~ (4, -1) => 0.0001
+(3, 78) ~ (4, -1) => 0.0001
+(3, 79) ~ (4, -1) => 0.0001
+(3, 80) ~ (4, -1) => 0.0001
+(3, 81) ~ (4, -1) => 0.0001
+(3, 82) ~ (4, -1) => 0.000421643
+(3, 83) ~ (4, -1) => 0.00517052
+(3, 84) ~ (4, -1) => 0.0111391
+(3, 85) ~ (4, -1) => 0.05856
+(3, 86) ~ (4, -1) => 0.373123
+(3, 87) ~ (4, -1) => 0.469254
+(3, 88) ~ (4, -1) => 0.5077
+(3, 89) ~ (4, -1) => 0.416554
+(3, 90) ~ (4, -1) => 0.493896
+(3, 91) ~ (4, -1) => 0.45829
+(3, 92) ~ (4, -1) => 0.249908
+(3, 93) ~ (4, -1) => 0.0756977
+(3, 94) ~ (4, -1) => 0.0363416
+(3, 95) ~ (4, -1) => 0.0283462
+(3, 96) ~ (4, -1) => 0.0242341
+(3, 97) ~ (4, -1) => 0.0356512
+(3, 98) ~ (4, -1) => 0.0242235
+(3, 99) ~ (4, -1) => 0.0207348
+(3, 100) ~ (4, -1) => 0.0360454
+(3, 101) ~ (4, -1) => 0.0361618
+(3, 102) ~ (4, -1) => 0.0352124
+(3, 103) ~ (4, -1) => 0.0386688
+(3, 104) ~ (4, -1) => 0.0275401
+(3, 105) ~ (4, -1) => 0.0219589
+(3, 106) ~ (4, -1) => 0.0190713
+(3, 107) ~ (4, -1) => 0.0057106
+(3, 108) ~ (4, -1) => 0.00105268
+(3, 109) ~ (4, -1) => 0.000180185
+(3, 110) ~ (4, -1) => 0.000227749
+(3, 111) ~ (4, -1) => 0.000197291
+(3, 112) ~ (4, -1) => 0.0001
+(3, 113) ~ (4, -1) => 0.0001
+(3, 114) ~ (4, -1) => 0.0001
+(3, 115) ~ (4, -1) => 0.0001
+(3, 116) ~ (4, -1) => 0.000542939
+(3, 117) ~ (4, -1) => 0.00116867
+(3, 118) ~ (4, -1) => 0.00186825
+(3, 119) ~ (4, -1) => 0.00193202
+(3, 120) ~ (4, -1) => 0.00398368
+(3, 121) ~ (4, -1) => 0.00526488
+(3, 122) ~ (4, -1) => 0.00686759
+(3, 123) ~ (4, -1) => 0.00861305
+(3, 124) ~ (4, -1) => 0.00878602
+(3, 125) ~ (4, -1) => 0.0106489
+(3, 126) ~ (4, -1) => 0.0132666
+(3, 127) ~ (4, -1) => 0.0178778
+(3, 128) ~ (4, -1) => 0.017417
+(3, 129) ~ (4, -1) => 0.0052954
+(3, 130) ~ (4, -1) => 0.052791
+(3, 131) ~ (4, -1) => 0.099076
+(3, 132) ~ (4, -1) => 0.138555
+(3, 133) ~ (4, -1) => 0.160853
+(3, 134) ~ (4, -1) => 0.16033
+(3, 135) ~ (4, -1) => 0.130466
+(3, 136) ~ (4, -1) => 0.127547
+(3, 137) ~ (4, -1) => 0.115841
+(3, 138) ~ (4, -1) => 0.100643
+(3, 139) ~ (4, -1) => 0.125387
+(3, 140) ~ (4, -1) => 0.067892
+(3, 141) ~ (4, -1) => 0.409183
+(3, 142) ~ (4, -1) => 0.161192
+(3, 143) ~ (4, -1) => 0.094386
+(3, 144) ~ (4, -1) => 0.0611184
+(3, 145) ~ (4, -1) => 0.0265153
+(3, 146) ~ (4, -1) => 0.018343
+(3, 147) ~ (4, -1) => 0.0105776
+(3, 148) ~ (4, -1) => 0.00339246
+(3, 149) ~ (4, -1) => 0.000195682
+(3, 150) ~ (4, -1) => 0.0001
+(3, 151) ~ (4, -1) => 0.0001
+(3, 152) ~ (4, -1) => 0.0001
+(3, 153) ~ (4, -1) => 0.0001
+(3, 154) ~ (4, -1) => 0.0001
+(3, 155) ~ (4, -1) => 0.0001
+(3, 156) ~ (4, -1) => 0.0001
+(3, 157) ~ (4, -1) => 0.0001
+(3, 158) ~ (4, -1) => 0.0001
+(3, 159) ~ (4, -1) => 0.0001
+(3, 160) ~ (4, -1) => 0.000786066
+(3, 161) ~ (4, -1) => 0.00115883
+(3, 162) ~ (4, -1) => 0.00108081
+(3, 163) ~ (4, -1) => 0.00102836
+(3, 164) ~ (4, -1) => 0.00141203
+(3, 165) ~ (4, -1) => 0.00147116
+(3, 166) ~ (4, -1) => 0.00165385
+(3, 167) ~ (4, -1) => 0.000982285
+(3, 168) ~ (4, -1) => 0.00072217
+(3, 169) ~ (4, -1) => 0.000541031
+(3, 170) ~ (4, -1) => 0.0001
+(3, 171) ~ (4, -1) => 0.000252128
+(3, 172) ~ (4, -1) => 0.000328481
+(3, 173) ~ (4, -1) => 0.000154912
+(3, 174) ~ (4, -1) => 0.0001
+(3, 175) ~ (4, -1) => 0.0001
+(3, 176) ~ (4, -1) => 0.0001
+(3, 177) ~ (4, -1) => 0.000212669
+(3, 178) ~ (4, -1) => 0.000364661
+(3, 179) ~ (4, -1) => 0.00040704
+(3, 180) ~ (4, -1) => 0.000314355
+(3, 181) ~ (4, -1) => 0.0001
+(3, 182) ~ (4, -1) => 0.0001
+(3, 183) ~ (4, -1) => 0.0001
+(3, 184) ~ (4, -1) => 0.0001
+(3, 185) ~ (4, -1) => 0.000362515
+(3, 186) ~ (4, -1) => 0.011914
+(3, 187) ~ (4, -1) => 0.00544709
+(3, 188) ~ (4, -1) => 0.00760347
+(3, 189) ~ (4, -1) => 0.0109749
+(3, 190) ~ (4, -1) => 0.00270709
+(3, 191) ~ (4, -1) => 0.0067709
+(3, 192) ~ (4, -1) => 0.0103966
+(3, 193) ~ (4, -1) => 0.016426
+(3, 194) ~ (4, -1) => 0.0458477
+(3, 195) ~ (4, -1) => 0.18418
+(3, 196) ~ (4, -1) => 0.0958237
+(3, 197) ~ (4, -1) => 0.0766888
+(3, 198) ~ (4, -1) => 0.0869624
+(3, 199) ~ (4, -1) => 0.109022
+(3, 200) ~ (4, -1) => 0.131961
+(3, 201) ~ (4, -1) => 0.240666
+(3, 202) ~ (4, -1) => 0.245176
+(3, 203) ~ (4, -1) => 0.159688
+(3, 204) ~ (4, -1) => 0.0465739
+(3, 205) ~ (4, -1) => 0.100783
+(3, 206) ~ (4, -1) => 0.034339
+(3, 207) ~ (4, -1) => 0.043404
+(3, 208) ~ (4, -1) => 0.0281405
+(3, 209) ~ (4, -1) => 0.0315587
+(3, 210) ~ (4, -1) => 0.0269687
+(3, 211) ~ (4, -1) => 0.0253214
+(3, 212) ~ (4, -1) => 0.0190563
+(3, 213) ~ (4, -1) => 0.0258598
+(3, 214) ~ (4, -1) => 0.0121868
+(3, 215) ~ (4, -1) => 0.0120449
+(3, 216) ~ (4, -1) => 0.0132236
+(3, 217) ~ (4, -1) => 0.0135099
+(3, 218) ~ (4, -1) => 0.0110143
+(3, 219) ~ (4, -1) => 0.0130536
+(3, 220) ~ (4, -1) => 0.017089
+(3, 221) ~ (4, -1) => 0.0209478
+(3, 222) ~ (4, -1) => 0.0308945
+(3, 223) ~ (4, -1) => 0.0594629
+(3, 224) ~ (4, -1) => 0.122687
+(3, 225) ~ (4, -1) => 0.138704
+(3, 226) ~ (4, -1) => 0.146616
+(3, 227) ~ (4, -1) => 0.152379
+(3, 228) ~ (4, -1) => 0.197838
+(3, 229) ~ (4, -1) => 0.133365
+(3, 230) ~ (4, -1) => 0.00604314
+(3, 231) ~ (4, -1) => 0.00107229
+(3, 232) ~ (4, -1) => 0.00169373
+(3, 233) ~ (4, -1) => 0.00145829
+(3, 234) ~ (4, -1) => 0.00272769
+(3, 235) ~ (4, -1) => 0.00395983
+(3, 236) ~ (4, -1) => 0.00461376
+(3, 237) ~ (4, -1) => 0.00408548
+(3, 238) ~ (4, -1) => 0.00313812
+
+(3, -1) ~ (4, 0) => 0.0249136
+(3, -1) ~ (4, 1) => 0.0312291
+(3, -1) ~ (4, 2) => 0.0429913
+(3, -1) ~ (4, 3) => 0.0477214
+(3, -1) ~ (4, 4) => 0.0372665
+(3, -1) ~ (4, 5) => 0.0276864
+(3, -1) ~ (4, 6) => 0.0367105
+(3, -1) ~ (4, 7) => 0.0468331
+(3, -1) ~ (4, 8) => 0.0520113
+(3, -1) ~ (4, 9) => 0.0321381
+(3, -1) ~ (4, 10) => 0.0175955
+(3, -1) ~ (4, 11) => 0.0116073
+(3, -1) ~ (4, 12) => 0.0135124
+(3, -1) ~ (4, 13) => 0.00927085
+(3, -1) ~ (4, 14) => 0.0113229
+(3, -1) ~ (4, 15) => 0.0129143
+(3, -1) ~ (4, 16) => 0.0135822
+(3, -1) ~ (4, 17) => 0.0196886
+(3, -1) ~ (4, 18) => 0.0496613
+(3, -1) ~ (4, 19) => 0.0286832
+(3, -1) ~ (4, 20) => 0.00636941
+(3, -1) ~ (4, 21) => 0.0011521
+(3, -1) ~ (4, 22) => 0.000136971
+(3, -1) ~ (4, 23) => 0.0001
+(3, -1) ~ (4, 24) => 0.0001
+(3, -1) ~ (4, 25) => 0.000936151
+(3, -1) ~ (4, 26) => 0.00500959
+(3, -1) ~ (4, 27) => 0.0158738
+(3, -1) ~ (4, 28) => 0.00853938
+(3, -1) ~ (4, 29) => 0.0233514
+(3, -1) ~ (4, 30) => 0.0296751
+(3, -1) ~ (4, 31) => 0.0311634
+(3, -1) ~ (4, 32) => 0.0310646
+(3, -1) ~ (4, 33) => 0.0143107
+(3, -1) ~ (4, 34) => 0.0169863
+(3, -1) ~ (4, 35) => 0.0163069
+(3, -1) ~ (4, 36) => 0.0153735
+(3, -1) ~ (4, 37) => 0.0127783
+(3, -1) ~ (4, 38) => 0.0131973
+(3, -1) ~ (4, 39) => 0.0144555
+(3, -1) ~ (4, 40) => 0.0348365
+(3, -1) ~ (4, 41) => 0.0262871
+(3, -1) ~ (4, 42) => 0.0327407
+(3, -1) ~ (4, 43) => 0.0359123
+(3, -1) ~ (4, 44) => 0.0239662
+(3, -1) ~ (4, 45) => 0.0170835
+(3, -1) ~ (4, 46) => 0.0289908
+(3, -1) ~ (4, 47) => 0.0252979
+(3, -1) ~ (4, 48) => 0.0205394
+(3, -1) ~ (4, 49) => 0.0498978
+(3, -1) ~ (4, 50) => 0.0172397
+(3, -1) ~ (4, 51) => 0.00865144
+(3, -1) ~ (4, 52) => 0.00461268
+(3, -1) ~ (4, 53) => 0.000643671
+(3, -1) ~ (4, 54) => 0.000117838
+(3, -1) ~ (4, 55) => 0.0001
+(3, -1) ~ (4, 56) => 0.0001
+(3, -1) ~ (4, 57) => 0.000317037
+(3, -1) ~ (4, 58) => 0.000473022
+(3, -1) ~ (4, 59) => 0.000517309
+(3, -1) ~ (4, 60) => 0.000514805
+(3, -1) ~ (4, 61) => 0.00133467
+(3, -1) ~ (4, 62) => 0.00232345
+(3, -1) ~ (4, 63) => 0.00374454
+(3, -1) ~ (4, 64) => 0.00487602
+(3, -1) ~ (4, 65) => 0.00513637
+(3, -1) ~ (4, 66) => 0.00494426
+(3, -1) ~ (4, 67) => 0.00257689
+(3, -1) ~ (4, 68) => 0.000223041
+(3, -1) ~ (4, 69) => 0.000176787
+(3, -1) ~ (4, 70) => 0.000541389
+(3, -1) ~ (4, 71) => 0.00117064
+(3, -1) ~ (4, 72) => 0.00115567
+(3, -1) ~ (4, 73) => 0.000177622
+(3, -1) ~ (4, 74) => 0.0001
+(3, -1) ~ (4, 75) => 0.0001
+(3, -1) ~ (4, 76) => 0.0001
+(3, -1) ~ (4, 77) => 0.0001
+(3, -1) ~ (4, 78) => 0.0001
+(3, -1) ~ (4, 79) => 0.0001
+(3, -1) ~ (4, 80) => 0.000421643
+(3, -1) ~ (4, 81) => 0.00517052
+(3, -1) ~ (4, 82) => 0.0111391
+(3, -1) ~ (4, 83) => 0.0028022
+(3, -1) ~ (4, 84) => 0.00928301
+(3, -1) ~ (4, 85) => 0.0196739
+(3, -1) ~ (4, 86) => 0.0223252
+(3, -1) ~ (4, 87) => 0.0260161
+(3, -1) ~ (4, 88) => 0.0228834
+(3, -1) ~ (4, 89) => 0.0363416
+(3, -1) ~ (4, 90) => 0.0395278
+(3, -1) ~ (4, 91) => 0.0514774
+(3, -1) ~ (4, 92) => 0.326926
+(3, -1) ~ (4, 93) => 0.442471
+(3, -1) ~ (4, 94) => 0.467349
+(3, -1) ~ (4, 95) => 0.61257
+(3, -1) ~ (4, 96) => 0.434718
+(3, -1) ~ (4, 97) => 0.393888
+(3, -1) ~ (4, 98) => 0.436968
+(3, -1) ~ (4, 99) => 0.472173
+(3, -1) ~ (4, 100) => 0.352107
+(3, -1) ~ (4, 101) => 0.300522
+(3, -1) ~ (4, 102) => 0.267514
+(3, -1) ~ (4, 103) => 0.254169
+(3, -1) ~ (4, 104) => 0.267938
+(3, -1) ~ (4, 105) => 0.195678
+(3, -1) ~ (4, 106) => 0.0318516
+(3, -1) ~ (4, 107) => 0.0057106
+(3, -1) ~ (4, 108) => 0.00105268
+(3, -1) ~ (4, 109) => 0.000180185
+(3, -1) ~ (4, 110) => 0.000227749
+(3, -1) ~ (4, 111) => 0.000197291
+(3, -1) ~ (4, 112) => 0.0001
+(3, -1) ~ (4, 113) => 0.0001
+(3, -1) ~ (4, 114) => 0.0001
+(3, -1) ~ (4, 115) => 0.0001
+(3, -1) ~ (4, 116) => 0.000542939
+(3, -1) ~ (4, 117) => 0.00116867
+(3, -1) ~ (4, 118) => 0.00186825
+(3, -1) ~ (4, 119) => 0.00193202
+(3, -1) ~ (4, 120) => 0.00398368
+(3, -1) ~ (4, 121) => 0.00526488
+(3, -1) ~ (4, 122) => 0.00686759
+(3, -1) ~ (4, 123) => 0.00861305
+(3, -1) ~ (4, 124) => 0.00878602
+(3, -1) ~ (4, 125) => 0.0106489
+(3, -1) ~ (4, 126) => 0.0132666
+(3, -1) ~ (4, 127) => 0.00346729
+(3, -1) ~ (4, 128) => 0.00277723
+(3, -1) ~ (4, 129) => 0.00409102
+(3, -1) ~ (4, 130) => 0.0217607
+(3, -1) ~ (4, 131) => 0.0403322
+(3, -1) ~ (4, 132) => 0.0603136
+(3, -1) ~ (4, 133) => 0.0501179
+(3, -1) ~ (4, 134) => 0.0279671
+(3, -1) ~ (4, 135) => 0.0450833
+(3, -1) ~ (4, 136) => 0.0553932
+(3, -1) ~ (4, 137) => 0.0593698
+(3, -1) ~ (4, 138) => 0.0746651
+(3, -1) ~ (4, 139) => 0.123882
+(3, -1) ~ (4, 140) => 0.149273
+(3, -1) ~ (4, 141) => 0.0789851
+(3, -1) ~ (4, 142) => 0.0804265
+(3, -1) ~ (4, 143) => 0.0878573
+(3, -1) ~ (4, 144) => 0.0562247
+(3, -1) ~ (4, 145) => 0.053735
+(3, -1) ~ (4, 146) => 0.025565
+(3, -1) ~ (4, 147) => 0.00339246
+(3, -1) ~ (4, 148) => 0.000195682
+(3, -1) ~ (4, 149) => 0.0001
+(3, -1) ~ (4, 150) => 0.0001
+(3, -1) ~ (4, 151) => 0.0001
+(3, -1) ~ (4, 152) => 0.0001
+(3, -1) ~ (4, 153) => 0.0001
+(3, -1) ~ (4, 154) => 0.0001
+(3, -1) ~ (4, 155) => 0.0001
+(3, -1) ~ (4, 156) => 0.0001
+(3, -1) ~ (4, 157) => 0.0001
+(3, -1) ~ (4, 158) => 0.0001
+(3, -1) ~ (4, 159) => 0.000786066
+(3, -1) ~ (4, 160) => 0.00115883
+(3, -1) ~ (4, 161) => 0.00108081
+(3, -1) ~ (4, 162) => 0.00102836
+(3, -1) ~ (4, 163) => 0.00141203
+(3, -1) ~ (4, 164) => 0.00147116
+(3, -1) ~ (4, 165) => 0.00165385
+(3, -1) ~ (4, 166) => 0.000982285
+(3, -1) ~ (4, 167) => 0.00072217
+(3, -1) ~ (4, 168) => 0.000541031
+(3, -1) ~ (4, 169) => 0.0001
+(3, -1) ~ (4, 170) => 0.000252128
+(3, -1) ~ (4, 171) => 0.000328481
+(3, -1) ~ (4, 172) => 0.000154912
+(3, -1) ~ (4, 173) => 0.0001
+(3, -1) ~ (4, 174) => 0.0001
+(3, -1) ~ (4, 175) => 0.0001
+(3, -1) ~ (4, 176) => 0.000212669
+(3, -1) ~ (4, 177) => 0.000364661
+(3, -1) ~ (4, 178) => 0.00040704
+(3, -1) ~ (4, 179) => 0.000314355
+(3, -1) ~ (4, 180) => 0.0001
+(3, -1) ~ (4, 181) => 0.0001
+(3, -1) ~ (4, 182) => 0.0001
+(3, -1) ~ (4, 183) => 0.0001
+(3, -1) ~ (4, 184) => 0.000362515
+(3, -1) ~ (4, 185) => 0.011914
+(3, -1) ~ (4, 186) => 0.0236585
+(3, -1) ~ (4, 187) => 0.0357308
+(3, -1) ~ (4, 188) => 0.038949
+(3, -1) ~ (4, 189) => 0.0674359
+(3, -1) ~ (4, 190) => 0.0517381
+(3, -1) ~ (4, 191) => 0.0215944
+(3, -1) ~ (4, 192) => 0.0141849
+(3, -1) ~ (4, 193) => 0.0190164
+(3, -1) ~ (4, 194) => 0.099467
+(3, -1) ~ (4, 195) => 0.0741048
+(3, -1) ~ (4, 196) => 0.0289407
+(3, -1) ~ (4, 197) => 0.0295253
+(3, -1) ~ (4, 198) => 0.0459892
+(3, -1) ~ (4, 199) => 0.0208516
+(3, -1) ~ (4, 200) => 0.0110848
+(3, -1) ~ (4, 201) => 0.00827348
+(3, -1) ~ (4, 202) => 0.0155731
+(3, -1) ~ (4, 203) => 0.0189866
+(3, -1) ~ (4, 204) => 0.0178031
+(3, -1) ~ (4, 205) => 0.0185339
+(3, -1) ~ (4, 206) => 0.0281405
+(3, -1) ~ (4, 207) => 0.0315587
+(3, -1) ~ (4, 208) => 0.0269687
+(3, -1) ~ (4, 209) => 0.0253214
+(3, -1) ~ (4, 210) => 0.0190563
+(3, -1) ~ (4, 211) => 0.0258598
+(3, -1) ~ (4, 212) => 0.0359852
+(3, -1) ~ (4, 213) => 0.0280243
+(3, -1) ~ (4, 214) => 0.0288253
+(3, -1) ~ (4, 215) => 0.0246651
+(3, -1) ~ (4, 216) => 0.0245826
+(3, -1) ~ (4, 217) => 0.036433
+(3, -1) ~ (4, 218) => 0.164964
+(3, -1) ~ (4, 219) => 0.268562
+(3, -1) ~ (4, 220) => 0.512336
+(3, -1) ~ (4, 221) => 0.547546
+(3, -1) ~ (4, 222) => 0.186027
+(3, -1) ~ (4, 223) => 0.0752987
+(3, -1) ~ (4, 224) => 0.0626991
+(3, -1) ~ (4, 225) => 0.0312123
+(3, -1) ~ (4, 226) => 0.0601346
+(3, -1) ~ (4, 227) => 0.00587869
+(3, -1) ~ (4, 228) => 0.00184113
+(3, -1) ~ (4, 229) => 0.00604314
+(3, -1) ~ (4, 230) => 0.00107229
+(3, -1) ~ (4, 231) => 0.00169373
+(3, -1) ~ (4, 232) => 0.00145829
+(3, -1) ~ (4, 233) => 0.00272769
+(3, -1) ~ (4, 234) => 0.00395983
+(3, -1) ~ (4, 235) => 0.00461376
+(3, -1) ~ (4, 236) => 0.00408548
+(3, -1) ~ (4, 237) => 0.00313812
+
+; Sparse posterior probability matrix for sequences 3 and 5
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(3, 0) ~ (5, 0) => 0.501935
+(3, 1) ~ (5, 0) => 0.48644
+(3, 1) ~ (5, 1) => 0.390926
+(3, 1) ~ (5, 2) => 0.0101618
+(3, 2) ~ (5, 1) => 0.586952
+(3, 2) ~ (5, 2) => 0.331122
+(3, 3) ~ (5, 2) => 0.639813
+(3, 3) ~ (5, 3) => 0.284245
+(3, 4) ~ (5, 2) => 0.0129092
+(3, 4) ~ (5, 3) => 0.689515
+(3, 4) ~ (5, 4) => 0.267188
+(3, 5) ~ (5, 3) => 0.0100894
+(3, 5) ~ (5, 4) => 0.714287
+(3, 5) ~ (5, 5) => 0.16637
+(3, 6) ~ (5, 5) => 0.82519
+(3, 6) ~ (5, 6) => 0.0379714
+(3, 7) ~ (5, 6) => 0.959517
+(3, 8) ~ (5, 7) => 0.996875
+(3, 9) ~ (5, 8) => 0.99901
+(3, 10) ~ (5, 9) => 0.999668
+(3, 11) ~ (5, 10) => 0.999715
+(3, 12) ~ (5, 11) => 0.999811
+(3, 13) ~ (5, 12) => 0.999716
+(3, 14) ~ (5, 13) => 0.996745
+(3, 15) ~ (5, 14) => 0.994892
+(3, 16) ~ (5, 15) => 0.992157
+(3, 17) ~ (5, 16) => 0.989885
+(3, 18) ~ (5, 17) => 0.990172
+(3, 19) ~ (5, 18) => 0.993664
+(3, 20) ~ (5, 19) => 0.997258
+(3, 21) ~ (5, 20) => 0.999004
+(3, 22) ~ (5, 21) => 0.999879
+(3, 23) ~ (5, 22) => 0.999997
+(3, 24) ~ (5, 23) => 0.999978
+(3, 25) ~ (5, 24) => 0.99974
+(3, 26) ~ (5, 25) => 0.998063
+(3, 27) ~ (5, 26) => 0.99673
+(3, 28) ~ (5, 27) => 0.979527
+(3, 29) ~ (5, 28) => 0.962668
+(3, 30) ~ (5, 29) => 0.867626
+(3, 31) ~ (5, 27) => 0.0176343
+(3, 31) ~ (5, 30) => 0.801518
+(3, 32) ~ (5, 28) => 0.0338486
+(3, 32) ~ (5, 31) => 0.795244
+(3, 33) ~ (5, 29) => 0.130633
+(3, 33) ~ (5, 32) => 0.777133
+(3, 34) ~ (5, 30) => 0.195675
+(3, 34) ~ (5, 33) => 0.742507
+(3, 35) ~ (5, 31) => 0.202219
+(3, 35) ~ (5, 34) => 0.697786
+(3, 36) ~ (5, 32) => 0.218282
+(3, 36) ~ (5, 35) => 0.6134
+(3, 37) ~ (5, 33) => 0.240578
+(3, 37) ~ (5, 36) => 0.159804
+(3, 38) ~ (5, 33) => 0.0113623
+(3, 38) ~ (5, 34) => 0.284176
+(3, 38) ~ (5, 37) => 0.0491357
+(3, 39) ~ (5, 34) => 0.0106858
+(3, 39) ~ (5, 35) => 0.366396
+(3, 39) ~ (5, 38) => 0.0343438
+(3, 40) ~ (5, 36) => 0.821424
+(3, 40) ~ (5, 39) => 0.0293656
+(3, 41) ~ (5, 37) => 0.939382
+(3, 41) ~ (5, 40) => 0.0291821
+(3, 42) ~ (5, 38) => 0.958872
+(3, 42) ~ (5, 41) => 0.0294271
+(3, 43) ~ (5, 39) => 0.963925
+(3, 43) ~ (5, 42) => 0.0294518
+(3, 44) ~ (5, 40) => 0.963688
+(3, 44) ~ (5, 43) => 0.0307969
+(3, 45) ~ (5, 41) => 0.96524
+(3, 45) ~ (5, 44) => 0.0297339
+(3, 46) ~ (5, 42) => 0.966889
+(3, 46) ~ (5, 45) => 0.0286671
+(3, 47) ~ (5, 43) => 0.965998
+(3, 47) ~ (5, 46) => 0.0252859
+(3, 48) ~ (5, 44) => 0.966294
+(3, 48) ~ (5, 47) => 0.0172225
+(3, 49) ~ (5, 45) => 0.966107
+(3, 50) ~ (5, 46) => 0.936092
+(3, 50) ~ (5, 47) => 0.0406918
+(3, 51) ~ (5, 47) => 0.904978
+(3, 51) ~ (5, 48) => 0.0831536
+(3, 52) ~ (5, 48) => 0.635654
+(3, 52) ~ (5, 49) => 0.350092
+(3, 53) ~ (5, 49) => 0.231284
+(3, 53) ~ (5, 50) => 0.755451
+(3, 54) ~ (5, 50) => 0.159932
+(3, 54) ~ (5, 51) => 0.831653
+(3, 55) ~ (5, 51) => 0.0533727
+(3, 55) ~ (5, 52) => 0.94539
+(3, 56) ~ (5, 53) => 0.998071
+(3, 57) ~ (5, 54) => 0.999753
+(3, 58) ~ (5, 55) => 0.999934
+(3, 59) ~ (5, 56) => 0.999753
+(3, 60) ~ (5, 57) => 0.998701
+(3, 61) ~ (5, 58) => 0.959586
+(3, 62) ~ (5, 58) => 0.0400821
+(3, 62) ~ (5, 59) => 0.941392
+(3, 63) ~ (5, 59) => 0.0579732
+(3, 63) ~ (5, 60) => 0.793893
+(3, 64) ~ (5, 60) => 0.20421
+(3, 64) ~ (5, 61) => 0.64705
+(3, 65) ~ (5, 61) => 0.350423
+(3, 65) ~ (5, 62) => 0.498119
+(3, 66) ~ (5, 62) => 0.496786
+(3, 66) ~ (5, 63) => 0.256303
+(3, 67) ~ (5, 63) => 0.737786
+(3, 67) ~ (5, 64) => 0.200967
+(3, 68) ~ (5, 64) => 0.791596
+(3, 68) ~ (5, 65) => 0.148307
+(3, 69) ~ (5, 65) => 0.84602
+(3, 69) ~ (5, 66) => 0.0167467
+(3, 70) ~ (5, 66) => 0.982261
+(3, 71) ~ (5, 67) => 0.99688
+(3, 72) ~ (5, 68) => 0.997761
+(3, 73) ~ (5, 69) => 0.999069
+(3, 74) ~ (5, 70) => 0.999409
+(3, 75) ~ (5, 71) => 0.999944
+(3, 76) ~ (5, 72) => 0.999979
+(3, 77) ~ (5, 73) => 0.999987
+(3, 78) ~ (5, 74) => 0.999973
+(3, 79) ~ (5, 75) => 0.999972
+(3, 80) ~ (5, 76) => 0.999958
+(3, 81) ~ (5, 77) => 0.99907
+(3, 82) ~ (5, 78) => 0.998825
+(3, 83) ~ (5, 79) => 0.998669
+(3, 84) ~ (5, 80) => 0.99884
+(3, 85) ~ (5, 81) => 0.999501
+(3, 86) ~ (5, 82) => 0.999899
+(3, 87) ~ (5, 83) => 0.99981
+(3, 88) ~ (5, 84) => 0.999853
+(3, 89) ~ (5, 85) => 0.999945
+(3, 90) ~ (5, 86) => 0.999856
+(3, 91) ~ (5, 87) => 0.999832
+(3, 92) ~ (5, 88) => 0.999935
+(3, 93) ~ (5, 89) => 0.999809
+(3, 94) ~ (5, 90) => 0.99972
+(3, 95) ~ (5, 91) => 0.999144
+(3, 96) ~ (5, 92) => 0.998731
+(3, 97) ~ (5, 93) => 0.998883
+(3, 98) ~ (5, 94) => 0.999247
+(3, 99) ~ (5, 95) => 0.999717
+(3, 100) ~ (5, 96) => 0.999251
+(3, 101) ~ (5, 97) => 0.998927
+(3, 102) ~ (5, 98) => 0.998617
+(3, 103) ~ (5, 99) => 0.99857
+(3, 104) ~ (5, 100) => 0.998975
+(3, 105) ~ (5, 101) => 0.999537
+(3, 106) ~ (5, 102) => 0.999758
+(3, 107) ~ (5, 103) => 0.999908
+(3, 108) ~ (5, 104) => 0.999967
+(3, 109) ~ (5, 105) => 0.99999
+(3, 110) ~ (5, 106) => 0.999951
+(3, 111) ~ (5, 107) => 0.999938
+(3, 112) ~ (5, 108) => 0.999976
+(3, 113) ~ (5, 109) => 0.99997
+(3, 114) ~ (5, 110) => 0.999962
+(3, 115) ~ (5, 111) => 0.999973
+(3, 116) ~ (5, 112) => 0.999996
+(3, 117) ~ (5, 113) => 0.999993
+(3, 118) ~ (5, 114) => 0.999986
+(3, 119) ~ (5, 115) => 0.999819
+(3, 120) ~ (5, 116) => 0.998453
+(3, 121) ~ (5, 117) => 0.998068
+(3, 122) ~ (5, 118) => 0.996792
+(3, 123) ~ (5, 119) => 0.996844
+(3, 124) ~ (5, 120) => 0.999461
+(3, 125) ~ (5, 121) => 0.999346
+(3, 126) ~ (5, 122) => 0.999175
+(3, 127) ~ (5, 123) => 0.999255
+(3, 128) ~ (5, 124) => 0.999789
+(3, 129) ~ (5, 125) => 0.999962
+(3, 130) ~ (5, 126) => 0.999987
+(3, 131) ~ (5, 127) => 0.999993
+(3, 132) ~ (5, 128) => 0.999996
+(3, 133) ~ (5, 129) => 0.999995
+(3, 134) ~ (5, 130) => 0.999996
+(3, 135) ~ (5, 131) => 0.999988
+(3, 136) ~ (5, 132) => 0.999984
+(3, 137) ~ (5, 133) => 0.999936
+(3, 138) ~ (5, 134) => 0.999931
+(3, 139) ~ (5, 135) => 0.999975
+(3, 140) ~ (5, 136) => 0.999929
+(3, 141) ~ (5, 137) => 0.999877
+(3, 142) ~ (5, 138) => 0.99991
+(3, 143) ~ (5, 139) => 0.999983
+(3, 144) ~ (5, 140) => 0.99999
+(3, 145) ~ (5, 141) => 0.999978
+(3, 146) ~ (5, 142) => 0.999973
+(3, 147) ~ (5, 143) => 0.999982
+(3, 148) ~ (5, 144) => 0.999989
+(3, 149) ~ (5, 145) => 0.999997
+(3, 150) ~ (5, 146) => 0.999997
+(3, 151) ~ (5, 147) => 0.999991
+(3, 152) ~ (5, 148) => 0.99996
+(3, 153) ~ (5, 149) => 0.999901
+(3, 154) ~ (5, 150) => 0.999897
+(3, 155) ~ (5, 151) => 0.999957
+(3, 156) ~ (5, 152) => 0.999977
+(3, 157) ~ (5, 153) => 0.999922
+(3, 158) ~ (5, 154) => 0.999899
+(3, 159) ~ (5, 155) => 0.999809
+(3, 160) ~ (5, 156) => 0.999737
+(3, 161) ~ (5, 157) => 0.999158
+(3, 162) ~ (5, 158) => 0.998951
+(3, 163) ~ (5, 159) => 0.999108
+(3, 164) ~ (5, 160) => 0.999268
+(3, 165) ~ (5, 161) => 0.999635
+(3, 166) ~ (5, 162) => 0.999888
+(3, 167) ~ (5, 163) => 0.999955
+(3, 168) ~ (5, 164) => 0.999991
+(3, 169) ~ (5, 165) => 0.999985
+(3, 170) ~ (5, 166) => 0.999828
+(3, 171) ~ (5, 167) => 0.99948
+(3, 172) ~ (5, 168) => 0.99877
+(3, 173) ~ (5, 169) => 0.998858
+(3, 174) ~ (5, 170) => 0.999391
+(3, 175) ~ (5, 171) => 0.999924
+(3, 176) ~ (5, 172) => 0.999933
+(3, 177) ~ (5, 173) => 0.999872
+(3, 178) ~ (5, 174) => 0.99971
+(3, 179) ~ (5, 175) => 0.999559
+(3, 180) ~ (5, 176) => 0.99957
+(3, 181) ~ (5, 177) => 0.999761
+(3, 182) ~ (5, 178) => 0.999964
+(3, 183) ~ (5, 179) => 0.999995
+(3, 184) ~ (5, 180) => 0.999924
+(3, 185) ~ (5, 181) => 0.999848
+(3, 186) ~ (5, 182) => 0.996639
+(3, 187) ~ (5, 183) => 0.99281
+(3, 188) ~ (5, 184) => 0.988571
+(3, 189) ~ (5, 185) => 0.980677
+(3, 189) ~ (5, 186) => 0.0126861
+(3, 190) ~ (5, 186) => 0.971089
+(3, 190) ~ (5, 187) => 0.0171869
+(3, 191) ~ (5, 187) => 0.960689
+(3, 191) ~ (5, 188) => 0.0167335
+(3, 192) ~ (5, 187) => 0.011708
+(3, 192) ~ (5, 188) => 0.931883
+(3, 192) ~ (5, 189) => 0.0140752
+(3, 193) ~ (5, 188) => 0.0360679
+(3, 193) ~ (5, 189) => 0.919576
+(3, 193) ~ (5, 190) => 0.0132692
+(3, 194) ~ (5, 189) => 0.0488157
+(3, 194) ~ (5, 190) => 0.907796
+(3, 195) ~ (5, 190) => 0.0599797
+(3, 195) ~ (5, 191) => 0.903189
+(3, 196) ~ (5, 191) => 0.0696801
+(3, 196) ~ (5, 192) => 0.792728
+(3, 196) ~ (5, 193) => 0.0140078
+(3, 197) ~ (5, 192) => 0.171756
+(3, 197) ~ (5, 193) => 0.691711
+(3, 197) ~ (5, 194) => 0.0115629
+(3, 198) ~ (5, 193) => 0.272801
+(3, 198) ~ (5, 194) => 0.525836
+(3, 199) ~ (5, 194) => 0.442522
+(3, 199) ~ (5, 195) => 0.4417
+(3, 200) ~ (5, 195) => 0.530504
+(3, 200) ~ (5, 196) => 0.320527
+(3, 201) ~ (5, 196) => 0.657363
+(3, 201) ~ (5, 197) => 0.0426322
+(3, 202) ~ (5, 197) => 0.950248
+(3, 202) ~ (5, 198) => 0.0341275
+(3, 203) ~ (5, 198) => 0.9625
+(3, 203) ~ (5, 199) => 0.0253895
+(3, 204) ~ (5, 199) => 0.972016
+(3, 204) ~ (5, 200) => 0.0232212
+(3, 205) ~ (5, 200) => 0.974522
+(3, 205) ~ (5, 201) => 0.0144147
+(3, 206) ~ (5, 201) => 0.983757
+(3, 207) ~ (5, 202) => 0.990367
+(3, 208) ~ (5, 203) => 0.997165
+(3, 209) ~ (5, 204) => 0.998042
+(3, 210) ~ (5, 205) => 0.999549
+(3, 211) ~ (5, 206) => 0.999489
+(3, 212) ~ (5, 207) => 0.999656
+(3, 213) ~ (5, 208) => 0.998202
+(3, 214) ~ (5, 209) => 0.993613
+(3, 215) ~ (5, 210) => 0.959154
+(3, 215) ~ (5, 211) => 0.0402022
+(3, 216) ~ (5, 211) => 0.948764
+(3, 216) ~ (5, 212) => 0.0505854
+(3, 217) ~ (5, 212) => 0.94769
+(3, 217) ~ (5, 213) => 0.0499067
+(3, 218) ~ (5, 213) => 0.949655
+(3, 218) ~ (5, 214) => 0.0325627
+(3, 219) ~ (5, 214) => 0.967223
+(3, 219) ~ (5, 215) => 0.0151152
+(3, 220) ~ (5, 215) => 0.984661
+(3, 221) ~ (5, 216) => 0.996001
+(3, 222) ~ (5, 217) => 0.998056
+(3, 223) ~ (5, 218) => 0.999539
+(3, 224) ~ (5, 219) => 0.999652
+(3, 225) ~ (5, 220) => 0.999369
+(3, 226) ~ (5, 221) => 0.999186
+(3, 227) ~ (5, 222) => 0.99927
+(3, 228) ~ (5, 223) => 0.999739
+(3, 229) ~ (5, 224) => 0.999843
+(3, 230) ~ (5, 225) => 0.999989
+(3, 231) ~ (5, 226) => 0.999992
+(3, 232) ~ (5, 227) => 0.999943
+(3, 233) ~ (5, 228) => 0.999786
+(3, 234) ~ (5, 229) => 0.998515
+(3, 235) ~ (5, 230) => 0.997021
+(3, 236) ~ (5, 231) => 0.995883
+(3, 237) ~ (5, 232) => 0.995177
+(3, 238) ~ (5, 233) => 0.995589
+
+; gap posteriors
+(3, 0) ~ (5, -1) => 0.498065
+(3, 1) ~ (5, -1) => 0.112472
+(3, 2) ~ (5, -1) => 0.0819268
+(3, 3) ~ (5, -1) => 0.075942
+(3, 4) ~ (5, -1) => 0.0303884
+(3, 5) ~ (5, -1) => 0.109253
+(3, 6) ~ (5, -1) => 0.136839
+(3, 7) ~ (5, -1) => 0.0404828
+(3, 8) ~ (5, -1) => 0.00312519
+(3, 9) ~ (5, -1) => 0.000989854
+(3, 10) ~ (5, -1) => 0.000332177
+(3, 11) ~ (5, -1) => 0.000285387
+(3, 12) ~ (5, -1) => 0.000189066
+(3, 13) ~ (5, -1) => 0.000284195
+(3, 14) ~ (5, -1) => 0.00325525
+(3, 15) ~ (5, -1) => 0.00510758
+(3, 16) ~ (5, -1) => 0.00784349
+(3, 17) ~ (5, -1) => 0.0101147
+(3, 18) ~ (5, -1) => 0.00982839
+(3, 19) ~ (5, -1) => 0.00633556
+(3, 20) ~ (5, -1) => 0.00274241
+(3, 21) ~ (5, -1) => 0.000995636
+(3, 22) ~ (5, -1) => 0.000120997
+(3, 23) ~ (5, -1) => 0.0001
+(3, 24) ~ (5, -1) => 0.0001
+(3, 25) ~ (5, -1) => 0.000259697
+(3, 26) ~ (5, -1) => 0.00193715
+(3, 27) ~ (5, -1) => 0.00326985
+(3, 28) ~ (5, -1) => 0.0204731
+(3, 29) ~ (5, -1) => 0.0373315
+(3, 30) ~ (5, -1) => 0.132374
+(3, 31) ~ (5, -1) => 0.180848
+(3, 32) ~ (5, -1) => 0.170907
+(3, 33) ~ (5, -1) => 0.092234
+(3, 34) ~ (5, -1) => 0.0618187
+(3, 35) ~ (5, -1) => 0.0999948
+(3, 36) ~ (5, -1) => 0.168319
+(3, 37) ~ (5, -1) => 0.599618
+(3, 38) ~ (5, -1) => 0.655326
+(3, 39) ~ (5, -1) => 0.588574
+(3, 40) ~ (5, -1) => 0.149211
+(3, 41) ~ (5, -1) => 0.0314355
+(3, 42) ~ (5, -1) => 0.0117004
+(3, 43) ~ (5, -1) => 0.00662309
+(3, 44) ~ (5, -1) => 0.00551516
+(3, 45) ~ (5, -1) => 0.00502591
+(3, 46) ~ (5, -1) => 0.00444421
+(3, 47) ~ (5, -1) => 0.00871636
+(3, 48) ~ (5, -1) => 0.0164832
+(3, 49) ~ (5, -1) => 0.0338932
+(3, 50) ~ (5, -1) => 0.0232164
+(3, 51) ~ (5, -1) => 0.011868
+(3, 52) ~ (5, -1) => 0.0142536
+(3, 53) ~ (5, -1) => 0.0132649
+(3, 54) ~ (5, -1) => 0.00841528
+(3, 55) ~ (5, -1) => 0.00123703
+(3, 56) ~ (5, -1) => 0.00192946
+(3, 57) ~ (5, -1) => 0.000246763
+(3, 58) ~ (5, -1) => 0.0001
+(3, 59) ~ (5, -1) => 0.000246704
+(3, 60) ~ (5, -1) => 0.00129867
+(3, 61) ~ (5, -1) => 0.0404139
+(3, 62) ~ (5, -1) => 0.0185262
+(3, 63) ~ (5, -1) => 0.148134
+(3, 64) ~ (5, -1) => 0.14874
+(3, 65) ~ (5, -1) => 0.151459
+(3, 66) ~ (5, -1) => 0.246911
+(3, 67) ~ (5, -1) => 0.0612473
+(3, 68) ~ (5, -1) => 0.0600971
+(3, 69) ~ (5, -1) => 0.137233
+(3, 70) ~ (5, -1) => 0.0177386
+(3, 71) ~ (5, -1) => 0.0031203
+(3, 72) ~ (5, -1) => 0.00223863
+(3, 73) ~ (5, -1) => 0.000930965
+(3, 74) ~ (5, -1) => 0.000591457
+(3, 75) ~ (5, -1) => 0.0001
+(3, 76) ~ (5, -1) => 0.0001
+(3, 77) ~ (5, -1) => 0.0001
+(3, 78) ~ (5, -1) => 0.0001
+(3, 79) ~ (5, -1) => 0.0001
+(3, 80) ~ (5, -1) => 0.0001
+(3, 81) ~ (5, -1) => 0.000930071
+(3, 82) ~ (5, -1) => 0.00117522
+(3, 83) ~ (5, -1) => 0.00133109
+(3, 84) ~ (5, -1) => 0.00115985
+(3, 85) ~ (5, -1) => 0.000499249
+(3, 86) ~ (5, -1) => 0.000100672
+(3, 87) ~ (5, -1) => 0.000189841
+(3, 88) ~ (5, -1) => 0.000146866
+(3, 89) ~ (5, -1) => 0.0001
+(3, 90) ~ (5, -1) => 0.000143588
+(3, 91) ~ (5, -1) => 0.000168264
+(3, 92) ~ (5, -1) => 0.0001
+(3, 93) ~ (5, -1) => 0.000190675
+(3, 94) ~ (5, -1) => 0.000280082
+(3, 95) ~ (5, -1) => 0.000855565
+(3, 96) ~ (5, -1) => 0.00126904
+(3, 97) ~ (5, -1) => 0.00111663
+(3, 98) ~ (5, -1) => 0.000753284
+(3, 99) ~ (5, -1) => 0.00028336
+(3, 100) ~ (5, -1) => 0.00074929
+(3, 101) ~ (5, -1) => 0.0010727
+(3, 102) ~ (5, -1) => 0.00138301
+(3, 103) ~ (5, -1) => 0.00143009
+(3, 104) ~ (5, -1) => 0.00102538
+(3, 105) ~ (5, -1) => 0.000463188
+(3, 106) ~ (5, -1) => 0.000242174
+(3, 107) ~ (5, -1) => 0.0001
+(3, 108) ~ (5, -1) => 0.0001
+(3, 109) ~ (5, -1) => 0.0001
+(3, 110) ~ (5, -1) => 0.0001
+(3, 111) ~ (5, -1) => 0.0001
+(3, 112) ~ (5, -1) => 0.0001
+(3, 113) ~ (5, -1) => 0.0001
+(3, 114) ~ (5, -1) => 0.0001
+(3, 115) ~ (5, -1) => 0.0001
+(3, 116) ~ (5, -1) => 0.0001
+(3, 117) ~ (5, -1) => 0.0001
+(3, 118) ~ (5, -1) => 0.0001
+(3, 119) ~ (5, -1) => 0.000180602
+(3, 120) ~ (5, -1) => 0.00154704
+(3, 121) ~ (5, -1) => 0.00193202
+(3, 122) ~ (5, -1) => 0.00320792
+(3, 123) ~ (5, -1) => 0.00315636
+(3, 124) ~ (5, -1) => 0.000539362
+(3, 125) ~ (5, -1) => 0.000653565
+(3, 126) ~ (5, -1) => 0.000825405
+(3, 127) ~ (5, -1) => 0.000745118
+(3, 128) ~ (5, -1) => 0.000211477
+(3, 129) ~ (5, -1) => 0.0001
+(3, 130) ~ (5, -1) => 0.0001
+(3, 131) ~ (5, -1) => 0.0001
+(3, 132) ~ (5, -1) => 0.0001
+(3, 133) ~ (5, -1) => 0.0001
+(3, 134) ~ (5, -1) => 0.0001
+(3, 135) ~ (5, -1) => 0.0001
+(3, 136) ~ (5, -1) => 0.0001
+(3, 137) ~ (5, -1) => 0.0001
+(3, 138) ~ (5, -1) => 0.0001
+(3, 139) ~ (5, -1) => 0.0001
+(3, 140) ~ (5, -1) => 0.0001
+(3, 141) ~ (5, -1) => 0.000123143
+(3, 142) ~ (5, -1) => 0.0001
+(3, 143) ~ (5, -1) => 0.0001
+(3, 144) ~ (5, -1) => 0.0001
+(3, 145) ~ (5, -1) => 0.0001
+(3, 146) ~ (5, -1) => 0.0001
+(3, 147) ~ (5, -1) => 0.0001
+(3, 148) ~ (5, -1) => 0.0001
+(3, 149) ~ (5, -1) => 0.0001
+(3, 150) ~ (5, -1) => 0.0001
+(3, 151) ~ (5, -1) => 0.0001
+(3, 152) ~ (5, -1) => 0.0001
+(3, 153) ~ (5, -1) => 0.0001
+(3, 154) ~ (5, -1) => 0.00010252
+(3, 155) ~ (5, -1) => 0.0001
+(3, 156) ~ (5, -1) => 0.0001
+(3, 157) ~ (5, -1) => 0.0001
+(3, 158) ~ (5, -1) => 0.000101268
+(3, 159) ~ (5, -1) => 0.000190854
+(3, 160) ~ (5, -1) => 0.000262856
+(3, 161) ~ (5, -1) => 0.000842273
+(3, 162) ~ (5, -1) => 0.00104904
+(3, 163) ~ (5, -1) => 0.000891566
+(3, 164) ~ (5, -1) => 0.000731826
+(3, 165) ~ (5, -1) => 0.000365257
+(3, 166) ~ (5, -1) => 0.000111878
+(3, 167) ~ (5, -1) => 0.0001
+(3, 168) ~ (5, -1) => 0.0001
+(3, 169) ~ (5, -1) => 0.0001
+(3, 170) ~ (5, -1) => 0.000172198
+(3, 171) ~ (5, -1) => 0.000519991
+(3, 172) ~ (5, -1) => 0.00122958
+(3, 173) ~ (5, -1) => 0.00114179
+(3, 174) ~ (5, -1) => 0.0006091
+(3, 175) ~ (5, -1) => 0.0001
+(3, 176) ~ (5, -1) => 0.0001
+(3, 177) ~ (5, -1) => 0.00012821
+(3, 178) ~ (5, -1) => 0.000290275
+(3, 179) ~ (5, -1) => 0.000441074
+(3, 180) ~ (5, -1) => 0.000430465
+(3, 181) ~ (5, -1) => 0.000238717
+(3, 182) ~ (5, -1) => 0.0001
+(3, 183) ~ (5, -1) => 0.0001
+(3, 184) ~ (5, -1) => 0.0001
+(3, 185) ~ (5, -1) => 0.000151873
+(3, 186) ~ (5, -1) => 0.00336063
+(3, 187) ~ (5, -1) => 0.00719023
+(3, 188) ~ (5, -1) => 0.0114287
+(3, 189) ~ (5, -1) => 0.00663644
+(3, 190) ~ (5, -1) => 0.0117244
+(3, 191) ~ (5, -1) => 0.0225771
+(3, 192) ~ (5, -1) => 0.0423337
+(3, 193) ~ (5, -1) => 0.0310874
+(3, 194) ~ (5, -1) => 0.0433885
+(3, 195) ~ (5, -1) => 0.0368309
+(3, 196) ~ (5, -1) => 0.123584
+(3, 197) ~ (5, -1) => 0.12497
+(3, 198) ~ (5, -1) => 0.201363
+(3, 199) ~ (5, -1) => 0.115778
+(3, 200) ~ (5, -1) => 0.148969
+(3, 201) ~ (5, -1) => 0.300005
+(3, 202) ~ (5, -1) => 0.0156246
+(3, 203) ~ (5, -1) => 0.0121109
+(3, 204) ~ (5, -1) => 0.004763
+(3, 205) ~ (5, -1) => 0.0110629
+(3, 206) ~ (5, -1) => 0.0162433
+(3, 207) ~ (5, -1) => 0.00963253
+(3, 208) ~ (5, -1) => 0.00283521
+(3, 209) ~ (5, -1) => 0.00195801
+(3, 210) ~ (5, -1) => 0.000450909
+(3, 211) ~ (5, -1) => 0.000511169
+(3, 212) ~ (5, -1) => 0.000343621
+(3, 213) ~ (5, -1) => 0.00179845
+(3, 214) ~ (5, -1) => 0.00638652
+(3, 215) ~ (5, -1) => 0.000643779
+(3, 216) ~ (5, -1) => 0.000650886
+(3, 217) ~ (5, -1) => 0.00240277
+(3, 218) ~ (5, -1) => 0.0177826
+(3, 219) ~ (5, -1) => 0.0176623
+(3, 220) ~ (5, -1) => 0.015339
+(3, 221) ~ (5, -1) => 0.00399911
+(3, 222) ~ (5, -1) => 0.00194448
+(3, 223) ~ (5, -1) => 0.000460863
+(3, 224) ~ (5, -1) => 0.000347912
+(3, 225) ~ (5, -1) => 0.000630677
+(3, 226) ~ (5, -1) => 0.00081408
+(3, 227) ~ (5, -1) => 0.000730276
+(3, 228) ~ (5, -1) => 0.000261426
+(3, 229) ~ (5, -1) => 0.000156999
+(3, 230) ~ (5, -1) => 0.0001
+(3, 231) ~ (5, -1) => 0.0001
+(3, 232) ~ (5, -1) => 0.0001
+(3, 233) ~ (5, -1) => 0.000213742
+(3, 234) ~ (5, -1) => 0.00148493
+(3, 235) ~ (5, -1) => 0.00297862
+(3, 236) ~ (5, -1) => 0.00411654
+(3, 237) ~ (5, -1) => 0.00482345
+(3, 238) ~ (5, -1) => 0.00441128
+
+(3, -1) ~ (5, 0) => 0.0116247
+(3, -1) ~ (5, 1) => 0.022122
+(3, -1) ~ (5, 2) => 0.00599473
+(3, -1) ~ (5, 3) => 0.0161505
+(3, -1) ~ (5, 4) => 0.0185252
+(3, -1) ~ (5, 5) => 0.00844002
+(3, -1) ~ (5, 6) => 0.00251138
+(3, -1) ~ (5, 7) => 0.00312519
+(3, -1) ~ (5, 8) => 0.000989854
+(3, -1) ~ (5, 9) => 0.000332177
+(3, -1) ~ (5, 10) => 0.000285387
+(3, -1) ~ (5, 11) => 0.000189066
+(3, -1) ~ (5, 12) => 0.000284195
+(3, -1) ~ (5, 13) => 0.00325525
+(3, -1) ~ (5, 14) => 0.00510758
+(3, -1) ~ (5, 15) => 0.00784349
+(3, -1) ~ (5, 16) => 0.0101147
+(3, -1) ~ (5, 17) => 0.00982839
+(3, -1) ~ (5, 18) => 0.00633556
+(3, -1) ~ (5, 19) => 0.00274241
+(3, -1) ~ (5, 20) => 0.000995636
+(3, -1) ~ (5, 21) => 0.000120997
+(3, -1) ~ (5, 22) => 0.0001
+(3, -1) ~ (5, 23) => 0.0001
+(3, -1) ~ (5, 24) => 0.000259697
+(3, -1) ~ (5, 25) => 0.00193715
+(3, -1) ~ (5, 26) => 0.00326985
+(3, -1) ~ (5, 27) => 0.00283881
+(3, -1) ~ (5, 28) => 0.0034829
+(3, -1) ~ (5, 29) => 0.0017409
+(3, -1) ~ (5, 30) => 0.00280748
+(3, -1) ~ (5, 31) => 0.00253651
+(3, -1) ~ (5, 32) => 0.00458568
+(3, -1) ~ (5, 33) => 0.00555259
+(3, -1) ~ (5, 34) => 0.00735235
+(3, -1) ~ (5, 35) => 0.0202038
+(3, -1) ~ (5, 36) => 0.0187726
+(3, -1) ~ (5, 37) => 0.011482
+(3, -1) ~ (5, 38) => 0.00678372
+(3, -1) ~ (5, 39) => 0.00670922
+(3, -1) ~ (5, 40) => 0.00712991
+(3, -1) ~ (5, 41) => 0.00533271
+(3, -1) ~ (5, 42) => 0.00365949
+(3, -1) ~ (5, 43) => 0.00320542
+(3, -1) ~ (5, 44) => 0.00397182
+(3, -1) ~ (5, 45) => 0.00522614
+(3, -1) ~ (5, 46) => 0.0386223
+(3, -1) ~ (5, 47) => 0.0371073
+(3, -1) ~ (5, 48) => 0.281192
+(3, -1) ~ (5, 49) => 0.418624
+(3, -1) ~ (5, 50) => 0.0846169
+(3, -1) ~ (5, 51) => 0.114974
+(3, -1) ~ (5, 52) => 0.0546098
+(3, -1) ~ (5, 53) => 0.00192946
+(3, -1) ~ (5, 54) => 0.000246763
+(3, -1) ~ (5, 55) => 0.0001
+(3, -1) ~ (5, 56) => 0.000246704
+(3, -1) ~ (5, 57) => 0.00129867
+(3, -1) ~ (5, 58) => 0.000331815
+(3, -1) ~ (5, 59) => 0.00063514
+(3, -1) ~ (5, 60) => 0.00189771
+(3, -1) ~ (5, 61) => 0.00252706
+(3, -1) ~ (5, 62) => 0.00509557
+(3, -1) ~ (5, 63) => 0.00591069
+(3, -1) ~ (5, 64) => 0.00743711
+(3, -1) ~ (5, 65) => 0.00567269
+(3, -1) ~ (5, 66) => 0.00099194
+(3, -1) ~ (5, 67) => 0.0031203
+(3, -1) ~ (5, 68) => 0.00223863
+(3, -1) ~ (5, 69) => 0.000930965
+(3, -1) ~ (5, 70) => 0.000591457
+(3, -1) ~ (5, 71) => 0.0001
+(3, -1) ~ (5, 72) => 0.0001
+(3, -1) ~ (5, 73) => 0.0001
+(3, -1) ~ (5, 74) => 0.0001
+(3, -1) ~ (5, 75) => 0.0001
+(3, -1) ~ (5, 76) => 0.0001
+(3, -1) ~ (5, 77) => 0.000930071
+(3, -1) ~ (5, 78) => 0.00117522
+(3, -1) ~ (5, 79) => 0.00133109
+(3, -1) ~ (5, 80) => 0.00115985
+(3, -1) ~ (5, 81) => 0.000499249
+(3, -1) ~ (5, 82) => 0.000100672
+(3, -1) ~ (5, 83) => 0.000189841
+(3, -1) ~ (5, 84) => 0.000146866
+(3, -1) ~ (5, 85) => 0.0001
+(3, -1) ~ (5, 86) => 0.000143588
+(3, -1) ~ (5, 87) => 0.000168264
+(3, -1) ~ (5, 88) => 0.0001
+(3, -1) ~ (5, 89) => 0.000190675
+(3, -1) ~ (5, 90) => 0.000280082
+(3, -1) ~ (5, 91) => 0.000855565
+(3, -1) ~ (5, 92) => 0.00126904
+(3, -1) ~ (5, 93) => 0.00111663
+(3, -1) ~ (5, 94) => 0.000753284
+(3, -1) ~ (5, 95) => 0.00028336
+(3, -1) ~ (5, 96) => 0.00074929
+(3, -1) ~ (5, 97) => 0.0010727
+(3, -1) ~ (5, 98) => 0.00138301
+(3, -1) ~ (5, 99) => 0.00143009
+(3, -1) ~ (5, 100) => 0.00102538
+(3, -1) ~ (5, 101) => 0.000463188
+(3, -1) ~ (5, 102) => 0.000242174
+(3, -1) ~ (5, 103) => 0.0001
+(3, -1) ~ (5, 104) => 0.0001
+(3, -1) ~ (5, 105) => 0.0001
+(3, -1) ~ (5, 106) => 0.0001
+(3, -1) ~ (5, 107) => 0.0001
+(3, -1) ~ (5, 108) => 0.0001
+(3, -1) ~ (5, 109) => 0.0001
+(3, -1) ~ (5, 110) => 0.0001
+(3, -1) ~ (5, 111) => 0.0001
+(3, -1) ~ (5, 112) => 0.0001
+(3, -1) ~ (5, 113) => 0.0001
+(3, -1) ~ (5, 114) => 0.0001
+(3, -1) ~ (5, 115) => 0.000180602
+(3, -1) ~ (5, 116) => 0.00154704
+(3, -1) ~ (5, 117) => 0.00193202
+(3, -1) ~ (5, 118) => 0.00320792
+(3, -1) ~ (5, 119) => 0.00315636
+(3, -1) ~ (5, 120) => 0.000539362
+(3, -1) ~ (5, 121) => 0.000653565
+(3, -1) ~ (5, 122) => 0.000825405
+(3, -1) ~ (5, 123) => 0.000745118
+(3, -1) ~ (5, 124) => 0.000211477
+(3, -1) ~ (5, 125) => 0.0001
+(3, -1) ~ (5, 126) => 0.0001
+(3, -1) ~ (5, 127) => 0.0001
+(3, -1) ~ (5, 128) => 0.0001
+(3, -1) ~ (5, 129) => 0.0001
+(3, -1) ~ (5, 130) => 0.0001
+(3, -1) ~ (5, 131) => 0.0001
+(3, -1) ~ (5, 132) => 0.0001
+(3, -1) ~ (5, 133) => 0.0001
+(3, -1) ~ (5, 134) => 0.0001
+(3, -1) ~ (5, 135) => 0.0001
+(3, -1) ~ (5, 136) => 0.0001
+(3, -1) ~ (5, 137) => 0.000123143
+(3, -1) ~ (5, 138) => 0.0001
+(3, -1) ~ (5, 139) => 0.0001
+(3, -1) ~ (5, 140) => 0.0001
+(3, -1) ~ (5, 141) => 0.0001
+(3, -1) ~ (5, 142) => 0.0001
+(3, -1) ~ (5, 143) => 0.0001
+(3, -1) ~ (5, 144) => 0.0001
+(3, -1) ~ (5, 145) => 0.0001
+(3, -1) ~ (5, 146) => 0.0001
+(3, -1) ~ (5, 147) => 0.0001
+(3, -1) ~ (5, 148) => 0.0001
+(3, -1) ~ (5, 149) => 0.0001
+(3, -1) ~ (5, 150) => 0.00010252
+(3, -1) ~ (5, 151) => 0.0001
+(3, -1) ~ (5, 152) => 0.0001
+(3, -1) ~ (5, 153) => 0.0001
+(3, -1) ~ (5, 154) => 0.000101268
+(3, -1) ~ (5, 155) => 0.000190854
+(3, -1) ~ (5, 156) => 0.000262856
+(3, -1) ~ (5, 157) => 0.000842273
+(3, -1) ~ (5, 158) => 0.00104904
+(3, -1) ~ (5, 159) => 0.000891566
+(3, -1) ~ (5, 160) => 0.000731826
+(3, -1) ~ (5, 161) => 0.000365257
+(3, -1) ~ (5, 162) => 0.000111878
+(3, -1) ~ (5, 163) => 0.0001
+(3, -1) ~ (5, 164) => 0.0001
+(3, -1) ~ (5, 165) => 0.0001
+(3, -1) ~ (5, 166) => 0.000172198
+(3, -1) ~ (5, 167) => 0.000519991
+(3, -1) ~ (5, 168) => 0.00122958
+(3, -1) ~ (5, 169) => 0.00114179
+(3, -1) ~ (5, 170) => 0.0006091
+(3, -1) ~ (5, 171) => 0.0001
+(3, -1) ~ (5, 172) => 0.0001
+(3, -1) ~ (5, 173) => 0.00012821
+(3, -1) ~ (5, 174) => 0.000290275
+(3, -1) ~ (5, 175) => 0.000441074
+(3, -1) ~ (5, 176) => 0.000430465
+(3, -1) ~ (5, 177) => 0.000238717
+(3, -1) ~ (5, 178) => 0.0001
+(3, -1) ~ (5, 179) => 0.0001
+(3, -1) ~ (5, 180) => 0.0001
+(3, -1) ~ (5, 181) => 0.000151873
+(3, -1) ~ (5, 182) => 0.00336063
+(3, -1) ~ (5, 183) => 0.00719023
+(3, -1) ~ (5, 184) => 0.0114287
+(3, -1) ~ (5, 185) => 0.0193225
+(3, -1) ~ (5, 186) => 0.0162252
+(3, -1) ~ (5, 187) => 0.0104157
+(3, -1) ~ (5, 188) => 0.0153155
+(3, -1) ~ (5, 189) => 0.0175335
+(3, -1) ~ (5, 190) => 0.0189553
+(3, -1) ~ (5, 191) => 0.0271305
+(3, -1) ~ (5, 192) => 0.0355152
+(3, -1) ~ (5, 193) => 0.0214802
+(3, -1) ~ (5, 194) => 0.020079
+(3, -1) ~ (5, 195) => 0.0277961
+(3, -1) ~ (5, 196) => 0.0221101
+(3, -1) ~ (5, 197) => 0.00711989
+(3, -1) ~ (5, 198) => 0.00337291
+(3, -1) ~ (5, 199) => 0.00259471
+(3, -1) ~ (5, 200) => 0.00225639
+(3, -1) ~ (5, 201) => 0.00182855
+(3, -1) ~ (5, 202) => 0.00963253
+(3, -1) ~ (5, 203) => 0.00283521
+(3, -1) ~ (5, 204) => 0.00195801
+(3, -1) ~ (5, 205) => 0.000450909
+(3, -1) ~ (5, 206) => 0.000511169
+(3, -1) ~ (5, 207) => 0.000343621
+(3, -1) ~ (5, 208) => 0.00179845
+(3, -1) ~ (5, 209) => 0.00638652
+(3, -1) ~ (5, 210) => 0.0408459
+(3, -1) ~ (5, 211) => 0.0110342
+(3, -1) ~ (5, 212) => 0.00172406
+(3, -1) ~ (5, 213) => 0.000438571
+(3, -1) ~ (5, 214) => 0.000214815
+(3, -1) ~ (5, 215) => 0.000223815
+(3, -1) ~ (5, 216) => 0.00399911
+(3, -1) ~ (5, 217) => 0.00194448
+(3, -1) ~ (5, 218) => 0.000460863
+(3, -1) ~ (5, 219) => 0.000347912
+(3, -1) ~ (5, 220) => 0.000630677
+(3, -1) ~ (5, 221) => 0.00081408
+(3, -1) ~ (5, 222) => 0.000730276
+(3, -1) ~ (5, 223) => 0.000261426
+(3, -1) ~ (5, 224) => 0.000156999
+(3, -1) ~ (5, 225) => 0.0001
+(3, -1) ~ (5, 226) => 0.0001
+(3, -1) ~ (5, 227) => 0.0001
+(3, -1) ~ (5, 228) => 0.000213742
+(3, -1) ~ (5, 229) => 0.00148493
+(3, -1) ~ (5, 230) => 0.00297862
+(3, -1) ~ (5, 231) => 0.00411654
+(3, -1) ~ (5, 232) => 0.00482345
+(3, -1) ~ (5, 233) => 0.00441128
+
+; Sparse posterior probability matrix for sequences 4 and 5
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(4, 0) ~ (5, 0) => 0.991697
+(4, 1) ~ (5, 1) => 0.979934
+(4, 2) ~ (5, 2) => 0.912263
+(4, 3) ~ (5, 2) => 0.0175144
+(4, 3) ~ (5, 3) => 0.749855
+(4, 4) ~ (5, 3) => 0.0524001
+(4, 4) ~ (5, 4) => 0.439019
+(4, 4) ~ (5, 5) => 0.019692
+(4, 5) ~ (5, 2) => 0.0554116
+(4, 5) ~ (5, 4) => 0.044772
+(4, 5) ~ (5, 5) => 0.384828
+(4, 5) ~ (5, 6) => 0.0285336
+(4, 6) ~ (5, 3) => 0.172431
+(4, 6) ~ (5, 5) => 0.0501567
+(4, 6) ~ (5, 6) => 0.0907301
+(4, 6) ~ (5, 7) => 0.0708937
+(4, 7) ~ (5, 4) => 0.484598
+(4, 7) ~ (5, 6) => 0.11106
+(4, 7) ~ (5, 7) => 0.057601
+(4, 7) ~ (5, 8) => 0.0573761
+(4, 8) ~ (5, 5) => 0.524962
+(4, 8) ~ (5, 6) => 0.0119001
+(4, 8) ~ (5, 7) => 0.123273
+(4, 8) ~ (5, 8) => 0.0377591
+(4, 8) ~ (5, 9) => 0.0349957
+(4, 9) ~ (5, 6) => 0.711895
+(4, 9) ~ (5, 8) => 0.162611
+(4, 9) ~ (5, 9) => 0.0168709
+(4, 9) ~ (5, 10) => 0.0231115
+(4, 10) ~ (5, 7) => 0.737377
+(4, 10) ~ (5, 9) => 0.205062
+(4, 11) ~ (5, 8) => 0.718004
+(4, 11) ~ (5, 10) => 0.24907
+(4, 12) ~ (5, 9) => 0.568692
+(4, 12) ~ (5, 11) => 0.414661
+(4, 13) ~ (5, 10) => 0.397542
+(4, 13) ~ (5, 11) => 0.0223839
+(4, 13) ~ (5, 12) => 0.562633
+(4, 14) ~ (5, 11) => 0.309075
+(4, 14) ~ (5, 12) => 0.0249949
+(4, 14) ~ (5, 13) => 0.648832
+(4, 15) ~ (5, 12) => 0.147399
+(4, 15) ~ (5, 13) => 0.0186717
+(4, 15) ~ (5, 14) => 0.822563
+(4, 16) ~ (5, 13) => 0.0117158
+(4, 16) ~ (5, 15) => 0.980655
+(4, 17) ~ (5, 16) => 0.998331
+(4, 18) ~ (5, 17) => 0.999354
+(4, 19) ~ (5, 18) => 0.9994
+(4, 20) ~ (5, 19) => 0.999656
+(4, 21) ~ (5, 20) => 0.999772
+(4, 22) ~ (5, 21) => 0.999904
+(4, 23) ~ (5, 22) => 0.999942
+(4, 24) ~ (5, 23) => 0.99982
+(4, 25) ~ (5, 24) => 0.998441
+(4, 26) ~ (5, 25) => 0.991443
+(4, 27) ~ (5, 26) => 0.979296
+(4, 28) ~ (5, 26) => 0.0189358
+(4, 28) ~ (5, 27) => 0.974228
+(4, 29) ~ (5, 27) => 0.0219114
+(4, 29) ~ (5, 28) => 0.972476
+(4, 30) ~ (5, 28) => 0.0225773
+(4, 30) ~ (5, 29) => 0.973472
+(4, 31) ~ (5, 29) => 0.0186767
+(4, 31) ~ (5, 30) => 0.979326
+(4, 32) ~ (5, 31) => 0.993977
+(4, 33) ~ (5, 32) => 0.995496
+(4, 34) ~ (5, 33) => 0.994387
+(4, 35) ~ (5, 34) => 0.993063
+(4, 36) ~ (5, 35) => 0.993502
+(4, 37) ~ (5, 36) => 0.995787
+(4, 38) ~ (5, 37) => 0.997318
+(4, 39) ~ (5, 38) => 0.997312
+(4, 40) ~ (5, 39) => 0.996773
+(4, 41) ~ (5, 40) => 0.997472
+(4, 42) ~ (5, 41) => 0.996228
+(4, 43) ~ (5, 42) => 0.996508
+(4, 44) ~ (5, 43) => 0.999298
+(4, 45) ~ (5, 44) => 0.998442
+(4, 46) ~ (5, 45) => 0.998075
+(4, 47) ~ (5, 46) => 0.998492
+(4, 48) ~ (5, 47) => 0.999628
+(4, 49) ~ (5, 48) => 0.999315
+(4, 50) ~ (5, 49) => 0.999244
+(4, 51) ~ (5, 50) => 0.999557
+(4, 52) ~ (5, 51) => 0.9997
+(4, 53) ~ (5, 52) => 0.999992
+(4, 54) ~ (5, 53) => 0.999992
+(4, 55) ~ (5, 54) => 0.99989
+(4, 56) ~ (5, 55) => 0.999077
+(4, 57) ~ (5, 56) => 0.983224
+(4, 58) ~ (5, 56) => 0.0129493
+(4, 58) ~ (5, 57) => 0.967451
+(4, 59) ~ (5, 57) => 0.0251793
+(4, 59) ~ (5, 58) => 0.883315
+(4, 60) ~ (5, 58) => 0.107699
+(4, 60) ~ (5, 59) => 0.870657
+(4, 61) ~ (5, 59) => 0.117726
+(4, 61) ~ (5, 60) => 0.811434
+(4, 61) ~ (5, 61) => 0.0189447
+(4, 62) ~ (5, 60) => 0.16843
+(4, 62) ~ (5, 61) => 0.757065
+(4, 62) ~ (5, 62) => 0.0205162
+(4, 63) ~ (5, 61) => 0.21879
+(4, 63) ~ (5, 62) => 0.304644
+(4, 63) ~ (5, 63) => 0.0400312
+(4, 64) ~ (5, 62) => 0.649813
+(4, 64) ~ (5, 63) => 0.157468
+(4, 64) ~ (5, 64) => 0.0487662
+(4, 65) ~ (5, 63) => 0.787217
+(4, 65) ~ (5, 64) => 0.105002
+(4, 65) ~ (5, 65) => 0.031472
+(4, 66) ~ (5, 64) => 0.840949
+(4, 66) ~ (5, 65) => 0.0560462
+(4, 67) ~ (5, 65) => 0.91065
+(4, 68) ~ (5, 66) => 0.996247
+(4, 69) ~ (5, 67) => 0.999286
+(4, 70) ~ (5, 68) => 0.99885
+(4, 71) ~ (5, 69) => 0.999118
+(4, 72) ~ (5, 70) => 0.99967
+(4, 73) ~ (5, 71) => 0.999952
+(4, 74) ~ (5, 72) => 0.999986
+(4, 75) ~ (5, 73) => 0.999966
+(4, 76) ~ (5, 74) => 0.999873
+(4, 77) ~ (5, 75) => 0.999712
+(4, 78) ~ (5, 76) => 0.997778
+(4, 79) ~ (5, 77) => 0.911924
+(4, 79) ~ (5, 78) => 0.0399049
+(4, 80) ~ (5, 78) => 0.877491
+(4, 80) ~ (5, 79) => 0.0444782
+(4, 81) ~ (5, 79) => 0.807386
+(4, 81) ~ (5, 80) => 0.0618952
+(4, 82) ~ (5, 77) => 0.0403393
+(4, 82) ~ (5, 80) => 0.745158
+(4, 82) ~ (5, 81) => 0.0576096
+(4, 83) ~ (5, 78) => 0.0624854
+(4, 83) ~ (5, 80) => 0.0218748
+(4, 83) ~ (5, 81) => 0.703513
+(4, 83) ~ (5, 82) => 0.0403615
+(4, 84) ~ (5, 79) => 0.108016
+(4, 84) ~ (5, 80) => 0.0237587
+(4, 84) ~ (5, 81) => 0.0502033
+(4, 84) ~ (5, 82) => 0.620344
+(4, 84) ~ (5, 83) => 0.0261696
+(4, 84) ~ (5, 85) => 0.0129049
+(4, 85) ~ (5, 80) => 0.128073
+(4, 85) ~ (5, 81) => 0.0164063
+(4, 85) ~ (5, 82) => 0.150609
+(4, 85) ~ (5, 83) => 0.4421
+(4, 85) ~ (5, 84) => 0.0197721
+(4, 85) ~ (5, 86) => 0.0133109
+(4, 86) ~ (5, 81) => 0.142603
+(4, 86) ~ (5, 83) => 0.35213
+(4, 86) ~ (5, 84) => 0.206134
+(4, 86) ~ (5, 85) => 0.0126332
+(4, 86) ~ (5, 87) => 0.0129993
+(4, 87) ~ (5, 82) => 0.0660617
+(4, 87) ~ (5, 84) => 0.674652
+(4, 87) ~ (5, 85) => 0.0964684
+(4, 87) ~ (5, 86) => 0.0127315
+(4, 87) ~ (5, 88) => 0.0129553
+(4, 88) ~ (5, 83) => 0.0118055
+(4, 88) ~ (5, 85) => 0.849604
+(4, 88) ~ (5, 86) => 0.069336
+(4, 88) ~ (5, 87) => 0.0121369
+(4, 88) ~ (5, 89) => 0.0129575
+(4, 89) ~ (5, 86) => 0.878824
+(4, 89) ~ (5, 87) => 0.0508736
+(4, 89) ~ (5, 88) => 0.0129093
+(4, 89) ~ (5, 90) => 0.0125386
+(4, 90) ~ (5, 87) => 0.903725
+(4, 90) ~ (5, 88) => 0.0375328
+(4, 90) ~ (5, 89) => 0.0135442
+(4, 91) ~ (5, 88) => 0.919873
+(4, 91) ~ (5, 89) => 0.0174058
+(4, 91) ~ (5, 90) => 0.0181008
+(4, 92) ~ (5, 89) => 0.943577
+(4, 93) ~ (5, 90) => 0.956481
+(4, 94) ~ (5, 91) => 0.986929
+(4, 95) ~ (5, 92) => 0.997046
+(4, 96) ~ (5, 93) => 0.998901
+(4, 97) ~ (5, 94) => 0.997225
+(4, 98) ~ (5, 95) => 0.991247
+(4, 99) ~ (5, 96) => 0.927545
+(4, 100) ~ (5, 96) => 0.0635944
+(4, 100) ~ (5, 97) => 0.780445
+(4, 101) ~ (5, 97) => 0.115161
+(4, 101) ~ (5, 98) => 0.636892
+(4, 102) ~ (5, 97) => 0.0892044
+(4, 102) ~ (5, 98) => 0.169473
+(4, 102) ~ (5, 99) => 0.485616
+(4, 103) ~ (5, 98) => 0.172993
+(4, 103) ~ (5, 99) => 0.216358
+(4, 103) ~ (5, 100) => 0.323292
+(4, 104) ~ (5, 99) => 0.273576
+(4, 104) ~ (5, 100) => 0.378203
+(4, 104) ~ (5, 101) => 0.14312
+(4, 105) ~ (5, 100) => 0.0826387
+(4, 105) ~ (5, 101) => 0.755185
+(4, 105) ~ (5, 102) => 0.0536536
+(4, 106) ~ (5, 101) => 0.0292408
+(4, 106) ~ (5, 102) => 0.90726
+(4, 106) ~ (5, 103) => 0.0128189
+(4, 107) ~ (5, 103) => 0.977187
+(4, 108) ~ (5, 104) => 0.993763
+(4, 109) ~ (5, 105) => 0.999806
+(4, 110) ~ (5, 106) => 0.999956
+(4, 111) ~ (5, 107) => 0.999982
+(4, 112) ~ (5, 108) => 0.999987
+(4, 113) ~ (5, 109) => 0.99997
+(4, 114) ~ (5, 110) => 0.99993
+(4, 115) ~ (5, 111) => 0.999877
+(4, 116) ~ (5, 112) => 0.999272
+(4, 117) ~ (5, 113) => 0.997905
+(4, 118) ~ (5, 114) => 0.996055
+(4, 119) ~ (5, 115) => 0.995388
+(4, 120) ~ (5, 116) => 0.987455
+(4, 121) ~ (5, 117) => 0.981562
+(4, 122) ~ (5, 118) => 0.976131
+(4, 123) ~ (5, 117) => 0.0136727
+(4, 123) ~ (5, 119) => 0.975452
+(4, 124) ~ (5, 118) => 0.0189666
+(4, 124) ~ (5, 120) => 0.974688
+(4, 125) ~ (5, 119) => 0.0190977
+(4, 125) ~ (5, 121) => 0.972238
+(4, 126) ~ (5, 120) => 0.0197414
+(4, 126) ~ (5, 122) => 0.963008
+(4, 127) ~ (5, 121) => 0.0227725
+(4, 127) ~ (5, 123) => 0.963567
+(4, 128) ~ (5, 122) => 0.0342402
+(4, 128) ~ (5, 124) => 0.962104
+(4, 129) ~ (5, 123) => 0.0356696
+(4, 129) ~ (5, 125) => 0.956914
+(4, 130) ~ (5, 124) => 0.0368804
+(4, 130) ~ (5, 126) => 0.890247
+(4, 130) ~ (5, 129) => 0.0165156
+(4, 131) ~ (5, 125) => 0.0401186
+(4, 131) ~ (5, 127) => 0.808262
+(4, 131) ~ (5, 128) => 0.0134412
+(4, 131) ~ (5, 130) => 0.0313812
+(4, 132) ~ (5, 126) => 0.0646188
+(4, 132) ~ (5, 127) => 0.0128781
+(4, 132) ~ (5, 128) => 0.661035
+(4, 132) ~ (5, 129) => 0.0237735
+(4, 132) ~ (5, 130) => 0.0124272
+(4, 132) ~ (5, 131) => 0.0418569
+(4, 132) ~ (5, 133) => 0.0101764
+(4, 133) ~ (5, 127) => 0.101633
+(4, 133) ~ (5, 128) => 0.0181393
+(4, 133) ~ (5, 129) => 0.63167
+(4, 133) ~ (5, 130) => 0.0313643
+(4, 133) ~ (5, 131) => 0.0156989
+(4, 133) ~ (5, 132) => 0.0444972
+(4, 133) ~ (5, 134) => 0.0113635
+(4, 134) ~ (5, 128) => 0.211818
+(4, 134) ~ (5, 129) => 0.0210982
+(4, 134) ~ (5, 130) => 0.555826
+(4, 134) ~ (5, 131) => 0.0799173
+(4, 134) ~ (5, 132) => 0.0172378
+(4, 134) ~ (5, 133) => 0.0462234
+(4, 134) ~ (5, 135) => 0.0148785
+(4, 135) ~ (5, 129) => 0.205536
+(4, 135) ~ (5, 130) => 0.0204298
+(4, 135) ~ (5, 131) => 0.445106
+(4, 135) ~ (5, 132) => 0.185733
+(4, 135) ~ (5, 133) => 0.0240459
+(4, 135) ~ (5, 134) => 0.0493429
+(4, 135) ~ (5, 136) => 0.0103193
+(4, 136) ~ (5, 130) => 0.199756
+(4, 136) ~ (5, 131) => 0.0218772
+(4, 136) ~ (5, 132) => 0.344879
+(4, 136) ~ (5, 133) => 0.296604
+(4, 136) ~ (5, 134) => 0.0190493
+(4, 136) ~ (5, 135) => 0.0481526
+(4, 137) ~ (5, 129) => 0.0162622
+(4, 137) ~ (5, 131) => 0.15587
+(4, 137) ~ (5, 132) => 0.029561
+(4, 137) ~ (5, 133) => 0.296495
+(4, 137) ~ (5, 134) => 0.387931
+(4, 137) ~ (5, 135) => 0.0182651
+(4, 137) ~ (5, 136) => 0.0460607
+(4, 138) ~ (5, 130) => 0.0244895
+(4, 138) ~ (5, 132) => 0.115498
+(4, 138) ~ (5, 133) => 0.0316436
+(4, 138) ~ (5, 134) => 0.303482
+(4, 138) ~ (5, 135) => 0.419629
+(4, 138) ~ (5, 136) => 0.0136077
+(4, 138) ~ (5, 137) => 0.0404103
+(4, 139) ~ (5, 131) => 0.0263556
+(4, 139) ~ (5, 133) => 0.0984052
+(4, 139) ~ (5, 134) => 0.027568
+(4, 139) ~ (5, 135) => 0.279063
+(4, 139) ~ (5, 136) => 0.486093
+(4, 139) ~ (5, 137) => 0.0106673
+(4, 139) ~ (5, 138) => 0.0234269
+(4, 140) ~ (5, 132) => 0.0273216
+(4, 140) ~ (5, 134) => 0.0851947
+(4, 140) ~ (5, 135) => 0.0203716
+(4, 140) ~ (5, 136) => 0.270775
+(4, 140) ~ (5, 137) => 0.533033
+(4, 140) ~ (5, 139) => 0.0173544
+(4, 141) ~ (5, 133) => 0.0246714
+(4, 141) ~ (5, 135) => 0.0267439
+(4, 141) ~ (5, 137) => 0.178367
+(4, 141) ~ (5, 138) => 0.729351
+(4, 141) ~ (5, 140) => 0.0167251
+(4, 142) ~ (5, 134) => 0.0117175
+(4, 142) ~ (5, 136) => 0.0125979
+(4, 142) ~ (5, 138) => 0.0808088
+(4, 142) ~ (5, 139) => 0.867198
+(4, 143) ~ (5, 139) => 0.0420874
+(4, 143) ~ (5, 140) => 0.923009
+(4, 144) ~ (5, 141) => 0.994481
+(4, 145) ~ (5, 142) => 0.994528
+(4, 146) ~ (5, 143) => 0.995285
+(4, 147) ~ (5, 144) => 0.998924
+(4, 148) ~ (5, 145) => 0.999937
+(4, 149) ~ (5, 146) => 0.999988
+(4, 150) ~ (5, 147) => 0.999978
+(4, 151) ~ (5, 148) => 0.999834
+(4, 152) ~ (5, 149) => 0.999715
+(4, 153) ~ (5, 150) => 0.999763
+(4, 154) ~ (5, 151) => 0.999905
+(4, 155) ~ (5, 152) => 0.999973
+(4, 156) ~ (5, 153) => 0.999903
+(4, 157) ~ (5, 154) => 0.999381
+(4, 158) ~ (5, 155) => 0.998601
+(4, 159) ~ (5, 156) => 0.996588
+(4, 160) ~ (5, 157) => 0.995186
+(4, 161) ~ (5, 158) => 0.99525
+(4, 162) ~ (5, 159) => 0.995388
+(4, 163) ~ (5, 160) => 0.9952
+(4, 164) ~ (5, 161) => 0.995061
+(4, 165) ~ (5, 162) => 0.994839
+(4, 166) ~ (5, 163) => 0.997274
+(4, 167) ~ (5, 164) => 0.997699
+(4, 168) ~ (5, 165) => 0.9983
+(4, 169) ~ (5, 166) => 0.999597
+(4, 170) ~ (5, 167) => 0.999931
+(4, 171) ~ (5, 168) => 0.999927
+(4, 172) ~ (5, 169) => 0.999917
+(4, 173) ~ (5, 170) => 0.999962
+(4, 174) ~ (5, 171) => 0.999969
+(4, 175) ~ (5, 172) => 0.999904
+(4, 176) ~ (5, 173) => 0.999713
+(4, 177) ~ (5, 174) => 0.999444
+(4, 178) ~ (5, 175) => 0.999473
+(4, 179) ~ (5, 176) => 0.999644
+(4, 180) ~ (5, 177) => 0.999869
+(4, 181) ~ (5, 178) => 0.999939
+(4, 182) ~ (5, 179) => 0.99995
+(4, 183) ~ (5, 180) => 0.999933
+(4, 184) ~ (5, 181) => 0.999918
+(4, 185) ~ (5, 182) => 0.999207
+(4, 186) ~ (5, 183) => 0.998534
+(4, 187) ~ (5, 184) => 0.997983
+(4, 188) ~ (5, 185) => 0.993793
+(4, 189) ~ (5, 186) => 0.989392
+(4, 190) ~ (5, 187) => 0.974521
+(4, 191) ~ (5, 187) => 0.0229916
+(4, 191) ~ (5, 188) => 0.96636
+(4, 192) ~ (5, 188) => 0.0277932
+(4, 192) ~ (5, 189) => 0.909195
+(4, 192) ~ (5, 191) => 0.0178671
+(4, 193) ~ (5, 189) => 0.0662925
+(4, 193) ~ (5, 190) => 0.804318
+(4, 193) ~ (5, 192) => 0.0360613
+(4, 194) ~ (5, 190) => 0.152294
+(4, 194) ~ (5, 191) => 0.80189
+(4, 194) ~ (5, 193) => 0.0342183
+(4, 195) ~ (5, 191) => 0.141637
+(4, 195) ~ (5, 192) => 0.81276
+(4, 195) ~ (5, 194) => 0.0311249
+(4, 196) ~ (5, 192) => 0.122447
+(4, 196) ~ (5, 193) => 0.832518
+(4, 196) ~ (5, 195) => 0.0163448
+(4, 197) ~ (5, 193) => 0.117926
+(4, 197) ~ (5, 194) => 0.835697
+(4, 197) ~ (5, 195) => 0.0111676
+(4, 198) ~ (5, 194) => 0.0984847
+(4, 198) ~ (5, 195) => 0.860901
+(4, 198) ~ (5, 196) => 0.0205571
+(4, 199) ~ (5, 195) => 0.08009
+(4, 199) ~ (5, 196) => 0.881803
+(4, 199) ~ (5, 197) => 0.0168026
+(4, 200) ~ (5, 196) => 0.0485721
+(4, 200) ~ (5, 197) => 0.920448
+(4, 200) ~ (5, 198) => 0.0117355
+(4, 201) ~ (5, 197) => 0.0310406
+(4, 201) ~ (5, 198) => 0.948131
+(4, 202) ~ (5, 198) => 0.0129935
+(4, 202) ~ (5, 199) => 0.974535
+(4, 203) ~ (5, 200) => 0.984237
+(4, 204) ~ (5, 201) => 0.992832
+(4, 205) ~ (5, 202) => 0.99747
+(4, 206) ~ (5, 203) => 0.998777
+(4, 207) ~ (5, 204) => 0.997484
+(4, 208) ~ (5, 205) => 0.997208
+(4, 209) ~ (5, 206) => 0.997798
+(4, 210) ~ (5, 207) => 0.999329
+(4, 211) ~ (5, 208) => 0.999432
+(4, 212) ~ (5, 209) => 0.998118
+(4, 213) ~ (5, 210) => 0.997809
+(4, 214) ~ (5, 211) => 0.997594
+(4, 215) ~ (5, 212) => 0.993974
+(4, 216) ~ (5, 213) => 0.991368
+(4, 217) ~ (5, 214) => 0.989309
+(4, 218) ~ (5, 215) => 0.974487
+(4, 219) ~ (5, 215) => 0.0159262
+(4, 219) ~ (5, 216) => 0.943091
+(4, 220) ~ (5, 216) => 0.0402485
+(4, 220) ~ (5, 217) => 0.597892
+(4, 221) ~ (5, 217) => 0.371447
+(4, 221) ~ (5, 218) => 0.100179
+(4, 222) ~ (5, 217) => 0.0108068
+(4, 222) ~ (5, 218) => 0.865488
+(4, 222) ~ (5, 219) => 0.0514171
+(4, 223) ~ (5, 217) => 0.013435
+(4, 223) ~ (5, 218) => 0.0101998
+(4, 223) ~ (5, 219) => 0.918256
+(4, 223) ~ (5, 220) => 0.0304178
+(4, 224) ~ (5, 218) => 0.0120889
+(4, 224) ~ (5, 220) => 0.948775
+(4, 225) ~ (5, 221) => 0.992003
+(4, 226) ~ (5, 222) => 0.996834
+(4, 227) ~ (5, 223) => 0.999751
+(4, 228) ~ (5, 224) => 0.999946
+(4, 229) ~ (5, 225) => 0.999971
+(4, 230) ~ (5, 226) => 0.999489
+(4, 231) ~ (5, 227) => 0.993171
+(4, 232) ~ (5, 228) => 0.992642
+(4, 233) ~ (5, 229) => 0.988214
+(4, 234) ~ (5, 230) => 0.986684
+(4, 235) ~ (5, 231) => 0.986058
+(4, 236) ~ (5, 232) => 0.987291
+(4, 237) ~ (5, 233) => 0.991024
+
+; gap posteriors
+(4, 0) ~ (5, -1) => 0.00830293
+(4, 1) ~ (5, -1) => 0.0200657
+(4, 2) ~ (5, -1) => 0.0877373
+(4, 3) ~ (5, -1) => 0.232631
+(4, 4) ~ (5, -1) => 0.488889
+(4, 5) ~ (5, -1) => 0.486454
+(4, 6) ~ (5, -1) => 0.615789
+(4, 7) ~ (5, -1) => 0.289365
+(4, 8) ~ (5, -1) => 0.267109
+(4, 9) ~ (5, -1) => 0.0855115
+(4, 10) ~ (5, -1) => 0.0575607
+(4, 11) ~ (5, -1) => 0.0329259
+(4, 12) ~ (5, -1) => 0.0166478
+(4, 13) ~ (5, -1) => 0.0174409
+(4, 14) ~ (5, -1) => 0.0170979
+(4, 15) ~ (5, -1) => 0.0113667
+(4, 16) ~ (5, -1) => 0.0076288
+(4, 17) ~ (5, -1) => 0.00166917
+(4, 18) ~ (5, -1) => 0.000645757
+(4, 19) ~ (5, -1) => 0.00060004
+(4, 20) ~ (5, -1) => 0.000344455
+(4, 21) ~ (5, -1) => 0.000227749
+(4, 22) ~ (5, -1) => 0.0001
+(4, 23) ~ (5, -1) => 0.0001
+(4, 24) ~ (5, -1) => 0.000180185
+(4, 25) ~ (5, -1) => 0.00155902
+(4, 26) ~ (5, -1) => 0.0085572
+(4, 27) ~ (5, -1) => 0.0207042
+(4, 28) ~ (5, -1) => 0.00683653
+(4, 29) ~ (5, -1) => 0.00561303
+(4, 30) ~ (5, -1) => 0.0039506
+(4, 31) ~ (5, -1) => 0.00199711
+(4, 32) ~ (5, -1) => 0.00602311
+(4, 33) ~ (5, -1) => 0.00450391
+(4, 34) ~ (5, -1) => 0.00561333
+(4, 35) ~ (5, -1) => 0.00693655
+(4, 36) ~ (5, -1) => 0.00649816
+(4, 37) ~ (5, -1) => 0.00421274
+(4, 38) ~ (5, -1) => 0.00268179
+(4, 39) ~ (5, -1) => 0.00268757
+(4, 40) ~ (5, -1) => 0.00322717
+(4, 41) ~ (5, -1) => 0.00252825
+(4, 42) ~ (5, -1) => 0.00377244
+(4, 43) ~ (5, -1) => 0.00349224
+(4, 44) ~ (5, -1) => 0.000701845
+(4, 45) ~ (5, -1) => 0.00155759
+(4, 46) ~ (5, -1) => 0.00192535
+(4, 47) ~ (5, -1) => 0.00150841
+(4, 48) ~ (5, -1) => 0.000372052
+(4, 49) ~ (5, -1) => 0.000685096
+(4, 50) ~ (5, -1) => 0.000755787
+(4, 51) ~ (5, -1) => 0.000443041
+(4, 52) ~ (5, -1) => 0.00030005
+(4, 53) ~ (5, -1) => 0.0001
+(4, 54) ~ (5, -1) => 0.0001
+(4, 55) ~ (5, -1) => 0.000110149
+(4, 56) ~ (5, -1) => 0.000923097
+(4, 57) ~ (5, -1) => 0.016776
+(4, 58) ~ (5, -1) => 0.0195995
+(4, 59) ~ (5, -1) => 0.0915062
+(4, 60) ~ (5, -1) => 0.0216439
+(4, 61) ~ (5, -1) => 0.0518963
+(4, 62) ~ (5, -1) => 0.0539894
+(4, 63) ~ (5, -1) => 0.436534
+(4, 64) ~ (5, -1) => 0.143953
+(4, 65) ~ (5, -1) => 0.0763088
+(4, 66) ~ (5, -1) => 0.103005
+(4, 67) ~ (5, -1) => 0.0893503
+(4, 68) ~ (5, -1) => 0.00375253
+(4, 69) ~ (5, -1) => 0.000714064
+(4, 70) ~ (5, -1) => 0.00115037
+(4, 71) ~ (5, -1) => 0.00088191
+(4, 72) ~ (5, -1) => 0.000329554
+(4, 73) ~ (5, -1) => 0.0001
+(4, 74) ~ (5, -1) => 0.0001
+(4, 75) ~ (5, -1) => 0.0001
+(4, 76) ~ (5, -1) => 0.000126898
+(4, 77) ~ (5, -1) => 0.00028795
+(4, 78) ~ (5, -1) => 0.00222164
+(4, 79) ~ (5, -1) => 0.0481706
+(4, 80) ~ (5, -1) => 0.0780304
+(4, 81) ~ (5, -1) => 0.130719
+(4, 82) ~ (5, -1) => 0.156893
+(4, 83) ~ (5, -1) => 0.171765
+(4, 84) ~ (5, -1) => 0.158603
+(4, 85) ~ (5, -1) => 0.229728
+(4, 86) ~ (5, -1) => 0.2735
+(4, 87) ~ (5, -1) => 0.137132
+(4, 88) ~ (5, -1) => 0.0441598
+(4, 89) ~ (5, -1) => 0.0448542
+(4, 90) ~ (5, -1) => 0.0451982
+(4, 91) ~ (5, -1) => 0.0446208
+(4, 92) ~ (5, -1) => 0.0564228
+(4, 93) ~ (5, -1) => 0.0435186
+(4, 94) ~ (5, -1) => 0.0130714
+(4, 95) ~ (5, -1) => 0.00295448
+(4, 96) ~ (5, -1) => 0.00109863
+(4, 97) ~ (5, -1) => 0.00277549
+(4, 98) ~ (5, -1) => 0.00875264
+(4, 99) ~ (5, -1) => 0.0724546
+(4, 100) ~ (5, -1) => 0.155961
+(4, 101) ~ (5, -1) => 0.247946
+(4, 102) ~ (5, -1) => 0.255707
+(4, 103) ~ (5, -1) => 0.287356
+(4, 104) ~ (5, -1) => 0.205101
+(4, 105) ~ (5, -1) => 0.108523
+(4, 106) ~ (5, -1) => 0.0506801
+(4, 107) ~ (5, -1) => 0.0228128
+(4, 108) ~ (5, -1) => 0.00623691
+(4, 109) ~ (5, -1) => 0.000193536
+(4, 110) ~ (5, -1) => 0.0001
+(4, 111) ~ (5, -1) => 0.0001
+(4, 112) ~ (5, -1) => 0.0001
+(4, 113) ~ (5, -1) => 0.0001
+(4, 114) ~ (5, -1) => 0.0001
+(4, 115) ~ (5, -1) => 0.000123084
+(4, 116) ~ (5, -1) => 0.000728011
+(4, 117) ~ (5, -1) => 0.00209528
+(4, 118) ~ (5, -1) => 0.00394499
+(4, 119) ~ (5, -1) => 0.00461245
+(4, 120) ~ (5, -1) => 0.012545
+(4, 121) ~ (5, -1) => 0.0184383
+(4, 122) ~ (5, -1) => 0.0238687
+(4, 123) ~ (5, -1) => 0.010875
+(4, 124) ~ (5, -1) => 0.00634587
+(4, 125) ~ (5, -1) => 0.00866425
+(4, 126) ~ (5, -1) => 0.0172509
+(4, 127) ~ (5, -1) => 0.01366
+(4, 128) ~ (5, -1) => 0.00365621
+(4, 129) ~ (5, -1) => 0.00741619
+(4, 130) ~ (5, -1) => 0.0563572
+(4, 131) ~ (5, -1) => 0.106797
+(4, 132) ~ (5, -1) => 0.173235
+(4, 133) ~ (5, -1) => 0.145634
+(4, 134) ~ (5, -1) => 0.0530007
+(4, 135) ~ (5, -1) => 0.0594869
+(4, 136) ~ (5, -1) => 0.0696822
+(4, 137) ~ (5, -1) => 0.0495547
+(4, 138) ~ (5, -1) => 0.0512398
+(4, 139) ~ (5, -1) => 0.0484207
+(4, 140) ~ (5, -1) => 0.0459497
+(4, 141) ~ (5, -1) => 0.0241418
+(4, 142) ~ (5, -1) => 0.0276774
+(4, 143) ~ (5, -1) => 0.0349033
+(4, 144) ~ (5, -1) => 0.00551897
+(4, 145) ~ (5, -1) => 0.00547171
+(4, 146) ~ (5, -1) => 0.00471509
+(4, 147) ~ (5, -1) => 0.00107574
+(4, 148) ~ (5, -1) => 0.0001
+(4, 149) ~ (5, -1) => 0.0001
+(4, 150) ~ (5, -1) => 0.0001
+(4, 151) ~ (5, -1) => 0.000165939
+(4, 152) ~ (5, -1) => 0.000285149
+(4, 153) ~ (5, -1) => 0.000236571
+(4, 154) ~ (5, -1) => 0.0001
+(4, 155) ~ (5, -1) => 0.0001
+(4, 156) ~ (5, -1) => 0.0001
+(4, 157) ~ (5, -1) => 0.000618815
+(4, 158) ~ (5, -1) => 0.00139904
+(4, 159) ~ (5, -1) => 0.00341249
+(4, 160) ~ (5, -1) => 0.00481391
+(4, 161) ~ (5, -1) => 0.00474977
+(4, 162) ~ (5, -1) => 0.00461185
+(4, 163) ~ (5, -1) => 0.00480044
+(4, 164) ~ (5, -1) => 0.00493944
+(4, 165) ~ (5, -1) => 0.00516111
+(4, 166) ~ (5, -1) => 0.00272596
+(4, 167) ~ (5, -1) => 0.0023011
+(4, 168) ~ (5, -1) => 0.00169957
+(4, 169) ~ (5, -1) => 0.000403464
+(4, 170) ~ (5, -1) => 0.0001
+(4, 171) ~ (5, -1) => 0.0001
+(4, 172) ~ (5, -1) => 0.0001
+(4, 173) ~ (5, -1) => 0.0001
+(4, 174) ~ (5, -1) => 0.0001
+(4, 175) ~ (5, -1) => 0.0001
+(4, 176) ~ (5, -1) => 0.000287175
+(4, 177) ~ (5, -1) => 0.000555873
+(4, 178) ~ (5, -1) => 0.000527382
+(4, 179) ~ (5, -1) => 0.000355721
+(4, 180) ~ (5, -1) => 0.000130832
+(4, 181) ~ (5, -1) => 0.0001
+(4, 182) ~ (5, -1) => 0.0001
+(4, 183) ~ (5, -1) => 0.0001
+(4, 184) ~ (5, -1) => 0.0001
+(4, 185) ~ (5, -1) => 0.000792623
+(4, 186) ~ (5, -1) => 0.00146574
+(4, 187) ~ (5, -1) => 0.00201696
+(4, 188) ~ (5, -1) => 0.00620741
+(4, 189) ~ (5, -1) => 0.0106084
+(4, 190) ~ (5, -1) => 0.0254791
+(4, 191) ~ (5, -1) => 0.0106484
+(4, 192) ~ (5, -1) => 0.0451448
+(4, 193) ~ (5, -1) => 0.0933278
+(4, 194) ~ (5, -1) => 0.0115977
+(4, 195) ~ (5, -1) => 0.0144784
+(4, 196) ~ (5, -1) => 0.0286904
+(4, 197) ~ (5, -1) => 0.0352095
+(4, 198) ~ (5, -1) => 0.0200569
+(4, 199) ~ (5, -1) => 0.0213048
+(4, 200) ~ (5, -1) => 0.0192446
+(4, 201) ~ (5, -1) => 0.0208282
+(4, 202) ~ (5, -1) => 0.0124717
+(4, 203) ~ (5, -1) => 0.0157629
+(4, 204) ~ (5, -1) => 0.00716817
+(4, 205) ~ (5, -1) => 0.00253022
+(4, 206) ~ (5, -1) => 0.00122267
+(4, 207) ~ (5, -1) => 0.00251597
+(4, 208) ~ (5, -1) => 0.002792
+(4, 209) ~ (5, -1) => 0.00220209
+(4, 210) ~ (5, -1) => 0.000670612
+(4, 211) ~ (5, -1) => 0.000568151
+(4, 212) ~ (5, -1) => 0.00188202
+(4, 213) ~ (5, -1) => 0.00219101
+(4, 214) ~ (5, -1) => 0.00240576
+(4, 215) ~ (5, -1) => 0.00602597
+(4, 216) ~ (5, -1) => 0.00863236
+(4, 217) ~ (5, -1) => 0.0106911
+(4, 218) ~ (5, -1) => 0.0255126
+(4, 219) ~ (5, -1) => 0.0409829
+(4, 220) ~ (5, -1) => 0.36186
+(4, 221) ~ (5, -1) => 0.528374
+(4, 222) ~ (5, -1) => 0.0722878
+(4, 223) ~ (5, -1) => 0.0276918
+(4, 224) ~ (5, -1) => 0.0391362
+(4, 225) ~ (5, -1) => 0.00799662
+(4, 226) ~ (5, -1) => 0.0031665
+(4, 227) ~ (5, -1) => 0.000249028
+(4, 228) ~ (5, -1) => 0.0001
+(4, 229) ~ (5, -1) => 0.0001
+(4, 230) ~ (5, -1) => 0.000510991
+(4, 231) ~ (5, -1) => 0.00682896
+(4, 232) ~ (5, -1) => 0.00735795
+(4, 233) ~ (5, -1) => 0.0117856
+(4, 234) ~ (5, -1) => 0.0133163
+(4, 235) ~ (5, -1) => 0.0139425
+(4, 236) ~ (5, -1) => 0.0127094
+(4, 237) ~ (5, -1) => 0.00897563
+
+(4, -1) ~ (5, 0) => 0.00830293
+(4, -1) ~ (5, 1) => 0.0200657
+(4, -1) ~ (5, 2) => 0.0148113
+(4, -1) ~ (5, 3) => 0.0253138
+(4, -1) ~ (5, 4) => 0.0316113
+(4, -1) ~ (5, 5) => 0.0203605
+(4, -1) ~ (5, 6) => 0.0458813
+(4, -1) ~ (5, 7) => 0.0108548
+(4, -1) ~ (5, 8) => 0.02425
+(4, -1) ~ (5, 9) => 0.17438
+(4, -1) ~ (5, 10) => 0.330276
+(4, -1) ~ (5, 11) => 0.25388
+(4, -1) ~ (5, 12) => 0.264973
+(4, -1) ~ (5, 13) => 0.32078
+(4, -1) ~ (5, 14) => 0.177437
+(4, -1) ~ (5, 15) => 0.0193446
+(4, -1) ~ (5, 16) => 0.00166917
+(4, -1) ~ (5, 17) => 0.000645757
+(4, -1) ~ (5, 18) => 0.00060004
+(4, -1) ~ (5, 19) => 0.000344455
+(4, -1) ~ (5, 20) => 0.000227749
+(4, -1) ~ (5, 21) => 0.0001
+(4, -1) ~ (5, 22) => 0.0001
+(4, -1) ~ (5, 23) => 0.000180185
+(4, -1) ~ (5, 24) => 0.00155902
+(4, -1) ~ (5, 25) => 0.0085572
+(4, -1) ~ (5, 26) => 0.00176845
+(4, -1) ~ (5, 27) => 0.00386084
+(4, -1) ~ (5, 28) => 0.00494721
+(4, -1) ~ (5, 29) => 0.00785119
+(4, -1) ~ (5, 30) => 0.0206738
+(4, -1) ~ (5, 31) => 0.00602311
+(4, -1) ~ (5, 32) => 0.00450391
+(4, -1) ~ (5, 33) => 0.00561333
+(4, -1) ~ (5, 34) => 0.00693655
+(4, -1) ~ (5, 35) => 0.00649816
+(4, -1) ~ (5, 36) => 0.00421274
+(4, -1) ~ (5, 37) => 0.00268179
+(4, -1) ~ (5, 38) => 0.00268757
+(4, -1) ~ (5, 39) => 0.00322717
+(4, -1) ~ (5, 40) => 0.00252825
+(4, -1) ~ (5, 41) => 0.00377244
+(4, -1) ~ (5, 42) => 0.00349224
+(4, -1) ~ (5, 43) => 0.000701845
+(4, -1) ~ (5, 44) => 0.00155759
+(4, -1) ~ (5, 45) => 0.00192535
+(4, -1) ~ (5, 46) => 0.00150841
+(4, -1) ~ (5, 47) => 0.000372052
+(4, -1) ~ (5, 48) => 0.000685096
+(4, -1) ~ (5, 49) => 0.000755787
+(4, -1) ~ (5, 50) => 0.000443041
+(4, -1) ~ (5, 51) => 0.00030005
+(4, -1) ~ (5, 52) => 0.0001
+(4, -1) ~ (5, 53) => 0.0001
+(4, -1) ~ (5, 54) => 0.000110149
+(4, -1) ~ (5, 55) => 0.000923097
+(4, -1) ~ (5, 56) => 0.00382677
+(4, -1) ~ (5, 57) => 0.00736943
+(4, -1) ~ (5, 58) => 0.00898623
+(4, -1) ~ (5, 59) => 0.0116176
+(4, -1) ~ (5, 60) => 0.0201368
+(4, -1) ~ (5, 61) => 0.00520004
+(4, -1) ~ (5, 62) => 0.0250269
+(4, -1) ~ (5, 63) => 0.0152845
+(4, -1) ~ (5, 64) => 0.0052827
+(4, -1) ~ (5, 65) => 0.00183207
+(4, -1) ~ (5, 66) => 0.00375253
+(4, -1) ~ (5, 67) => 0.000714064
+(4, -1) ~ (5, 68) => 0.00115037
+(4, -1) ~ (5, 69) => 0.00088191
+(4, -1) ~ (5, 70) => 0.000329554
+(4, -1) ~ (5, 71) => 0.0001
+(4, -1) ~ (5, 72) => 0.0001
+(4, -1) ~ (5, 73) => 0.0001
+(4, -1) ~ (5, 74) => 0.000126898
+(4, -1) ~ (5, 75) => 0.00028795
+(4, -1) ~ (5, 76) => 0.00222164
+(4, -1) ~ (5, 77) => 0.0477362
+(4, -1) ~ (5, 78) => 0.0201183
+(4, -1) ~ (5, 79) => 0.0401195
+(4, -1) ~ (5, 80) => 0.0192403
+(4, -1) ~ (5, 81) => 0.0296648
+(4, -1) ~ (5, 82) => 0.122623
+(4, -1) ~ (5, 83) => 0.167794
+(4, -1) ~ (5, 84) => 0.0994424
+(4, -1) ~ (5, 85) => 0.0283891
+(4, -1) ~ (5, 86) => 0.0257975
+(4, -1) ~ (5, 87) => 0.0202653
+(4, -1) ~ (5, 88) => 0.0167301
+(4, -1) ~ (5, 89) => 0.0125154
+(4, -1) ~ (5, 90) => 0.0128792
+(4, -1) ~ (5, 91) => 0.0130714
+(4, -1) ~ (5, 92) => 0.00295448
+(4, -1) ~ (5, 93) => 0.00109863
+(4, -1) ~ (5, 94) => 0.00277549
+(4, -1) ~ (5, 95) => 0.00875264
+(4, -1) ~ (5, 96) => 0.00886019
+(4, -1) ~ (5, 97) => 0.0151895
+(4, -1) ~ (5, 98) => 0.0206416
+(4, -1) ~ (5, 99) => 0.0244502
+(4, -1) ~ (5, 100) => 0.215866
+(4, -1) ~ (5, 101) => 0.0724543
+(4, -1) ~ (5, 102) => 0.0390862
+(4, -1) ~ (5, 103) => 0.00999391
+(4, -1) ~ (5, 104) => 0.00623691
+(4, -1) ~ (5, 105) => 0.000193536
+(4, -1) ~ (5, 106) => 0.0001
+(4, -1) ~ (5, 107) => 0.0001
+(4, -1) ~ (5, 108) => 0.0001
+(4, -1) ~ (5, 109) => 0.0001
+(4, -1) ~ (5, 110) => 0.0001
+(4, -1) ~ (5, 111) => 0.000123084
+(4, -1) ~ (5, 112) => 0.000728011
+(4, -1) ~ (5, 113) => 0.00209528
+(4, -1) ~ (5, 114) => 0.00394499
+(4, -1) ~ (5, 115) => 0.00461245
+(4, -1) ~ (5, 116) => 0.012545
+(4, -1) ~ (5, 117) => 0.0047656
+(4, -1) ~ (5, 118) => 0.0049021
+(4, -1) ~ (5, 119) => 0.00545003
+(4, -1) ~ (5, 120) => 0.00557105
+(4, -1) ~ (5, 121) => 0.0049895
+(4, -1) ~ (5, 122) => 0.00275214
+(4, -1) ~ (5, 123) => 0.00076291
+(4, -1) ~ (5, 124) => 0.00101596
+(4, -1) ~ (5, 125) => 0.00296714
+(4, -1) ~ (5, 126) => 0.0451344
+(4, -1) ~ (5, 127) => 0.0772271
+(4, -1) ~ (5, 128) => 0.0955666
+(4, -1) ~ (5, 129) => 0.0851445
+(4, -1) ~ (5, 130) => 0.124327
+(4, -1) ~ (5, 131) => 0.213319
+(4, -1) ~ (5, 132) => 0.235272
+(4, -1) ~ (5, 133) => 0.171735
+(4, -1) ~ (5, 134) => 0.10435
+(4, -1) ~ (5, 135) => 0.172896
+(4, -1) ~ (5, 136) => 0.160547
+(4, -1) ~ (5, 137) => 0.237522
+(4, -1) ~ (5, 138) => 0.166414
+(4, -1) ~ (5, 139) => 0.0733598
+(4, -1) ~ (5, 140) => 0.0602657
+(4, -1) ~ (5, 141) => 0.00551897
+(4, -1) ~ (5, 142) => 0.00547171
+(4, -1) ~ (5, 143) => 0.00471509
+(4, -1) ~ (5, 144) => 0.00107574
+(4, -1) ~ (5, 145) => 0.0001
+(4, -1) ~ (5, 146) => 0.0001
+(4, -1) ~ (5, 147) => 0.0001
+(4, -1) ~ (5, 148) => 0.000165939
+(4, -1) ~ (5, 149) => 0.000285149
+(4, -1) ~ (5, 150) => 0.000236571
+(4, -1) ~ (5, 151) => 0.0001
+(4, -1) ~ (5, 152) => 0.0001
+(4, -1) ~ (5, 153) => 0.0001
+(4, -1) ~ (5, 154) => 0.000618815
+(4, -1) ~ (5, 155) => 0.00139904
+(4, -1) ~ (5, 156) => 0.00341249
+(4, -1) ~ (5, 157) => 0.00481391
+(4, -1) ~ (5, 158) => 0.00474977
+(4, -1) ~ (5, 159) => 0.00461185
+(4, -1) ~ (5, 160) => 0.00480044
+(4, -1) ~ (5, 161) => 0.00493944
+(4, -1) ~ (5, 162) => 0.00516111
+(4, -1) ~ (5, 163) => 0.00272596
+(4, -1) ~ (5, 164) => 0.0023011
+(4, -1) ~ (5, 165) => 0.00169957
+(4, -1) ~ (5, 166) => 0.000403464
+(4, -1) ~ (5, 167) => 0.0001
+(4, -1) ~ (5, 168) => 0.0001
+(4, -1) ~ (5, 169) => 0.0001
+(4, -1) ~ (5, 170) => 0.0001
+(4, -1) ~ (5, 171) => 0.0001
+(4, -1) ~ (5, 172) => 0.0001
+(4, -1) ~ (5, 173) => 0.000287175
+(4, -1) ~ (5, 174) => 0.000555873
+(4, -1) ~ (5, 175) => 0.000527382
+(4, -1) ~ (5, 176) => 0.000355721
+(4, -1) ~ (5, 177) => 0.000130832
+(4, -1) ~ (5, 178) => 0.0001
+(4, -1) ~ (5, 179) => 0.0001
+(4, -1) ~ (5, 180) => 0.0001
+(4, -1) ~ (5, 181) => 0.0001
+(4, -1) ~ (5, 182) => 0.000792623
+(4, -1) ~ (5, 183) => 0.00146574
+(4, -1) ~ (5, 184) => 0.00201696
+(4, -1) ~ (5, 185) => 0.00620741
+(4, -1) ~ (5, 186) => 0.0106084
+(4, -1) ~ (5, 187) => 0.00248756
+(4, -1) ~ (5, 188) => 0.00584678
+(4, -1) ~ (5, 189) => 0.0245125
+(4, -1) ~ (5, 190) => 0.0433872
+(4, -1) ~ (5, 191) => 0.0386063
+(4, -1) ~ (5, 192) => 0.0287319
+(4, -1) ~ (5, 193) => 0.0153383
+(4, -1) ~ (5, 194) => 0.0346931
+(4, -1) ~ (5, 195) => 0.0314964
+(4, -1) ~ (5, 196) => 0.0490682
+(4, -1) ~ (5, 197) => 0.0317091
+(4, -1) ~ (5, 198) => 0.0271398
+(4, -1) ~ (5, 199) => 0.0254651
+(4, -1) ~ (5, 200) => 0.0157629
+(4, -1) ~ (5, 201) => 0.00716817
+(4, -1) ~ (5, 202) => 0.00253022
+(4, -1) ~ (5, 203) => 0.00122267
+(4, -1) ~ (5, 204) => 0.00251597
+(4, -1) ~ (5, 205) => 0.002792
+(4, -1) ~ (5, 206) => 0.00220209
+(4, -1) ~ (5, 207) => 0.000670612
+(4, -1) ~ (5, 208) => 0.000568151
+(4, -1) ~ (5, 209) => 0.00188202
+(4, -1) ~ (5, 210) => 0.00219101
+(4, -1) ~ (5, 211) => 0.00240576
+(4, -1) ~ (5, 212) => 0.00602597
+(4, -1) ~ (5, 213) => 0.00863236
+(4, -1) ~ (5, 214) => 0.0106911
+(4, -1) ~ (5, 215) => 0.0095864
+(4, -1) ~ (5, 216) => 0.0166607
+(4, -1) ~ (5, 217) => 0.00641899
+(4, -1) ~ (5, 218) => 0.0120443
+(4, -1) ~ (5, 219) => 0.0303273
+(4, -1) ~ (5, 220) => 0.0208074
+(4, -1) ~ (5, 221) => 0.00799662
+(4, -1) ~ (5, 222) => 0.0031665
+(4, -1) ~ (5, 223) => 0.000249028
+(4, -1) ~ (5, 224) => 0.0001
+(4, -1) ~ (5, 225) => 0.0001
+(4, -1) ~ (5, 226) => 0.000510991
+(4, -1) ~ (5, 227) => 0.00682896
+(4, -1) ~ (5, 228) => 0.00735795
+(4, -1) ~ (5, 229) => 0.0117856
+(4, -1) ~ (5, 230) => 0.0133163
+(4, -1) ~ (5, 231) => 0.0139425
+(4, -1) ~ (5, 232) => 0.0127094
+(4, -1) ~ (5, 233) => 0.00897563
+
diff --git a/examples/RV12.BBS12030.mfa b/examples/RV12.BBS12030.mfa
new file mode 100644
index 0000000..1c4a080
--- /dev/null
+++ b/examples/RV12.BBS12030.mfa
@@ -0,0 +1,13 @@
+>POL_MPMV
+APQQCA-EPITWKSDE--P-VWVDQWPLTNDKLAAAQQLVQEQLEAGHITESS--SPWNTPIFVIKKK-SGKWRLLQDLRAVNATMVLMGALQPGLPSPV----AIPQ-GYLKIIIDLKDCFFSIPLHPSDQKRFAFSLPSTNFKEPMQRFQWKVLPQGMANSPTLCQKYVATAIHKVRHAWKQMYIIHYMDDILIAGKDGQ-QVLQCFDQLKQELTAAGLHIAPEKVQL-QDPYTYLGFELNGPKI
+>POL_BIV06
+HTEKIEPL--PVKVRG--PGPKVPQWPLTKEKYQALKEIVKDLLAEGKISEAAWDNPYNTPVFVIKKKGTGRWRMLMDFRELNKITVKGQEFSTGLPYPP----GIKE-CEHLTAIDIKDAYFTIPLHEDFRPFTAFSVVPVNREGPIERFQWNVLPQGWVCSPAIYQTTTQKIIENIKKSHPDVMLYQYMDDLLIGSNRD--DHKQIVQEIRDKLGSYGFKTPDEKVQ--EERVKWIGFELTPKKW
+>POL_CAEVC
+LEEKRIPI-TKVKLKEGCTGPHVPQWPLTEEKLKGLTEIIDKLVEEGKLGKAPPHWTCNTPIFCIKKK-SGKWRMLIDFRELNKQTEDLTEAQLGLPHPG----GLQK-KKHVTILDIGDAYFTIPLYEPYREYTCFTLLSPNNLGPCKRYYWKVLPQGWKLSPSVYQFTMQEILEDWIQQHPEIQFGIYMDDIYIGSDLEIKKHREIVKDLANYIAQYGFTLPEEKRQK-GYPAKWLGFELHPQTW
+>1bqm_A
+PISPIETV--PVKLKPGMDGPKVKQWPLTEEKIKALVEICTEMEKEGKISKIGPENPYNTPVFAIKKKDSTKWRKLVDFRELNKRTQDFWEVQLGIPHPA----GLKK-KKSVTVLDVGDAYFSVPLDEDFRKYTAFTIPSINNETPGIRYQYNVLPQGWKGSPAIFQSSMTKILEPFKKQNPDIVIYQYMDDLYVGSDLEIGQHRTKIEELRQHLLRWGLTTPDKKHQK-EPPFLWMGYELHPDKW
+>1d0e_A
+LAVRQAPLI--IPLKATSTPVSIKQYPMSQEARLGIKPHIQRLLDQGILVPCQ--SPWNTPLLPVKKPGTNDYRPVQDLREVNKRVEDI---HPTVPNPYNLLSGLPPSHQWYTVLDLKDAFFCLRLHPTSQPLFAFEWRDPEM-GISGQLTWTRLPQGFKNSPTLFDEALHRDLADFRIQHPDLILLQYVDDLLLAATSEL-DCQQGTRALLQTLGNLGYRASAKKAQICQKQVKYLGYLLKEGQR
+>POL_RSVP
+VALHLA-IPLKW--KPDHTPVWIDQWPLPEGKLVALTQLVEKELQLGHIEPSL--SCWNTPVFVIRKA-SGSYRLLHDLRAVNAKLVPFGAVQQGAPVLS----ALPR-GWPLMVLDLKDCFFSIPLAEQDREAFAFTLPSVNNQAPARRFQWKVLPQGMTCSPTICQLVVGQVLEPLRLKHPSLCMLHYMDDLLLAASSHD-GLEAAGEEVISTLERAGFTISPDKVQR-EPGVQYLGYKLGSTYV
+
diff --git a/examples/RV12.BBS12030.reference.mfa b/examples/RV12.BBS12030.reference.mfa
new file mode 100644
index 0000000..24877df
--- /dev/null
+++ b/examples/RV12.BBS12030.reference.mfa
@@ -0,0 +1,36 @@
+>POL_MPMV
+APQQCAEPITWKSDE---PVWVDQWPLTNDKLAAAQQLVQEQLEAGHITE
+SS--SPWNTPIFVIKKKS-GKWRLLQDLRAVNATMVLMGALQPGLP-SPV
+AIPQGY-LKIIIDLKDCFFSIPLHPSDQKRFAFSLPSTNFKEPMQRFQWK
+VLPQGMANSPTLCQKYVATAIHKVRHAWKQMYIIHYMDDILIAGKD-GQQ
+VLQCFDQLKQELTAAGLHIAPEKVQL-QDPYTYLGFELNGPKI
+>POL_BIV06
+HTEK-IEPLPVKVRG--PGPKVPQWPLTKEKYQALKEIVKDLLAEGKISE
+AAWDNPYNTPVFVIKKKGTGRWRMLMDFRELNKITVKGQEFSTGLP-YPP
+GIKECE-HLTAIDIKDAYFTIPLHEDFRPFTAFSVVPVNREGPIERFQWN
+VLPQGWVCSPAIYQTTTQKIIENIKKSHPDVMLYQYMDDLLIGSNR--DD
+HKQIVQEIRDKLGSYGFKTPDEKVQE--ERVKWIGFELTPKKW
+>POL_CAEVC
+LEEKRIPITKVKLKEGCTGPHVPQWPLTEEKLKGLTEIIDKLVEEGKLGK
+APPHWTCNTPIFCIKKKS-GKWRMLIDFRELNKQTEDLTEAQLGLP-HPG
+GLQKKK-HVTILDIGDAYFTIPLYEPYREYTCFTLLSPNNLGPCKRYYWK
+VLPQGWKLSPSVYQFTMQEILEDWIQQHPEIQFGIYMDDIYIGSDLEIKK
+HREIVKDLANYIAQYGFTLPEEKRQK-GYPAKWLGFELHPQTW
+>1bqm_A
+PISP-IETVPVKLKPGMDGPKVKQWPLTEEKIKALVEICTEMEKEGKISK
+IGPENPYNTPVFAIKKKDSTKWRKLVDFRELNKRTQDFWEVQLGIP-HPA
+GLKKKK-SVTVLDVGDAYFSVPLDEDFRKYTAFTIPSINNETPGIRYQYN
+VLPQGWKGSPAIFQSSMTKILEPFKKQNPDIVIYQYMDDLYVGSDLEIGQ
+HRTKIEELRQHLLRWGLTTPDKKHQK-EPPFLWMGYELHPDKW
+>1d0e_A
+LAVR-QAPLIIPLKATSTPVSIKQYPMSQEARLGIKPHIQRLLDQGILVP
+CQ--SPWNTPLLPVKKPGTNDYRPVQDLREVNKRVEDIHPTVPNPYNLLS
+GLPPSHQWYTVLDLKDAFFCLRLHPTSQPLFAFEWRDPEMGISG-QLTWT
+RLPQGFKNSPTLFDEALHRDLADFRIQHPDLILLQYVDDLLLAATS-ELD
+CQQGTRALLQTLGNLGYRASAKKAQICQKQVKYLGYLLKEGQR
+>POL_RSVP
+VALHLAIPLKWKPDH--TPVWIDQWPLPEGKLVALTQLVEKELQLGHIEP
+SL--SCWNTPVFVIRKAS-GSYRLLHDLRAVNAKLVPFGAVQQGAP-VLS
+ALPRGW-PLMVLDLKDCFFSIPLAEQDREAFAFTLPSVNNQAPARRFQWK
+VLPQGMTCSPTICQLVVGQVLEPLRLKHPSLCMLHYMDDLLLAASS-HDG
+LEAAGEEVISTLERAGFTISPDKVQR-EPGVQYLGYKLGSTYV
diff --git a/examples/RV12.BBS12030.reference.stock b/examples/RV12.BBS12030.reference.stock
new file mode 100644
index 0000000..4e096fc
--- /dev/null
+++ b/examples/RV12.BBS12030.reference.stock
@@ -0,0 +1,8 @@
+# STOCKHOLM 1.0
+POL_MPMV APQQCAEPITWKSDE...PVWVDQWPLTNDKLAAAQQLVQEQLEAGHITESS..SPWNTPIFVIKKKS.GKWRLLQDLRAVNATMVLMGALQPGLP.SPVAIPQGY.LKIIIDLKDCFFSIPLHPSDQKRFAFSLPSTNFKEPMQRFQWKVLPQGMANSPTLCQKYVATAIHKVRHAWKQMYIIHYMDDILIAGKD.GQQVLQCFDQLKQELTAAGLHIAPEKVQL.QDPYTYLGFELNGPKI
+POL_BIV06 HTEK.IEPLPVKVRG..PGPKVPQWPLTKEKYQALKEIVKDLLAEGKISEAAWDNPYNTPVFVIKKKGTGRWRMLMDFRELNKITVKGQEFSTGLP.YPPGIKECE.HLTAIDIKDAYFTIPLHEDFRPFTAFSVVPVNREGPIERFQWNVLPQGWVCSPAIYQTTTQKIIENIKKSHPDVMLYQYMDDLLIGSNR..DDHKQIVQEIRDKLGSYGFKTPDEKVQE..ERVKWIGFELTPKKW
+POL_CAEVC LEEKRIPITKVKLKEGCTGPHVPQWPLTEEKLKGLTEIIDKLVEEGKLGKAPPHWTCNTPIFCIKKKS.GKWRMLIDFRELNKQTEDLTEAQLGLP.HPGGLQKKK.HVTILDIGDAYFTIPLYEPYREYTCFTLLSPNNLGPCKRYYWKVLPQGWKLSPSVYQFTMQEILEDWIQQHPEIQFGIYMDDIYIGSDLEIKKHREIVKDLANYIAQYGFTLPEEKRQK.GYPAKWLGFELHPQTW
+1bqm_A PISP.IETVPVKLKPGMDGPKVKQWPLTEEKIKALVEICTEMEKEGKISKIGPENPYNTPVFAIKKKDSTKWRKLVDFRELNKRTQDFWEVQLGIP.HPAGLKKKK.SVTVLDVGDAYFSVPLDEDFRKYTAFTIPSINNETPGIRYQYNVLPQGWKGSPAIFQSSMTKILEPFKKQNPDIVIYQYMDDLYVGSDLEIGQHRTKIEELRQHLLRWGLTTPDKKHQK.EPPFLWMGYELHPDKW
+POL_RSVP VALHLAIPLKWKPDH..TPVWIDQWPLPEGKLVALTQLVEKELQLGHIEPSL..SCWNTPVFVIRKAS.GSYRLLHDLRAVNAKLVPFGAVQQGAP.VLSALPRGW.PLMVLDLKDCFFSIPLAEQDREAFAFTLPSVNNQAPARRFQWKVLPQGMTCSPTICQLVVGQVLEPLRLKHPSLCMLHYMDDLLLAASS.HDGLEAAGEEVISTLERAGFTISPDKVQR.EPGVQYLGYKLGSTYV
+1d0e_A LAVR.QAPLIIPLKATSTPVSIKQYPMSQEARLGIKPHIQRLLDQGILVPCQ..SPWNTPLLPVKKPGTNDYRPVQDLREVNKRVEDIHPTVPNPYNLLSGLPPSHQWYTVLDLKDAFFCLRLHPTSQPLFAFEWRDPEMGISG.QLTWTRLPQGFKNSPTLFDEALHRDLADFRIQHPDLILLQYVDDLLLAATS.ELDCQQGTRALLQTLGNLGYRASAKKAQICQKQVKYLGYLLKEGQR
+//
diff --git a/examples/RV12.BBS12030.stock b/examples/RV12.BBS12030.stock
new file mode 100644
index 0000000..046f133
--- /dev/null
+++ b/examples/RV12.BBS12030.stock
@@ -0,0 +1,10 @@
+# STOCKHOLM 1.0
+#=GF Accuracy 0.900656
+POL_MPMV APQQCA-EPITWKSDE--P-VWVDQWPLTNDKLAAAQQLVQEQLEAGHITESS--SPWNTPIFVIKKK-SGKWRLLQDLRAVNATMVLMGALQPGLPSPV----AIPQ-GYLKIIIDLKDCFFSIPLHPSDQKRFAFSLPSTNFKEPMQRFQWKVLPQGMANSPTLCQKYVATAIHKVRHAWKQMYIIHYMDDILIAGKDGQ-QVLQCFDQLKQELTAAGLHIAPEKVQL-QDPYTYLGFELNGPKI
+POL_BIV06 HTEKIEPL--PVKVRG--PGPKVPQWPLTKEKYQALKEIVKDLLAEGKISEAAWDNPYNTPVFVIKKKGTGRWRMLMDFRELNKITVKGQEFSTGLPYPP----GIKE-CEHLTAIDIKDAYFTIPLHEDFRPFTAFSVVPVNREGPIERFQWNVLPQGWVCSPAIYQTTTQKIIENIKKSHPDVMLYQYMDDLLIGSNRD--DHKQIVQEIRDKLGSYGFKTPDEKVQ--EERVKWIGFELTPKKW
+POL_CAEVC LEEKRIPI-TKVKLKEGCTGPHVPQWPLTEEKLKGLTEIIDKLVEEGKLGKAPPHWTCNTPIFCIKKK-SGKWRMLIDFRELNKQTEDLTEAQLGLPHPG----GLQK-KKHVTILDIGDAYFTIPLYEPYREYTCFTLLSPNNLGPCKRYYWKVLPQGWKLSPSVYQFTMQEILEDWIQQHPEIQFGIYMDDIYIGSDLEIKKHREIVKDLANYIAQYGFTLPEEKRQK-GYPAKWLGFELHPQTW
+1bqm_A PISPIETV--PVKLKPGMDGPKVKQWPLTEEKIKALVEICTEMEKEGKISKIGPENPYNTPVFAIKKKDSTKWRKLVDFRELNKRTQDFWEVQLGIPHPA----GLKK-KKSVTVLDVGDAYFSVPLDEDFRKYTAFTIPSINNETPGIRYQYNVLPQGWKGSPAIFQSSMTKILEPFKKQNPDIVIYQYMDDLYVGSDLEIGQHRTKIEELRQHLLRWGLTTPDKKHQK-EPPFLWMGYELHPDKW
+1d0e_A LAVRQAPLI--IPLKATSTPVSIKQYPMSQEARLGIKPHIQRLLDQGILVPCQ--SPWNTPLLPVKKPGTNDYRPVQDLREVNKRVEDI---HPTVPNPYNLLSGLPPSHQWYTVLDLKDAFFCLRLHPTSQPLFAFEWRDPEM-GISGQLTWTRLPQGFKNSPTLFDEALHRDLADFRIQHPDLILLQYVDDLLLAATSEL-DCQQGTRALLQTLGNLGYRASAKKAQICQKQVKYLGYLLKEGQR
+POL_RSVP VALHLA-IPLKW--KPDHTPVWIDQWPLPEGKLVALTQLVEKELQLGHIEPSL--SCWNTPVFVIRKA-SGSYRLLHDLRAVNAKLVPFGAVQQGAPVLS----ALPR-GWPLMVLDLKDCFFSIPLAEQDREAFAFTLPSVNNQAPARRFQWKVLPQGMTCSPTICQLVVGQVLEPLRLKHPSLCMLHYMDDLLLAASSHD-GLEAAGEEVISTLERAGFTISPDKVQR-EPGVQYLGYKLGSTYV
+#=GC Accuracy 8777655523455565676788999999999999999999999999988877655788999999998768999999999999999988888888888888334288873788999999999999999999999999999998888888899999999999999999999999999999999999999999999999887665366677788999999999999999999746789999999999999
+//
diff --git a/examples/U5.aln1.fasta b/examples/U5.aln1.fasta
new file mode 100644
index 0000000..8af7851
--- /dev/null
+++ b/examples/U5.aln1.fasta
@@ -0,0 +1,20 @@
+>AC005719.2-130462_130570
+UACUCUGGUUUCUCUUCAAUUGUCGAAUAAAUCUUUCGCCUUUUACUAAA
+GAUUUCCGUGGAGAGGAACACUCUAAUGAGUCUAAACUCAAUUUUUGUAU
+GACCUGGCU
+>AC000104.1-17376_17496
+AGCCAUGUGGUGAGCACAUAGCGAACUAUUCUUUCGCCUUUUACUAAAGA
+AUACCGUGUGCUCUCCACGCUAAGUGGCAUACGCCUAUUUUUGGAGGGUU
+CCCACUUUACUGUGGGUCCCA
+>AC009948.3-27597_27481
+AUACUCUGGAUUCUCUUCAGAUCAUAUAUCUUUUGCCUUUUAUUAGAAUU
+UCUAGAGAGAGGAUAAAUUAUGAGUUUGUAGCCAGUUUUUUCUUUGCUUU
+UUAUUUUUGGCAGGGUU
+>AL606646.3-46909_46786
+AGCUGCGCAGUGGGCACAAAGCGAACUAUUCUUUCGCCUUUUACUAAAGA
+AUACCGUGUGCACGCUGCAAAUAGCAGCAUACUCUAAUUUUUUGAGGGGA
+UUUCCUAUCUAAGGACAAACCCCA
+>M23811.1-5_119
+AUACUCUGGUUUCUCUUCAGAUCGUAUAAAUCUUUCCCCUUUCANCAAAG
+AUUUCCGUGGAGAGGAACAACUCUGAGUCUUAAACCAAUUUUUUGAGCCU
+UGUUCCGGCAAGGCU
diff --git a/examples/U5.aln1.fasta.gui b/examples/U5.aln1.fasta.gui
new file mode 100644
index 0000000..0c08714
--- /dev/null
+++ b/examples/U5.aln1.fasta.gui
@@ -0,0 +1,1048 @@
+; Initial DAG
+; Format is:
+; column: (sequence, position)
+; sequence is 0-based and position is 0-based
+
+0: (0, 0)
+1: (1, 0)
+2: (2, 0)
+3: (3, 0)
+4: (4, 0)
+5: (0, 1)
+6: (1, 1)
+7: (2, 1)
+8: (3, 1)
+9: (4, 1)
+10: (0, 2)
+11: (1, 2)
+12: (2, 2)
+13: (3, 2)
+14: (4, 2)
+15: (0, 3)
+16: (1, 3)
+17: (2, 3)
+18: (3, 3)
+19: (4, 3)
+20: (0, 4)
+21: (1, 4)
+22: (2, 4)
+23: (3, 4)
+24: (4, 4)
+25: (0, 5)
+26: (1, 5)
+27: (2, 5)
+28: (3, 5)
+29: (4, 5)
+30: (0, 6)
+31: (1, 6)
+32: (2, 6)
+33: (3, 6)
+34: (4, 6)
+35: (0, 7)
+36: (1, 7)
+37: (2, 7)
+38: (3, 7)
+39: (4, 7)
+40: (0, 8)
+41: (1, 8)
+42: (2, 8)
+43: (3, 8)
+44: (4, 8)
+45: (0, 9)
+46: (1, 9)
+47: (2, 9)
+48: (3, 9)
+49: (4, 9)
+50: (0, 10)
+51: (1, 10)
+52: (2, 10)
+53: (3, 10)
+54: (4, 10)
+55: (0, 11)
+56: (1, 11)
+57: (2, 11)
+58: (3, 11)
+59: (4, 11)
+60: (0, 12)
+61: (1, 12)
+62: (2, 12)
+63: (3, 12)
+64: (4, 12)
+65: (0, 13)
+66: (1, 13)
+67: (2, 13)
+68: (3, 13)
+69: (4, 13)
+70: (0, 14)
+71: (1, 14)
+72: (2, 14)
+73: (3, 14)
+74: (4, 14)
+75: (0, 15)
+76: (1, 15)
+77: (2, 15)
+78: (3, 15)
+79: (4, 15)
+80: (0, 16)
+81: (1, 16)
+82: (2, 16)
+83: (3, 16)
+84: (4, 16)
+85: (0, 17)
+86: (1, 17)
+87: (2, 17)
+88: (3, 17)
+89: (4, 17)
+90: (0, 18)
+91: (1, 18)
+92: (2, 18)
+93: (3, 18)
+94: (4, 18)
+95: (0, 19)
+96: (1, 19)
+97: (2, 19)
+98: (3, 19)
+99: (4, 19)
+100: (0, 20)
+101: (1, 20)
+102: (2, 20)
+103: (3, 20)
+104: (4, 20)
+105: (0, 21)
+106: (1, 21)
+107: (2, 21)
+108: (3, 21)
+109: (4, 21)
+110: (0, 22)
+111: (1, 22)
+112: (2, 22)
+113: (3, 22)
+114: (4, 22)
+115: (0, 23)
+116: (1, 23)
+117: (2, 23)
+118: (3, 23)
+119: (4, 23)
+120: (0, 24)
+121: (1, 24)
+122: (2, 24)
+123: (3, 24)
+124: (4, 24)
+125: (0, 25)
+126: (1, 25)
+127: (2, 25)
+128: (3, 25)
+129: (4, 25)
+130: (0, 26)
+131: (1, 26)
+132: (2, 26)
+133: (3, 26)
+134: (4, 26)
+135: (0, 27)
+136: (1, 27)
+137: (2, 27)
+138: (3, 27)
+139: (4, 27)
+140: (0, 28)
+141: (1, 28)
+142: (2, 28)
+143: (3, 28)
+144: (4, 28)
+145: (0, 29)
+146: (1, 29)
+147: (2, 29)
+148: (3, 29)
+149: (4, 29)
+150: (0, 30)
+151: (1, 30)
+152: (2, 30)
+153: (3, 30)
+154: (4, 30)
+155: (0, 31)
+156: (1, 31)
+157: (2, 31)
+158: (3, 31)
+159: (4, 31)
+160: (0, 32)
+161: (1, 32)
+162: (2, 32)
+163: (3, 32)
+164: (4, 32)
+165: (0, 33)
+166: (1, 33)
+167: (2, 33)
+168: (3, 33)
+169: (4, 33)
+170: (0, 34)
+171: (1, 34)
+172: (2, 34)
+173: (3, 34)
+174: (4, 34)
+175: (0, 35)
+176: (1, 35)
+177: (2, 35)
+178: (3, 35)
+179: (4, 35)
+180: (0, 36)
+181: (1, 36)
+182: (2, 36)
+183: (3, 36)
+184: (4, 36)
+185: (0, 37)
+186: (1, 37)
+187: (2, 37)
+188: (3, 37)
+189: (4, 37)
+190: (0, 38)
+191: (1, 38)
+192: (2, 38)
+193: (3, 38)
+194: (4, 38)
+195: (0, 39)
+196: (1, 39)
+197: (2, 39)
+198: (3, 39)
+199: (4, 39)
+200: (0, 40)
+201: (1, 40)
+202: (2, 40)
+203: (3, 40)
+204: (4, 40)
+205: (0, 41)
+206: (1, 41)
+207: (2, 41)
+208: (3, 41)
+209: (4, 41)
+210: (0, 42)
+211: (1, 42)
+212: (2, 42)
+213: (3, 42)
+214: (4, 42)
+215: (0, 43)
+216: (1, 43)
+217: (2, 43)
+218: (3, 43)
+219: (4, 43)
+220: (0, 44)
+221: (1, 44)
+222: (2, 44)
+223: (3, 44)
+224: (4, 44)
+225: (0, 45)
+226: (1, 45)
+227: (2, 45)
+228: (3, 45)
+229: (4, 45)
+230: (0, 46)
+231: (1, 46)
+232: (2, 46)
+233: (3, 46)
+234: (4, 46)
+235: (0, 47)
+236: (1, 47)
+237: (2, 47)
+238: (3, 47)
+239: (4, 47)
+240: (0, 48)
+241: (1, 48)
+242: (2, 48)
+243: (3, 48)
+244: (4, 48)
+245: (0, 49)
+246: (1, 49)
+247: (2, 49)
+248: (3, 49)
+249: (4, 49)
+250: (0, 50)
+251: (1, 50)
+252: (2, 50)
+253: (3, 50)
+254: (4, 50)
+255: (0, 51)
+256: (1, 51)
+257: (2, 51)
+258: (3, 51)
+259: (4, 51)
+260: (0, 52)
+261: (1, 52)
+262: (2, 52)
+263: (3, 52)
+264: (4, 52)
+265: (0, 53)
+266: (1, 53)
+267: (2, 53)
+268: (3, 53)
+269: (4, 53)
+270: (0, 54)
+271: (1, 54)
+272: (2, 54)
+273: (3, 54)
+274: (4, 54)
+275: (0, 55)
+276: (1, 55)
+277: (2, 55)
+278: (3, 55)
+279: (4, 55)
+280: (0, 56)
+281: (1, 56)
+282: (2, 56)
+283: (3, 56)
+284: (4, 56)
+285: (0, 57)
+286: (1, 57)
+287: (2, 57)
+288: (3, 57)
+289: (4, 57)
+290: (0, 58)
+291: (1, 58)
+292: (2, 58)
+293: (3, 58)
+294: (4, 58)
+295: (0, 59)
+296: (1, 59)
+297: (2, 59)
+298: (3, 59)
+299: (4, 59)
+300: (0, 60)
+301: (1, 60)
+302: (2, 60)
+303: (3, 60)
+304: (4, 60)
+305: (0, 61)
+306: (1, 61)
+307: (2, 61)
+308: (3, 61)
+309: (4, 61)
+310: (0, 62)
+311: (1, 62)
+312: (2, 62)
+313: (3, 62)
+314: (4, 62)
+315: (0, 63)
+316: (1, 63)
+317: (2, 63)
+318: (3, 63)
+319: (4, 63)
+320: (0, 64)
+321: (1, 64)
+322: (2, 64)
+323: (3, 64)
+324: (4, 64)
+325: (0, 65)
+326: (1, 65)
+327: (2, 65)
+328: (3, 65)
+329: (4, 65)
+330: (0, 66)
+331: (1, 66)
+332: (2, 66)
+333: (3, 66)
+334: (4, 66)
+335: (0, 67)
+336: (1, 67)
+337: (2, 67)
+338: (3, 67)
+339: (4, 67)
+340: (0, 68)
+341: (1, 68)
+342: (2, 68)
+343: (3, 68)
+344: (4, 68)
+345: (0, 69)
+346: (1, 69)
+347: (2, 69)
+348: (3, 69)
+349: (4, 69)
+350: (0, 70)
+351: (1, 70)
+352: (2, 70)
+353: (3, 70)
+354: (4, 70)
+355: (0, 71)
+356: (1, 71)
+357: (2, 71)
+358: (3, 71)
+359: (4, 71)
+360: (0, 72)
+361: (1, 72)
+362: (2, 72)
+363: (3, 72)
+364: (4, 72)
+365: (0, 73)
+366: (1, 73)
+367: (2, 73)
+368: (3, 73)
+369: (4, 73)
+370: (0, 74)
+371: (1, 74)
+372: (2, 74)
+373: (3, 74)
+374: (4, 74)
+375: (0, 75)
+376: (1, 75)
+377: (2, 75)
+378: (3, 75)
+379: (4, 75)
+380: (0, 76)
+381: (1, 76)
+382: (2, 76)
+383: (3, 76)
+384: (4, 76)
+385: (0, 77)
+386: (1, 77)
+387: (2, 77)
+388: (3, 77)
+389: (4, 77)
+390: (0, 78)
+391: (1, 78)
+392: (2, 78)
+393: (3, 78)
+394: (4, 78)
+395: (0, 79)
+396: (1, 79)
+397: (2, 79)
+398: (3, 79)
+399: (4, 79)
+400: (0, 80)
+401: (1, 80)
+402: (2, 80)
+403: (3, 80)
+404: (4, 80)
+405: (0, 81)
+406: (1, 81)
+407: (2, 81)
+408: (3, 81)
+409: (4, 81)
+410: (0, 82)
+411: (1, 82)
+412: (2, 82)
+413: (3, 82)
+414: (4, 82)
+415: (0, 83)
+416: (1, 83)
+417: (2, 83)
+418: (3, 83)
+419: (4, 83)
+420: (0, 84)
+421: (1, 84)
+422: (2, 84)
+423: (3, 84)
+424: (4, 84)
+425: (0, 85)
+426: (1, 85)
+427: (2, 85)
+428: (3, 85)
+429: (4, 85)
+430: (0, 86)
+431: (1, 86)
+432: (2, 86)
+433: (3, 86)
+434: (4, 86)
+435: (0, 87)
+436: (1, 87)
+437: (2, 87)
+438: (3, 87)
+439: (4, 87)
+440: (0, 88)
+441: (1, 88)
+442: (2, 88)
+443: (3, 88)
+444: (4, 88)
+445: (0, 89)
+446: (1, 89)
+447: (2, 89)
+448: (3, 89)
+449: (4, 89)
+450: (0, 90)
+451: (1, 90)
+452: (2, 90)
+453: (3, 90)
+454: (4, 90)
+455: (0, 91)
+456: (1, 91)
+457: (2, 91)
+458: (3, 91)
+459: (4, 91)
+460: (0, 92)
+461: (1, 92)
+462: (2, 92)
+463: (3, 92)
+464: (4, 92)
+465: (0, 93)
+466: (1, 93)
+467: (2, 93)
+468: (3, 93)
+469: (4, 93)
+470: (0, 94)
+471: (1, 94)
+472: (2, 94)
+473: (3, 94)
+474: (4, 94)
+475: (0, 95)
+476: (1, 95)
+477: (2, 95)
+478: (3, 95)
+479: (4, 95)
+480: (0, 96)
+481: (1, 96)
+482: (2, 96)
+483: (3, 96)
+484: (4, 96)
+485: (0, 97)
+486: (1, 97)
+487: (2, 97)
+488: (3, 97)
+489: (4, 97)
+490: (0, 98)
+491: (1, 98)
+492: (2, 98)
+493: (3, 98)
+494: (4, 98)
+495: (0, 99)
+496: (1, 99)
+497: (2, 99)
+498: (3, 99)
+499: (4, 99)
+500: (0, 100)
+501: (1, 100)
+502: (2, 100)
+503: (3, 100)
+504: (4, 100)
+505: (0, 101)
+506: (1, 101)
+507: (2, 101)
+508: (3, 101)
+509: (4, 101)
+510: (0, 102)
+511: (1, 102)
+512: (2, 102)
+513: (3, 102)
+514: (4, 102)
+515: (0, 103)
+516: (1, 103)
+517: (2, 103)
+518: (3, 103)
+519: (4, 103)
+520: (0, 104)
+521: (1, 104)
+522: (2, 104)
+523: (3, 104)
+524: (4, 104)
+525: (0, 105)
+526: (1, 105)
+527: (2, 105)
+528: (3, 105)
+529: (4, 105)
+530: (0, 106)
+531: (1, 106)
+532: (2, 106)
+533: (3, 106)
+534: (4, 106)
+535: (0, 107)
+536: (1, 107)
+537: (2, 107)
+538: (3, 107)
+539: (4, 107)
+540: (0, 108)
+541: (1, 108)
+542: (2, 108)
+543: (3, 108)
+544: (4, 108)
+545: (1, 109)
+546: (2, 109)
+547: (3, 109)
+548: (4, 109)
+549: (1, 110)
+550: (2, 110)
+551: (3, 110)
+552: (4, 110)
+553: (1, 111)
+554: (2, 111)
+555: (3, 111)
+556: (4, 111)
+557: (1, 112)
+558: (2, 112)
+559: (3, 112)
+560: (4, 112)
+561: (1, 113)
+562: (2, 113)
+563: (3, 113)
+564: (4, 113)
+565: (1, 114)
+566: (2, 114)
+567: (3, 114)
+568: (4, 114)
+569: (1, 115)
+570: (2, 115)
+571: (3, 115)
+572: (1, 116)
+573: (2, 116)
+574: (3, 116)
+575: (1, 117)
+576: (3, 117)
+577: (1, 118)
+578: (3, 118)
+579: (1, 119)
+580: (3, 119)
+581: (1, 120)
+582: (3, 120)
+583: (3, 121)
+584: (3, 122)
+585: (3, 123)
+
+; Merges (added edges)
+; Format is:
+; source_column -> dest_column
+; (new accuracy is source_column_accuracy + dest_column_accuracy + accuracy_change)
+; (note that all accuracies are unnormalized)
+
+108 -> 106
+178 -> 176
+3 -> 1
+128 -> 126
+113 -> 111
+218 -> 216
+268 -> 266
+73 -> 71
+263 -> 261
+78 -> 76
+585 -> 581
+223 -> 221
+133 -> 131
+173 -> 171
+83 -> 81
+258 -> 256
+273 -> 271
+213 -> 211
+138 -> 136
+123 -> 121
+118 -> 116
+183 -> 181
+243 -> 241
+103 -> 101
+253 -> 251
+248 -> 246
+188 -> 186
+8 -> 6
+153 -> 151
+228 -> 226
+143 -> 141
+238 -> 236
+148 -> 146
+233 -> 231
+278 -> 276
+168 -> 166
+68 -> 66
+158 -> 156
+403 -> 401
+88 -> 86
+53 -> 51
+163 -> 161
+98 -> 96
+208 -> 206
+193 -> 191
+13 -> 11
+48 -> 46
+58 -> 56
+290 -> 289
+93 -> 91
+283 -> 281
+584 -> 579
+203 -> 201
+63 -> 61
+285 -> 284
+198 -> 196
+4 -> 2
+288 -> 286
+408 -> 406
+583 -> 577
+9 -> 7
+14 -> 12
+398 -> 396
+94 -> 92
+255 -> 254
+19 -> 17
+89 -> 87
+25 -> 34
+43 -> 41
+225 -> 218
+99 -> 97
+305 -> 304
+30 -> 39
+35 -> 44
+250 -> 249
+24 -> 22
+38 -> 36
+160 -> 159
+310 -> 309
+155 -> 154
+295 -> 294
+315 -> 314
+280 -> 279
+293 -> 291
+33 -> 31
+27 -> 29
+18 -> 16
+300 -> 299
+275 -> 274
+185 -> 178
+23 -> 21
+55 -> 64
+28 -> 26
+223 -> 230
+582 -> 575
+220 -> 213
+180 -> 173
+60 -> 69
+298 -> 296
+74 -> 72
+357 -> 374
+183 -> 190
+188 -> 195
+362 -> 379
+104 -> 102
+320 -> 319
+84 -> 82
+228 -> 235
+40 -> 49
+79 -> 77
+393 -> 391
+260 -> 259
+270 -> 269
+59 -> 50
+233 -> 240
+325 -> 324
+238 -> 245
+150 -> 149
+32 -> 25
+54 -> 45
+265 -> 264
+175 -> 168
+193 -> 200
+215 -> 208
+367 -> 384
+27 -> 20
+165 -> 164
+388 -> 386
+573 -> 568
+62 -> 55
+60 -> 67
+550 -> 544
+170 -> 163
+198 -> 205
+210 -> 203
+570 -> 564
+65 -> 74
+413 -> 411
+250 -> 243
+383 -> 381
+566 -> 560
+109 -> 107
+548 -> 554
+580 -> 572
+145 -> 144
+30 -> 37
+418 -> 416
+369 -> 352
+24 -> 15
+562 -> 556
+303 -> 301
+558 -> 552
+378 -> 376
+140 -> 139
+165 -> 158
+175 -> 174
+248 -> 255
+423 -> 421
+35 -> 42
+170 -> 169
+160 -> 153
+244 -> 238
+578 -> 569
+412 -> 429
+373 -> 371
+179 -> 180
+424 -> 407
+400 -> 389
+428 -> 426
+308 -> 306
+433 -> 431
+368 -> 366
+70 -> 79
+135 -> 134
+313 -> 311
+57 -> 59
+576 -> 565
+239 -> 233
+188 -> 194
+318 -> 316
+323 -> 321
+253 -> 260
+574 -> 561
+189 -> 183
+330 -> 329
+184 -> 185
+193 -> 199
+19 -> 10
+516 -> 533
+258 -> 265
+571 -> 557
+234 -> 228
+114 -> 112
+521 -> 538
+54 -> 52
+155 -> 148
+438 -> 444
+395 -> 367
+47 -> 40
+531 -> 547
+204 -> 198
+443 -> 449
+567 -> 553
+207 -> 219
+417 -> 434
+541 -> 555
+543 -> 526
+551 -> 536
+263 -> 270
+563 -> 549
+448 -> 454
+559 -> 545
+546 -> 539
+573 -> 540
+453 -> 459
+328 -> 326
+209 -> 210
+458 -> 464
+394 -> 405
+214 -> 202
+363 -> 361
+327 -> 344
+450 -> 439
+463 -> 469
+75 -> 84
+364 -> 347
+268 -> 275
+292 -> 310
+334 -> 335
+420 -> 409
+414 -> 425
+468 -> 474
+333 -> 331
+150 -> 143
+359 -> 342
+305 -> 287
+332 -> 349
+338 -> 336
+297 -> 315
+130 -> 123
+113 -> 119
+528 -> 511
+354 -> 337
+145 -> 138
+419 -> 402
+343 -> 341
+523 -> 506
+339 -> 322
+372 -> 400
+125 -> 118
+229 -> 223
+542 -> 534
+302 -> 320
+358 -> 356
+273 -> 280
+224 -> 225
+348 -> 346
+353 -> 351
+300 -> 282
+140 -> 133
+129 -> 130
+135 -> 128
+570 -> 535
+307 -> 325
+473 -> 479
+436 -> 438
+80 -> 89
+14 -> 5
+518 -> 501
+177 -> 189
+390 -> 362
+182 -> 188
+184 -> 172
+214 -> 215
+382 -> 399
+192 -> 204
+295 -> 277
+209 -> 197
+441 -> 443
+193 -> 187
+394 -> 377
+175 -> 162
+267 -> 285
+170 -> 157
+387 -> 404
+207 -> 220
+448 -> 446
+312 -> 330
+566 -> 530
+179 -> 167
+3 -> 0
+165 -> 152
+478 -> 476
+453 -> 451
+290 -> 272
+385 -> 357
+414 -> 397
+458 -> 456
+160 -> 147
+513 -> 496
+124 -> 125
+483 -> 481
+382 -> 410
+115 -> 108
+120 -> 113
+420 -> 392
+562 -> 525
+427 -> 436
+440 -> 412
+415 -> 387
+417 -> 445
+98 -> 104
+432 -> 441
+334 -> 317
+419 -> 430
+437 -> 448
+339 -> 340
+85 -> 94
+477 -> 488
+463 -> 461
+450 -> 422
+473 -> 471
+99 -> 93
+212 -> 224
+468 -> 466
+278 -> 267
+109 -> 103
+273 -> 262
+258 -> 247
+217 -> 229
+442 -> 453
+268 -> 257
+88 -> 85
+450 -> 433
+486 -> 477
+478 -> 484
+155 -> 142
+483 -> 472
+283 -> 290
+491 -> 487
+417 -> 428
+482 -> 493
+83 -> 80
+435 -> 424
+263 -> 252
+253 -> 242
+403 -> 420
+9 -> 8
+447 -> 458
+408 -> 414
+415 -> 398
+537 -> 529
+78 -> 75
+393 -> 382
+497 -> 508
+30 -> 33
+394 -> 388
+440 -> 423
+435 -> 418
+363 -> 369
+359 -> 353
+48 -> 54
+419 -> 413
+18 -> 24
+558 -> 520
+510 -> 550
+73 -> 70
+32 -> 28
+503 -> 492
+115 -> 114
+548 -> 515
+354 -> 348
+57 -> 53
+38 -> 35
+19 -> 13
+372 -> 383
+68 -> 65
+532 -> 524
+47 -> 43
+222 -> 234
+395 -> 378
+60 -> 63
+364 -> 358
+427 -> 455
+521 -> 517
+390 -> 373
+385 -> 368
+546 -> 505
+62 -> 58
+343 -> 332
+528 -> 507
+248 -> 237
+295 -> 288
+516 -> 512
+531 -> 527
+452 -> 463
+542 -> 500
+543 -> 522
+27 -> 23
+338 -> 327
+135 -> 122
+513 -> 502
+244 -> 232
+239 -> 227
+432 -> 460
+150 -> 137
+129 -> 117
+90 -> 99
+585 -> 573
+498 -> 504
+127 -> 140
+4 -> 3
+437 -> 465
+483 -> 489
+110 -> 109
+486 -> 494
+478 -> 467
+482 -> 499
+300 -> 293
+145 -> 132
+473 -> 462
+380 -> 363
+468 -> 457
+333 -> 339
+584 -> 570
+559 -> 537
+442 -> 470
+354 -> 350
+298 -> 305
+334 -> 328
+323 -> 312
+360 -> 364
+338 -> 345
+359 -> 355
+303 -> 292
+318 -> 307
+105 -> 98
+297 -> 308
+503 -> 509
+497 -> 514
+313 -> 302
+541 -> 532
+447 -> 475
+546 -> 567
+563 -> 542
+510 -> 571
+583 -> 566
+548 -> 574
+551 -> 519
+558 -> 576
diff --git a/examples/U5.aln1.fasta.probs b/examples/U5.aln1.fasta.probs
new file mode 100644
index 0000000..a7829ab
--- /dev/null
+++ b/examples/U5.aln1.fasta.probs
@@ -0,0 +1,5984 @@
+; Sparse posterior probability matrix for sequences 0 and 1
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (1, 0) => 0.955781
+(0, 1) ~ (1, 0) => 0.0190555
+(0, 1) ~ (1, 1) => 0.912252
+(0, 1) ~ (1, 2) => 0.0105248
+(0, 1) ~ (1, 3) => 0.0133075
+(0, 2) ~ (1, 1) => 0.0209977
+(0, 2) ~ (1, 2) => 0.874424
+(0, 2) ~ (1, 3) => 0.0154671
+(0, 2) ~ (1, 4) => 0.0226548
+(0, 3) ~ (1, 1) => 0.0196753
+(0, 3) ~ (1, 2) => 0.0273041
+(0, 3) ~ (1, 3) => 0.726734
+(0, 3) ~ (1, 4) => 0.0157996
+(0, 3) ~ (1, 5) => 0.0953547
+(0, 4) ~ (1, 2) => 0.0319297
+(0, 4) ~ (1, 3) => 0.067984
+(0, 4) ~ (1, 4) => 0.680085
+(0, 4) ~ (1, 5) => 0.0116951
+(0, 4) ~ (1, 6) => 0.112408
+(0, 5) ~ (1, 3) => 0.0407208
+(0, 5) ~ (1, 4) => 0.0682074
+(0, 5) ~ (1, 5) => 0.647314
+(0, 5) ~ (1, 6) => 0.0131494
+(0, 5) ~ (1, 7) => 0.132174
+(0, 6) ~ (1, 4) => 0.0520418
+(0, 6) ~ (1, 5) => 0.0631816
+(0, 6) ~ (1, 6) => 0.569612
+(0, 6) ~ (1, 7) => 0.0161404
+(0, 6) ~ (1, 8) => 0.148254
+(0, 6) ~ (1, 9) => 0.0102426
+(0, 7) ~ (1, 5) => 0.067176
+(0, 7) ~ (1, 6) => 0.0678155
+(0, 7) ~ (1, 7) => 0.408404
+(0, 7) ~ (1, 8) => 0.0378794
+(0, 7) ~ (1, 9) => 0.158665
+(0, 7) ~ (1, 10) => 0.011368
+(0, 8) ~ (1, 6) => 0.118383
+(0, 8) ~ (1, 7) => 0.0637549
+(0, 8) ~ (1, 8) => 0.373476
+(0, 8) ~ (1, 9) => 0.0398726
+(0, 8) ~ (1, 10) => 0.139781
+(0, 8) ~ (1, 11) => 0.0156673
+(0, 9) ~ (1, 7) => 0.236134
+(0, 9) ~ (1, 8) => 0.0512678
+(0, 9) ~ (1, 9) => 0.342077
+(0, 9) ~ (1, 10) => 0.0401088
+(0, 9) ~ (1, 11) => 0.116978
+(0, 9) ~ (1, 12) => 0.0204481
+(0, 10) ~ (1, 8) => 0.272716
+(0, 10) ~ (1, 9) => 0.0392182
+(0, 10) ~ (1, 10) => 0.283308
+(0, 10) ~ (1, 11) => 0.0364696
+(0, 10) ~ (1, 12) => 0.071815
+(0, 10) ~ (1, 13) => 0.0236613
+(0, 11) ~ (1, 9) => 0.315187
+(0, 11) ~ (1, 10) => 0.0132011
+(0, 11) ~ (1, 11) => 0.218109
+(0, 11) ~ (1, 12) => 0.0246686
+(0, 11) ~ (1, 13) => 0.0253074
+(0, 11) ~ (1, 14) => 0.0274044
+(0, 12) ~ (1, 7) => 0.0102384
+(0, 12) ~ (1, 10) => 0.423171
+(0, 12) ~ (1, 11) => 0.0146818
+(0, 12) ~ (1, 12) => 0.161497
+(0, 12) ~ (1, 13) => 0.0228265
+(0, 12) ~ (1, 15) => 0.0233721
+(0, 13) ~ (1, 11) => 0.507985
+(0, 13) ~ (1, 13) => 0.104007
+(0, 13) ~ (1, 14) => 0.0187096
+(0, 13) ~ (1, 16) => 0.0218637
+(0, 14) ~ (1, 12) => 0.6349
+(0, 14) ~ (1, 14) => 0.0805833
+(0, 14) ~ (1, 15) => 0.0104555
+(0, 14) ~ (1, 17) => 0.0160535
+(0, 15) ~ (1, 13) => 0.75582
+(0, 15) ~ (1, 15) => 0.0792743
+(0, 15) ~ (1, 18) => 0.0119581
+(0, 16) ~ (1, 14) => 0.833899
+(0, 16) ~ (1, 16) => 0.0807219
+(0, 17) ~ (1, 15) => 0.855765
+(0, 17) ~ (1, 17) => 0.0759621
+(0, 18) ~ (1, 16) => 0.856102
+(0, 18) ~ (1, 17) => 0.0176095
+(0, 18) ~ (1, 18) => 0.0562912
+(0, 19) ~ (1, 17) => 0.866292
+(0, 19) ~ (1, 18) => 0.0194196
+(0, 19) ~ (1, 19) => 0.0474252
+(0, 20) ~ (1, 18) => 0.889104
+(0, 20) ~ (1, 19) => 0.0193283
+(0, 20) ~ (1, 20) => 0.0254255
+(0, 21) ~ (1, 19) => 0.90256
+(0, 21) ~ (1, 20) => 0.0158611
+(0, 22) ~ (1, 20) => 0.939409
+(0, 23) ~ (1, 21) => 0.98546
+(0, 24) ~ (1, 22) => 0.993083
+(0, 25) ~ (1, 23) => 0.995994
+(0, 26) ~ (1, 24) => 0.996037
+(0, 27) ~ (1, 25) => 0.994532
+(0, 28) ~ (1, 26) => 0.994573
+(0, 29) ~ (1, 27) => 0.995833
+(0, 30) ~ (1, 28) => 0.996636
+(0, 31) ~ (1, 29) => 0.998186
+(0, 32) ~ (1, 30) => 0.999387
+(0, 33) ~ (1, 31) => 0.999406
+(0, 34) ~ (1, 32) => 0.999465
+(0, 35) ~ (1, 33) => 0.99963
+(0, 36) ~ (1, 34) => 0.99986
+(0, 37) ~ (1, 35) => 0.999892
+(0, 38) ~ (1, 36) => 0.999828
+(0, 39) ~ (1, 37) => 0.999812
+(0, 40) ~ (1, 38) => 0.999558
+(0, 41) ~ (1, 39) => 0.999374
+(0, 42) ~ (1, 40) => 0.999371
+(0, 43) ~ (1, 41) => 0.999548
+(0, 44) ~ (1, 42) => 0.999853
+(0, 45) ~ (1, 43) => 0.999923
+(0, 46) ~ (1, 44) => 0.999877
+(0, 47) ~ (1, 45) => 0.9998
+(0, 48) ~ (1, 46) => 0.999748
+(0, 49) ~ (1, 47) => 0.999717
+(0, 50) ~ (1, 48) => 0.999573
+(0, 51) ~ (1, 49) => 0.998869
+(0, 52) ~ (1, 50) => 0.997224
+(0, 53) ~ (1, 51) => 0.995993
+(0, 54) ~ (1, 52) => 0.994468
+(0, 55) ~ (1, 53) => 0.991632
+(0, 56) ~ (1, 54) => 0.985606
+(0, 57) ~ (1, 55) => 0.944177
+(0, 58) ~ (1, 55) => 0.0265006
+(0, 58) ~ (1, 56) => 0.87153
+(0, 59) ~ (1, 56) => 0.0720967
+(0, 59) ~ (1, 57) => 0.608071
+(0, 60) ~ (1, 55) => 0.0101286
+(0, 60) ~ (1, 57) => 0.27671
+(0, 60) ~ (1, 58) => 0.312061
+(0, 60) ~ (1, 59) => 0.0232169
+(0, 60) ~ (1, 71) => 0.0120082
+(0, 61) ~ (1, 56) => 0.0182258
+(0, 61) ~ (1, 58) => 0.479357
+(0, 61) ~ (1, 59) => 0.169536
+(0, 61) ~ (1, 60) => 0.021815
+(0, 61) ~ (1, 72) => 0.0235455
+(0, 62) ~ (1, 57) => 0.0334257
+(0, 62) ~ (1, 59) => 0.57027
+(0, 62) ~ (1, 60) => 0.1132
+(0, 62) ~ (1, 61) => 0.0205684
+(0, 62) ~ (1, 73) => 0.0261783
+(0, 63) ~ (1, 58) => 0.0465739
+(0, 63) ~ (1, 60) => 0.603604
+(0, 63) ~ (1, 61) => 0.0937682
+(0, 63) ~ (1, 62) => 0.0196152
+(0, 63) ~ (1, 74) => 0.0267622
+(0, 64) ~ (1, 58) => 0.0227045
+(0, 64) ~ (1, 59) => 0.0496802
+(0, 64) ~ (1, 61) => 0.61879
+(0, 64) ~ (1, 62) => 0.0604561
+(0, 64) ~ (1, 63) => 0.0131166
+(0, 64) ~ (1, 75) => 0.0276561
+(0, 65) ~ (1, 57) => 0.0279173
+(0, 65) ~ (1, 59) => 0.038821
+(0, 65) ~ (1, 60) => 0.0374689
+(0, 65) ~ (1, 62) => 0.663667
+(0, 65) ~ (1, 63) => 0.0316686
+(0, 65) ~ (1, 64) => 0.0105141
+(0, 65) ~ (1, 76) => 0.0279244
+(0, 66) ~ (1, 58) => 0.0457541
+(0, 66) ~ (1, 60) => 0.0361892
+(0, 66) ~ (1, 61) => 0.0277136
+(0, 66) ~ (1, 62) => 0.0102296
+(0, 66) ~ (1, 63) => 0.730059
+(0, 66) ~ (1, 64) => 0.018464
+(0, 66) ~ (1, 65) => 0.0107454
+(0, 66) ~ (1, 77) => 0.027747
+(0, 67) ~ (1, 59) => 0.0512618
+(0, 67) ~ (1, 61) => 0.0298039
+(0, 67) ~ (1, 62) => 0.0160453
+(0, 67) ~ (1, 64) => 0.784292
+(0, 67) ~ (1, 66) => 0.012218
+(0, 67) ~ (1, 78) => 0.0277513
+(0, 68) ~ (1, 60) => 0.058744
+(0, 68) ~ (1, 62) => 0.0209999
+(0, 68) ~ (1, 65) => 0.843451
+(0, 68) ~ (1, 67) => 0.0118981
+(0, 68) ~ (1, 79) => 0.027428
+(0, 69) ~ (1, 61) => 0.0549642
+(0, 69) ~ (1, 66) => 0.871347
+(0, 69) ~ (1, 68) => 0.0110099
+(0, 69) ~ (1, 80) => 0.0276431
+(0, 70) ~ (1, 62) => 0.0551212
+(0, 70) ~ (1, 67) => 0.876962
+(0, 70) ~ (1, 69) => 0.0103075
+(0, 70) ~ (1, 81) => 0.027496
+(0, 71) ~ (1, 63) => 0.0539286
+(0, 71) ~ (1, 68) => 0.878775
+(0, 71) ~ (1, 82) => 0.0265814
+(0, 72) ~ (1, 64) => 0.0506046
+(0, 72) ~ (1, 69) => 0.878268
+(0, 72) ~ (1, 83) => 0.0255172
+(0, 73) ~ (1, 65) => 0.04286
+(0, 73) ~ (1, 69) => 0.0175811
+(0, 73) ~ (1, 70) => 0.852129
+(0, 73) ~ (1, 84) => 0.0213315
+(0, 74) ~ (1, 66) => 0.0375082
+(0, 74) ~ (1, 70) => 0.0559184
+(0, 74) ~ (1, 71) => 0.795584
+(0, 74) ~ (1, 85) => 0.0202562
+(0, 75) ~ (1, 67) => 0.0124091
+(0, 75) ~ (1, 71) => 0.142514
+(0, 75) ~ (1, 72) => 0.72986
+(0, 75) ~ (1, 86) => 0.0195303
+(0, 76) ~ (1, 72) => 0.202453
+(0, 76) ~ (1, 73) => 0.45246
+(0, 76) ~ (1, 74) => 0.0123025
+(0, 76) ~ (1, 87) => 0.0155426
+(0, 76) ~ (1, 92) => 0.010213
+(0, 77) ~ (1, 73) => 0.457994
+(0, 77) ~ (1, 74) => 0.329742
+(0, 77) ~ (1, 75) => 0.012425
+(0, 77) ~ (1, 93) => 0.0188961
+(0, 78) ~ (1, 72) => 0.011573
+(0, 78) ~ (1, 74) => 0.563981
+(0, 78) ~ (1, 75) => 0.274704
+(0, 78) ~ (1, 94) => 0.0209174
+(0, 79) ~ (1, 73) => 0.0160841
+(0, 79) ~ (1, 75) => 0.615566
+(0, 79) ~ (1, 76) => 0.252635
+(0, 79) ~ (1, 95) => 0.0210412
+(0, 80) ~ (1, 74) => 0.0158497
+(0, 80) ~ (1, 75) => 0.0153541
+(0, 80) ~ (1, 76) => 0.636336
+(0, 80) ~ (1, 77) => 0.18752
+(0, 80) ~ (1, 96) => 0.0200879
+(0, 81) ~ (1, 75) => 0.0110017
+(0, 81) ~ (1, 76) => 0.0218454
+(0, 81) ~ (1, 77) => 0.681897
+(0, 81) ~ (1, 78) => 0.159055
+(0, 81) ~ (1, 97) => 0.0191894
+(0, 82) ~ (1, 77) => 0.0489473
+(0, 82) ~ (1, 78) => 0.666442
+(0, 82) ~ (1, 79) => 0.158616
+(0, 82) ~ (1, 98) => 0.0190439
+(0, 83) ~ (1, 78) => 0.0950423
+(0, 83) ~ (1, 79) => 0.664043
+(0, 83) ~ (1, 80) => 0.151967
+(0, 83) ~ (1, 99) => 0.0181822
+(0, 84) ~ (1, 79) => 0.101157
+(0, 84) ~ (1, 80) => 0.666437
+(0, 84) ~ (1, 81) => 0.140836
+(0, 84) ~ (1, 98) => 0.0111528
+(0, 84) ~ (1, 100) => 0.0175403
+(0, 85) ~ (1, 80) => 0.112392
+(0, 85) ~ (1, 81) => 0.663204
+(0, 85) ~ (1, 82) => 0.134625
+(0, 85) ~ (1, 99) => 0.0155553
+(0, 85) ~ (1, 101) => 0.0175376
+(0, 86) ~ (1, 81) => 0.118388
+(0, 86) ~ (1, 82) => 0.666099
+(0, 86) ~ (1, 83) => 0.124511
+(0, 86) ~ (1, 100) => 0.0205257
+(0, 86) ~ (1, 102) => 0.0179841
+(0, 87) ~ (1, 82) => 0.109186
+(0, 87) ~ (1, 83) => 0.68696
+(0, 87) ~ (1, 84) => 0.0648237
+(0, 87) ~ (1, 101) => 0.0216128
+(0, 87) ~ (1, 103) => 0.0174105
+(0, 88) ~ (1, 83) => 0.0885205
+(0, 88) ~ (1, 84) => 0.768023
+(0, 88) ~ (1, 85) => 0.0537249
+(0, 88) ~ (1, 102) => 0.0247279
+(0, 88) ~ (1, 104) => 0.0168926
+(0, 89) ~ (1, 84) => 0.0608595
+(0, 89) ~ (1, 85) => 0.798675
+(0, 89) ~ (1, 86) => 0.0592958
+(0, 89) ~ (1, 103) => 0.0252848
+(0, 89) ~ (1, 105) => 0.0135127
+(0, 90) ~ (1, 85) => 0.0395198
+(0, 90) ~ (1, 86) => 0.823114
+(0, 90) ~ (1, 87) => 0.0573967
+(0, 90) ~ (1, 104) => 0.0232005
+(0, 90) ~ (1, 105) => 0.0117404
+(0, 90) ~ (1, 106) => 0.010847
+(0, 91) ~ (1, 86) => 0.0339333
+(0, 91) ~ (1, 87) => 0.824811
+(0, 91) ~ (1, 88) => 0.0581789
+(0, 91) ~ (1, 105) => 0.0216241
+(0, 91) ~ (1, 106) => 0.0187687
+(0, 92) ~ (1, 87) => 0.0311315
+(0, 92) ~ (1, 88) => 0.82324
+(0, 92) ~ (1, 89) => 0.0582241
+(0, 92) ~ (1, 106) => 0.0196918
+(0, 92) ~ (1, 107) => 0.02349
+(0, 93) ~ (1, 88) => 0.027998
+(0, 93) ~ (1, 89) => 0.820855
+(0, 93) ~ (1, 90) => 0.0578087
+(0, 93) ~ (1, 107) => 0.0173348
+(0, 93) ~ (1, 108) => 0.028051
+(0, 94) ~ (1, 89) => 0.0242389
+(0, 94) ~ (1, 90) => 0.816347
+(0, 94) ~ (1, 91) => 0.0564935
+(0, 94) ~ (1, 108) => 0.0133212
+(0, 94) ~ (1, 109) => 0.0355269
+(0, 95) ~ (1, 90) => 0.0187092
+(0, 95) ~ (1, 91) => 0.806331
+(0, 95) ~ (1, 92) => 0.0527142
+(0, 95) ~ (1, 94) => 0.0102272
+(0, 95) ~ (1, 110) => 0.0557606
+(0, 96) ~ (1, 91) => 0.0116151
+(0, 96) ~ (1, 92) => 0.790989
+(0, 96) ~ (1, 93) => 0.0522624
+(0, 96) ~ (1, 95) => 0.0155777
+(0, 96) ~ (1, 111) => 0.0698909
+(0, 97) ~ (1, 92) => 0.0103297
+(0, 97) ~ (1, 93) => 0.759073
+(0, 97) ~ (1, 94) => 0.0471455
+(0, 97) ~ (1, 96) => 0.0189512
+(0, 97) ~ (1, 112) => 0.0779562
+(0, 98) ~ (1, 94) => 0.735282
+(0, 98) ~ (1, 95) => 0.0431647
+(0, 98) ~ (1, 97) => 0.0223802
+(0, 98) ~ (1, 113) => 0.0825924
+(0, 99) ~ (1, 95) => 0.617237
+(0, 99) ~ (1, 96) => 0.0472389
+(0, 99) ~ (1, 97) => 0.0140068
+(0, 99) ~ (1, 98) => 0.0406061
+(0, 99) ~ (1, 99) => 0.0107393
+(0, 99) ~ (1, 101) => 0.0100058
+(0, 99) ~ (1, 105) => 0.0159537
+(0, 99) ~ (1, 106) => 0.0256216
+(0, 99) ~ (1, 110) => 0.0111619
+(0, 99) ~ (1, 114) => 0.101145
+(0, 100) ~ (1, 95) => 0.0137526
+(0, 100) ~ (1, 96) => 0.534565
+(0, 100) ~ (1, 97) => 0.0514532
+(0, 100) ~ (1, 98) => 0.0211864
+(0, 100) ~ (1, 99) => 0.0473042
+(0, 100) ~ (1, 102) => 0.0204327
+(0, 100) ~ (1, 106) => 0.0201189
+(0, 100) ~ (1, 107) => 0.0344597
+(0, 100) ~ (1, 111) => 0.0132619
+(0, 100) ~ (1, 113) => 0.0102198
+(0, 100) ~ (1, 115) => 0.123609
+(0, 100) ~ (1, 116) => 0.0112084
+(0, 101) ~ (1, 97) => 0.230517
+(0, 101) ~ (1, 98) => 0.0372257
+(0, 101) ~ (1, 99) => 0.0634879
+(0, 101) ~ (1, 100) => 0.0953402
+(0, 101) ~ (1, 101) => 0.0176806
+(0, 101) ~ (1, 102) => 0.0134453
+(0, 101) ~ (1, 103) => 0.0928785
+(0, 101) ~ (1, 107) => 0.0453404
+(0, 101) ~ (1, 108) => 0.0819846
+(0, 101) ~ (1, 109) => 0.0118031
+(0, 101) ~ (1, 112) => 0.0108352
+(0, 101) ~ (1, 113) => 0.0190053
+(0, 101) ~ (1, 116) => 0.139159
+(0, 101) ~ (1, 117) => 0.0284953
+(0, 102) ~ (1, 98) => 0.0434527
+(0, 102) ~ (1, 99) => 0.0245287
+(0, 102) ~ (1, 100) => 0.0999212
+(0, 102) ~ (1, 101) => 0.144747
+(0, 102) ~ (1, 102) => 0.0255465
+(0, 102) ~ (1, 103) => 0.0218414
+(0, 102) ~ (1, 104) => 0.0979418
+(0, 102) ~ (1, 108) => 0.0712781
+(0, 102) ~ (1, 109) => 0.080708
+(0, 102) ~ (1, 110) => 0.0182407
+(0, 102) ~ (1, 114) => 0.0342098
+(0, 102) ~ (1, 117) => 0.158208
+(0, 102) ~ (1, 118) => 0.0498651
+(0, 103) ~ (1, 100) => 0.0246746
+(0, 103) ~ (1, 101) => 0.0873146
+(0, 103) ~ (1, 102) => 0.133846
+(0, 103) ~ (1, 103) => 0.0118895
+(0, 103) ~ (1, 104) => 0.0315775
+(0, 103) ~ (1, 105) => 0.0616888
+(0, 103) ~ (1, 109) => 0.116685
+(0, 103) ~ (1, 110) => 0.0488048
+(0, 103) ~ (1, 111) => 0.0531044
+(0, 103) ~ (1, 113) => 0.0107438
+(0, 103) ~ (1, 115) => 0.0630268
+(0, 103) ~ (1, 117) => 0.010401
+(0, 103) ~ (1, 118) => 0.149638
+(0, 103) ~ (1, 119) => 0.0471877
+(0, 104) ~ (1, 101) => 0.0136559
+(0, 104) ~ (1, 102) => 0.0327547
+(0, 104) ~ (1, 103) => 0.0753044
+(0, 104) ~ (1, 105) => 0.0268471
+(0, 104) ~ (1, 106) => 0.0610189
+(0, 104) ~ (1, 110) => 0.123405
+(0, 104) ~ (1, 111) => 0.0433962
+(0, 104) ~ (1, 112) => 0.11614
+(0, 104) ~ (1, 113) => 0.0286055
+(0, 104) ~ (1, 114) => 0.022368
+(0, 104) ~ (1, 116) => 0.115763
+(0, 104) ~ (1, 119) => 0.0460151
+(0, 104) ~ (1, 120) => 0.0395558
+(0, 105) ~ (1, 102) => 0.0111706
+(0, 105) ~ (1, 103) => 0.0162446
+(0, 105) ~ (1, 104) => 0.0338363
+(0, 105) ~ (1, 106) => 0.0149514
+(0, 105) ~ (1, 107) => 0.0518803
+(0, 105) ~ (1, 111) => 0.114171
+(0, 105) ~ (1, 112) => 0.0411473
+(0, 105) ~ (1, 113) => 0.149986
+(0, 105) ~ (1, 114) => 0.0495592
+(0, 105) ~ (1, 115) => 0.0353493
+(0, 105) ~ (1, 117) => 0.146158
+(0, 105) ~ (1, 120) => 0.0280593
+(0, 106) ~ (1, 103) => 0.0128672
+(0, 106) ~ (1, 105) => 0.0189441
+(0, 106) ~ (1, 108) => 0.0482931
+(0, 106) ~ (1, 112) => 0.0703195
+(0, 106) ~ (1, 113) => 0.0452992
+(0, 106) ~ (1, 114) => 0.150449
+(0, 106) ~ (1, 115) => 0.0507409
+(0, 106) ~ (1, 116) => 0.0333239
+(0, 106) ~ (1, 118) => 0.241952
+(0, 107) ~ (1, 104) => 0.0172431
+(0, 107) ~ (1, 109) => 0.046614
+(0, 107) ~ (1, 113) => 0.0286193
+(0, 107) ~ (1, 114) => 0.0189649
+(0, 107) ~ (1, 115) => 0.0817706
+(0, 107) ~ (1, 117) => 0.031447
+(0, 107) ~ (1, 118) => 0.0145906
+(0, 107) ~ (1, 119) => 0.592633
+(0, 108) ~ (1, 105) => 0.0151487
+(0, 108) ~ (1, 110) => 0.0403175
+(0, 108) ~ (1, 114) => 0.022777
+(0, 108) ~ (1, 115) => 0.0161006
+(0, 108) ~ (1, 116) => 0.0741007
+(0, 108) ~ (1, 118) => 0.0212062
+(0, 108) ~ (1, 119) => 0.0109562
+(0, 108) ~ (1, 120) => 0.676778
+
+; gap posteriors
+(0, 0) ~ (1, -1) => 0.0442191
+(0, 1) ~ (1, -1) => 0.0448606
+(0, 2) ~ (1, -1) => 0.0664562
+(0, 3) ~ (1, -1) => 0.115133
+(0, 4) ~ (1, -1) => 0.0958986
+(0, 5) ~ (1, -1) => 0.0984342
+(0, 6) ~ (1, -1) => 0.140528
+(0, 7) ~ (1, -1) => 0.248691
+(0, 8) ~ (1, -1) => 0.249066
+(0, 9) ~ (1, -1) => 0.192987
+(0, 10) ~ (1, -1) => 0.272812
+(0, 11) ~ (1, -1) => 0.376122
+(0, 12) ~ (1, -1) => 0.344213
+(0, 13) ~ (1, -1) => 0.347435
+(0, 14) ~ (1, -1) => 0.258008
+(0, 15) ~ (1, -1) => 0.152947
+(0, 16) ~ (1, -1) => 0.0853793
+(0, 17) ~ (1, -1) => 0.068273
+(0, 18) ~ (1, -1) => 0.0699971
+(0, 19) ~ (1, -1) => 0.0668631
+(0, 20) ~ (1, -1) => 0.0661417
+(0, 21) ~ (1, -1) => 0.0815793
+(0, 22) ~ (1, -1) => 0.0605909
+(0, 23) ~ (1, -1) => 0.0145403
+(0, 24) ~ (1, -1) => 0.00691658
+(0, 25) ~ (1, -1) => 0.00400645
+(0, 26) ~ (1, -1) => 0.00396299
+(0, 27) ~ (1, -1) => 0.00546825
+(0, 28) ~ (1, -1) => 0.00542748
+(0, 29) ~ (1, -1) => 0.00416726
+(0, 30) ~ (1, -1) => 0.00336421
+(0, 31) ~ (1, -1) => 0.00181377
+(0, 32) ~ (1, -1) => 0.000612557
+(0, 33) ~ (1, -1) => 0.000594258
+(0, 34) ~ (1, -1) => 0.000535309
+(0, 35) ~ (1, -1) => 0.000370204
+(0, 36) ~ (1, -1) => 0.000140488
+(0, 37) ~ (1, -1) => 0.000108242
+(0, 38) ~ (1, -1) => 0.000171959
+(0, 39) ~ (1, -1) => 0.000187516
+(0, 40) ~ (1, -1) => 0.000442266
+(0, 41) ~ (1, -1) => 0.000625849
+(0, 42) ~ (1, -1) => 0.000629306
+(0, 43) ~ (1, -1) => 0.000451684
+(0, 44) ~ (1, -1) => 0.000146925
+(0, 45) ~ (1, -1) => 0.0001
+(0, 46) ~ (1, -1) => 0.000122845
+(0, 47) ~ (1, -1) => 0.000199974
+(0, 48) ~ (1, -1) => 0.000251591
+(0, 49) ~ (1, -1) => 0.000282645
+(0, 50) ~ (1, -1) => 0.000427306
+(0, 51) ~ (1, -1) => 0.00113058
+(0, 52) ~ (1, -1) => 0.00277579
+(0, 53) ~ (1, -1) => 0.0040071
+(0, 54) ~ (1, -1) => 0.00553179
+(0, 55) ~ (1, -1) => 0.00836772
+(0, 56) ~ (1, -1) => 0.0143945
+(0, 57) ~ (1, -1) => 0.0558231
+(0, 58) ~ (1, -1) => 0.101969
+(0, 59) ~ (1, -1) => 0.319832
+(0, 60) ~ (1, -1) => 0.365875
+(0, 61) ~ (1, -1) => 0.287521
+(0, 62) ~ (1, -1) => 0.236358
+(0, 63) ~ (1, -1) => 0.209676
+(0, 64) ~ (1, -1) => 0.207596
+(0, 65) ~ (1, -1) => 0.162018
+(0, 66) ~ (1, -1) => 0.0930976
+(0, 67) ~ (1, -1) => 0.0786276
+(0, 68) ~ (1, -1) => 0.0374794
+(0, 69) ~ (1, -1) => 0.035036
+(0, 70) ~ (1, -1) => 0.0301134
+(0, 71) ~ (1, -1) => 0.0407152
+(0, 72) ~ (1, -1) => 0.0456103
+(0, 73) ~ (1, -1) => 0.0660981
+(0, 74) ~ (1, -1) => 0.0907334
+(0, 75) ~ (1, -1) => 0.0956865
+(0, 76) ~ (1, -1) => 0.307029
+(0, 77) ~ (1, -1) => 0.180943
+(0, 78) ~ (1, -1) => 0.128825
+(0, 79) ~ (1, -1) => 0.0946744
+(0, 80) ~ (1, -1) => 0.124853
+(0, 81) ~ (1, -1) => 0.107012
+(0, 82) ~ (1, -1) => 0.10695
+(0, 83) ~ (1, -1) => 0.0707652
+(0, 84) ~ (1, -1) => 0.062877
+(0, 85) ~ (1, -1) => 0.0566865
+(0, 86) ~ (1, -1) => 0.052492
+(0, 87) ~ (1, -1) => 0.100007
+(0, 88) ~ (1, -1) => 0.048111
+(0, 89) ~ (1, -1) => 0.0423725
+(0, 90) ~ (1, -1) => 0.0341812
+(0, 91) ~ (1, -1) => 0.0426841
+(0, 92) ~ (1, -1) => 0.0442227
+(0, 93) ~ (1, -1) => 0.0479523
+(0, 94) ~ (1, -1) => 0.0540726
+(0, 95) ~ (1, -1) => 0.0562578
+(0, 96) ~ (1, -1) => 0.0596652
+(0, 97) ~ (1, -1) => 0.0865443
+(0, 98) ~ (1, -1) => 0.116581
+(0, 99) ~ (1, -1) => 0.106284
+(0, 100) ~ (1, -1) => 0.0984284
+(0, 101) ~ (1, -1) => 0.112802
+(0, 102) ~ (1, -1) => 0.129511
+(0, 103) ~ (1, -1) => 0.149417
+(0, 104) ~ (1, -1) => 0.25517
+(0, 105) ~ (1, -1) => 0.307486
+(0, 106) ~ (1, -1) => 0.327812
+(0, 107) ~ (1, -1) => 0.168117
+(0, 108) ~ (1, -1) => 0.122615
+
+(0, -1) ~ (1, 0) => 0.0251636
+(0, -1) ~ (1, 1) => 0.0470754
+(0, -1) ~ (1, 2) => 0.0558171
+(0, -1) ~ (1, 3) => 0.135787
+(0, -1) ~ (1, 4) => 0.161212
+(0, -1) ~ (1, 5) => 0.115278
+(0, -1) ~ (1, 6) => 0.118633
+(0, -1) ~ (1, 7) => 0.133154
+(0, -1) ~ (1, 8) => 0.116408
+(0, -1) ~ (1, 9) => 0.0947371
+(0, -1) ~ (1, 10) => 0.0890624
+(0, -1) ~ (1, 11) => 0.0901092
+(0, -1) ~ (1, 12) => 0.0866719
+(0, -1) ~ (1, 13) => 0.0683777
+(0, -1) ~ (1, 14) => 0.0394039
+(0, -1) ~ (1, 15) => 0.0311331
+(0, -1) ~ (1, 16) => 0.0413123
+(0, -1) ~ (1, 17) => 0.0240828
+(0, -1) ~ (1, 18) => 0.0232266
+(0, -1) ~ (1, 19) => 0.0306869
+(0, -1) ~ (1, 20) => 0.0193044
+(0, -1) ~ (1, 21) => 0.0145403
+(0, -1) ~ (1, 22) => 0.00691658
+(0, -1) ~ (1, 23) => 0.00400645
+(0, -1) ~ (1, 24) => 0.00396299
+(0, -1) ~ (1, 25) => 0.00546825
+(0, -1) ~ (1, 26) => 0.00542748
+(0, -1) ~ (1, 27) => 0.00416726
+(0, -1) ~ (1, 28) => 0.00336421
+(0, -1) ~ (1, 29) => 0.00181377
+(0, -1) ~ (1, 30) => 0.000612557
+(0, -1) ~ (1, 31) => 0.000594258
+(0, -1) ~ (1, 32) => 0.000535309
+(0, -1) ~ (1, 33) => 0.000370204
+(0, -1) ~ (1, 34) => 0.000140488
+(0, -1) ~ (1, 35) => 0.000108242
+(0, -1) ~ (1, 36) => 0.000171959
+(0, -1) ~ (1, 37) => 0.000187516
+(0, -1) ~ (1, 38) => 0.000442266
+(0, -1) ~ (1, 39) => 0.000625849
+(0, -1) ~ (1, 40) => 0.000629306
+(0, -1) ~ (1, 41) => 0.000451684
+(0, -1) ~ (1, 42) => 0.000146925
+(0, -1) ~ (1, 43) => 0.0001
+(0, -1) ~ (1, 44) => 0.000122845
+(0, -1) ~ (1, 45) => 0.000199974
+(0, -1) ~ (1, 46) => 0.000251591
+(0, -1) ~ (1, 47) => 0.000282645
+(0, -1) ~ (1, 48) => 0.000427306
+(0, -1) ~ (1, 49) => 0.00113058
+(0, -1) ~ (1, 50) => 0.00277579
+(0, -1) ~ (1, 51) => 0.0040071
+(0, -1) ~ (1, 52) => 0.00553179
+(0, -1) ~ (1, 53) => 0.00836772
+(0, -1) ~ (1, 54) => 0.0143945
+(0, -1) ~ (1, 55) => 0.019194
+(0, -1) ~ (1, 56) => 0.0381474
+(0, -1) ~ (1, 57) => 0.0538763
+(0, -1) ~ (1, 58) => 0.0935495
+(0, -1) ~ (1, 59) => 0.0972144
+(0, -1) ~ (1, 60) => 0.128978
+(0, -1) ~ (1, 61) => 0.154392
+(0, -1) ~ (1, 62) => 0.153865
+(0, -1) ~ (1, 63) => 0.171227
+(0, -1) ~ (1, 64) => 0.136125
+(0, -1) ~ (1, 65) => 0.102944
+(0, -1) ~ (1, 66) => 0.0789269
+(0, -1) ~ (1, 67) => 0.098731
+(0, -1) ~ (1, 68) => 0.110215
+(0, -1) ~ (1, 69) => 0.0938435
+(0, -1) ~ (1, 70) => 0.0919522
+(0, -1) ~ (1, 71) => 0.0498935
+(0, -1) ~ (1, 72) => 0.0325683
+(0, -1) ~ (1, 73) => 0.0472838
+(0, -1) ~ (1, 74) => 0.0513622
+(0, -1) ~ (1, 75) => 0.0432935
+(0, -1) ~ (1, 76) => 0.0612597
+(0, -1) ~ (1, 77) => 0.0538893
+(0, -1) ~ (1, 78) => 0.0517092
+(0, -1) ~ (1, 79) => 0.0487552
+(0, -1) ~ (1, 80) => 0.0415613
+(0, -1) ~ (1, 81) => 0.0500764
+(0, -1) ~ (1, 82) => 0.0635084
+(0, -1) ~ (1, 83) => 0.0744907
+(0, -1) ~ (1, 84) => 0.0849623
+(0, -1) ~ (1, 85) => 0.0878246
+(0, -1) ~ (1, 86) => 0.0641261
+(0, -1) ~ (1, 87) => 0.0711183
+(0, -1) ~ (1, 88) => 0.0905832
+(0, -1) ~ (1, 89) => 0.0966819
+(0, -1) ~ (1, 90) => 0.107135
+(0, -1) ~ (1, 91) => 0.12556
+(0, -1) ~ (1, 92) => 0.135754
+(0, -1) ~ (1, 93) => 0.169768
+(0, -1) ~ (1, 94) => 0.186428
+(0, -1) ~ (1, 95) => 0.289226
+(0, -1) ~ (1, 96) => 0.379157
+(0, -1) ~ (1, 97) => 0.662453
+(0, -1) ~ (1, 98) => 0.827332
+(0, -1) ~ (1, 99) => 0.820202
+(0, -1) ~ (1, 100) => 0.741998
+(0, -1) ~ (1, 101) => 0.687446
+(0, -1) ~ (1, 102) => 0.720092
+(0, -1) ~ (1, 103) => 0.726279
+(0, -1) ~ (1, 104) => 0.779308
+(0, -1) ~ (1, 105) => 0.814541
+(0, -1) ~ (1, 106) => 0.828982
+(0, -1) ~ (1, 107) => 0.827495
+(0, -1) ~ (1, 108) => 0.757072
+(0, -1) ~ (1, 109) => 0.708663
+(0, -1) ~ (1, 110) => 0.702309
+(0, -1) ~ (1, 111) => 0.706176
+(0, -1) ~ (1, 112) => 0.683602
+(0, -1) ~ (1, 113) => 0.624928
+(0, -1) ~ (1, 114) => 0.600527
+(0, -1) ~ (1, 115) => 0.629403
+(0, -1) ~ (1, 116) => 0.626445
+(0, -1) ~ (1, 117) => 0.62529
+(0, -1) ~ (1, 118) => 0.522749
+(0, -1) ~ (1, 119) => 0.303208
+(0, -1) ~ (1, 120) => 0.255607
+
+; Sparse posterior probability matrix for sequences 0 and 2
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (2, 0) => 0.13347
+(0, 0) ~ (2, 1) => 0.859029
+(0, 1) ~ (2, 1) => 0.0182693
+(0, 1) ~ (2, 2) => 0.974051
+(0, 2) ~ (2, 3) => 0.994328
+(0, 3) ~ (2, 4) => 0.998345
+(0, 4) ~ (2, 5) => 0.999238
+(0, 5) ~ (2, 6) => 0.999476
+(0, 6) ~ (2, 7) => 0.999192
+(0, 7) ~ (2, 8) => 0.998642
+(0, 8) ~ (2, 9) => 0.996309
+(0, 9) ~ (2, 10) => 0.996466
+(0, 10) ~ (2, 11) => 0.997562
+(0, 11) ~ (2, 12) => 0.999201
+(0, 12) ~ (2, 13) => 0.999098
+(0, 13) ~ (2, 14) => 0.998934
+(0, 14) ~ (2, 15) => 0.996929
+(0, 15) ~ (2, 16) => 0.991021
+(0, 16) ~ (2, 17) => 0.981556
+(0, 17) ~ (2, 18) => 0.921234
+(0, 17) ~ (2, 19) => 0.0191206
+(0, 18) ~ (2, 19) => 0.669417
+(0, 18) ~ (2, 20) => 0.04944
+(0, 19) ~ (2, 20) => 0.217216
+(0, 19) ~ (2, 21) => 0.0494654
+(0, 20) ~ (2, 19) => 0.0763835
+(0, 20) ~ (2, 21) => 0.152628
+(0, 20) ~ (2, 22) => 0.0299022
+(0, 21) ~ (2, 19) => 0.0216768
+(0, 21) ~ (2, 20) => 0.46137
+(0, 21) ~ (2, 22) => 0.0548227
+(0, 21) ~ (2, 23) => 0.0167674
+(0, 22) ~ (2, 21) => 0.542275
+(0, 22) ~ (2, 24) => 0.0103477
+(0, 23) ~ (2, 18) => 0.026181
+(0, 23) ~ (2, 20) => 0.0132822
+(0, 23) ~ (2, 22) => 0.60977
+(0, 24) ~ (2, 18) => 0.0126957
+(0, 24) ~ (2, 19) => 0.136091
+(0, 24) ~ (2, 20) => 0.011321
+(0, 24) ~ (2, 21) => 0.016028
+(0, 24) ~ (2, 23) => 0.352329
+(0, 25) ~ (2, 19) => 0.0235385
+(0, 25) ~ (2, 20) => 0.161705
+(0, 25) ~ (2, 21) => 0.0109455
+(0, 25) ~ (2, 22) => 0.0677881
+(0, 25) ~ (2, 23) => 0.0134744
+(0, 25) ~ (2, 24) => 0.26465
+(0, 26) ~ (2, 20) => 0.0256202
+(0, 26) ~ (2, 21) => 0.0310658
+(0, 26) ~ (2, 23) => 0.535806
+(0, 26) ~ (2, 25) => 0.238174
+(0, 27) ~ (2, 21) => 0.015557
+(0, 27) ~ (2, 22) => 0.0146573
+(0, 27) ~ (2, 24) => 0.670523
+(0, 27) ~ (2, 26) => 0.208743
+(0, 28) ~ (2, 23) => 0.0142464
+(0, 28) ~ (2, 25) => 0.726461
+(0, 28) ~ (2, 27) => 0.11989
+(0, 29) ~ (2, 24) => 0.011089
+(0, 29) ~ (2, 26) => 0.7621
+(0, 29) ~ (2, 28) => 0.03191
+(0, 30) ~ (2, 27) => 0.862484
+(0, 31) ~ (2, 28) => 0.958084
+(0, 32) ~ (2, 29) => 0.993327
+(0, 33) ~ (2, 30) => 0.994226
+(0, 34) ~ (2, 31) => 0.995296
+(0, 35) ~ (2, 32) => 0.995921
+(0, 36) ~ (2, 33) => 0.997086
+(0, 37) ~ (2, 34) => 0.999681
+(0, 38) ~ (2, 35) => 0.999349
+(0, 39) ~ (2, 36) => 0.998953
+(0, 40) ~ (2, 37) => 0.99242
+(0, 41) ~ (2, 38) => 0.986219
+(0, 42) ~ (2, 38) => 0.0109901
+(0, 42) ~ (2, 39) => 0.980183
+(0, 43) ~ (2, 39) => 0.0159384
+(0, 43) ~ (2, 40) => 0.974269
+(0, 44) ~ (2, 40) => 0.0207285
+(0, 44) ~ (2, 41) => 0.958618
+(0, 45) ~ (2, 41) => 0.036216
+(0, 45) ~ (2, 42) => 0.889383
+(0, 46) ~ (2, 42) => 0.101968
+(0, 46) ~ (2, 43) => 0.853718
+(0, 47) ~ (2, 43) => 0.13459
+(0, 47) ~ (2, 44) => 0.745057
+(0, 48) ~ (2, 44) => 0.235842
+(0, 48) ~ (2, 45) => 0.635304
+(0, 49) ~ (2, 44) => 0.0134665
+(0, 49) ~ (2, 45) => 0.334652
+(0, 49) ~ (2, 46) => 0.534847
+(0, 50) ~ (2, 45) => 0.0204611
+(0, 50) ~ (2, 46) => 0.434325
+(0, 50) ~ (2, 47) => 0.243132
+(0, 51) ~ (2, 46) => 0.014603
+(0, 51) ~ (2, 47) => 0.735247
+(0, 51) ~ (2, 48) => 0.14021
+(0, 52) ~ (2, 48) => 0.844699
+(0, 52) ~ (2, 49) => 0.106662
+(0, 53) ~ (2, 49) => 0.878277
+(0, 53) ~ (2, 50) => 0.0729474
+(0, 54) ~ (2, 50) => 0.912487
+(0, 54) ~ (2, 51) => 0.0378245
+(0, 55) ~ (2, 51) => 0.94663
+(0, 55) ~ (2, 52) => 0.0359206
+(0, 56) ~ (2, 52) => 0.933448
+(0, 56) ~ (2, 53) => 0.0379663
+(0, 57) ~ (2, 53) => 0.928829
+(0, 57) ~ (2, 54) => 0.0401115
+(0, 58) ~ (2, 52) => 0.017165
+(0, 58) ~ (2, 54) => 0.921743
+(0, 58) ~ (2, 55) => 0.0130406
+(0, 59) ~ (2, 53) => 0.0224117
+(0, 59) ~ (2, 55) => 0.949528
+(0, 60) ~ (2, 54) => 0.0269787
+(0, 60) ~ (2, 56) => 0.959117
+(0, 61) ~ (2, 55) => 0.026664
+(0, 61) ~ (2, 57) => 0.965343
+(0, 62) ~ (2, 56) => 0.0256537
+(0, 62) ~ (2, 58) => 0.967762
+(0, 63) ~ (2, 57) => 0.0243379
+(0, 63) ~ (2, 59) => 0.967454
+(0, 64) ~ (2, 58) => 0.0225511
+(0, 64) ~ (2, 60) => 0.963716
+(0, 65) ~ (2, 59) => 0.0186428
+(0, 65) ~ (2, 61) => 0.958363
+(0, 66) ~ (2, 60) => 0.0177682
+(0, 66) ~ (2, 61) => 0.0123755
+(0, 66) ~ (2, 62) => 0.923611
+(0, 66) ~ (2, 63) => 0.0145654
+(0, 67) ~ (2, 61) => 0.0172152
+(0, 67) ~ (2, 62) => 0.0241255
+(0, 67) ~ (2, 63) => 0.827221
+(0, 67) ~ (2, 64) => 0.0740666
+(0, 67) ~ (2, 65) => 0.0141576
+(0, 68) ~ (2, 62) => 0.0182574
+(0, 68) ~ (2, 63) => 0.0337703
+(0, 68) ~ (2, 64) => 0.80243
+(0, 68) ~ (2, 65) => 0.0792221
+(0, 69) ~ (2, 63) => 0.0257667
+(0, 69) ~ (2, 64) => 0.0390069
+(0, 69) ~ (2, 65) => 0.784852
+(0, 69) ~ (2, 66) => 0.0832024
+(0, 70) ~ (2, 64) => 0.0346207
+(0, 70) ~ (2, 65) => 0.0348889
+(0, 70) ~ (2, 66) => 0.612149
+(0, 70) ~ (2, 67) => 0.0664532
+(0, 71) ~ (2, 65) => 0.0470558
+(0, 71) ~ (2, 66) => 0.0210357
+(0, 71) ~ (2, 67) => 0.440304
+(0, 71) ~ (2, 68) => 0.0594009
+(0, 72) ~ (2, 66) => 0.228487
+(0, 72) ~ (2, 67) => 0.0292197
+(0, 72) ~ (2, 68) => 0.262116
+(0, 72) ~ (2, 69) => 0.0244334
+(0, 73) ~ (2, 67) => 0.418465
+(0, 73) ~ (2, 68) => 0.0459949
+(0, 73) ~ (2, 69) => 0.0181661
+(0, 73) ~ (2, 70) => 0.0163759
+(0, 74) ~ (2, 68) => 0.593541
+(0, 74) ~ (2, 69) => 0.0329988
+(0, 75) ~ (2, 69) => 0.90526
+(0, 76) ~ (2, 70) => 0.959444
+(0, 77) ~ (2, 71) => 0.988058
+(0, 78) ~ (2, 72) => 0.992381
+(0, 79) ~ (2, 73) => 0.994517
+(0, 80) ~ (2, 74) => 0.986031
+(0, 81) ~ (2, 75) => 0.97584
+(0, 82) ~ (2, 76) => 0.968404
+(0, 83) ~ (2, 77) => 0.948204
+(0, 83) ~ (2, 78) => 0.0236257
+(0, 84) ~ (2, 78) => 0.889931
+(0, 84) ~ (2, 79) => 0.0723983
+(0, 85) ~ (2, 79) => 0.880713
+(0, 85) ~ (2, 80) => 0.0784834
+(0, 86) ~ (2, 80) => 0.848714
+(0, 86) ~ (2, 81) => 0.0889068
+(0, 87) ~ (2, 81) => 0.845122
+(0, 87) ~ (2, 82) => 0.0375461
+(0, 88) ~ (2, 82) => 0.891827
+(0, 88) ~ (2, 83) => 0.0349059
+(0, 89) ~ (2, 83) => 0.890069
+(0, 89) ~ (2, 84) => 0.0362772
+(0, 90) ~ (2, 84) => 0.86254
+(0, 90) ~ (2, 85) => 0.037994
+(0, 90) ~ (2, 89) => 0.0114329
+(0, 90) ~ (2, 96) => 0.0113355
+(0, 90) ~ (2, 102) => 0.0173901
+(0, 91) ~ (2, 85) => 0.766973
+(0, 91) ~ (2, 86) => 0.0504965
+(0, 91) ~ (2, 87) => 0.0135434
+(0, 91) ~ (2, 88) => 0.0102145
+(0, 91) ~ (2, 90) => 0.0219673
+(0, 91) ~ (2, 97) => 0.0454084
+(0, 91) ~ (2, 99) => 0.0121022
+(0, 91) ~ (2, 103) => 0.0195584
+(0, 92) ~ (2, 86) => 0.670179
+(0, 92) ~ (2, 87) => 0.0598819
+(0, 92) ~ (2, 88) => 0.0196568
+(0, 92) ~ (2, 89) => 0.0143779
+(0, 92) ~ (2, 91) => 0.0308706
+(0, 92) ~ (2, 97) => 0.0113944
+(0, 92) ~ (2, 98) => 0.0794772
+(0, 92) ~ (2, 100) => 0.017191
+(0, 92) ~ (2, 104) => 0.0216945
+(0, 93) ~ (2, 87) => 0.521868
+(0, 93) ~ (2, 88) => 0.0618575
+(0, 93) ~ (2, 89) => 0.0198052
+(0, 93) ~ (2, 90) => 0.0125906
+(0, 93) ~ (2, 92) => 0.109223
+(0, 93) ~ (2, 93) => 0.0108269
+(0, 93) ~ (2, 97) => 0.0173647
+(0, 93) ~ (2, 98) => 0.0153931
+(0, 93) ~ (2, 99) => 0.11493
+(0, 93) ~ (2, 101) => 0.0219698
+(0, 93) ~ (2, 105) => 0.0222753
+(0, 94) ~ (2, 87) => 0.0100653
+(0, 94) ~ (2, 88) => 0.375799
+(0, 94) ~ (2, 89) => 0.0594088
+(0, 94) ~ (2, 90) => 0.0151489
+(0, 94) ~ (2, 92) => 0.0105044
+(0, 94) ~ (2, 93) => 0.186994
+(0, 94) ~ (2, 94) => 0.0104094
+(0, 94) ~ (2, 98) => 0.0303462
+(0, 94) ~ (2, 99) => 0.0175566
+(0, 94) ~ (2, 100) => 0.151839
+(0, 94) ~ (2, 102) => 0.0263854
+(0, 94) ~ (2, 104) => 0.0104285
+(0, 94) ~ (2, 106) => 0.0225624
+(0, 95) ~ (2, 89) => 0.2161
+(0, 95) ~ (2, 90) => 0.0505557
+(0, 95) ~ (2, 92) => 0.01104
+(0, 95) ~ (2, 93) => 0.010377
+(0, 95) ~ (2, 94) => 0.262304
+(0, 95) ~ (2, 99) => 0.0400939
+(0, 95) ~ (2, 100) => 0.0155669
+(0, 95) ~ (2, 101) => 0.185858
+(0, 95) ~ (2, 103) => 0.0722747
+(0, 95) ~ (2, 104) => 0.0142828
+(0, 95) ~ (2, 107) => 0.0176944
+(0, 96) ~ (2, 90) => 0.0652454
+(0, 96) ~ (2, 91) => 0.0380874
+(0, 96) ~ (2, 93) => 0.010382
+(0, 96) ~ (2, 95) => 0.335616
+(0, 96) ~ (2, 100) => 0.047049
+(0, 96) ~ (2, 102) => 0.219643
+(0, 96) ~ (2, 104) => 0.117787
+(0, 96) ~ (2, 108) => 0.0112672
+(0, 97) ~ (2, 91) => 0.0158469
+(0, 97) ~ (2, 92) => 0.0312256
+(0, 97) ~ (2, 94) => 0.0126311
+(0, 97) ~ (2, 96) => 0.0817213
+(0, 97) ~ (2, 97) => 0.0169875
+(0, 97) ~ (2, 98) => 0.0146479
+(0, 97) ~ (2, 99) => 0.0182118
+(0, 97) ~ (2, 100) => 0.0141674
+(0, 97) ~ (2, 101) => 0.106773
+(0, 97) ~ (2, 103) => 0.172614
+(0, 97) ~ (2, 104) => 0.0171756
+(0, 97) ~ (2, 105) => 0.388809
+(0, 97) ~ (2, 106) => 0.0117474
+(0, 98) ~ (2, 93) => 0.0224562
+(0, 98) ~ (2, 95) => 0.0111021
+(0, 98) ~ (2, 97) => 0.0487443
+(0, 98) ~ (2, 98) => 0.01161
+(0, 98) ~ (2, 99) => 0.0107129
+(0, 98) ~ (2, 100) => 0.0139255
+(0, 98) ~ (2, 102) => 0.119014
+(0, 98) ~ (2, 104) => 0.116036
+(0, 98) ~ (2, 105) => 0.0158865
+(0, 98) ~ (2, 106) => 0.527116
+(0, 99) ~ (2, 94) => 0.0162243
+(0, 99) ~ (2, 98) => 0.0240906
+(0, 99) ~ (2, 103) => 0.0607398
+(0, 99) ~ (2, 105) => 0.0608477
+(0, 99) ~ (2, 106) => 0.0118267
+(0, 99) ~ (2, 107) => 0.745883
+(0, 100) ~ (2, 95) => 0.0101757
+(0, 100) ~ (2, 108) => 0.958018
+(0, 101) ~ (2, 109) => 0.978585
+(0, 102) ~ (2, 110) => 0.986513
+(0, 103) ~ (2, 111) => 0.986351
+(0, 104) ~ (2, 112) => 0.985981
+(0, 105) ~ (2, 113) => 0.991188
+(0, 106) ~ (2, 114) => 0.993165
+(0, 107) ~ (2, 115) => 0.993857
+(0, 108) ~ (2, 116) => 0.996177
+
+; gap posteriors
+(0, 0) ~ (2, -1) => 0.00750101
+(0, 1) ~ (2, -1) => 0.00767988
+(0, 2) ~ (2, -1) => 0.00567204
+(0, 3) ~ (2, -1) => 0.00165546
+(0, 4) ~ (2, -1) => 0.000762343
+(0, 5) ~ (2, -1) => 0.000523686
+(0, 6) ~ (2, -1) => 0.000807822
+(0, 7) ~ (2, -1) => 0.00135761
+(0, 8) ~ (2, -1) => 0.00369143
+(0, 9) ~ (2, -1) => 0.00353408
+(0, 10) ~ (2, -1) => 0.00243783
+(0, 11) ~ (2, -1) => 0.000798643
+(0, 12) ~ (2, -1) => 0.000902474
+(0, 13) ~ (2, -1) => 0.00106609
+(0, 14) ~ (2, -1) => 0.00307125
+(0, 15) ~ (2, -1) => 0.00897861
+(0, 16) ~ (2, -1) => 0.0184444
+(0, 17) ~ (2, -1) => 0.0596452
+(0, 18) ~ (2, -1) => 0.281143
+(0, 19) ~ (2, -1) => 0.733318
+(0, 20) ~ (2, -1) => 0.741087
+(0, 21) ~ (2, -1) => 0.445363
+(0, 22) ~ (2, -1) => 0.447377
+(0, 23) ~ (2, -1) => 0.350767
+(0, 24) ~ (2, -1) => 0.471535
+(0, 25) ~ (2, -1) => 0.457899
+(0, 26) ~ (2, -1) => 0.169334
+(0, 27) ~ (2, -1) => 0.0905196
+(0, 28) ~ (2, -1) => 0.139402
+(0, 29) ~ (2, -1) => 0.194901
+(0, 30) ~ (2, -1) => 0.137516
+(0, 31) ~ (2, -1) => 0.0419161
+(0, 32) ~ (2, -1) => 0.0066734
+(0, 33) ~ (2, -1) => 0.00577378
+(0, 34) ~ (2, -1) => 0.00470376
+(0, 35) ~ (2, -1) => 0.00407916
+(0, 36) ~ (2, -1) => 0.00291401
+(0, 37) ~ (2, -1) => 0.000319362
+(0, 38) ~ (2, -1) => 0.000650764
+(0, 39) ~ (2, -1) => 0.00104707
+(0, 40) ~ (2, -1) => 0.00757957
+(0, 41) ~ (2, -1) => 0.0137811
+(0, 42) ~ (2, -1) => 0.00882703
+(0, 43) ~ (2, -1) => 0.00979227
+(0, 44) ~ (2, -1) => 0.0206531
+(0, 45) ~ (2, -1) => 0.0744011
+(0, 46) ~ (2, -1) => 0.0443142
+(0, 47) ~ (2, -1) => 0.120352
+(0, 48) ~ (2, -1) => 0.128854
+(0, 49) ~ (2, -1) => 0.117034
+(0, 50) ~ (2, -1) => 0.302082
+(0, 51) ~ (2, -1) => 0.10994
+(0, 52) ~ (2, -1) => 0.0486389
+(0, 53) ~ (2, -1) => 0.0487757
+(0, 54) ~ (2, -1) => 0.0496887
+(0, 55) ~ (2, -1) => 0.0174489
+(0, 56) ~ (2, -1) => 0.0285855
+(0, 57) ~ (2, -1) => 0.0310597
+(0, 58) ~ (2, -1) => 0.0480516
+(0, 59) ~ (2, -1) => 0.0280604
+(0, 60) ~ (2, -1) => 0.0139043
+(0, 61) ~ (2, -1) => 0.00799346
+(0, 62) ~ (2, -1) => 0.00658476
+(0, 63) ~ (2, -1) => 0.00820857
+(0, 64) ~ (2, -1) => 0.0137333
+(0, 65) ~ (2, -1) => 0.0229944
+(0, 66) ~ (2, -1) => 0.0316797
+(0, 67) ~ (2, -1) => 0.0432139
+(0, 68) ~ (2, -1) => 0.0663205
+(0, 69) ~ (2, -1) => 0.0671719
+(0, 70) ~ (2, -1) => 0.251888
+(0, 71) ~ (2, -1) => 0.432204
+(0, 72) ~ (2, -1) => 0.455744
+(0, 73) ~ (2, -1) => 0.500998
+(0, 74) ~ (2, -1) => 0.37346
+(0, 75) ~ (2, -1) => 0.0947401
+(0, 76) ~ (2, -1) => 0.0405555
+(0, 77) ~ (2, -1) => 0.0119422
+(0, 78) ~ (2, -1) => 0.00761926
+(0, 79) ~ (2, -1) => 0.00548255
+(0, 80) ~ (2, -1) => 0.0139688
+(0, 81) ~ (2, -1) => 0.0241596
+(0, 82) ~ (2, -1) => 0.0315956
+(0, 83) ~ (2, -1) => 0.0281707
+(0, 84) ~ (2, -1) => 0.0376709
+(0, 85) ~ (2, -1) => 0.0408035
+(0, 86) ~ (2, -1) => 0.0623792
+(0, 87) ~ (2, -1) => 0.117332
+(0, 88) ~ (2, -1) => 0.0732673
+(0, 89) ~ (2, -1) => 0.0736542
+(0, 90) ~ (2, -1) => 0.0593072
+(0, 91) ~ (2, -1) => 0.0597363
+(0, 92) ~ (2, -1) => 0.0752767
+(0, 93) ~ (2, -1) => 0.0718957
+(0, 94) ~ (2, -1) => 0.0725517
+(0, 95) ~ (2, -1) => 0.103853
+(0, 96) ~ (2, -1) => 0.154923
+(0, 97) ~ (2, -1) => 0.0974416
+(0, 98) ~ (2, -1) => 0.103396
+(0, 99) ~ (2, -1) => 0.0803875
+(0, 100) ~ (2, -1) => 0.0318059
+(0, 101) ~ (2, -1) => 0.0214149
+(0, 102) ~ (2, -1) => 0.0134872
+(0, 103) ~ (2, -1) => 0.0136493
+(0, 104) ~ (2, -1) => 0.014019
+(0, 105) ~ (2, -1) => 0.00881171
+(0, 106) ~ (2, -1) => 0.0068351
+(0, 107) ~ (2, -1) => 0.00614262
+(0, 108) ~ (2, -1) => 0.00382251
+
+(0, -1) ~ (2, 0) => 0.86653
+(0, -1) ~ (2, 1) => 0.122701
+(0, -1) ~ (2, 2) => 0.0259492
+(0, -1) ~ (2, 3) => 0.00567204
+(0, -1) ~ (2, 4) => 0.00165546
+(0, -1) ~ (2, 5) => 0.000762343
+(0, -1) ~ (2, 6) => 0.000523686
+(0, -1) ~ (2, 7) => 0.000807822
+(0, -1) ~ (2, 8) => 0.00135761
+(0, -1) ~ (2, 9) => 0.00369143
+(0, -1) ~ (2, 10) => 0.00353408
+(0, -1) ~ (2, 11) => 0.00243783
+(0, -1) ~ (2, 12) => 0.000798643
+(0, -1) ~ (2, 13) => 0.000902474
+(0, -1) ~ (2, 14) => 0.00106609
+(0, -1) ~ (2, 15) => 0.00307125
+(0, -1) ~ (2, 16) => 0.00897861
+(0, -1) ~ (2, 17) => 0.0184444
+(0, -1) ~ (2, 18) => 0.0398891
+(0, -1) ~ (2, 19) => 0.0537728
+(0, -1) ~ (2, 20) => 0.0600455
+(0, -1) ~ (2, 21) => 0.182036
+(0, -1) ~ (2, 22) => 0.22306
+(0, -1) ~ (2, 23) => 0.0673764
+(0, -1) ~ (2, 24) => 0.0433901
+(0, -1) ~ (2, 25) => 0.0353646
+(0, -1) ~ (2, 26) => 0.0291569
+(0, -1) ~ (2, 27) => 0.0176267
+(0, -1) ~ (2, 28) => 0.0100061
+(0, -1) ~ (2, 29) => 0.0066734
+(0, -1) ~ (2, 30) => 0.00577378
+(0, -1) ~ (2, 31) => 0.00470376
+(0, -1) ~ (2, 32) => 0.00407916
+(0, -1) ~ (2, 33) => 0.00291401
+(0, -1) ~ (2, 34) => 0.000319362
+(0, -1) ~ (2, 35) => 0.000650764
+(0, -1) ~ (2, 36) => 0.00104707
+(0, -1) ~ (2, 37) => 0.00757957
+(0, -1) ~ (2, 38) => 0.00279102
+(0, -1) ~ (2, 39) => 0.00387865
+(0, -1) ~ (2, 40) => 0.00500218
+(0, -1) ~ (2, 41) => 0.00516551
+(0, -1) ~ (2, 42) => 0.00864945
+(0, -1) ~ (2, 43) => 0.0116915
+(0, -1) ~ (2, 44) => 0.00563445
+(0, -1) ~ (2, 45) => 0.0095823
+(0, -1) ~ (2, 46) => 0.0162249
+(0, -1) ~ (2, 47) => 0.021621
+(0, -1) ~ (2, 48) => 0.0150912
+(0, -1) ~ (2, 49) => 0.015061
+(0, -1) ~ (2, 50) => 0.0145659
+(0, -1) ~ (2, 51) => 0.015545
+(0, -1) ~ (2, 52) => 0.0134663
+(0, -1) ~ (2, 53) => 0.0107932
+(0, -1) ~ (2, 54) => 0.0111669
+(0, -1) ~ (2, 55) => 0.0107675
+(0, -1) ~ (2, 56) => 0.0152293
+(0, -1) ~ (2, 57) => 0.0103196
+(0, -1) ~ (2, 58) => 0.00968737
+(0, -1) ~ (2, 59) => 0.0139037
+(0, -1) ~ (2, 60) => 0.0185162
+(0, -1) ~ (2, 61) => 0.0120465
+(0, -1) ~ (2, 62) => 0.034006
+(0, -1) ~ (2, 63) => 0.0986763
+(0, -1) ~ (2, 64) => 0.0498759
+(0, -1) ~ (2, 65) => 0.0398235
+(0, -1) ~ (2, 66) => 0.0551264
+(0, -1) ~ (2, 67) => 0.0455586
+(0, -1) ~ (2, 68) => 0.0389465
+(0, -1) ~ (2, 69) => 0.0191418
+(0, -1) ~ (2, 70) => 0.0241796
+(0, -1) ~ (2, 71) => 0.0119422
+(0, -1) ~ (2, 72) => 0.00761926
+(0, -1) ~ (2, 73) => 0.00548255
+(0, -1) ~ (2, 74) => 0.0139688
+(0, -1) ~ (2, 75) => 0.0241596
+(0, -1) ~ (2, 76) => 0.0315956
+(0, -1) ~ (2, 77) => 0.0517964
+(0, -1) ~ (2, 78) => 0.0864435
+(0, -1) ~ (2, 79) => 0.0468885
+(0, -1) ~ (2, 80) => 0.0728027
+(0, -1) ~ (2, 81) => 0.0659714
+(0, -1) ~ (2, 82) => 0.0706271
+(0, -1) ~ (2, 83) => 0.0750254
+(0, -1) ~ (2, 84) => 0.101183
+(0, -1) ~ (2, 85) => 0.195033
+(0, -1) ~ (2, 86) => 0.279325
+(0, -1) ~ (2, 87) => 0.394641
+(0, -1) ~ (2, 88) => 0.532472
+(0, -1) ~ (2, 89) => 0.678875
+(0, -1) ~ (2, 90) => 0.834492
+(0, -1) ~ (2, 91) => 0.915195
+(0, -1) ~ (2, 92) => 0.838007
+(0, -1) ~ (2, 93) => 0.758964
+(0, -1) ~ (2, 94) => 0.698432
+(0, -1) ~ (2, 95) => 0.643107
+(0, -1) ~ (2, 96) => 0.906943
+(0, -1) ~ (2, 97) => 0.860101
+(0, -1) ~ (2, 98) => 0.824435
+(0, -1) ~ (2, 99) => 0.786393
+(0, -1) ~ (2, 100) => 0.740261
+(0, -1) ~ (2, 101) => 0.6854
+(0, -1) ~ (2, 102) => 0.617567
+(0, -1) ~ (2, 103) => 0.674813
+(0, -1) ~ (2, 104) => 0.702595
+(0, -1) ~ (2, 105) => 0.512181
+(0, -1) ~ (2, 106) => 0.426748
+(0, -1) ~ (2, 107) => 0.236422
+(0, -1) ~ (2, 108) => 0.0307145
+(0, -1) ~ (2, 109) => 0.0214149
+(0, -1) ~ (2, 110) => 0.0134872
+(0, -1) ~ (2, 111) => 0.0136493
+(0, -1) ~ (2, 112) => 0.014019
+(0, -1) ~ (2, 113) => 0.00881171
+(0, -1) ~ (2, 114) => 0.0068351
+(0, -1) ~ (2, 115) => 0.00614262
+(0, -1) ~ (2, 116) => 0.00382251
+
+; Sparse posterior probability matrix for sequences 0 and 3
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (3, 0) => 0.991867
+(0, 1) ~ (3, 1) => 0.974115
+(0, 2) ~ (3, 2) => 0.961081
+(0, 3) ~ (3, 1) => 0.014365
+(0, 3) ~ (3, 3) => 0.945116
+(0, 4) ~ (3, 2) => 0.024977
+(0, 4) ~ (3, 4) => 0.921852
+(0, 5) ~ (3, 3) => 0.0349324
+(0, 5) ~ (3, 5) => 0.908765
+(0, 6) ~ (3, 4) => 0.0443889
+(0, 6) ~ (3, 6) => 0.898018
+(0, 7) ~ (3, 5) => 0.0482922
+(0, 7) ~ (3, 7) => 0.872846
+(0, 8) ~ (3, 6) => 0.0540385
+(0, 8) ~ (3, 8) => 0.857428
+(0, 9) ~ (3, 7) => 0.0699503
+(0, 9) ~ (3, 9) => 0.841362
+(0, 10) ~ (3, 8) => 0.0834428
+(0, 10) ~ (3, 10) => 0.831451
+(0, 11) ~ (3, 9) => 0.0969963
+(0, 11) ~ (3, 11) => 0.816566
+(0, 11) ~ (3, 14) => 0.0124248
+(0, 12) ~ (3, 10) => 0.109624
+(0, 12) ~ (3, 12) => 0.804971
+(0, 12) ~ (3, 13) => 0.0102351
+(0, 12) ~ (3, 15) => 0.0121488
+(0, 13) ~ (3, 11) => 0.119702
+(0, 13) ~ (3, 13) => 0.795845
+(0, 13) ~ (3, 14) => 0.011362
+(0, 13) ~ (3, 16) => 0.0116506
+(0, 14) ~ (3, 12) => 0.130479
+(0, 14) ~ (3, 14) => 0.786263
+(0, 15) ~ (3, 13) => 0.143877
+(0, 15) ~ (3, 15) => 0.788794
+(0, 16) ~ (3, 14) => 0.161463
+(0, 16) ~ (3, 16) => 0.792121
+(0, 17) ~ (3, 15) => 0.165109
+(0, 17) ~ (3, 17) => 0.766247
+(0, 17) ~ (3, 18) => 0.0113069
+(0, 18) ~ (3, 16) => 0.164137
+(0, 18) ~ (3, 18) => 0.714271
+(0, 18) ~ (3, 19) => 0.0151941
+(0, 19) ~ (3, 17) => 0.185587
+(0, 19) ~ (3, 18) => 0.0146845
+(0, 19) ~ (3, 19) => 0.592247
+(0, 19) ~ (3, 20) => 0.0116545
+(0, 20) ~ (3, 18) => 0.231775
+(0, 20) ~ (3, 19) => 0.0257255
+(0, 20) ~ (3, 20) => 0.324196
+(0, 21) ~ (3, 19) => 0.339297
+(0, 21) ~ (3, 20) => 0.0301383
+(0, 21) ~ (3, 21) => 0.0666182
+(0, 22) ~ (3, 20) => 0.60957
+(0, 22) ~ (3, 21) => 0.0104292
+(0, 22) ~ (3, 22) => 0.0192422
+(0, 23) ~ (3, 21) => 0.902166
+(0, 24) ~ (3, 22) => 0.95988
+(0, 25) ~ (3, 23) => 0.984829
+(0, 26) ~ (3, 24) => 0.987869
+(0, 27) ~ (3, 25) => 0.988073
+(0, 28) ~ (3, 26) => 0.989046
+(0, 29) ~ (3, 27) => 0.991758
+(0, 30) ~ (3, 28) => 0.99358
+(0, 31) ~ (3, 29) => 0.997051
+(0, 32) ~ (3, 30) => 0.999062
+(0, 33) ~ (3, 31) => 0.999254
+(0, 34) ~ (3, 32) => 0.999402
+(0, 35) ~ (3, 33) => 0.9996
+(0, 36) ~ (3, 34) => 0.999838
+(0, 37) ~ (3, 35) => 0.999856
+(0, 38) ~ (3, 36) => 0.999821
+(0, 39) ~ (3, 37) => 0.999812
+(0, 40) ~ (3, 38) => 0.999612
+(0, 41) ~ (3, 39) => 0.999465
+(0, 42) ~ (3, 40) => 0.999461
+(0, 43) ~ (3, 41) => 0.999602
+(0, 44) ~ (3, 42) => 0.99985
+(0, 45) ~ (3, 43) => 0.999937
+(0, 46) ~ (3, 44) => 0.999857
+(0, 47) ~ (3, 45) => 0.999718
+(0, 48) ~ (3, 46) => 0.999626
+(0, 49) ~ (3, 47) => 0.999585
+(0, 50) ~ (3, 48) => 0.999493
+(0, 51) ~ (3, 49) => 0.998941
+(0, 52) ~ (3, 50) => 0.998031
+(0, 53) ~ (3, 51) => 0.99748
+(0, 54) ~ (3, 52) => 0.996233
+(0, 55) ~ (3, 53) => 0.9949
+(0, 56) ~ (3, 54) => 0.989551
+(0, 57) ~ (3, 55) => 0.955213
+(0, 57) ~ (3, 57) => 0.0136794
+(0, 58) ~ (3, 56) => 0.907935
+(0, 58) ~ (3, 58) => 0.0253974
+(0, 59) ~ (3, 57) => 0.727875
+(0, 59) ~ (3, 59) => 0.0331362
+(0, 60) ~ (3, 57) => 0.0146408
+(0, 60) ~ (3, 58) => 0.485344
+(0, 60) ~ (3, 59) => 0.0120704
+(0, 60) ~ (3, 60) => 0.0337401
+(0, 60) ~ (3, 69) => 0.0158254
+(0, 61) ~ (3, 56) => 0.0171183
+(0, 61) ~ (3, 58) => 0.0220779
+(0, 61) ~ (3, 59) => 0.350409
+(0, 61) ~ (3, 61) => 0.0259184
+(0, 61) ~ (3, 70) => 0.0250855
+(0, 62) ~ (3, 57) => 0.0420222
+(0, 62) ~ (3, 59) => 0.0193769
+(0, 62) ~ (3, 60) => 0.284863
+(0, 62) ~ (3, 62) => 0.0134591
+(0, 62) ~ (3, 71) => 0.027765
+(0, 63) ~ (3, 57) => 0.0238364
+(0, 63) ~ (3, 58) => 0.0631463
+(0, 63) ~ (3, 61) => 0.217285
+(0, 63) ~ (3, 72) => 0.0362992
+(0, 64) ~ (3, 56) => 0.0152465
+(0, 64) ~ (3, 58) => 0.0927079
+(0, 64) ~ (3, 59) => 0.0668901
+(0, 64) ~ (3, 62) => 0.139885
+(0, 64) ~ (3, 73) => 0.0411432
+(0, 64) ~ (3, 75) => 0.0113381
+(0, 65) ~ (3, 57) => 0.104605
+(0, 65) ~ (3, 59) => 0.171434
+(0, 65) ~ (3, 60) => 0.0560972
+(0, 65) ~ (3, 63) => 0.115796
+(0, 65) ~ (3, 74) => 0.0416983
+(0, 65) ~ (3, 76) => 0.0169663
+(0, 66) ~ (3, 58) => 0.194882
+(0, 66) ~ (3, 60) => 0.2015
+(0, 66) ~ (3, 61) => 0.0430429
+(0, 66) ~ (3, 64) => 0.0497717
+(0, 66) ~ (3, 75) => 0.044634
+(0, 66) ~ (3, 77) => 0.0208961
+(0, 67) ~ (3, 59) => 0.235583
+(0, 67) ~ (3, 61) => 0.293474
+(0, 67) ~ (3, 62) => 0.0261363
+(0, 67) ~ (3, 65) => 0.0381385
+(0, 67) ~ (3, 76) => 0.0404211
+(0, 67) ~ (3, 78) => 0.0342904
+(0, 68) ~ (3, 60) => 0.303049
+(0, 68) ~ (3, 62) => 0.373825
+(0, 68) ~ (3, 63) => 0.027698
+(0, 68) ~ (3, 64) => 0.0133455
+(0, 68) ~ (3, 66) => 0.0221875
+(0, 68) ~ (3, 74) => 0.010068
+(0, 68) ~ (3, 77) => 0.0411259
+(0, 68) ~ (3, 79) => 0.0399721
+(0, 69) ~ (3, 61) => 0.312766
+(0, 69) ~ (3, 63) => 0.385471
+(0, 69) ~ (3, 64) => 0.031448
+(0, 69) ~ (3, 65) => 0.0114137
+(0, 69) ~ (3, 78) => 0.0244809
+(0, 69) ~ (3, 80) => 0.0719196
+(0, 70) ~ (3, 62) => 0.312942
+(0, 70) ~ (3, 64) => 0.42824
+(0, 70) ~ (3, 65) => 0.0428359
+(0, 70) ~ (3, 81) => 0.0954376
+(0, 71) ~ (3, 63) => 0.261022
+(0, 71) ~ (3, 65) => 0.405952
+(0, 71) ~ (3, 66) => 0.141716
+(0, 71) ~ (3, 82) => 0.09836
+(0, 72) ~ (3, 64) => 0.215664
+(0, 72) ~ (3, 66) => 0.315336
+(0, 72) ~ (3, 67) => 0.315479
+(0, 72) ~ (3, 83) => 0.0997662
+(0, 73) ~ (3, 65) => 0.157186
+(0, 73) ~ (3, 67) => 0.296916
+(0, 73) ~ (3, 68) => 0.392722
+(0, 73) ~ (3, 84) => 0.0987119
+(0, 74) ~ (3, 66) => 0.0480228
+(0, 74) ~ (3, 68) => 0.292354
+(0, 74) ~ (3, 69) => 0.503763
+(0, 74) ~ (3, 85) => 0.0971298
+(0, 75) ~ (3, 67) => 0.0215303
+(0, 75) ~ (3, 69) => 0.271876
+(0, 75) ~ (3, 70) => 0.539216
+(0, 75) ~ (3, 72) => 0.0134451
+(0, 75) ~ (3, 86) => 0.0891791
+(0, 75) ~ (3, 91) => 0.0105919
+(0, 76) ~ (3, 68) => 0.019059
+(0, 76) ~ (3, 70) => 0.243047
+(0, 76) ~ (3, 71) => 0.556662
+(0, 76) ~ (3, 73) => 0.0163024
+(0, 76) ~ (3, 87) => 0.056616
+(0, 76) ~ (3, 92) => 0.0368875
+(0, 77) ~ (3, 69) => 0.0173785
+(0, 77) ~ (3, 71) => 0.222453
+(0, 77) ~ (3, 72) => 0.558701
+(0, 77) ~ (3, 73) => 0.0102431
+(0, 77) ~ (3, 74) => 0.0218837
+(0, 77) ~ (3, 88) => 0.0181105
+(0, 77) ~ (3, 93) => 0.0634052
+(0, 78) ~ (3, 70) => 0.0178464
+(0, 78) ~ (3, 72) => 0.217009
+(0, 78) ~ (3, 73) => 0.563099
+(0, 78) ~ (3, 75) => 0.0244981
+(0, 78) ~ (3, 89) => 0.0102946
+(0, 78) ~ (3, 94) => 0.066627
+(0, 78) ~ (3, 105) => 0.0101852
+(0, 79) ~ (3, 71) => 0.0123995
+(0, 79) ~ (3, 73) => 0.182787
+(0, 79) ~ (3, 74) => 0.599869
+(0, 79) ~ (3, 76) => 0.0226281
+(0, 79) ~ (3, 81) => 0.0106908
+(0, 79) ~ (3, 95) => 0.0650684
+(0, 79) ~ (3, 106) => 0.0155031
+(0, 80) ~ (3, 72) => 0.0112811
+(0, 80) ~ (3, 74) => 0.087327
+(0, 80) ~ (3, 75) => 0.684033
+(0, 80) ~ (3, 76) => 0.0113438
+(0, 80) ~ (3, 77) => 0.0148334
+(0, 80) ~ (3, 82) => 0.0148941
+(0, 80) ~ (3, 96) => 0.0573306
+(0, 80) ~ (3, 107) => 0.0274085
+(0, 81) ~ (3, 74) => 0.0144068
+(0, 81) ~ (3, 75) => 0.0201001
+(0, 81) ~ (3, 76) => 0.751018
+(0, 81) ~ (3, 77) => 0.0171833
+(0, 81) ~ (3, 83) => 0.0168698
+(0, 81) ~ (3, 97) => 0.0547837
+(0, 81) ~ (3, 108) => 0.0340277
+(0, 82) ~ (3, 75) => 0.0103497
+(0, 82) ~ (3, 76) => 0.0115249
+(0, 82) ~ (3, 77) => 0.77672
+(0, 82) ~ (3, 78) => 0.0103467
+(0, 82) ~ (3, 84) => 0.0166738
+(0, 82) ~ (3, 98) => 0.0535908
+(0, 82) ~ (3, 109) => 0.0352399
+(0, 83) ~ (3, 78) => 0.811445
+(0, 83) ~ (3, 85) => 0.0156155
+(0, 83) ~ (3, 99) => 0.0532808
+(0, 83) ~ (3, 110) => 0.0358514
+(0, 84) ~ (3, 79) => 0.822349
+(0, 84) ~ (3, 86) => 0.0128328
+(0, 84) ~ (3, 100) => 0.0516994
+(0, 84) ~ (3, 111) => 0.0360597
+(0, 85) ~ (3, 80) => 0.840365
+(0, 85) ~ (3, 101) => 0.0511545
+(0, 85) ~ (3, 112) => 0.0357699
+(0, 86) ~ (3, 81) => 0.848328
+(0, 86) ~ (3, 102) => 0.0509413
+(0, 86) ~ (3, 113) => 0.0357834
+(0, 87) ~ (3, 82) => 0.845725
+(0, 87) ~ (3, 103) => 0.0532815
+(0, 87) ~ (3, 114) => 0.0358498
+(0, 88) ~ (3, 83) => 0.839716
+(0, 88) ~ (3, 104) => 0.0584378
+(0, 88) ~ (3, 115) => 0.0360585
+(0, 89) ~ (3, 84) => 0.7526
+(0, 89) ~ (3, 85) => 0.0599529
+(0, 89) ~ (3, 86) => 0.0296563
+(0, 89) ~ (3, 105) => 0.059679
+(0, 89) ~ (3, 116) => 0.0349406
+(0, 90) ~ (3, 85) => 0.728871
+(0, 90) ~ (3, 86) => 0.0708182
+(0, 90) ~ (3, 87) => 0.034256
+(0, 90) ~ (3, 106) => 0.0622201
+(0, 90) ~ (3, 117) => 0.0326939
+(0, 91) ~ (3, 86) => 0.668594
+(0, 91) ~ (3, 87) => 0.0784444
+(0, 91) ~ (3, 88) => 0.0558643
+(0, 91) ~ (3, 100) => 0.0101903
+(0, 91) ~ (3, 107) => 0.0632142
+(0, 91) ~ (3, 118) => 0.0252447
+(0, 92) ~ (3, 87) => 0.629973
+(0, 92) ~ (3, 88) => 0.0795967
+(0, 92) ~ (3, 89) => 0.0669656
+(0, 92) ~ (3, 90) => 0.0101919
+(0, 92) ~ (3, 100) => 0.0144457
+(0, 92) ~ (3, 108) => 0.0630319
+(0, 92) ~ (3, 119) => 0.0183905
+(0, 93) ~ (3, 88) => 0.583995
+(0, 93) ~ (3, 89) => 0.0787383
+(0, 93) ~ (3, 90) => 0.0769678
+(0, 93) ~ (3, 91) => 0.0115219
+(0, 93) ~ (3, 94) => 0.011943
+(0, 93) ~ (3, 101) => 0.0197777
+(0, 93) ~ (3, 105) => 0.0200286
+(0, 93) ~ (3, 109) => 0.065146
+(0, 93) ~ (3, 110) => 0.0101183
+(0, 93) ~ (3, 120) => 0.0127699
+(0, 94) ~ (3, 89) => 0.531055
+(0, 94) ~ (3, 90) => 0.0753495
+(0, 94) ~ (3, 91) => 0.085714
+(0, 94) ~ (3, 92) => 0.011579
+(0, 94) ~ (3, 95) => 0.0215582
+(0, 94) ~ (3, 102) => 0.024578
+(0, 94) ~ (3, 106) => 0.030443
+(0, 94) ~ (3, 107) => 0.0115912
+(0, 94) ~ (3, 110) => 0.0659741
+(0, 94) ~ (3, 111) => 0.0132391
+(0, 95) ~ (3, 88) => 0.0102005
+(0, 95) ~ (3, 90) => 0.442012
+(0, 95) ~ (3, 91) => 0.0663616
+(0, 95) ~ (3, 92) => 0.0907712
+(0, 95) ~ (3, 94) => 0.011365
+(0, 95) ~ (3, 96) => 0.0501476
+(0, 95) ~ (3, 103) => 0.0281384
+(0, 95) ~ (3, 105) => 0.0107482
+(0, 95) ~ (3, 107) => 0.0484393
+(0, 95) ~ (3, 108) => 0.0151439
+(0, 95) ~ (3, 111) => 0.0685351
+(0, 95) ~ (3, 112) => 0.01832
+(0, 96) ~ (3, 89) => 0.0111218
+(0, 96) ~ (3, 91) => 0.28779
+(0, 96) ~ (3, 92) => 0.0413488
+(0, 96) ~ (3, 93) => 0.0870736
+(0, 96) ~ (3, 95) => 0.0147642
+(0, 96) ~ (3, 96) => 0.0108115
+(0, 96) ~ (3, 97) => 0.132779
+(0, 96) ~ (3, 98) => 0.0127242
+(0, 96) ~ (3, 104) => 0.0392315
+(0, 96) ~ (3, 106) => 0.0117491
+(0, 96) ~ (3, 108) => 0.0648507
+(0, 96) ~ (3, 109) => 0.0237535
+(0, 96) ~ (3, 112) => 0.0743493
+(0, 96) ~ (3, 113) => 0.032238
+(0, 96) ~ (3, 115) => 0.0101208
+(0, 97) ~ (3, 90) => 0.0254378
+(0, 97) ~ (3, 92) => 0.25068
+(0, 97) ~ (3, 93) => 0.0376745
+(0, 97) ~ (3, 94) => 0.0619782
+(0, 97) ~ (3, 98) => 0.1498
+(0, 97) ~ (3, 99) => 0.0100059
+(0, 97) ~ (3, 105) => 0.0468964
+(0, 97) ~ (3, 107) => 0.0130706
+(0, 97) ~ (3, 109) => 0.0772233
+(0, 97) ~ (3, 110) => 0.0446944
+(0, 97) ~ (3, 113) => 0.0717253
+(0, 97) ~ (3, 114) => 0.0361129
+(0, 97) ~ (3, 116) => 0.0149417
+(0, 98) ~ (3, 91) => 0.0378831
+(0, 98) ~ (3, 93) => 0.184411
+(0, 98) ~ (3, 94) => 0.0403483
+(0, 98) ~ (3, 95) => 0.0377974
+(0, 98) ~ (3, 99) => 0.191259
+(0, 98) ~ (3, 106) => 0.0494657
+(0, 98) ~ (3, 108) => 0.0113081
+(0, 98) ~ (3, 110) => 0.0838197
+(0, 98) ~ (3, 111) => 0.0728766
+(0, 98) ~ (3, 114) => 0.0736242
+(0, 98) ~ (3, 115) => 0.0407857
+(0, 98) ~ (3, 116) => 0.0141635
+(0, 98) ~ (3, 117) => 0.0207971
+(0, 99) ~ (3, 92) => 0.0467466
+(0, 99) ~ (3, 94) => 0.162349
+(0, 99) ~ (3, 95) => 0.0326715
+(0, 99) ~ (3, 96) => 0.0294381
+(0, 99) ~ (3, 97) => 0.010125
+(0, 99) ~ (3, 100) => 0.196725
+(0, 99) ~ (3, 107) => 0.0417373
+(0, 99) ~ (3, 109) => 0.016544
+(0, 99) ~ (3, 111) => 0.0776338
+(0, 99) ~ (3, 112) => 0.0808213
+(0, 99) ~ (3, 115) => 0.0625637
+(0, 99) ~ (3, 116) => 0.0728052
+(0, 99) ~ (3, 117) => 0.0153595
+(0, 99) ~ (3, 118) => 0.020623
+(0, 100) ~ (3, 93) => 0.0522395
+(0, 100) ~ (3, 95) => 0.14318
+(0, 100) ~ (3, 96) => 0.0294341
+(0, 100) ~ (3, 97) => 0.0258355
+(0, 100) ~ (3, 98) => 0.0137276
+(0, 100) ~ (3, 101) => 0.192967
+(0, 100) ~ (3, 108) => 0.0233295
+(0, 100) ~ (3, 110) => 0.0184516
+(0, 100) ~ (3, 112) => 0.0706635
+(0, 100) ~ (3, 113) => 0.100264
+(0, 100) ~ (3, 115) => 0.0100613
+(0, 100) ~ (3, 116) => 0.0562208
+(0, 100) ~ (3, 117) => 0.109408
+(0, 100) ~ (3, 118) => 0.0142399
+(0, 100) ~ (3, 119) => 0.0199222
+(0, 101) ~ (3, 94) => 0.0502431
+(0, 101) ~ (3, 96) => 0.0865531
+(0, 101) ~ (3, 97) => 0.0151774
+(0, 101) ~ (3, 98) => 0.0104691
+(0, 101) ~ (3, 99) => 0.0138871
+(0, 101) ~ (3, 102) => 0.223103
+(0, 101) ~ (3, 106) => 0.0122098
+(0, 101) ~ (3, 111) => 0.0248912
+(0, 101) ~ (3, 113) => 0.0435809
+(0, 101) ~ (3, 114) => 0.105325
+(0, 101) ~ (3, 116) => 0.0138169
+(0, 101) ~ (3, 117) => 0.0533272
+(0, 101) ~ (3, 118) => 0.197682
+(0, 101) ~ (3, 119) => 0.0174761
+(0, 101) ~ (3, 120) => 0.0208059
+(0, 102) ~ (3, 95) => 0.0382806
+(0, 102) ~ (3, 97) => 0.0577083
+(0, 102) ~ (3, 103) => 0.266776
+(0, 102) ~ (3, 107) => 0.0127087
+(0, 102) ~ (3, 112) => 0.0227507
+(0, 102) ~ (3, 114) => 0.0359802
+(0, 102) ~ (3, 115) => 0.0927652
+(0, 102) ~ (3, 117) => 0.0105106
+(0, 102) ~ (3, 118) => 0.0358772
+(0, 102) ~ (3, 119) => 0.22904
+(0, 102) ~ (3, 120) => 0.040913
+(0, 102) ~ (3, 121) => 0.0362747
+(0, 103) ~ (3, 96) => 0.0317339
+(0, 103) ~ (3, 98) => 0.0418883
+(0, 103) ~ (3, 104) => 0.268866
+(0, 103) ~ (3, 108) => 0.0220587
+(0, 103) ~ (3, 113) => 0.0213385
+(0, 103) ~ (3, 115) => 0.0468599
+(0, 103) ~ (3, 116) => 0.0642117
+(0, 103) ~ (3, 118) => 0.0239171
+(0, 103) ~ (3, 119) => 0.045325
+(0, 103) ~ (3, 120) => 0.221968
+(0, 103) ~ (3, 121) => 0.0432267
+(0, 103) ~ (3, 122) => 0.0351748
+(0, 104) ~ (3, 97) => 0.0243852
+(0, 104) ~ (3, 99) => 0.0245661
+(0, 104) ~ (3, 105) => 0.234761
+(0, 104) ~ (3, 109) => 0.0211158
+(0, 104) ~ (3, 114) => 0.0181447
+(0, 104) ~ (3, 116) => 0.0436209
+(0, 104) ~ (3, 117) => 0.0590502
+(0, 104) ~ (3, 119) => 0.0847257
+(0, 104) ~ (3, 120) => 0.0343696
+(0, 104) ~ (3, 121) => 0.143275
+(0, 104) ~ (3, 122) => 0.0176062
+(0, 104) ~ (3, 123) => 0.0299903
+(0, 105) ~ (3, 98) => 0.0206177
+(0, 105) ~ (3, 106) => 0.164928
+(0, 105) ~ (3, 110) => 0.0129426
+(0, 105) ~ (3, 111) => 0.011612
+(0, 105) ~ (3, 112) => 0.0172103
+(0, 105) ~ (3, 113) => 0.0189059
+(0, 105) ~ (3, 115) => 0.0129021
+(0, 105) ~ (3, 117) => 0.0353416
+(0, 105) ~ (3, 118) => 0.0512569
+(0, 105) ~ (3, 119) => 0.0126678
+(0, 105) ~ (3, 120) => 0.211911
+(0, 105) ~ (3, 121) => 0.0210921
+(0, 105) ~ (3, 122) => 0.048548
+(0, 105) ~ (3, 123) => 0.0121027
+(0, 106) ~ (3, 107) => 0.124204
+(0, 106) ~ (3, 112) => 0.0138327
+(0, 106) ~ (3, 113) => 0.0152609
+(0, 106) ~ (3, 114) => 0.0181298
+(0, 106) ~ (3, 118) => 0.0305098
+(0, 106) ~ (3, 119) => 0.0468182
+(0, 106) ~ (3, 120) => 0.0163132
+(0, 106) ~ (3, 121) => 0.396034
+(0, 106) ~ (3, 123) => 0.0317564
+(0, 107) ~ (3, 108) => 0.111968
+(0, 107) ~ (3, 115) => 0.0187075
+(0, 107) ~ (3, 119) => 0.0276148
+(0, 107) ~ (3, 120) => 0.0417804
+(0, 107) ~ (3, 121) => 0.0204929
+(0, 107) ~ (3, 122) => 0.621408
+(0, 108) ~ (3, 109) => 0.0952417
+(0, 108) ~ (3, 116) => 0.0159129
+(0, 108) ~ (3, 120) => 0.0217687
+(0, 108) ~ (3, 121) => 0.0332801
+(0, 108) ~ (3, 122) => 0.0177422
+(0, 108) ~ (3, 123) => 0.69857
+
+; gap posteriors
+(0, 0) ~ (3, -1) => 0.00813264
+(0, 1) ~ (3, -1) => 0.0258849
+(0, 2) ~ (3, -1) => 0.0389194
+(0, 3) ~ (3, -1) => 0.0405192
+(0, 4) ~ (3, -1) => 0.0531709
+(0, 5) ~ (3, -1) => 0.0563022
+(0, 6) ~ (3, -1) => 0.0575928
+(0, 7) ~ (3, -1) => 0.0788615
+(0, 8) ~ (3, -1) => 0.0885333
+(0, 9) ~ (3, -1) => 0.088688
+(0, 10) ~ (3, -1) => 0.0851059
+(0, 11) ~ (3, -1) => 0.0740128
+(0, 12) ~ (3, -1) => 0.0630217
+(0, 13) ~ (3, -1) => 0.0614411
+(0, 14) ~ (3, -1) => 0.0832577
+(0, 15) ~ (3, -1) => 0.0673295
+(0, 16) ~ (3, -1) => 0.0464157
+(0, 17) ~ (3, -1) => 0.0573365
+(0, 18) ~ (3, -1) => 0.106397
+(0, 19) ~ (3, -1) => 0.195827
+(0, 20) ~ (3, -1) => 0.418303
+(0, 21) ~ (3, -1) => 0.563946
+(0, 22) ~ (3, -1) => 0.360759
+(0, 23) ~ (3, -1) => 0.0978343
+(0, 24) ~ (3, -1) => 0.0401203
+(0, 25) ~ (3, -1) => 0.0151714
+(0, 26) ~ (3, -1) => 0.0121314
+(0, 27) ~ (3, -1) => 0.0119274
+(0, 28) ~ (3, -1) => 0.0109543
+(0, 29) ~ (3, -1) => 0.00824177
+(0, 30) ~ (3, -1) => 0.00641978
+(0, 31) ~ (3, -1) => 0.0029487
+(0, 32) ~ (3, -1) => 0.000938058
+(0, 33) ~ (3, -1) => 0.000746369
+(0, 34) ~ (3, -1) => 0.000598431
+(0, 35) ~ (3, -1) => 0.000399947
+(0, 36) ~ (3, -1) => 0.000161827
+(0, 37) ~ (3, -1) => 0.000144482
+(0, 38) ~ (3, -1) => 0.000179291
+(0, 39) ~ (3, -1) => 0.000188351
+(0, 40) ~ (3, -1) => 0.000388086
+(0, 41) ~ (3, -1) => 0.000535131
+(0, 42) ~ (3, -1) => 0.000538945
+(0, 43) ~ (3, -1) => 0.000398278
+(0, 44) ~ (3, -1) => 0.000149846
+(0, 45) ~ (3, -1) => 0.0001
+(0, 46) ~ (3, -1) => 0.000142753
+(0, 47) ~ (3, -1) => 0.000281751
+(0, 48) ~ (3, -1) => 0.000373542
+(0, 49) ~ (3, -1) => 0.000415087
+(0, 50) ~ (3, -1) => 0.000506997
+(0, 51) ~ (3, -1) => 0.00105882
+(0, 52) ~ (3, -1) => 0.0019685
+(0, 53) ~ (3, -1) => 0.00251979
+(0, 54) ~ (3, -1) => 0.00376737
+(0, 55) ~ (3, -1) => 0.00510007
+(0, 56) ~ (3, -1) => 0.0104493
+(0, 57) ~ (3, -1) => 0.031108
+(0, 58) ~ (3, -1) => 0.0666679
+(0, 59) ~ (3, -1) => 0.238989
+(0, 60) ~ (3, -1) => 0.438379
+(0, 61) ~ (3, -1) => 0.559391
+(0, 62) ~ (3, -1) => 0.612514
+(0, 63) ~ (3, -1) => 0.659433
+(0, 64) ~ (3, -1) => 0.632789
+(0, 65) ~ (3, -1) => 0.493403
+(0, 66) ~ (3, -1) => 0.445273
+(0, 67) ~ (3, -1) => 0.331957
+(0, 68) ~ (3, -1) => 0.168729
+(0, 69) ~ (3, -1) => 0.162501
+(0, 70) ~ (3, -1) => 0.120545
+(0, 71) ~ (3, -1) => 0.0929495
+(0, 72) ~ (3, -1) => 0.0537543
+(0, 73) ~ (3, -1) => 0.0544643
+(0, 74) ~ (3, -1) => 0.0587308
+(0, 75) ~ (3, -1) => 0.0541616
+(0, 76) ~ (3, -1) => 0.0714257
+(0, 77) ~ (3, -1) => 0.0878251
+(0, 78) ~ (3, -1) => 0.0904407
+(0, 79) ~ (3, -1) => 0.0910551
+(0, 80) ~ (3, -1) => 0.0915482
+(0, 81) ~ (3, -1) => 0.0916103
+(0, 82) ~ (3, -1) => 0.085554
+(0, 83) ~ (3, -1) => 0.0838077
+(0, 84) ~ (3, -1) => 0.0770595
+(0, 85) ~ (3, -1) => 0.0727105
+(0, 86) ~ (3, -1) => 0.0649474
+(0, 87) ~ (3, -1) => 0.0651438
+(0, 88) ~ (3, -1) => 0.0657876
+(0, 89) ~ (3, -1) => 0.0631709
+(0, 90) ~ (3, -1) => 0.0711407
+(0, 91) ~ (3, -1) => 0.0984477
+(0, 92) ~ (3, -1) => 0.117405
+(0, 93) ~ (3, -1) => 0.108994
+(0, 94) ~ (3, -1) => 0.128919
+(0, 95) ~ (3, -1) => 0.139817
+(0, 96) ~ (3, -1) => 0.145293
+(0, 97) ~ (3, -1) => 0.159759
+(0, 98) ~ (3, -1) => 0.141462
+(0, 99) ~ (3, -1) => 0.133857
+(0, 100) ~ (3, -1) => 0.120057
+(0, 101) ~ (3, -1) => 0.111452
+(0, 102) ~ (3, -1) => 0.120415
+(0, 103) ~ (3, -1) => 0.133431
+(0, 104) ~ (3, -1) => 0.26439
+(0, 105) ~ (3, -1) => 0.347961
+(0, 106) ~ (3, -1) => 0.30714
+(0, 107) ~ (3, -1) => 0.158028
+(0, 108) ~ (3, -1) => 0.117485
+
+(0, -1) ~ (3, 0) => 0.00813264
+(0, -1) ~ (3, 1) => 0.01152
+(0, -1) ~ (3, 2) => 0.0139424
+(0, -1) ~ (3, 3) => 0.0199518
+(0, -1) ~ (3, 4) => 0.033759
+(0, -1) ~ (3, 5) => 0.0429425
+(0, -1) ~ (3, 6) => 0.0479432
+(0, -1) ~ (3, 7) => 0.0572033
+(0, -1) ~ (3, 8) => 0.059129
+(0, -1) ~ (3, 9) => 0.061642
+(0, -1) ~ (3, 10) => 0.0589249
+(0, -1) ~ (3, 11) => 0.0637322
+(0, -1) ~ (3, 12) => 0.0645505
+(0, -1) ~ (3, 13) => 0.0500437
+(0, -1) ~ (3, 14) => 0.0284864
+(0, -1) ~ (3, 15) => 0.0339478
+(0, -1) ~ (3, 16) => 0.0320911
+(0, -1) ~ (3, 17) => 0.0481662
+(0, -1) ~ (3, 18) => 0.0279616
+(0, -1) ~ (3, 19) => 0.0275358
+(0, -1) ~ (3, 20) => 0.0244409
+(0, -1) ~ (3, 21) => 0.020787
+(0, -1) ~ (3, 22) => 0.0208781
+(0, -1) ~ (3, 23) => 0.0151714
+(0, -1) ~ (3, 24) => 0.0121314
+(0, -1) ~ (3, 25) => 0.0119274
+(0, -1) ~ (3, 26) => 0.0109543
+(0, -1) ~ (3, 27) => 0.00824177
+(0, -1) ~ (3, 28) => 0.00641978
+(0, -1) ~ (3, 29) => 0.0029487
+(0, -1) ~ (3, 30) => 0.000938058
+(0, -1) ~ (3, 31) => 0.000746369
+(0, -1) ~ (3, 32) => 0.000598431
+(0, -1) ~ (3, 33) => 0.000399947
+(0, -1) ~ (3, 34) => 0.000161827
+(0, -1) ~ (3, 35) => 0.000144482
+(0, -1) ~ (3, 36) => 0.000179291
+(0, -1) ~ (3, 37) => 0.000188351
+(0, -1) ~ (3, 38) => 0.000388086
+(0, -1) ~ (3, 39) => 0.000535131
+(0, -1) ~ (3, 40) => 0.000538945
+(0, -1) ~ (3, 41) => 0.000398278
+(0, -1) ~ (3, 42) => 0.000149846
+(0, -1) ~ (3, 43) => 0.0001
+(0, -1) ~ (3, 44) => 0.000142753
+(0, -1) ~ (3, 45) => 0.000281751
+(0, -1) ~ (3, 46) => 0.000373542
+(0, -1) ~ (3, 47) => 0.000415087
+(0, -1) ~ (3, 48) => 0.000506997
+(0, -1) ~ (3, 49) => 0.00105882
+(0, -1) ~ (3, 50) => 0.0019685
+(0, -1) ~ (3, 51) => 0.00251979
+(0, -1) ~ (3, 52) => 0.00376737
+(0, -1) ~ (3, 53) => 0.00510007
+(0, -1) ~ (3, 54) => 0.0104493
+(0, -1) ~ (3, 55) => 0.0447875
+(0, -1) ~ (3, 56) => 0.0597006
+(0, -1) ~ (3, 57) => 0.0733408
+(0, -1) ~ (3, 58) => 0.116444
+(0, -1) ~ (3, 59) => 0.111101
+(0, -1) ~ (3, 60) => 0.12075
+(0, -1) ~ (3, 61) => 0.107515
+(0, -1) ~ (3, 62) => 0.133753
+(0, -1) ~ (3, 63) => 0.210013
+(0, -1) ~ (3, 64) => 0.261531
+(0, -1) ~ (3, 65) => 0.344473
+(0, -1) ~ (3, 66) => 0.472737
+(0, -1) ~ (3, 67) => 0.366075
+(0, -1) ~ (3, 68) => 0.295865
+(0, -1) ~ (3, 69) => 0.191157
+(0, -1) ~ (3, 70) => 0.174805
+(0, -1) ~ (3, 71) => 0.180721
+(0, -1) ~ (3, 72) => 0.163264
+(0, -1) ~ (3, 73) => 0.186426
+(0, -1) ~ (3, 74) => 0.224748
+(0, -1) ~ (3, 75) => 0.205047
+(0, -1) ~ (3, 76) => 0.146098
+(0, -1) ~ (3, 77) => 0.129241
+(0, -1) ~ (3, 78) => 0.119438
+(0, -1) ~ (3, 79) => 0.137679
+(0, -1) ~ (3, 80) => 0.0877153
+(0, -1) ~ (3, 81) => 0.0455436
+(0, -1) ~ (3, 82) => 0.041021
+(0, -1) ~ (3, 83) => 0.0436479
+(0, -1) ~ (3, 84) => 0.132014
+(0, -1) ~ (3, 85) => 0.0984307
+(0, -1) ~ (3, 86) => 0.128919
+(0, -1) ~ (3, 87) => 0.20071
+(0, -1) ~ (3, 88) => 0.252233
+(0, -1) ~ (3, 89) => 0.301824
+(0, -1) ~ (3, 90) => 0.370041
+(0, -1) ~ (3, 91) => 0.500137
+(0, -1) ~ (3, 92) => 0.521987
+(0, -1) ~ (3, 93) => 0.575197
+(0, -1) ~ (3, 94) => 0.595146
+(0, -1) ~ (3, 95) => 0.64668
+(0, -1) ~ (3, 96) => 0.704551
+(0, -1) ~ (3, 97) => 0.679206
+(0, -1) ~ (3, 98) => 0.697182
+(0, -1) ~ (3, 99) => 0.707001
+(0, -1) ~ (3, 100) => 0.72694
+(0, -1) ~ (3, 101) => 0.736101
+(0, -1) ~ (3, 102) => 0.701378
+(0, -1) ~ (3, 103) => 0.651804
+(0, -1) ~ (3, 104) => 0.633464
+(0, -1) ~ (3, 105) => 0.617702
+(0, -1) ~ (3, 106) => 0.653481
+(0, -1) ~ (3, 107) => 0.657626
+(0, -1) ~ (3, 108) => 0.654281
+(0, -1) ~ (3, 109) => 0.665736
+(0, -1) ~ (3, 110) => 0.728148
+(0, -1) ~ (3, 111) => 0.695153
+(0, -1) ~ (3, 112) => 0.666282
+(0, -1) ~ (3, 113) => 0.660904
+(0, -1) ~ (3, 114) => 0.676833
+(0, -1) ~ (3, 115) => 0.669175
+(0, -1) ~ (3, 116) => 0.669366
+(0, -1) ~ (3, 117) => 0.663512
+(0, -1) ~ (3, 118) => 0.600649
+(0, -1) ~ (3, 119) => 0.49802
+(0, -1) ~ (3, 120) => 0.3774
+(0, -1) ~ (3, 121) => 0.306325
+(0, -1) ~ (3, 122) => 0.259521
+(0, -1) ~ (3, 123) => 0.227581
+
+; Sparse posterior probability matrix for sequences 0 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (4, 0) => 0.0685493
+(0, 0) ~ (4, 1) => 0.928174
+(0, 1) ~ (4, 2) => 0.990694
+(0, 2) ~ (4, 3) => 0.999008
+(0, 3) ~ (4, 4) => 0.999664
+(0, 4) ~ (4, 5) => 0.999885
+(0, 5) ~ (4, 6) => 0.999936
+(0, 6) ~ (4, 7) => 0.999927
+(0, 7) ~ (4, 8) => 0.999926
+(0, 8) ~ (4, 9) => 0.999752
+(0, 9) ~ (4, 10) => 0.999633
+(0, 10) ~ (4, 11) => 0.999691
+(0, 11) ~ (4, 12) => 0.999873
+(0, 12) ~ (4, 13) => 0.999844
+(0, 13) ~ (4, 14) => 0.999783
+(0, 14) ~ (4, 15) => 0.998772
+(0, 15) ~ (4, 16) => 0.997554
+(0, 16) ~ (4, 17) => 0.993503
+(0, 17) ~ (4, 18) => 0.93804
+(0, 17) ~ (4, 19) => 0.0363687
+(0, 17) ~ (4, 20) => 0.0117184
+(0, 18) ~ (4, 19) => 0.573393
+(0, 18) ~ (4, 20) => 0.281092
+(0, 19) ~ (4, 20) => 0.399574
+(0, 19) ~ (4, 21) => 0.23041
+(0, 20) ~ (4, 19) => 0.0191132
+(0, 20) ~ (4, 21) => 0.209082
+(0, 20) ~ (4, 22) => 0.148643
+(0, 21) ~ (4, 19) => 0.105571
+(0, 21) ~ (4, 20) => 0.166341
+(0, 21) ~ (4, 22) => 0.0124598
+(0, 21) ~ (4, 23) => 0.141672
+(0, 22) ~ (4, 21) => 0.544217
+(0, 22) ~ (4, 24) => 0.1303
+(0, 23) ~ (4, 22) => 0.828868
+(0, 23) ~ (4, 25) => 0.0156221
+(0, 24) ~ (4, 23) => 0.853434
+(0, 25) ~ (4, 24) => 0.864326
+(0, 26) ~ (4, 25) => 0.98019
+(0, 27) ~ (4, 26) => 0.997835
+(0, 28) ~ (4, 27) => 0.998673
+(0, 29) ~ (4, 28) => 0.999198
+(0, 30) ~ (4, 29) => 0.999648
+(0, 31) ~ (4, 30) => 0.999915
+(0, 32) ~ (4, 31) => 0.999919
+(0, 33) ~ (4, 32) => 0.999554
+(0, 34) ~ (4, 33) => 0.999314
+(0, 35) ~ (4, 34) => 0.999256
+(0, 36) ~ (4, 35) => 0.998656
+(0, 37) ~ (4, 36) => 0.996646
+(0, 38) ~ (4, 37) => 0.997332
+(0, 39) ~ (4, 38) => 0.997869
+(0, 40) ~ (4, 39) => 0.997757
+(0, 41) ~ (4, 40) => 0.997212
+(0, 42) ~ (4, 41) => 0.996675
+(0, 43) ~ (4, 42) => 0.995236
+(0, 44) ~ (4, 43) => 0.995604
+(0, 45) ~ (4, 44) => 0.98826
+(0, 46) ~ (4, 45) => 0.98982
+(0, 47) ~ (4, 46) => 0.997883
+(0, 48) ~ (4, 47) => 0.998663
+(0, 49) ~ (4, 48) => 0.999265
+(0, 50) ~ (4, 49) => 0.999919
+(0, 51) ~ (4, 50) => 0.999945
+(0, 52) ~ (4, 51) => 0.999731
+(0, 53) ~ (4, 52) => 0.99962
+(0, 54) ~ (4, 53) => 0.99971
+(0, 55) ~ (4, 54) => 0.999883
+(0, 56) ~ (4, 55) => 0.99991
+(0, 57) ~ (4, 56) => 0.999979
+(0, 58) ~ (4, 57) => 0.999982
+(0, 59) ~ (4, 58) => 0.999912
+(0, 60) ~ (4, 59) => 0.999889
+(0, 61) ~ (4, 60) => 0.999927
+(0, 62) ~ (4, 61) => 0.999917
+(0, 63) ~ (4, 62) => 0.99991
+(0, 64) ~ (4, 63) => 0.999789
+(0, 65) ~ (4, 64) => 0.999673
+(0, 66) ~ (4, 65) => 0.997048
+(0, 67) ~ (4, 66) => 0.993512
+(0, 68) ~ (4, 67) => 0.957964
+(0, 68) ~ (4, 68) => 0.0367749
+(0, 69) ~ (4, 68) => 0.525538
+(0, 69) ~ (4, 69) => 0.46585
+(0, 70) ~ (4, 69) => 0.079997
+(0, 70) ~ (4, 70) => 0.893719
+(0, 71) ~ (4, 70) => 0.0332981
+(0, 71) ~ (4, 71) => 0.926287
+(0, 72) ~ (4, 70) => 0.0138136
+(0, 72) ~ (4, 71) => 0.0203423
+(0, 72) ~ (4, 72) => 0.923354
+(0, 73) ~ (4, 71) => 0.014364
+(0, 73) ~ (4, 72) => 0.0183578
+(0, 73) ~ (4, 73) => 0.502176
+(0, 74) ~ (4, 71) => 0.0113816
+(0, 74) ~ (4, 74) => 0.0798016
+(0, 75) ~ (4, 72) => 0.0316094
+(0, 75) ~ (4, 75) => 0.0406294
+(0, 76) ~ (4, 73) => 0.485605
+(0, 77) ~ (4, 74) => 0.917435
+(0, 78) ~ (4, 75) => 0.957652
+(0, 79) ~ (4, 76) => 0.997743
+(0, 80) ~ (4, 77) => 0.998173
+(0, 81) ~ (4, 78) => 0.994806
+(0, 82) ~ (4, 79) => 0.921947
+(0, 82) ~ (4, 80) => 0.0775773
+(0, 83) ~ (4, 80) => 0.848199
+(0, 83) ~ (4, 81) => 0.149434
+(0, 84) ~ (4, 81) => 0.842274
+(0, 84) ~ (4, 82) => 0.154807
+(0, 85) ~ (4, 82) => 0.836848
+(0, 85) ~ (4, 83) => 0.160303
+(0, 86) ~ (4, 83) => 0.831399
+(0, 86) ~ (4, 84) => 0.159048
+(0, 87) ~ (4, 84) => 0.838789
+(0, 87) ~ (4, 85) => 0.1022
+(0, 88) ~ (4, 85) => 0.89583
+(0, 88) ~ (4, 86) => 0.0948958
+(0, 89) ~ (4, 86) => 0.89989
+(0, 89) ~ (4, 87) => 0.0977824
+(0, 90) ~ (4, 87) => 0.896267
+(0, 90) ~ (4, 88) => 0.100007
+(0, 91) ~ (4, 88) => 0.843611
+(0, 91) ~ (4, 89) => 0.142713
+(0, 92) ~ (4, 89) => 0.786196
+(0, 92) ~ (4, 90) => 0.184553
+(0, 93) ~ (4, 90) => 0.71564
+(0, 93) ~ (4, 91) => 0.224687
+(0, 93) ~ (4, 92) => 0.0109676
+(0, 93) ~ (4, 98) => 0.0273412
+(0, 94) ~ (4, 91) => 0.575572
+(0, 94) ~ (4, 92) => 0.258137
+(0, 94) ~ (4, 99) => 0.117471
+(0, 95) ~ (4, 92) => 0.425969
+(0, 95) ~ (4, 93) => 0.284325
+(0, 95) ~ (4, 100) => 0.206556
+(0, 96) ~ (4, 93) => 0.0253261
+(0, 96) ~ (4, 94) => 0.2962
+(0, 96) ~ (4, 96) => 0.0581775
+(0, 96) ~ (4, 97) => 0.0205122
+(0, 96) ~ (4, 101) => 0.29298
+(0, 97) ~ (4, 91) => 0.0207503
+(0, 97) ~ (4, 93) => 0.0350199
+(0, 97) ~ (4, 95) => 0.0997539
+(0, 97) ~ (4, 97) => 0.0347398
+(0, 97) ~ (4, 98) => 0.0594673
+(0, 97) ~ (4, 99) => 0.0201582
+(0, 97) ~ (4, 100) => 0.0390003
+(0, 97) ~ (4, 102) => 0.260646
+(0, 97) ~ (4, 103) => 0.149235
+(0, 98) ~ (4, 92) => 0.0395182
+(0, 98) ~ (4, 94) => 0.0272065
+(0, 98) ~ (4, 95) => 0.0258033
+(0, 98) ~ (4, 96) => 0.0704728
+(0, 98) ~ (4, 98) => 0.0234196
+(0, 98) ~ (4, 99) => 0.0750239
+(0, 98) ~ (4, 101) => 0.0400529
+(0, 98) ~ (4, 103) => 0.200792
+(0, 98) ~ (4, 104) => 0.20384
+(0, 99) ~ (4, 93) => 0.219145
+(0, 99) ~ (4, 95) => 0.0228627
+(0, 99) ~ (4, 97) => 0.0279184
+(0, 99) ~ (4, 99) => 0.0200692
+(0, 99) ~ (4, 100) => 0.106985
+(0, 99) ~ (4, 102) => 0.03746
+(0, 99) ~ (4, 103) => 0.0219254
+(0, 99) ~ (4, 104) => 0.107637
+(0, 99) ~ (4, 105) => 0.349067
+(0, 100) ~ (4, 94) => 0.225204
+(0, 100) ~ (4, 96) => 0.0274896
+(0, 100) ~ (4, 101) => 0.104691
+(0, 100) ~ (4, 105) => 0.015137
+(0, 100) ~ (4, 106) => 0.547125
+(0, 101) ~ (4, 95) => 0.206583
+(0, 101) ~ (4, 96) => 0.0333389
+(0, 101) ~ (4, 97) => 0.0164481
+(0, 101) ~ (4, 102) => 0.0894267
+(0, 101) ~ (4, 103) => 0.0102073
+(0, 101) ~ (4, 107) => 0.574461
+(0, 102) ~ (4, 96) => 0.0215192
+(0, 102) ~ (4, 97) => 0.175344
+(0, 102) ~ (4, 98) => 0.0304785
+(0, 102) ~ (4, 103) => 0.0868121
+(0, 102) ~ (4, 104) => 0.0306793
+(0, 102) ~ (4, 108) => 0.626721
+(0, 103) ~ (4, 97) => 0.0199041
+(0, 103) ~ (4, 98) => 0.173549
+(0, 103) ~ (4, 99) => 0.0240597
+(0, 103) ~ (4, 104) => 0.097902
+(0, 103) ~ (4, 105) => 0.0299256
+(0, 103) ~ (4, 109) => 0.631448
+(0, 104) ~ (4, 98) => 0.0118278
+(0, 104) ~ (4, 99) => 0.151768
+(0, 104) ~ (4, 100) => 0.0294297
+(0, 104) ~ (4, 105) => 0.0955867
+(0, 104) ~ (4, 110) => 0.671125
+(0, 105) ~ (4, 101) => 0.0174874
+(0, 105) ~ (4, 106) => 0.0843662
+(0, 105) ~ (4, 111) => 0.88025
+(0, 106) ~ (4, 107) => 0.058373
+(0, 106) ~ (4, 112) => 0.935492
+(0, 107) ~ (4, 108) => 0.0317586
+(0, 107) ~ (4, 113) => 0.967148
+(0, 108) ~ (4, 114) => 0.994341
+
+; gap posteriors
+(0, 0) ~ (4, -1) => 0.00327629
+(0, 1) ~ (4, -1) => 0.0093056
+(0, 2) ~ (4, -1) => 0.000991702
+(0, 3) ~ (4, -1) => 0.00033617
+(0, 4) ~ (4, -1) => 0.00011462
+(0, 5) ~ (4, -1) => 0.0001
+(0, 6) ~ (4, -1) => 0.0001
+(0, 7) ~ (4, -1) => 0.0001
+(0, 8) ~ (4, -1) => 0.000248313
+(0, 9) ~ (4, -1) => 0.000366569
+(0, 10) ~ (4, -1) => 0.000309169
+(0, 11) ~ (4, -1) => 0.00012666
+(0, 12) ~ (4, -1) => 0.000156105
+(0, 13) ~ (4, -1) => 0.000217438
+(0, 14) ~ (4, -1) => 0.00122839
+(0, 15) ~ (4, -1) => 0.00244635
+(0, 16) ~ (4, -1) => 0.00649691
+(0, 17) ~ (4, -1) => 0.0138724
+(0, 18) ~ (4, -1) => 0.145515
+(0, 19) ~ (4, -1) => 0.370016
+(0, 20) ~ (4, -1) => 0.623162
+(0, 21) ~ (4, -1) => 0.573956
+(0, 22) ~ (4, -1) => 0.325482
+(0, 23) ~ (4, -1) => 0.15551
+(0, 24) ~ (4, -1) => 0.146566
+(0, 25) ~ (4, -1) => 0.135674
+(0, 26) ~ (4, -1) => 0.0198103
+(0, 27) ~ (4, -1) => 0.00216538
+(0, 28) ~ (4, -1) => 0.00132662
+(0, 29) ~ (4, -1) => 0.0008021
+(0, 30) ~ (4, -1) => 0.000351548
+(0, 31) ~ (4, -1) => 0.0001
+(0, 32) ~ (4, -1) => 0.0001
+(0, 33) ~ (4, -1) => 0.000446498
+(0, 34) ~ (4, -1) => 0.00068593
+(0, 35) ~ (4, -1) => 0.000744045
+(0, 36) ~ (4, -1) => 0.00134385
+(0, 37) ~ (4, -1) => 0.00335401
+(0, 38) ~ (4, -1) => 0.00266784
+(0, 39) ~ (4, -1) => 0.00213093
+(0, 40) ~ (4, -1) => 0.00224334
+(0, 41) ~ (4, -1) => 0.00278765
+(0, 42) ~ (4, -1) => 0.00332457
+(0, 43) ~ (4, -1) => 0.00476408
+(0, 44) ~ (4, -1) => 0.00439626
+(0, 45) ~ (4, -1) => 0.0117399
+(0, 46) ~ (4, -1) => 0.0101799
+(0, 47) ~ (4, -1) => 0.00211692
+(0, 48) ~ (4, -1) => 0.00133735
+(0, 49) ~ (4, -1) => 0.000734568
+(0, 50) ~ (4, -1) => 0.0001
+(0, 51) ~ (4, -1) => 0.0001
+(0, 52) ~ (4, -1) => 0.000268519
+(0, 53) ~ (4, -1) => 0.000380456
+(0, 54) ~ (4, -1) => 0.000289798
+(0, 55) ~ (4, -1) => 0.000117421
+(0, 56) ~ (4, -1) => 0.0001
+(0, 57) ~ (4, -1) => 0.0001
+(0, 58) ~ (4, -1) => 0.0001
+(0, 59) ~ (4, -1) => 0.0001
+(0, 60) ~ (4, -1) => 0.000110865
+(0, 61) ~ (4, -1) => 0.0001
+(0, 62) ~ (4, -1) => 0.0001
+(0, 63) ~ (4, -1) => 0.0001
+(0, 64) ~ (4, -1) => 0.000210643
+(0, 65) ~ (4, -1) => 0.000327051
+(0, 66) ~ (4, -1) => 0.00295168
+(0, 67) ~ (4, -1) => 0.00648785
+(0, 68) ~ (4, -1) => 0.00526083
+(0, 69) ~ (4, -1) => 0.0086123
+(0, 70) ~ (4, -1) => 0.0262842
+(0, 71) ~ (4, -1) => 0.0404147
+(0, 72) ~ (4, -1) => 0.0424904
+(0, 73) ~ (4, -1) => 0.465102
+(0, 74) ~ (4, -1) => 0.908817
+(0, 75) ~ (4, -1) => 0.927761
+(0, 76) ~ (4, -1) => 0.514395
+(0, 77) ~ (4, -1) => 0.0825648
+(0, 78) ~ (4, -1) => 0.0423482
+(0, 79) ~ (4, -1) => 0.00225741
+(0, 80) ~ (4, -1) => 0.00182718
+(0, 81) ~ (4, -1) => 0.00519449
+(0, 82) ~ (4, -1) => 0.000475489
+(0, 83) ~ (4, -1) => 0.00236666
+(0, 84) ~ (4, -1) => 0.00291917
+(0, 85) ~ (4, -1) => 0.00284842
+(0, 86) ~ (4, -1) => 0.00955321
+(0, 87) ~ (4, -1) => 0.0590103
+(0, 88) ~ (4, -1) => 0.00927406
+(0, 89) ~ (4, -1) => 0.00232802
+(0, 90) ~ (4, -1) => 0.0037252
+(0, 91) ~ (4, -1) => 0.0136756
+(0, 92) ~ (4, -1) => 0.0292517
+(0, 93) ~ (4, -1) => 0.0213637
+(0, 94) ~ (4, -1) => 0.0488198
+(0, 95) ~ (4, -1) => 0.0831507
+(0, 96) ~ (4, -1) => 0.306804
+(0, 97) ~ (4, -1) => 0.281228
+(0, 98) ~ (4, -1) => 0.293871
+(0, 99) ~ (4, -1) => 0.0869304
+(0, 100) ~ (4, -1) => 0.0803542
+(0, 101) ~ (4, -1) => 0.0695347
+(0, 102) ~ (4, -1) => 0.0284455
+(0, 103) ~ (4, -1) => 0.0232119
+(0, 104) ~ (4, -1) => 0.0402629
+(0, 105) ~ (4, -1) => 0.0178959
+(0, 106) ~ (4, -1) => 0.00613475
+(0, 107) ~ (4, -1) => 0.00109333
+(0, 108) ~ (4, -1) => 0.00565946
+
+(0, -1) ~ (4, 0) => 0.931451
+(0, -1) ~ (4, 1) => 0.0718256
+(0, -1) ~ (4, 2) => 0.0093056
+(0, -1) ~ (4, 3) => 0.000991702
+(0, -1) ~ (4, 4) => 0.00033617
+(0, -1) ~ (4, 5) => 0.00011462
+(0, -1) ~ (4, 6) => 0.0001
+(0, -1) ~ (4, 7) => 0.0001
+(0, -1) ~ (4, 8) => 0.0001
+(0, -1) ~ (4, 9) => 0.000248313
+(0, -1) ~ (4, 10) => 0.000366569
+(0, -1) ~ (4, 11) => 0.000309169
+(0, -1) ~ (4, 12) => 0.00012666
+(0, -1) ~ (4, 13) => 0.000156105
+(0, -1) ~ (4, 14) => 0.000217438
+(0, -1) ~ (4, 15) => 0.00122839
+(0, -1) ~ (4, 16) => 0.00244635
+(0, -1) ~ (4, 17) => 0.00649691
+(0, -1) ~ (4, 18) => 0.0619596
+(0, -1) ~ (4, 19) => 0.265554
+(0, -1) ~ (4, 20) => 0.141275
+(0, -1) ~ (4, 21) => 0.01629
+(0, -1) ~ (4, 22) => 0.0100297
+(0, -1) ~ (4, 23) => 0.0048942
+(0, -1) ~ (4, 24) => 0.0053736
+(0, -1) ~ (4, 25) => 0.00418812
+(0, -1) ~ (4, 26) => 0.00216538
+(0, -1) ~ (4, 27) => 0.00132662
+(0, -1) ~ (4, 28) => 0.0008021
+(0, -1) ~ (4, 29) => 0.000351548
+(0, -1) ~ (4, 30) => 0.0001
+(0, -1) ~ (4, 31) => 0.0001
+(0, -1) ~ (4, 32) => 0.000446498
+(0, -1) ~ (4, 33) => 0.00068593
+(0, -1) ~ (4, 34) => 0.000744045
+(0, -1) ~ (4, 35) => 0.00134385
+(0, -1) ~ (4, 36) => 0.00335401
+(0, -1) ~ (4, 37) => 0.00266784
+(0, -1) ~ (4, 38) => 0.00213093
+(0, -1) ~ (4, 39) => 0.00224334
+(0, -1) ~ (4, 40) => 0.00278765
+(0, -1) ~ (4, 41) => 0.00332457
+(0, -1) ~ (4, 42) => 0.00476408
+(0, -1) ~ (4, 43) => 0.00439626
+(0, -1) ~ (4, 44) => 0.0117399
+(0, -1) ~ (4, 45) => 0.0101799
+(0, -1) ~ (4, 46) => 0.00211692
+(0, -1) ~ (4, 47) => 0.00133735
+(0, -1) ~ (4, 48) => 0.000734568
+(0, -1) ~ (4, 49) => 0.0001
+(0, -1) ~ (4, 50) => 0.0001
+(0, -1) ~ (4, 51) => 0.000268519
+(0, -1) ~ (4, 52) => 0.000380456
+(0, -1) ~ (4, 53) => 0.000289798
+(0, -1) ~ (4, 54) => 0.000117421
+(0, -1) ~ (4, 55) => 0.0001
+(0, -1) ~ (4, 56) => 0.0001
+(0, -1) ~ (4, 57) => 0.0001
+(0, -1) ~ (4, 58) => 0.0001
+(0, -1) ~ (4, 59) => 0.000110865
+(0, -1) ~ (4, 60) => 0.0001
+(0, -1) ~ (4, 61) => 0.0001
+(0, -1) ~ (4, 62) => 0.0001
+(0, -1) ~ (4, 63) => 0.000210643
+(0, -1) ~ (4, 64) => 0.000327051
+(0, -1) ~ (4, 65) => 0.00295168
+(0, -1) ~ (4, 66) => 0.00648785
+(0, -1) ~ (4, 67) => 0.0420357
+(0, -1) ~ (4, 68) => 0.437688
+(0, -1) ~ (4, 69) => 0.454153
+(0, -1) ~ (4, 70) => 0.0591694
+(0, -1) ~ (4, 71) => 0.0276248
+(0, -1) ~ (4, 72) => 0.0266792
+(0, -1) ~ (4, 73) => 0.012219
+(0, -1) ~ (4, 74) => 0.00276321
+(0, -1) ~ (4, 75) => 0.00171882
+(0, -1) ~ (4, 76) => 0.00225741
+(0, -1) ~ (4, 77) => 0.00182718
+(0, -1) ~ (4, 78) => 0.00519449
+(0, -1) ~ (4, 79) => 0.0780528
+(0, -1) ~ (4, 80) => 0.0742232
+(0, -1) ~ (4, 81) => 0.00829262
+(0, -1) ~ (4, 82) => 0.00834453
+(0, -1) ~ (4, 83) => 0.00829756
+(0, -1) ~ (4, 84) => 0.00216293
+(0, -1) ~ (4, 85) => 0.0019694
+(0, -1) ~ (4, 86) => 0.00521463
+(0, -1) ~ (4, 87) => 0.00595015
+(0, -1) ~ (4, 88) => 0.0563815
+(0, -1) ~ (4, 89) => 0.0710911
+(0, -1) ~ (4, 90) => 0.0998072
+(0, -1) ~ (4, 91) => 0.17899
+(0, -1) ~ (4, 92) => 0.265408
+(0, -1) ~ (4, 93) => 0.436184
+(0, -1) ~ (4, 94) => 0.45139
+(0, -1) ~ (4, 95) => 0.644997
+(0, -1) ~ (4, 96) => 0.789002
+(0, -1) ~ (4, 97) => 0.705133
+(0, -1) ~ (4, 98) => 0.673917
+(0, -1) ~ (4, 99) => 0.59145
+(0, -1) ~ (4, 100) => 0.618029
+(0, -1) ~ (4, 101) => 0.544789
+(0, -1) ~ (4, 102) => 0.612467
+(0, -1) ~ (4, 103) => 0.531028
+(0, -1) ~ (4, 104) => 0.559942
+(0, -1) ~ (4, 105) => 0.510284
+(0, -1) ~ (4, 106) => 0.368509
+(0, -1) ~ (4, 107) => 0.367166
+(0, -1) ~ (4, 108) => 0.34152
+(0, -1) ~ (4, 109) => 0.368552
+(0, -1) ~ (4, 110) => 0.328875
+(0, -1) ~ (4, 111) => 0.11975
+(0, -1) ~ (4, 112) => 0.0645077
+(0, -1) ~ (4, 113) => 0.0328519
+(0, -1) ~ (4, 114) => 0.00565946
+
+; Sparse posterior probability matrix for sequences 1 and 2
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (2, 0) => 0.929384
+(1, 0) ~ (2, 1) => 0.0172915
+(1, 1) ~ (2, 0) => 0.042805
+(1, 1) ~ (2, 1) => 0.82223
+(1, 1) ~ (2, 2) => 0.0354121
+(1, 2) ~ (2, 1) => 0.117478
+(1, 2) ~ (2, 2) => 0.724091
+(1, 2) ~ (2, 3) => 0.0611122
+(1, 3) ~ (2, 1) => 0.0108887
+(1, 3) ~ (2, 2) => 0.176789
+(1, 3) ~ (2, 3) => 0.635821
+(1, 3) ~ (2, 4) => 0.0793803
+(1, 3) ~ (2, 5) => 0.0106468
+(1, 4) ~ (2, 2) => 0.014396
+(1, 4) ~ (2, 3) => 0.236936
+(1, 4) ~ (2, 4) => 0.425423
+(1, 4) ~ (2, 5) => 0.0908381
+(1, 5) ~ (2, 4) => 0.432597
+(1, 5) ~ (2, 5) => 0.253413
+(1, 5) ~ (2, 6) => 0.144982
+(1, 6) ~ (2, 3) => 0.011298
+(1, 6) ~ (2, 4) => 0.0108901
+(1, 6) ~ (2, 5) => 0.545752
+(1, 6) ~ (2, 6) => 0.203459
+(1, 6) ~ (2, 7) => 0.148368
+(1, 7) ~ (2, 4) => 0.0159126
+(1, 7) ~ (2, 5) => 0.0109725
+(1, 7) ~ (2, 6) => 0.590091
+(1, 7) ~ (2, 7) => 0.176868
+(1, 7) ~ (2, 8) => 0.139487
+(1, 8) ~ (2, 5) => 0.0177648
+(1, 8) ~ (2, 6) => 0.0153628
+(1, 8) ~ (2, 7) => 0.611807
+(1, 8) ~ (2, 8) => 0.17702
+(1, 8) ~ (2, 9) => 0.140628
+(1, 9) ~ (2, 6) => 0.0187358
+(1, 9) ~ (2, 7) => 0.0215531
+(1, 9) ~ (2, 8) => 0.608021
+(1, 9) ~ (2, 9) => 0.162484
+(1, 9) ~ (2, 10) => 0.151334
+(1, 10) ~ (2, 7) => 0.020771
+(1, 10) ~ (2, 8) => 0.0233651
+(1, 10) ~ (2, 9) => 0.577406
+(1, 10) ~ (2, 10) => 0.157481
+(1, 10) ~ (2, 11) => 0.165292
+(1, 11) ~ (2, 8) => 0.0288916
+(1, 11) ~ (2, 9) => 0.0393763
+(1, 11) ~ (2, 10) => 0.564113
+(1, 11) ~ (2, 11) => 0.138604
+(1, 11) ~ (2, 12) => 0.171836
+(1, 12) ~ (2, 9) => 0.034084
+(1, 12) ~ (2, 10) => 0.0539404
+(1, 12) ~ (2, 11) => 0.555499
+(1, 12) ~ (2, 12) => 0.116379
+(1, 12) ~ (2, 13) => 0.183315
+(1, 13) ~ (2, 10) => 0.0353222
+(1, 13) ~ (2, 11) => 0.0690026
+(1, 13) ~ (2, 12) => 0.541904
+(1, 13) ~ (2, 13) => 0.116402
+(1, 13) ~ (2, 14) => 0.18681
+(1, 14) ~ (2, 11) => 0.0366529
+(1, 14) ~ (2, 12) => 0.0837644
+(1, 14) ~ (2, 13) => 0.530111
+(1, 14) ~ (2, 14) => 0.112121
+(1, 14) ~ (2, 15) => 0.191987
+(1, 15) ~ (2, 12) => 0.0368112
+(1, 15) ~ (2, 13) => 0.0909817
+(1, 15) ~ (2, 14) => 0.516477
+(1, 15) ~ (2, 15) => 0.0998659
+(1, 15) ~ (2, 16) => 0.195886
+(1, 16) ~ (2, 13) => 0.0422695
+(1, 16) ~ (2, 14) => 0.0931167
+(1, 16) ~ (2, 15) => 0.529851
+(1, 16) ~ (2, 16) => 0.0854771
+(1, 16) ~ (2, 17) => 0.197269
+(1, 17) ~ (2, 14) => 0.047089
+(1, 17) ~ (2, 15) => 0.0862661
+(1, 17) ~ (2, 16) => 0.541963
+(1, 17) ~ (2, 17) => 0.0677278
+(1, 17) ~ (2, 18) => 0.188521
+(1, 18) ~ (2, 15) => 0.0598441
+(1, 18) ~ (2, 16) => 0.0809816
+(1, 18) ~ (2, 17) => 0.556476
+(1, 18) ~ (2, 18) => 0.054198
+(1, 18) ~ (2, 19) => 0.172556
+(1, 19) ~ (2, 16) => 0.0646571
+(1, 19) ~ (2, 17) => 0.0327956
+(1, 19) ~ (2, 18) => 0.628362
+(1, 19) ~ (2, 19) => 0.0491989
+(1, 19) ~ (2, 20) => 0.164817
+(1, 20) ~ (2, 17) => 0.0717264
+(1, 20) ~ (2, 18) => 0.0195883
+(1, 20) ~ (2, 19) => 0.659299
+(1, 20) ~ (2, 20) => 0.0571077
+(1, 20) ~ (2, 21) => 0.149894
+(1, 21) ~ (2, 18) => 0.0761979
+(1, 21) ~ (2, 19) => 0.0148386
+(1, 21) ~ (2, 20) => 0.645614
+(1, 21) ~ (2, 21) => 0.0799899
+(1, 21) ~ (2, 22) => 0.137739
+(1, 22) ~ (2, 19) => 0.0811823
+(1, 22) ~ (2, 20) => 0.0184858
+(1, 22) ~ (2, 21) => 0.637586
+(1, 22) ~ (2, 22) => 0.0943935
+(1, 22) ~ (2, 23) => 0.112445
+(1, 23) ~ (2, 20) => 0.0780335
+(1, 23) ~ (2, 21) => 0.0244514
+(1, 23) ~ (2, 22) => 0.627977
+(1, 23) ~ (2, 23) => 0.114202
+(1, 23) ~ (2, 24) => 0.0991161
+(1, 24) ~ (2, 21) => 0.0680447
+(1, 24) ~ (2, 22) => 0.0257657
+(1, 24) ~ (2, 23) => 0.651617
+(1, 24) ~ (2, 24) => 0.116749
+(1, 24) ~ (2, 25) => 0.0870513
+(1, 25) ~ (2, 22) => 0.0544461
+(1, 25) ~ (2, 23) => 0.0362847
+(1, 25) ~ (2, 24) => 0.665073
+(1, 25) ~ (2, 25) => 0.120222
+(1, 25) ~ (2, 26) => 0.06589
+(1, 26) ~ (2, 23) => 0.0409649
+(1, 26) ~ (2, 24) => 0.049384
+(1, 26) ~ (2, 25) => 0.675642
+(1, 26) ~ (2, 26) => 0.125412
+(1, 26) ~ (2, 27) => 0.0454847
+(1, 27) ~ (2, 24) => 0.033542
+(1, 27) ~ (2, 25) => 0.0504847
+(1, 27) ~ (2, 26) => 0.705335
+(1, 27) ~ (2, 27) => 0.11588
+(1, 27) ~ (2, 28) => 0.0288436
+(1, 28) ~ (2, 25) => 0.0269162
+(1, 28) ~ (2, 26) => 0.0472427
+(1, 28) ~ (2, 27) => 0.748173
+(1, 28) ~ (2, 28) => 0.0833733
+(1, 28) ~ (2, 29) => 0.0189231
+(1, 29) ~ (2, 26) => 0.0218824
+(1, 29) ~ (2, 27) => 0.0261292
+(1, 29) ~ (2, 28) => 0.827432
+(1, 29) ~ (2, 29) => 0.0460351
+(1, 29) ~ (2, 30) => 0.0183381
+(1, 30) ~ (2, 27) => 0.0158313
+(1, 30) ~ (2, 28) => 0.0195295
+(1, 30) ~ (2, 29) => 0.886837
+(1, 30) ~ (2, 30) => 0.0386063
+(1, 30) ~ (2, 31) => 0.0154692
+(1, 31) ~ (2, 28) => 0.0105547
+(1, 31) ~ (2, 30) => 0.914645
+(1, 31) ~ (2, 31) => 0.0333228
+(1, 31) ~ (2, 32) => 0.013625
+(1, 32) ~ (2, 31) => 0.930864
+(1, 32) ~ (2, 32) => 0.0270294
+(1, 32) ~ (2, 33) => 0.0116473
+(1, 33) ~ (2, 32) => 0.942938
+(1, 33) ~ (2, 33) => 0.0200568
+(1, 34) ~ (2, 33) => 0.95557
+(1, 35) ~ (2, 34) => 0.973041
+(1, 36) ~ (2, 35) => 0.968987
+(1, 36) ~ (2, 36) => 0.0107443
+(1, 37) ~ (2, 36) => 0.964048
+(1, 37) ~ (2, 37) => 0.0117784
+(1, 38) ~ (2, 37) => 0.948846
+(1, 38) ~ (2, 38) => 0.0119975
+(1, 39) ~ (2, 37) => 0.0155902
+(1, 39) ~ (2, 38) => 0.933506
+(1, 39) ~ (2, 39) => 0.0116302
+(1, 40) ~ (2, 37) => 0.0112244
+(1, 40) ~ (2, 38) => 0.0228651
+(1, 40) ~ (2, 39) => 0.918937
+(1, 40) ~ (2, 40) => 0.010607
+(1, 41) ~ (2, 38) => 0.018838
+(1, 41) ~ (2, 39) => 0.0290577
+(1, 41) ~ (2, 40) => 0.900594
+(1, 42) ~ (2, 39) => 0.0266084
+(1, 42) ~ (2, 40) => 0.0331291
+(1, 42) ~ (2, 41) => 0.873648
+(1, 43) ~ (2, 40) => 0.04014
+(1, 43) ~ (2, 41) => 0.0407139
+(1, 43) ~ (2, 42) => 0.826359
+(1, 44) ~ (2, 41) => 0.0587632
+(1, 44) ~ (2, 42) => 0.0498568
+(1, 44) ~ (2, 43) => 0.780012
+(1, 45) ~ (2, 42) => 0.0967448
+(1, 45) ~ (2, 43) => 0.0471639
+(1, 45) ~ (2, 44) => 0.703343
+(1, 45) ~ (2, 46) => 0.0127504
+(1, 46) ~ (2, 43) => 0.14613
+(1, 46) ~ (2, 44) => 0.0443921
+(1, 46) ~ (2, 45) => 0.625478
+(1, 46) ~ (2, 46) => 0.0144963
+(1, 46) ~ (2, 47) => 0.0151322
+(1, 47) ~ (2, 44) => 0.223216
+(1, 47) ~ (2, 45) => 0.0329079
+(1, 47) ~ (2, 46) => 0.613432
+(1, 47) ~ (2, 47) => 0.0149047
+(1, 47) ~ (2, 48) => 0.0153323
+(1, 48) ~ (2, 45) => 0.302547
+(1, 48) ~ (2, 46) => 0.035359
+(1, 48) ~ (2, 47) => 0.597552
+(1, 48) ~ (2, 48) => 0.0135077
+(1, 48) ~ (2, 49) => 0.0156507
+(1, 49) ~ (2, 46) => 0.308441
+(1, 49) ~ (2, 47) => 0.043701
+(1, 49) ~ (2, 48) => 0.592943
+(1, 49) ~ (2, 49) => 0.0112589
+(1, 49) ~ (2, 50) => 0.0157552
+(1, 50) ~ (2, 47) => 0.313471
+(1, 50) ~ (2, 48) => 0.0468578
+(1, 50) ~ (2, 49) => 0.591521
+(1, 50) ~ (2, 51) => 0.0161321
+(1, 51) ~ (2, 48) => 0.315013
+(1, 51) ~ (2, 49) => 0.0501163
+(1, 51) ~ (2, 50) => 0.591645
+(1, 51) ~ (2, 52) => 0.0193748
+(1, 52) ~ (2, 49) => 0.313769
+(1, 52) ~ (2, 50) => 0.0496715
+(1, 52) ~ (2, 51) => 0.587646
+(1, 52) ~ (2, 53) => 0.0208746
+(1, 53) ~ (2, 50) => 0.309046
+(1, 53) ~ (2, 51) => 0.0430758
+(1, 53) ~ (2, 52) => 0.603282
+(1, 53) ~ (2, 54) => 0.0202618
+(1, 54) ~ (2, 51) => 0.304874
+(1, 54) ~ (2, 52) => 0.0354613
+(1, 54) ~ (2, 53) => 0.617142
+(1, 54) ~ (2, 55) => 0.0233862
+(1, 55) ~ (2, 52) => 0.298343
+(1, 55) ~ (2, 53) => 0.0210639
+(1, 55) ~ (2, 54) => 0.636886
+(1, 55) ~ (2, 56) => 0.0264612
+(1, 56) ~ (2, 53) => 0.299335
+(1, 56) ~ (2, 54) => 0.015838
+(1, 56) ~ (2, 55) => 0.636192
+(1, 56) ~ (2, 57) => 0.0279195
+(1, 57) ~ (2, 54) => 0.303092
+(1, 57) ~ (2, 55) => 0.0134675
+(1, 57) ~ (2, 56) => 0.63735
+(1, 57) ~ (2, 58) => 0.02958
+(1, 58) ~ (2, 55) => 0.300742
+(1, 58) ~ (2, 56) => 0.0145571
+(1, 58) ~ (2, 57) => 0.629349
+(1, 58) ~ (2, 59) => 0.0293924
+(1, 59) ~ (2, 56) => 0.29945
+(1, 59) ~ (2, 57) => 0.0189903
+(1, 59) ~ (2, 58) => 0.624073
+(1, 59) ~ (2, 60) => 0.0294932
+(1, 60) ~ (2, 57) => 0.289743
+(1, 60) ~ (2, 58) => 0.0291215
+(1, 60) ~ (2, 59) => 0.572471
+(1, 60) ~ (2, 60) => 0.0179927
+(1, 60) ~ (2, 61) => 0.0210304
+(1, 61) ~ (2, 58) => 0.268128
+(1, 61) ~ (2, 59) => 0.0840586
+(1, 61) ~ (2, 60) => 0.494549
+(1, 61) ~ (2, 61) => 0.0459014
+(1, 61) ~ (2, 62) => 0.0186935
+(1, 62) ~ (2, 59) => 0.248421
+(1, 62) ~ (2, 60) => 0.154721
+(1, 62) ~ (2, 61) => 0.361991
+(1, 62) ~ (2, 62) => 0.0684231
+(1, 62) ~ (2, 63) => 0.0173149
+(1, 63) ~ (2, 60) => 0.194387
+(1, 63) ~ (2, 61) => 0.319991
+(1, 63) ~ (2, 62) => 0.305419
+(1, 63) ~ (2, 63) => 0.0750051
+(1, 63) ~ (2, 64) => 0.0144464
+(1, 64) ~ (2, 61) => 0.13873
+(1, 64) ~ (2, 62) => 0.427606
+(1, 64) ~ (2, 63) => 0.269754
+(1, 64) ~ (2, 64) => 0.0710729
+(1, 64) ~ (2, 65) => 0.0133189
+(1, 65) ~ (2, 62) => 0.118507
+(1, 65) ~ (2, 63) => 0.491523
+(1, 65) ~ (2, 64) => 0.229984
+(1, 65) ~ (2, 65) => 0.0694424
+(1, 65) ~ (2, 66) => 0.0122065
+(1, 66) ~ (2, 63) => 0.105104
+(1, 66) ~ (2, 64) => 0.550619
+(1, 66) ~ (2, 65) => 0.203126
+(1, 66) ~ (2, 66) => 0.0680489
+(1, 66) ~ (2, 67) => 0.0110251
+(1, 67) ~ (2, 64) => 0.0940696
+(1, 67) ~ (2, 65) => 0.592731
+(1, 67) ~ (2, 66) => 0.161364
+(1, 67) ~ (2, 67) => 0.0614782
+(1, 67) ~ (2, 68) => 0.0101097
+(1, 68) ~ (2, 65) => 0.0832261
+(1, 68) ~ (2, 66) => 0.649777
+(1, 68) ~ (2, 67) => 0.113081
+(1, 68) ~ (2, 68) => 0.0531234
+(1, 69) ~ (2, 66) => 0.0730256
+(1, 69) ~ (2, 67) => 0.720741
+(1, 69) ~ (2, 68) => 0.0732072
+(1, 69) ~ (2, 69) => 0.0487046
+(1, 70) ~ (2, 67) => 0.0667276
+(1, 70) ~ (2, 68) => 0.779968
+(1, 70) ~ (2, 69) => 0.0432773
+(1, 70) ~ (2, 70) => 0.0467504
+(1, 71) ~ (2, 68) => 0.05794
+(1, 71) ~ (2, 69) => 0.822878
+(1, 71) ~ (2, 70) => 0.0294395
+(1, 71) ~ (2, 71) => 0.0399446
+(1, 72) ~ (2, 69) => 0.0505023
+(1, 72) ~ (2, 70) => 0.848721
+(1, 72) ~ (2, 71) => 0.0138873
+(1, 72) ~ (2, 72) => 0.0413473
+(1, 73) ~ (2, 70) => 0.0399709
+(1, 73) ~ (2, 71) => 0.879818
+(1, 73) ~ (2, 72) => 0.0124191
+(1, 73) ~ (2, 73) => 0.0400373
+(1, 74) ~ (2, 71) => 0.0373395
+(1, 74) ~ (2, 72) => 0.878766
+(1, 74) ~ (2, 73) => 0.0128142
+(1, 74) ~ (2, 74) => 0.0346456
+(1, 74) ~ (2, 75) => 0.0120938
+(1, 75) ~ (2, 72) => 0.0374456
+(1, 75) ~ (2, 73) => 0.882257
+(1, 75) ~ (2, 74) => 0.0160001
+(1, 75) ~ (2, 75) => 0.0262023
+(1, 75) ~ (2, 76) => 0.0141676
+(1, 76) ~ (2, 73) => 0.0411564
+(1, 76) ~ (2, 74) => 0.875654
+(1, 76) ~ (2, 75) => 0.0242115
+(1, 76) ~ (2, 76) => 0.018879
+(1, 76) ~ (2, 77) => 0.0167414
+(1, 77) ~ (2, 74) => 0.040077
+(1, 77) ~ (2, 75) => 0.874955
+(1, 77) ~ (2, 76) => 0.032268
+(1, 77) ~ (2, 77) => 0.0138322
+(1, 77) ~ (2, 78) => 0.0154469
+(1, 78) ~ (2, 75) => 0.0377049
+(1, 78) ~ (2, 76) => 0.873959
+(1, 78) ~ (2, 77) => 0.0387182
+(1, 78) ~ (2, 78) => 0.0117949
+(1, 78) ~ (2, 79) => 0.0138722
+(1, 79) ~ (2, 76) => 0.0343727
+(1, 79) ~ (2, 77) => 0.866346
+(1, 79) ~ (2, 78) => 0.0563503
+(1, 79) ~ (2, 79) => 0.0101123
+(1, 79) ~ (2, 80) => 0.011412
+(1, 80) ~ (2, 77) => 0.0224196
+(1, 80) ~ (2, 78) => 0.873832
+(1, 80) ~ (2, 79) => 0.0621327
+(1, 81) ~ (2, 78) => 0.0189537
+(1, 81) ~ (2, 79) => 0.877208
+(1, 81) ~ (2, 80) => 0.0625152
+(1, 81) ~ (2, 81) => 0.0112804
+(1, 82) ~ (2, 79) => 0.0107597
+(1, 82) ~ (2, 80) => 0.87903
+(1, 82) ~ (2, 81) => 0.0768312
+(1, 82) ~ (2, 82) => 0.0107417
+(1, 83) ~ (2, 81) => 0.814003
+(1, 83) ~ (2, 82) => 0.140112
+(1, 83) ~ (2, 83) => 0.013837
+(1, 84) ~ (2, 81) => 0.0102431
+(1, 84) ~ (2, 82) => 0.748324
+(1, 84) ~ (2, 83) => 0.20077
+(1, 84) ~ (2, 84) => 0.0159829
+(1, 85) ~ (2, 82) => 0.0107817
+(1, 85) ~ (2, 83) => 0.663804
+(1, 85) ~ (2, 84) => 0.266832
+(1, 85) ~ (2, 85) => 0.0258246
+(1, 86) ~ (2, 83) => 0.0202943
+(1, 86) ~ (2, 84) => 0.602306
+(1, 86) ~ (2, 85) => 0.321321
+(1, 86) ~ (2, 86) => 0.0259163
+(1, 87) ~ (2, 84) => 0.0205343
+(1, 87) ~ (2, 85) => 0.583567
+(1, 87) ~ (2, 86) => 0.344478
+(1, 87) ~ (2, 87) => 0.0255732
+(1, 88) ~ (2, 85) => 0.0207033
+(1, 88) ~ (2, 86) => 0.563291
+(1, 88) ~ (2, 87) => 0.365824
+(1, 88) ~ (2, 88) => 0.024726
+(1, 89) ~ (2, 86) => 0.020376
+(1, 89) ~ (2, 87) => 0.543333
+(1, 89) ~ (2, 88) => 0.387105
+(1, 89) ~ (2, 89) => 0.0234993
+(1, 90) ~ (2, 87) => 0.0196373
+(1, 90) ~ (2, 88) => 0.523655
+(1, 90) ~ (2, 89) => 0.40848
+(1, 90) ~ (2, 90) => 0.0218453
+(1, 91) ~ (2, 88) => 0.0184373
+(1, 91) ~ (2, 89) => 0.50363
+(1, 91) ~ (2, 90) => 0.429863
+(1, 91) ~ (2, 91) => 0.0192896
+(1, 92) ~ (2, 89) => 0.0162555
+(1, 92) ~ (2, 90) => 0.479382
+(1, 92) ~ (2, 91) => 0.446559
+(1, 92) ~ (2, 92) => 0.0259362
+(1, 93) ~ (2, 90) => 0.0136455
+(1, 93) ~ (2, 91) => 0.445265
+(1, 93) ~ (2, 92) => 0.476118
+(1, 93) ~ (2, 93) => 0.0305466
+(1, 94) ~ (2, 90) => 0.0107857
+(1, 94) ~ (2, 92) => 0.425591
+(1, 94) ~ (2, 93) => 0.494269
+(1, 94) ~ (2, 94) => 0.0334878
+(1, 95) ~ (2, 91) => 0.0125162
+(1, 95) ~ (2, 93) => 0.404787
+(1, 95) ~ (2, 94) => 0.511392
+(1, 95) ~ (2, 95) => 0.0355268
+(1, 96) ~ (2, 92) => 0.0140145
+(1, 96) ~ (2, 94) => 0.386103
+(1, 96) ~ (2, 95) => 0.53082
+(1, 96) ~ (2, 96) => 0.0334272
+(1, 97) ~ (2, 93) => 0.0157107
+(1, 97) ~ (2, 95) => 0.382154
+(1, 97) ~ (2, 96) => 0.531695
+(1, 97) ~ (2, 97) => 0.0335407
+(1, 98) ~ (2, 94) => 0.0176665
+(1, 98) ~ (2, 96) => 0.34229
+(1, 98) ~ (2, 97) => 0.554646
+(1, 98) ~ (2, 98) => 0.035199
+(1, 99) ~ (2, 95) => 0.0181342
+(1, 99) ~ (2, 96) => 0.0106321
+(1, 99) ~ (2, 97) => 0.343809
+(1, 99) ~ (2, 98) => 0.547122
+(1, 99) ~ (2, 99) => 0.0340438
+(1, 100) ~ (2, 96) => 0.0220976
+(1, 100) ~ (2, 97) => 0.0159121
+(1, 100) ~ (2, 98) => 0.342364
+(1, 100) ~ (2, 99) => 0.535001
+(1, 100) ~ (2, 100) => 0.0311686
+(1, 101) ~ (2, 97) => 0.0225695
+(1, 101) ~ (2, 98) => 0.0228608
+(1, 101) ~ (2, 99) => 0.344719
+(1, 101) ~ (2, 100) => 0.524369
+(1, 101) ~ (2, 101) => 0.0279266
+(1, 102) ~ (2, 98) => 0.0235268
+(1, 102) ~ (2, 99) => 0.030423
+(1, 102) ~ (2, 100) => 0.347359
+(1, 102) ~ (2, 101) => 0.514145
+(1, 102) ~ (2, 102) => 0.0240638
+(1, 103) ~ (2, 99) => 0.0246442
+(1, 103) ~ (2, 100) => 0.0376125
+(1, 103) ~ (2, 101) => 0.349494
+(1, 103) ~ (2, 102) => 0.502752
+(1, 103) ~ (2, 103) => 0.0213362
+(1, 104) ~ (2, 99) => 0.0102728
+(1, 104) ~ (2, 100) => 0.0263118
+(1, 104) ~ (2, 101) => 0.0459499
+(1, 104) ~ (2, 102) => 0.355941
+(1, 104) ~ (2, 103) => 0.479183
+(1, 104) ~ (2, 104) => 0.0196204
+(1, 105) ~ (2, 100) => 0.0114838
+(1, 105) ~ (2, 101) => 0.0279284
+(1, 105) ~ (2, 102) => 0.0529103
+(1, 105) ~ (2, 103) => 0.368635
+(1, 105) ~ (2, 104) => 0.462977
+(1, 105) ~ (2, 105) => 0.0184589
+(1, 106) ~ (2, 101) => 0.012064
+(1, 106) ~ (2, 102) => 0.0272517
+(1, 106) ~ (2, 103) => 0.0677298
+(1, 106) ~ (2, 104) => 0.373441
+(1, 106) ~ (2, 105) => 0.446071
+(1, 106) ~ (2, 106) => 0.0167508
+(1, 107) ~ (2, 102) => 0.0120302
+(1, 107) ~ (2, 103) => 0.0293463
+(1, 107) ~ (2, 104) => 0.0788439
+(1, 107) ~ (2, 105) => 0.376618
+(1, 107) ~ (2, 106) => 0.426185
+(1, 107) ~ (2, 107) => 0.013961
+(1, 108) ~ (2, 103) => 0.0130347
+(1, 108) ~ (2, 104) => 0.0304266
+(1, 108) ~ (2, 105) => 0.0890086
+(1, 108) ~ (2, 106) => 0.374281
+(1, 108) ~ (2, 107) => 0.39512
+(1, 109) ~ (2, 104) => 0.014761
+(1, 109) ~ (2, 105) => 0.0331751
+(1, 109) ~ (2, 106) => 0.107084
+(1, 109) ~ (2, 107) => 0.382677
+(1, 109) ~ (2, 108) => 0.372634
+(1, 110) ~ (2, 105) => 0.0169634
+(1, 110) ~ (2, 106) => 0.0370756
+(1, 110) ~ (2, 107) => 0.126844
+(1, 110) ~ (2, 108) => 0.384733
+(1, 110) ~ (2, 109) => 0.37508
+(1, 111) ~ (2, 106) => 0.018749
+(1, 111) ~ (2, 107) => 0.0386204
+(1, 111) ~ (2, 108) => 0.135027
+(1, 111) ~ (2, 109) => 0.38464
+(1, 111) ~ (2, 110) => 0.383956
+(1, 112) ~ (2, 107) => 0.0217494
+(1, 112) ~ (2, 108) => 0.0426043
+(1, 112) ~ (2, 109) => 0.116077
+(1, 112) ~ (2, 110) => 0.331632
+(1, 112) ~ (2, 111) => 0.438426
+(1, 113) ~ (2, 108) => 0.022966
+(1, 113) ~ (2, 109) => 0.0525866
+(1, 113) ~ (2, 110) => 0.100468
+(1, 113) ~ (2, 111) => 0.323153
+(1, 113) ~ (2, 112) => 0.46567
+(1, 113) ~ (2, 113) => 0.0106273
+(1, 114) ~ (2, 109) => 0.0214981
+(1, 114) ~ (2, 110) => 0.0515125
+(1, 114) ~ (2, 111) => 0.0927562
+(1, 114) ~ (2, 112) => 0.332265
+(1, 114) ~ (2, 113) => 0.468257
+(1, 114) ~ (2, 114) => 0.0109591
+(1, 115) ~ (2, 110) => 0.0148399
+(1, 115) ~ (2, 111) => 0.0555325
+(1, 115) ~ (2, 112) => 0.0947291
+(1, 115) ~ (2, 113) => 0.330329
+(1, 115) ~ (2, 114) => 0.46052
+(1, 116) ~ (2, 111) => 0.0112013
+(1, 116) ~ (2, 112) => 0.0622088
+(1, 116) ~ (2, 113) => 0.087186
+(1, 116) ~ (2, 114) => 0.292609
+(1, 116) ~ (2, 115) => 0.357443
+(1, 117) ~ (2, 113) => 0.0771577
+(1, 117) ~ (2, 114) => 0.0758997
+(1, 117) ~ (2, 115) => 0.222357
+(1, 117) ~ (2, 116) => 0.217988
+(1, 118) ~ (2, 114) => 0.140479
+(1, 118) ~ (2, 115) => 0.0772043
+(1, 118) ~ (2, 116) => 0.149643
+(1, 119) ~ (2, 115) => 0.324141
+(1, 119) ~ (2, 116) => 0.0668753
+(1, 120) ~ (2, 116) => 0.553252
+
+; gap posteriors
+(1, 0) ~ (2, -1) => 0.0533242
+(1, 1) ~ (2, -1) => 0.0995525
+(1, 2) ~ (2, -1) => 0.0973192
+(1, 3) ~ (2, -1) => 0.0864747
+(1, 4) ~ (2, -1) => 0.232407
+(1, 5) ~ (2, -1) => 0.169008
+(1, 6) ~ (2, -1) => 0.0802323
+(1, 7) ~ (2, -1) => 0.0666689
+(1, 8) ~ (2, -1) => 0.0374177
+(1, 9) ~ (2, -1) => 0.0378729
+(1, 10) ~ (2, -1) => 0.0556848
+(1, 11) ~ (2, -1) => 0.0571779
+(1, 12) ~ (2, -1) => 0.0567815
+(1, 13) ~ (2, -1) => 0.0505599
+(1, 14) ~ (2, -1) => 0.0453633
+(1, 15) ~ (2, -1) => 0.059978
+(1, 16) ~ (2, -1) => 0.0520169
+(1, 17) ~ (2, -1) => 0.0684326
+(1, 18) ~ (2, -1) => 0.0759452
+(1, 19) ~ (2, -1) => 0.0601686
+(1, 20) ~ (2, -1) => 0.0423847
+(1, 21) ~ (2, -1) => 0.0456207
+(1, 22) ~ (2, -1) => 0.0559075
+(1, 23) ~ (2, -1) => 0.0562205
+(1, 24) ~ (2, -1) => 0.0507723
+(1, 25) ~ (2, -1) => 0.0580846
+(1, 26) ~ (2, -1) => 0.063112
+(1, 27) ~ (2, -1) => 0.0659144
+(1, 28) ~ (2, -1) => 0.0753717
+(1, 29) ~ (2, -1) => 0.0601827
+(1, 30) ~ (2, -1) => 0.0237265
+(1, 31) ~ (2, -1) => 0.0278529
+(1, 32) ~ (2, -1) => 0.0304594
+(1, 33) ~ (2, -1) => 0.0370054
+(1, 34) ~ (2, -1) => 0.0444305
+(1, 35) ~ (2, -1) => 0.0269588
+(1, 36) ~ (2, -1) => 0.0202682
+(1, 37) ~ (2, -1) => 0.024174
+(1, 38) ~ (2, -1) => 0.0391565
+(1, 39) ~ (2, -1) => 0.0392738
+(1, 40) ~ (2, -1) => 0.0363661
+(1, 41) ~ (2, -1) => 0.0515102
+(1, 42) ~ (2, -1) => 0.066614
+(1, 43) ~ (2, -1) => 0.0927873
+(1, 44) ~ (2, -1) => 0.111368
+(1, 45) ~ (2, -1) => 0.139998
+(1, 46) ~ (2, -1) => 0.154371
+(1, 47) ~ (2, -1) => 0.100207
+(1, 48) ~ (2, -1) => 0.0353831
+(1, 49) ~ (2, -1) => 0.0279008
+(1, 50) ~ (2, -1) => 0.0320188
+(1, 51) ~ (2, -1) => 0.0238514
+(1, 52) ~ (2, -1) => 0.0280386
+(1, 53) ~ (2, -1) => 0.0243347
+(1, 54) ~ (2, -1) => 0.0191365
+(1, 55) ~ (2, -1) => 0.0172464
+(1, 56) ~ (2, -1) => 0.0207147
+(1, 57) ~ (2, -1) => 0.016511
+(1, 58) ~ (2, -1) => 0.0259595
+(1, 59) ~ (2, -1) => 0.0279939
+(1, 60) ~ (2, -1) => 0.0696409
+(1, 61) ~ (2, -1) => 0.0886693
+(1, 62) ~ (2, -1) => 0.149129
+(1, 63) ~ (2, -1) => 0.0907513
+(1, 64) ~ (2, -1) => 0.0795182
+(1, 65) ~ (2, -1) => 0.0783374
+(1, 66) ~ (2, -1) => 0.0620767
+(1, 67) ~ (2, -1) => 0.0802483
+(1, 68) ~ (2, -1) => 0.100793
+(1, 69) ~ (2, -1) => 0.084322
+(1, 70) ~ (2, -1) => 0.0632767
+(1, 71) ~ (2, -1) => 0.049798
+(1, 72) ~ (2, -1) => 0.0455418
+(1, 73) ~ (2, -1) => 0.0277549
+(1, 74) ~ (2, -1) => 0.0243411
+(1, 75) ~ (2, -1) => 0.0239275
+(1, 76) ~ (2, -1) => 0.023358
+(1, 77) ~ (2, -1) => 0.0234212
+(1, 78) ~ (2, -1) => 0.0239506
+(1, 79) ~ (2, -1) => 0.0214072
+(1, 80) ~ (2, -1) => 0.041616
+(1, 81) ~ (2, -1) => 0.0300431
+(1, 82) ~ (2, -1) => 0.0226379
+(1, 83) ~ (2, -1) => 0.0320482
+(1, 84) ~ (2, -1) => 0.0246805
+(1, 85) ~ (2, -1) => 0.032758
+(1, 86) ~ (2, -1) => 0.0301624
+(1, 87) ~ (2, -1) => 0.0258475
+(1, 88) ~ (2, -1) => 0.0254552
+(1, 89) ~ (2, -1) => 0.0256867
+(1, 90) ~ (2, -1) => 0.0263826
+(1, 91) ~ (2, -1) => 0.02878
+(1, 92) ~ (2, -1) => 0.0318665
+(1, 93) ~ (2, -1) => 0.0344249
+(1, 94) ~ (2, -1) => 0.0358664
+(1, 95) ~ (2, -1) => 0.0357784
+(1, 96) ~ (2, -1) => 0.0356352
+(1, 97) ~ (2, -1) => 0.036899
+(1, 98) ~ (2, -1) => 0.0501987
+(1, 99) ~ (2, -1) => 0.0462593
+(1, 100) ~ (2, -1) => 0.0534571
+(1, 101) ~ (2, -1) => 0.0575555
+(1, 102) ~ (2, -1) => 0.0604822
+(1, 103) ~ (2, -1) => 0.0641621
+(1, 104) ~ (2, -1) => 0.0627212
+(1, 105) ~ (2, -1) => 0.0576066
+(1, 106) ~ (2, -1) => 0.0566919
+(1, 107) ~ (2, -1) => 0.0630161
+(1, 108) ~ (2, -1) => 0.0981291
+(1, 109) ~ (2, -1) => 0.0896686
+(1, 110) ~ (2, -1) => 0.0593034
+(1, 111) ~ (2, -1) => 0.0390079
+(1, 112) ~ (2, -1) => 0.0495115
+(1, 113) ~ (2, -1) => 0.0245297
+(1, 114) ~ (2, -1) => 0.022752
+(1, 115) ~ (2, -1) => 0.0440501
+(1, 116) ~ (2, -1) => 0.189352
+(1, 117) ~ (2, -1) => 0.406598
+(1, 118) ~ (2, -1) => 0.632673
+(1, 119) ~ (2, -1) => 0.608984
+(1, 120) ~ (2, -1) => 0.446748
+
+(1, -1) ~ (2, 0) => 0.0278107
+(1, -1) ~ (2, 1) => 0.0321116
+(1, -1) ~ (2, 2) => 0.0493122
+(1, -1) ~ (2, 3) => 0.0548331
+(1, -1) ~ (2, 4) => 0.0357971
+(1, -1) ~ (2, 5) => 0.0706126
+(1, -1) ~ (2, 6) => 0.0273685
+(1, -1) ~ (2, 7) => 0.0206333
+(1, -1) ~ (2, 8) => 0.0232158
+(1, -1) ~ (2, 9) => 0.0460211
+(1, -1) ~ (2, 10) => 0.0378096
+(1, -1) ~ (2, 11) => 0.034949
+(1, -1) ~ (2, 12) => 0.0493049
+(1, -1) ~ (2, 13) => 0.0369203
+(1, -1) ~ (2, 14) => 0.0443864
+(1, -1) ~ (2, 15) => 0.0321862
+(1, -1) ~ (2, 16) => 0.0310346
+(1, -1) ~ (2, 17) => 0.0740055
+(1, -1) ~ (2, 18) => 0.0331325
+(1, -1) ~ (2, 19) => 0.0229255
+(1, -1) ~ (2, 20) => 0.0359412
+(1, -1) ~ (2, 21) => 0.0400348
+(1, -1) ~ (2, 22) => 0.0596792
+(1, -1) ~ (2, 23) => 0.0444861
+(1, -1) ~ (2, 24) => 0.0361366
+(1, -1) ~ (2, 25) => 0.0396835
+(1, -1) ~ (2, 26) => 0.0342379
+(1, -1) ~ (2, 27) => 0.0485015
+(1, -1) ~ (2, 28) => 0.0302664
+(1, -1) ~ (2, 29) => 0.0482048
+(1, -1) ~ (2, 30) => 0.028411
+(1, -1) ~ (2, 31) => 0.0203441
+(1, -1) ~ (2, 32) => 0.016408
+(1, -1) ~ (2, 33) => 0.0127263
+(1, -1) ~ (2, 34) => 0.0269588
+(1, -1) ~ (2, 35) => 0.0310125
+(1, -1) ~ (2, 36) => 0.025208
+(1, -1) ~ (2, 37) => 0.012561
+(1, -1) ~ (2, 38) => 0.0127936
+(1, -1) ~ (2, 39) => 0.0137663
+(1, -1) ~ (2, 40) => 0.0155297
+(1, -1) ~ (2, 41) => 0.0268745
+(1, -1) ~ (2, 42) => 0.0270396
+(1, -1) ~ (2, 43) => 0.0266939
+(1, -1) ~ (2, 44) => 0.0290496
+(1, -1) ~ (2, 45) => 0.039067
+(1, -1) ~ (2, 46) => 0.015521
+(1, -1) ~ (2, 47) => 0.0152388
+(1, -1) ~ (2, 48) => 0.0163464
+(1, -1) ~ (2, 49) => 0.0176841
+(1, -1) ~ (2, 50) => 0.0338828
+(1, -1) ~ (2, 51) => 0.0482727
+(1, -1) ~ (2, 52) => 0.0435395
+(1, -1) ~ (2, 53) => 0.0415836
+(1, -1) ~ (2, 54) => 0.0239226
+(1, -1) ~ (2, 55) => 0.0262116
+(1, -1) ~ (2, 56) => 0.0221824
+(1, -1) ~ (2, 57) => 0.0339982
+(1, -1) ~ (2, 58) => 0.0490972
+(1, -1) ~ (2, 59) => 0.0656571
+(1, -1) ~ (2, 60) => 0.108857
+(1, -1) ~ (2, 61) => 0.112356
+(1, -1) ~ (2, 62) => 0.0613523
+(1, -1) ~ (2, 63) => 0.0412989
+(1, -1) ~ (2, 64) => 0.0398079
+(1, -1) ~ (2, 65) => 0.0381556
+(1, -1) ~ (2, 66) => 0.035578
+(1, -1) ~ (2, 67) => 0.0269479
+(1, -1) ~ (2, 68) => 0.0256518
+(1, -1) ~ (2, 69) => 0.0346379
+(1, -1) ~ (2, 70) => 0.0351177
+(1, -1) ~ (2, 71) => 0.0290109
+(1, -1) ~ (2, 72) => 0.0300224
+(1, -1) ~ (2, 73) => 0.0237351
+(1, -1) ~ (2, 74) => 0.0336235
+(1, -1) ~ (2, 75) => 0.0248329
+(1, -1) ~ (2, 76) => 0.0263534
+(1, -1) ~ (2, 77) => 0.0419431
+(1, -1) ~ (2, 78) => 0.0236225
+(1, -1) ~ (2, 79) => 0.0259155
+(1, -1) ~ (2, 80) => 0.0470433
+(1, -1) ~ (2, 81) => 0.0876422
+(1, -1) ~ (2, 82) => 0.0900412
+(1, -1) ~ (2, 83) => 0.101295
+(1, -1) ~ (2, 84) => 0.094345
+(1, -1) ~ (2, 85) => 0.0485834
+(1, -1) ~ (2, 86) => 0.0459386
+(1, -1) ~ (2, 87) => 0.0456326
+(1, -1) ~ (2, 88) => 0.046077
+(1, -1) ~ (2, 89) => 0.0481353
+(1, -1) ~ (2, 90) => 0.044478
+(1, -1) ~ (2, 91) => 0.07637
+(1, -1) ~ (2, 92) => 0.0583397
+(1, -1) ~ (2, 93) => 0.0546871
+(1, -1) ~ (2, 94) => 0.0513507
+(1, -1) ~ (2, 95) => 0.0333645
+(1, -1) ~ (2, 96) => 0.0598577
+(1, -1) ~ (2, 97) => 0.0295233
+(1, -1) ~ (2, 98) => 0.028928
+(1, -1) ~ (2, 99) => 0.0208968
+(1, -1) ~ (2, 100) => 0.0216952
+(1, -1) ~ (2, 101) => 0.0224925
+(1, -1) ~ (2, 102) => 0.0250516
+(1, -1) ~ (2, 103) => 0.0207347
+(1, -1) ~ (2, 104) => 0.0199305
+(1, -1) ~ (2, 105) => 0.019705
+(1, -1) ~ (2, 106) => 0.0198746
+(1, -1) ~ (2, 107) => 0.0210281
+(1, -1) ~ (2, 108) => 0.0420354
+(1, -1) ~ (2, 109) => 0.0501183
+(1, -1) ~ (2, 110) => 0.117592
+(1, -1) ~ (2, 111) => 0.0789314
+(1, -1) ~ (2, 112) => 0.0451272
+(1, -1) ~ (2, 113) => 0.0264435
+(1, -1) ~ (2, 114) => 0.0195325
+(1, -1) ~ (2, 115) => 0.0188555
+(1, -1) ~ (2, 116) => 0.0122418
+
+; Sparse posterior probability matrix for sequences 1 and 3
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (3, 0) => 0.999999
+(1, 1) ~ (3, 1) => 0.999995
+(1, 2) ~ (3, 2) => 0.999985
+(1, 3) ~ (3, 3) => 0.999889
+(1, 4) ~ (3, 4) => 0.999874
+(1, 5) ~ (3, 5) => 0.999873
+(1, 6) ~ (3, 6) => 0.999908
+(1, 7) ~ (3, 7) => 0.999919
+(1, 8) ~ (3, 8) => 0.999934
+(1, 9) ~ (3, 9) => 0.999983
+(1, 10) ~ (3, 10) => 0.999988
+(1, 11) ~ (3, 11) => 0.999982
+(1, 12) ~ (3, 12) => 0.999979
+(1, 13) ~ (3, 13) => 0.99999
+(1, 14) ~ (3, 14) => 0.999999
+(1, 15) ~ (3, 15) => 0.999998
+(1, 16) ~ (3, 16) => 0.999998
+(1, 17) ~ (3, 17) => 0.999988
+(1, 18) ~ (3, 18) => 0.999981
+(1, 19) ~ (3, 19) => 0.999987
+(1, 20) ~ (3, 20) => 0.999996
+(1, 21) ~ (3, 21) => 0.999999
+(1, 22) ~ (3, 22) => 0.999999
+(1, 23) ~ (3, 23) => 0.999997
+(1, 24) ~ (3, 24) => 0.999998
+(1, 25) ~ (3, 25) => 0.999999
+(1, 26) ~ (3, 26) => 0.999998
+(1, 27) ~ (3, 27) => 0.999998
+(1, 28) ~ (3, 28) => 0.999994
+(1, 29) ~ (3, 29) => 0.999993
+(1, 30) ~ (3, 30) => 0.999995
+(1, 31) ~ (3, 31) => 0.999989
+(1, 32) ~ (3, 32) => 0.999987
+(1, 33) ~ (3, 33) => 0.99999
+(1, 34) ~ (3, 34) => 0.999998
+(1, 35) ~ (3, 35) => 0.999999
+(1, 36) ~ (3, 36) => 0.999997
+(1, 37) ~ (3, 37) => 0.999995
+(1, 38) ~ (3, 38) => 0.999985
+(1, 39) ~ (3, 39) => 0.999979
+(1, 40) ~ (3, 40) => 0.999979
+(1, 41) ~ (3, 41) => 0.999986
+(1, 42) ~ (3, 42) => 0.999998
+(1, 43) ~ (3, 43) => 0.999999
+(1, 44) ~ (3, 44) => 0.999998
+(1, 45) ~ (3, 45) => 0.999994
+(1, 46) ~ (3, 46) => 0.999992
+(1, 47) ~ (3, 47) => 0.999993
+(1, 48) ~ (3, 48) => 0.999996
+(1, 49) ~ (3, 49) => 0.999995
+(1, 50) ~ (3, 50) => 0.999996
+(1, 51) ~ (3, 51) => 0.999998
+(1, 52) ~ (3, 52) => 0.999998
+(1, 53) ~ (3, 53) => 0.999999
+(1, 54) ~ (3, 54) => 0.999998
+(1, 55) ~ (3, 55) => 0.999991
+(1, 56) ~ (3, 56) => 0.99998
+(1, 57) ~ (3, 57) => 0.999969
+(1, 58) ~ (3, 58) => 0.999909
+(1, 59) ~ (3, 59) => 0.999842
+(1, 60) ~ (3, 60) => 0.998969
+(1, 61) ~ (3, 61) => 0.998076
+(1, 62) ~ (3, 62) => 0.997816
+(1, 63) ~ (3, 63) => 0.997542
+(1, 64) ~ (3, 64) => 0.997481
+(1, 65) ~ (3, 65) => 0.995098
+(1, 66) ~ (3, 66) => 0.992859
+(1, 67) ~ (3, 67) => 0.992398
+(1, 68) ~ (3, 68) => 0.990694
+(1, 69) ~ (3, 69) => 0.989024
+(1, 70) ~ (3, 70) => 0.988881
+(1, 71) ~ (3, 71) => 0.989309
+(1, 72) ~ (3, 72) => 0.994666
+(1, 73) ~ (3, 73) => 0.997939
+(1, 74) ~ (3, 74) => 0.998304
+(1, 75) ~ (3, 75) => 0.998701
+(1, 76) ~ (3, 76) => 0.999292
+(1, 77) ~ (3, 77) => 0.999526
+(1, 78) ~ (3, 78) => 0.999742
+(1, 79) ~ (3, 79) => 0.999957
+(1, 80) ~ (3, 80) => 0.999988
+(1, 81) ~ (3, 81) => 0.999968
+(1, 82) ~ (3, 82) => 0.999319
+(1, 83) ~ (3, 83) => 0.99909
+(1, 84) ~ (3, 84) => 0.998565
+(1, 85) ~ (3, 85) => 0.998081
+(1, 86) ~ (3, 86) => 0.997952
+(1, 87) ~ (3, 87) => 0.993147
+(1, 88) ~ (3, 88) => 0.98832
+(1, 89) ~ (3, 89) => 0.98352
+(1, 90) ~ (3, 90) => 0.978747
+(1, 90) ~ (3, 91) => 0.0104724
+(1, 91) ~ (3, 91) => 0.964092
+(1, 91) ~ (3, 92) => 0.0128876
+(1, 91) ~ (3, 94) => 0.0203152
+(1, 92) ~ (3, 92) => 0.918312
+(1, 92) ~ (3, 93) => 0.0148008
+(1, 92) ~ (3, 95) => 0.0623527
+(1, 93) ~ (3, 93) => 0.914931
+(1, 93) ~ (3, 94) => 0.0142833
+(1, 93) ~ (3, 96) => 0.0657856
+(1, 94) ~ (3, 94) => 0.911129
+(1, 94) ~ (3, 95) => 0.0145292
+(1, 94) ~ (3, 97) => 0.0688287
+(1, 95) ~ (3, 95) => 0.890973
+(1, 95) ~ (3, 96) => 0.0168189
+(1, 95) ~ (3, 98) => 0.0842572
+(1, 96) ~ (3, 96) => 0.870903
+(1, 96) ~ (3, 97) => 0.0190278
+(1, 96) ~ (3, 99) => 0.0996572
+(1, 97) ~ (3, 97) => 0.820125
+(1, 97) ~ (3, 98) => 0.020595
+(1, 97) ~ (3, 99) => 0.0112229
+(1, 97) ~ (3, 100) => 0.146999
+(1, 98) ~ (3, 98) => 0.141339
+(1, 98) ~ (3, 100) => 0.0142477
+(1, 98) ~ (3, 101) => 0.834142
+(1, 99) ~ (3, 99) => 0.0354982
+(1, 99) ~ (3, 101) => 0.0110733
+(1, 99) ~ (3, 102) => 0.946965
+(1, 100) ~ (3, 103) => 0.985959
+(1, 101) ~ (3, 104) => 0.990537
+(1, 102) ~ (3, 105) => 0.991496
+(1, 103) ~ (3, 106) => 0.996662
+(1, 104) ~ (3, 107) => 0.996451
+(1, 105) ~ (3, 108) => 0.995791
+(1, 106) ~ (3, 109) => 0.995871
+(1, 107) ~ (3, 110) => 0.995709
+(1, 108) ~ (3, 111) => 0.995808
+(1, 109) ~ (3, 112) => 0.995372
+(1, 110) ~ (3, 113) => 0.995488
+(1, 111) ~ (3, 114) => 0.995841
+(1, 112) ~ (3, 115) => 0.996653
+(1, 113) ~ (3, 116) => 0.997334
+(1, 114) ~ (3, 117) => 0.997718
+(1, 115) ~ (3, 118) => 0.998463
+(1, 116) ~ (3, 119) => 0.9992
+(1, 117) ~ (3, 120) => 0.999861
+(1, 118) ~ (3, 121) => 0.999959
+(1, 119) ~ (3, 122) => 0.99998
+(1, 120) ~ (3, 123) => 0.999998
+
+; gap posteriors
+(1, 0) ~ (3, -1) => 0.0001
+(1, 1) ~ (3, -1) => 0.0001
+(1, 2) ~ (3, -1) => 0.0001
+(1, 3) ~ (3, -1) => 0.000110626
+(1, 4) ~ (3, -1) => 0.000126421
+(1, 5) ~ (3, -1) => 0.000127077
+(1, 6) ~ (3, -1) => 0.0001
+(1, 7) ~ (3, -1) => 0.0001
+(1, 8) ~ (3, -1) => 0.0001
+(1, 9) ~ (3, -1) => 0.0001
+(1, 10) ~ (3, -1) => 0.0001
+(1, 11) ~ (3, -1) => 0.0001
+(1, 12) ~ (3, -1) => 0.0001
+(1, 13) ~ (3, -1) => 0.0001
+(1, 14) ~ (3, -1) => 0.0001
+(1, 15) ~ (3, -1) => 0.0001
+(1, 16) ~ (3, -1) => 0.0001
+(1, 17) ~ (3, -1) => 0.0001
+(1, 18) ~ (3, -1) => 0.0001
+(1, 19) ~ (3, -1) => 0.0001
+(1, 20) ~ (3, -1) => 0.0001
+(1, 21) ~ (3, -1) => 0.0001
+(1, 22) ~ (3, -1) => 0.0001
+(1, 23) ~ (3, -1) => 0.0001
+(1, 24) ~ (3, -1) => 0.0001
+(1, 25) ~ (3, -1) => 0.0001
+(1, 26) ~ (3, -1) => 0.0001
+(1, 27) ~ (3, -1) => 0.0001
+(1, 28) ~ (3, -1) => 0.0001
+(1, 29) ~ (3, -1) => 0.0001
+(1, 30) ~ (3, -1) => 0.0001
+(1, 31) ~ (3, -1) => 0.0001
+(1, 32) ~ (3, -1) => 0.0001
+(1, 33) ~ (3, -1) => 0.0001
+(1, 34) ~ (3, -1) => 0.0001
+(1, 35) ~ (3, -1) => 0.0001
+(1, 36) ~ (3, -1) => 0.0001
+(1, 37) ~ (3, -1) => 0.0001
+(1, 38) ~ (3, -1) => 0.0001
+(1, 39) ~ (3, -1) => 0.0001
+(1, 40) ~ (3, -1) => 0.0001
+(1, 41) ~ (3, -1) => 0.0001
+(1, 42) ~ (3, -1) => 0.0001
+(1, 43) ~ (3, -1) => 0.0001
+(1, 44) ~ (3, -1) => 0.0001
+(1, 45) ~ (3, -1) => 0.0001
+(1, 46) ~ (3, -1) => 0.0001
+(1, 47) ~ (3, -1) => 0.0001
+(1, 48) ~ (3, -1) => 0.0001
+(1, 49) ~ (3, -1) => 0.0001
+(1, 50) ~ (3, -1) => 0.0001
+(1, 51) ~ (3, -1) => 0.0001
+(1, 52) ~ (3, -1) => 0.0001
+(1, 53) ~ (3, -1) => 0.0001
+(1, 54) ~ (3, -1) => 0.0001
+(1, 55) ~ (3, -1) => 0.0001
+(1, 56) ~ (3, -1) => 0.0001
+(1, 57) ~ (3, -1) => 0.0001
+(1, 58) ~ (3, -1) => 0.0001
+(1, 59) ~ (3, -1) => 0.000157654
+(1, 60) ~ (3, -1) => 0.00103092
+(1, 61) ~ (3, -1) => 0.00192356
+(1, 62) ~ (3, -1) => 0.00218374
+(1, 63) ~ (3, -1) => 0.00245762
+(1, 64) ~ (3, -1) => 0.00251859
+(1, 65) ~ (3, -1) => 0.00490153
+(1, 66) ~ (3, -1) => 0.00714064
+(1, 67) ~ (3, -1) => 0.00760156
+(1, 68) ~ (3, -1) => 0.00930601
+(1, 69) ~ (3, -1) => 0.0109764
+(1, 70) ~ (3, -1) => 0.0111188
+(1, 71) ~ (3, -1) => 0.0106911
+(1, 72) ~ (3, -1) => 0.00533408
+(1, 73) ~ (3, -1) => 0.00206101
+(1, 74) ~ (3, -1) => 0.00169611
+(1, 75) ~ (3, -1) => 0.00129902
+(1, 76) ~ (3, -1) => 0.000707984
+(1, 77) ~ (3, -1) => 0.000473738
+(1, 78) ~ (3, -1) => 0.000258029
+(1, 79) ~ (3, -1) => 0.0001
+(1, 80) ~ (3, -1) => 0.0001
+(1, 81) ~ (3, -1) => 0.0001
+(1, 82) ~ (3, -1) => 0.000681043
+(1, 83) ~ (3, -1) => 0.000909567
+(1, 84) ~ (3, -1) => 0.00143504
+(1, 85) ~ (3, -1) => 0.00191885
+(1, 86) ~ (3, -1) => 0.00204754
+(1, 87) ~ (3, -1) => 0.00685334
+(1, 88) ~ (3, -1) => 0.0116796
+(1, 89) ~ (3, -1) => 0.0164796
+(1, 90) ~ (3, -1) => 0.0107801
+(1, 91) ~ (3, -1) => 0.00270511
+(1, 92) ~ (3, -1) => 0.00453403
+(1, 93) ~ (3, -1) => 0.00500043
+(1, 94) ~ (3, -1) => 0.00551292
+(1, 95) ~ (3, -1) => 0.00795113
+(1, 96) ~ (3, -1) => 0.0104118
+(1, 97) ~ (3, -1) => 0.00105824
+(1, 98) ~ (3, -1) => 0.0102713
+(1, 99) ~ (3, -1) => 0.00646394
+(1, 100) ~ (3, -1) => 0.0140411
+(1, 101) ~ (3, -1) => 0.00946331
+(1, 102) ~ (3, -1) => 0.00850379
+(1, 103) ~ (3, -1) => 0.00333762
+(1, 104) ~ (3, -1) => 0.0035491
+(1, 105) ~ (3, -1) => 0.0042091
+(1, 106) ~ (3, -1) => 0.00412899
+(1, 107) ~ (3, -1) => 0.00429088
+(1, 108) ~ (3, -1) => 0.00419247
+(1, 109) ~ (3, -1) => 0.0046277
+(1, 110) ~ (3, -1) => 0.00451243
+(1, 111) ~ (3, -1) => 0.00415915
+(1, 112) ~ (3, -1) => 0.00334698
+(1, 113) ~ (3, -1) => 0.00266552
+(1, 114) ~ (3, -1) => 0.00228167
+(1, 115) ~ (3, -1) => 0.00153661
+(1, 116) ~ (3, -1) => 0.000800192
+(1, 117) ~ (3, -1) => 0.000139177
+(1, 118) ~ (3, -1) => 0.0001
+(1, 119) ~ (3, -1) => 0.0001
+(1, 120) ~ (3, -1) => 0.0001
+
+(1, -1) ~ (3, 0) => 0.0001
+(1, -1) ~ (3, 1) => 0.0001
+(1, -1) ~ (3, 2) => 0.0001
+(1, -1) ~ (3, 3) => 0.000110626
+(1, -1) ~ (3, 4) => 0.000126421
+(1, -1) ~ (3, 5) => 0.000127077
+(1, -1) ~ (3, 6) => 0.0001
+(1, -1) ~ (3, 7) => 0.0001
+(1, -1) ~ (3, 8) => 0.0001
+(1, -1) ~ (3, 9) => 0.0001
+(1, -1) ~ (3, 10) => 0.0001
+(1, -1) ~ (3, 11) => 0.0001
+(1, -1) ~ (3, 12) => 0.0001
+(1, -1) ~ (3, 13) => 0.0001
+(1, -1) ~ (3, 14) => 0.0001
+(1, -1) ~ (3, 15) => 0.0001
+(1, -1) ~ (3, 16) => 0.0001
+(1, -1) ~ (3, 17) => 0.0001
+(1, -1) ~ (3, 18) => 0.0001
+(1, -1) ~ (3, 19) => 0.0001
+(1, -1) ~ (3, 20) => 0.0001
+(1, -1) ~ (3, 21) => 0.0001
+(1, -1) ~ (3, 22) => 0.0001
+(1, -1) ~ (3, 23) => 0.0001
+(1, -1) ~ (3, 24) => 0.0001
+(1, -1) ~ (3, 25) => 0.0001
+(1, -1) ~ (3, 26) => 0.0001
+(1, -1) ~ (3, 27) => 0.0001
+(1, -1) ~ (3, 28) => 0.0001
+(1, -1) ~ (3, 29) => 0.0001
+(1, -1) ~ (3, 30) => 0.0001
+(1, -1) ~ (3, 31) => 0.0001
+(1, -1) ~ (3, 32) => 0.0001
+(1, -1) ~ (3, 33) => 0.0001
+(1, -1) ~ (3, 34) => 0.0001
+(1, -1) ~ (3, 35) => 0.0001
+(1, -1) ~ (3, 36) => 0.0001
+(1, -1) ~ (3, 37) => 0.0001
+(1, -1) ~ (3, 38) => 0.0001
+(1, -1) ~ (3, 39) => 0.0001
+(1, -1) ~ (3, 40) => 0.0001
+(1, -1) ~ (3, 41) => 0.0001
+(1, -1) ~ (3, 42) => 0.0001
+(1, -1) ~ (3, 43) => 0.0001
+(1, -1) ~ (3, 44) => 0.0001
+(1, -1) ~ (3, 45) => 0.0001
+(1, -1) ~ (3, 46) => 0.0001
+(1, -1) ~ (3, 47) => 0.0001
+(1, -1) ~ (3, 48) => 0.0001
+(1, -1) ~ (3, 49) => 0.0001
+(1, -1) ~ (3, 50) => 0.0001
+(1, -1) ~ (3, 51) => 0.0001
+(1, -1) ~ (3, 52) => 0.0001
+(1, -1) ~ (3, 53) => 0.0001
+(1, -1) ~ (3, 54) => 0.0001
+(1, -1) ~ (3, 55) => 0.0001
+(1, -1) ~ (3, 56) => 0.0001
+(1, -1) ~ (3, 57) => 0.0001
+(1, -1) ~ (3, 58) => 0.0001
+(1, -1) ~ (3, 59) => 0.000157654
+(1, -1) ~ (3, 60) => 0.00103092
+(1, -1) ~ (3, 61) => 0.00192356
+(1, -1) ~ (3, 62) => 0.00218374
+(1, -1) ~ (3, 63) => 0.00245762
+(1, -1) ~ (3, 64) => 0.00251859
+(1, -1) ~ (3, 65) => 0.00490153
+(1, -1) ~ (3, 66) => 0.00714064
+(1, -1) ~ (3, 67) => 0.00760156
+(1, -1) ~ (3, 68) => 0.00930601
+(1, -1) ~ (3, 69) => 0.0109764
+(1, -1) ~ (3, 70) => 0.0111188
+(1, -1) ~ (3, 71) => 0.0106911
+(1, -1) ~ (3, 72) => 0.00533408
+(1, -1) ~ (3, 73) => 0.00206101
+(1, -1) ~ (3, 74) => 0.00169611
+(1, -1) ~ (3, 75) => 0.00129902
+(1, -1) ~ (3, 76) => 0.000707984
+(1, -1) ~ (3, 77) => 0.000473738
+(1, -1) ~ (3, 78) => 0.000258029
+(1, -1) ~ (3, 79) => 0.0001
+(1, -1) ~ (3, 80) => 0.0001
+(1, -1) ~ (3, 81) => 0.0001
+(1, -1) ~ (3, 82) => 0.000681043
+(1, -1) ~ (3, 83) => 0.000909567
+(1, -1) ~ (3, 84) => 0.00143504
+(1, -1) ~ (3, 85) => 0.00191885
+(1, -1) ~ (3, 86) => 0.00204754
+(1, -1) ~ (3, 87) => 0.00685334
+(1, -1) ~ (3, 88) => 0.0116796
+(1, -1) ~ (3, 89) => 0.0164796
+(1, -1) ~ (3, 90) => 0.0212525
+(1, -1) ~ (3, 91) => 0.0254355
+(1, -1) ~ (3, 92) => 0.0687999
+(1, -1) ~ (3, 93) => 0.0702685
+(1, -1) ~ (3, 94) => 0.0542722
+(1, -1) ~ (3, 95) => 0.0321454
+(1, -1) ~ (3, 96) => 0.0464923
+(1, -1) ~ (3, 97) => 0.0920186
+(1, -1) ~ (3, 98) => 0.753809
+(1, -1) ~ (3, 99) => 0.853622
+(1, -1) ~ (3, 100) => 0.838753
+(1, -1) ~ (3, 101) => 0.154785
+(1, -1) ~ (3, 102) => 0.0530354
+(1, -1) ~ (3, 103) => 0.0140411
+(1, -1) ~ (3, 104) => 0.00946331
+(1, -1) ~ (3, 105) => 0.00850379
+(1, -1) ~ (3, 106) => 0.00333762
+(1, -1) ~ (3, 107) => 0.0035491
+(1, -1) ~ (3, 108) => 0.0042091
+(1, -1) ~ (3, 109) => 0.00412899
+(1, -1) ~ (3, 110) => 0.00429088
+(1, -1) ~ (3, 111) => 0.00419247
+(1, -1) ~ (3, 112) => 0.0046277
+(1, -1) ~ (3, 113) => 0.00451243
+(1, -1) ~ (3, 114) => 0.00415915
+(1, -1) ~ (3, 115) => 0.00334698
+(1, -1) ~ (3, 116) => 0.00266552
+(1, -1) ~ (3, 117) => 0.00228167
+(1, -1) ~ (3, 118) => 0.00153661
+(1, -1) ~ (3, 119) => 0.000800192
+(1, -1) ~ (3, 120) => 0.000139177
+(1, -1) ~ (3, 121) => 0.0001
+(1, -1) ~ (3, 122) => 0.0001
+(1, -1) ~ (3, 123) => 0.0001
+
+; Sparse posterior probability matrix for sequences 1 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (4, 0) => 0.977884
+(1, 0) ~ (4, 1) => 0.0113937
+(1, 1) ~ (4, 1) => 0.927252
+(1, 1) ~ (4, 2) => 0.042153
+(1, 1) ~ (4, 3) => 0.0127747
+(1, 2) ~ (4, 2) => 0.866112
+(1, 2) ~ (4, 3) => 0.0794915
+(1, 2) ~ (4, 4) => 0.0199289
+(1, 3) ~ (4, 2) => 0.0151885
+(1, 3) ~ (4, 3) => 0.837128
+(1, 3) ~ (4, 4) => 0.0859873
+(1, 3) ~ (4, 5) => 0.0305332
+(1, 4) ~ (4, 3) => 0.0232558
+(1, 4) ~ (4, 4) => 0.709573
+(1, 4) ~ (4, 5) => 0.131098
+(1, 4) ~ (4, 6) => 0.0344311
+(1, 5) ~ (4, 4) => 0.0930999
+(1, 5) ~ (4, 5) => 0.500577
+(1, 5) ~ (4, 6) => 0.292823
+(1, 5) ~ (4, 7) => 0.0377882
+(1, 6) ~ (4, 5) => 0.127621
+(1, 6) ~ (4, 6) => 0.431367
+(1, 6) ~ (4, 7) => 0.332032
+(1, 6) ~ (4, 8) => 0.040661
+(1, 7) ~ (4, 5) => 0.0109437
+(1, 7) ~ (4, 6) => 0.150859
+(1, 7) ~ (4, 7) => 0.40042
+(1, 7) ~ (4, 8) => 0.344523
+(1, 7) ~ (4, 9) => 0.037208
+(1, 7) ~ (4, 10) => 0.0137758
+(1, 8) ~ (4, 6) => 0.0141948
+(1, 8) ~ (4, 7) => 0.157869
+(1, 8) ~ (4, 8) => 0.383142
+(1, 8) ~ (4, 9) => 0.364443
+(1, 8) ~ (4, 10) => 0.0264855
+(1, 8) ~ (4, 11) => 0.0150548
+(1, 9) ~ (4, 7) => 0.0181872
+(1, 9) ~ (4, 8) => 0.153559
+(1, 9) ~ (4, 9) => 0.340327
+(1, 9) ~ (4, 10) => 0.415378
+(1, 9) ~ (4, 11) => 0.0162616
+(1, 9) ~ (4, 12) => 0.0181996
+(1, 10) ~ (4, 8) => 0.0188259
+(1, 10) ~ (4, 9) => 0.135392
+(1, 10) ~ (4, 10) => 0.301163
+(1, 10) ~ (4, 11) => 0.477788
+(1, 10) ~ (4, 12) => 0.0106144
+(1, 10) ~ (4, 13) => 0.0225215
+(1, 11) ~ (4, 9) => 0.023909
+(1, 11) ~ (4, 10) => 0.11172
+(1, 11) ~ (4, 11) => 0.256988
+(1, 11) ~ (4, 12) => 0.533917
+(1, 11) ~ (4, 14) => 0.0244303
+(1, 12) ~ (4, 10) => 0.0320822
+(1, 12) ~ (4, 11) => 0.0870719
+(1, 12) ~ (4, 12) => 0.205866
+(1, 12) ~ (4, 13) => 0.601812
+(1, 12) ~ (4, 15) => 0.0267331
+(1, 13) ~ (4, 11) => 0.0403388
+(1, 13) ~ (4, 12) => 0.0565114
+(1, 13) ~ (4, 13) => 0.19847
+(1, 13) ~ (4, 14) => 0.639109
+(1, 13) ~ (4, 16) => 0.0244478
+(1, 14) ~ (4, 12) => 0.0489896
+(1, 14) ~ (4, 13) => 0.030776
+(1, 14) ~ (4, 14) => 0.18741
+(1, 14) ~ (4, 15) => 0.681928
+(1, 14) ~ (4, 17) => 0.0223291
+(1, 15) ~ (4, 13) => 0.0403046
+(1, 15) ~ (4, 15) => 0.10546
+(1, 15) ~ (4, 16) => 0.804874
+(1, 15) ~ (4, 18) => 0.0186135
+(1, 16) ~ (4, 14) => 0.0304188
+(1, 16) ~ (4, 16) => 0.0220845
+(1, 16) ~ (4, 17) => 0.913533
+(1, 16) ~ (4, 19) => 0.0141646
+(1, 17) ~ (4, 15) => 0.0189769
+(1, 17) ~ (4, 18) => 0.949257
+(1, 17) ~ (4, 20) => 0.0120966
+(1, 18) ~ (4, 16) => 0.0145845
+(1, 18) ~ (4, 19) => 0.960677
+(1, 19) ~ (4, 20) => 0.977025
+(1, 20) ~ (4, 21) => 0.981673
+(1, 21) ~ (4, 22) => 0.991124
+(1, 22) ~ (4, 23) => 0.992042
+(1, 23) ~ (4, 24) => 0.989929
+(1, 24) ~ (4, 25) => 0.988962
+(1, 25) ~ (4, 26) => 0.985251
+(1, 26) ~ (4, 27) => 0.985343
+(1, 27) ~ (4, 28) => 0.988626
+(1, 28) ~ (4, 29) => 0.990667
+(1, 29) ~ (4, 30) => 0.994844
+(1, 30) ~ (4, 31) => 0.997848
+(1, 31) ~ (4, 32) => 0.997905
+(1, 32) ~ (4, 33) => 0.997844
+(1, 33) ~ (4, 34) => 0.997943
+(1, 34) ~ (4, 35) => 0.997465
+(1, 35) ~ (4, 36) => 0.996105
+(1, 36) ~ (4, 37) => 0.996256
+(1, 37) ~ (4, 38) => 0.996411
+(1, 38) ~ (4, 39) => 0.99489
+(1, 39) ~ (4, 40) => 0.993005
+(1, 40) ~ (4, 41) => 0.99132
+(1, 41) ~ (4, 42) => 0.988421
+(1, 42) ~ (4, 43) => 0.988646
+(1, 43) ~ (4, 44) => 0.984457
+(1, 44) ~ (4, 45) => 0.985808
+(1, 45) ~ (4, 46) => 0.993604
+(1, 46) ~ (4, 47) => 0.995652
+(1, 47) ~ (4, 48) => 0.997244
+(1, 48) ~ (4, 49) => 0.998742
+(1, 49) ~ (4, 50) => 0.997664
+(1, 50) ~ (4, 51) => 0.996077
+(1, 51) ~ (4, 52) => 0.995295
+(1, 52) ~ (4, 53) => 0.99448
+(1, 53) ~ (4, 54) => 0.992281
+(1, 54) ~ (4, 55) => 0.986835
+(1, 55) ~ (4, 56) => 0.958593
+(1, 55) ~ (4, 57) => 0.0122351
+(1, 56) ~ (4, 57) => 0.912656
+(1, 56) ~ (4, 58) => 0.0316237
+(1, 56) ~ (4, 59) => 0.0149783
+(1, 56) ~ (4, 60) => 0.0103135
+(1, 57) ~ (4, 57) => 0.0125303
+(1, 57) ~ (4, 58) => 0.804
+(1, 57) ~ (4, 59) => 0.0815811
+(1, 57) ~ (4, 60) => 0.0309546
+(1, 57) ~ (4, 61) => 0.0223054
+(1, 57) ~ (4, 62) => 0.0113832
+(1, 58) ~ (4, 58) => 0.0276067
+(1, 58) ~ (4, 59) => 0.625551
+(1, 58) ~ (4, 60) => 0.127137
+(1, 58) ~ (4, 61) => 0.079115
+(1, 58) ~ (4, 62) => 0.0315847
+(1, 58) ~ (4, 63) => 0.0332385
+(1, 59) ~ (4, 59) => 0.0694732
+(1, 59) ~ (4, 60) => 0.477595
+(1, 59) ~ (4, 61) => 0.172867
+(1, 59) ~ (4, 62) => 0.127467
+(1, 59) ~ (4, 63) => 0.0399162
+(1, 59) ~ (4, 64) => 0.0550534
+(1, 60) ~ (4, 60) => 0.0794726
+(1, 60) ~ (4, 61) => 0.390746
+(1, 60) ~ (4, 62) => 0.175175
+(1, 60) ~ (4, 63) => 0.186181
+(1, 60) ~ (4, 64) => 0.0287417
+(1, 60) ~ (4, 65) => 0.0585008
+(1, 61) ~ (4, 61) => 0.0851491
+(1, 61) ~ (4, 62) => 0.326717
+(1, 61) ~ (4, 63) => 0.161672
+(1, 61) ~ (4, 64) => 0.267397
+(1, 61) ~ (4, 65) => 0.0229023
+(1, 61) ~ (4, 66) => 0.0578624
+(1, 62) ~ (4, 62) => 0.0843536
+(1, 62) ~ (4, 63) => 0.269476
+(1, 62) ~ (4, 64) => 0.145737
+(1, 62) ~ (4, 65) => 0.347855
+(1, 62) ~ (4, 66) => 0.0151803
+(1, 62) ~ (4, 67) => 0.0569166
+(1, 63) ~ (4, 63) => 0.0817293
+(1, 63) ~ (4, 64) => 0.240185
+(1, 63) ~ (4, 65) => 0.141333
+(1, 63) ~ (4, 66) => 0.404821
+(1, 63) ~ (4, 68) => 0.0484056
+(1, 64) ~ (4, 64) => 0.0752635
+(1, 64) ~ (4, 65) => 0.205443
+(1, 64) ~ (4, 66) => 0.136682
+(1, 64) ~ (4, 67) => 0.469178
+(1, 64) ~ (4, 69) => 0.0404298
+(1, 65) ~ (4, 65) => 0.0796015
+(1, 65) ~ (4, 66) => 0.190568
+(1, 65) ~ (4, 67) => 0.141085
+(1, 65) ~ (4, 68) => 0.486451
+(1, 65) ~ (4, 70) => 0.037642
+(1, 66) ~ (4, 66) => 0.084771
+(1, 66) ~ (4, 67) => 0.183594
+(1, 66) ~ (4, 68) => 0.121305
+(1, 66) ~ (4, 69) => 0.515682
+(1, 66) ~ (4, 71) => 0.0338117
+(1, 67) ~ (4, 67) => 0.0774368
+(1, 67) ~ (4, 68) => 0.206889
+(1, 67) ~ (4, 69) => 0.0694123
+(1, 67) ~ (4, 70) => 0.518514
+(1, 67) ~ (4, 72) => 0.0309025
+(1, 68) ~ (4, 68) => 0.0485114
+(1, 68) ~ (4, 69) => 0.278791
+(1, 68) ~ (4, 70) => 0.0285533
+(1, 68) ~ (4, 71) => 0.507951
+(1, 68) ~ (4, 73) => 0.0167196
+(1, 69) ~ (4, 69) => 0.0208538
+(1, 69) ~ (4, 70) => 0.364035
+(1, 69) ~ (4, 71) => 0.0150551
+(1, 69) ~ (4, 72) => 0.50623
+(1, 70) ~ (4, 70) => 0.0132906
+(1, 70) ~ (4, 71) => 0.401061
+(1, 70) ~ (4, 72) => 0.0119897
+(1, 70) ~ (4, 73) => 0.444993
+(1, 71) ~ (4, 71) => 0.0121446
+(1, 71) ~ (4, 72) => 0.414208
+(1, 71) ~ (4, 74) => 0.331941
+(1, 72) ~ (4, 73) => 0.500718
+(1, 72) ~ (4, 75) => 0.325486
+(1, 73) ~ (4, 74) => 0.63177
+(1, 73) ~ (4, 76) => 0.285725
+(1, 74) ~ (4, 75) => 0.646166
+(1, 74) ~ (4, 77) => 0.244375
+(1, 75) ~ (4, 76) => 0.696902
+(1, 75) ~ (4, 78) => 0.153691
+(1, 76) ~ (4, 77) => 0.740307
+(1, 76) ~ (4, 79) => 0.127522
+(1, 77) ~ (4, 78) => 0.835523
+(1, 77) ~ (4, 80) => 0.106347
+(1, 78) ~ (4, 79) => 0.861003
+(1, 78) ~ (4, 81) => 0.100757
+(1, 79) ~ (4, 80) => 0.882578
+(1, 79) ~ (4, 82) => 0.093391
+(1, 80) ~ (4, 81) => 0.888871
+(1, 80) ~ (4, 83) => 0.0879499
+(1, 81) ~ (4, 82) => 0.893693
+(1, 81) ~ (4, 84) => 0.0633476
+(1, 82) ~ (4, 83) => 0.901217
+(1, 82) ~ (4, 85) => 0.0368415
+(1, 83) ~ (4, 84) => 0.927765
+(1, 83) ~ (4, 86) => 0.0291429
+(1, 84) ~ (4, 85) => 0.951929
+(1, 84) ~ (4, 87) => 0.0220994
+(1, 85) ~ (4, 86) => 0.957545
+(1, 85) ~ (4, 88) => 0.0202986
+(1, 86) ~ (4, 87) => 0.964921
+(1, 86) ~ (4, 89) => 0.0179408
+(1, 87) ~ (4, 88) => 0.963674
+(1, 87) ~ (4, 90) => 0.0168398
+(1, 88) ~ (4, 89) => 0.962017
+(1, 88) ~ (4, 91) => 0.0156665
+(1, 89) ~ (4, 90) => 0.959668
+(1, 89) ~ (4, 92) => 0.0143567
+(1, 90) ~ (4, 91) => 0.956733
+(1, 90) ~ (4, 93) => 0.0127484
+(1, 91) ~ (4, 92) => 0.951516
+(1, 92) ~ (4, 93) => 0.940599
+(1, 93) ~ (4, 94) => 0.934837
+(1, 94) ~ (4, 95) => 0.92017
+(1, 95) ~ (4, 96) => 0.846902
+(1, 95) ~ (4, 99) => 0.0138299
+(1, 96) ~ (4, 96) => 0.0131069
+(1, 96) ~ (4, 97) => 0.609516
+(1, 96) ~ (4, 100) => 0.0338021
+(1, 97) ~ (4, 94) => 0.0138531
+(1, 97) ~ (4, 96) => 0.0142177
+(1, 97) ~ (4, 97) => 0.0116918
+(1, 97) ~ (4, 98) => 0.502882
+(1, 97) ~ (4, 101) => 0.051098
+(1, 98) ~ (4, 95) => 0.0177879
+(1, 98) ~ (4, 98) => 0.0103423
+(1, 98) ~ (4, 99) => 0.45736
+(1, 98) ~ (4, 100) => 0.0107338
+(1, 98) ~ (4, 101) => 0.0105718
+(1, 98) ~ (4, 102) => 0.0568292
+(1, 99) ~ (4, 95) => 0.0160766
+(1, 99) ~ (4, 96) => 0.0321433
+(1, 99) ~ (4, 99) => 0.0128142
+(1, 99) ~ (4, 100) => 0.37559
+(1, 99) ~ (4, 102) => 0.0148087
+(1, 99) ~ (4, 103) => 0.0615177
+(1, 100) ~ (4, 96) => 0.0430997
+(1, 100) ~ (4, 97) => 0.0693336
+(1, 100) ~ (4, 98) => 0.0107814
+(1, 100) ~ (4, 100) => 0.0107752
+(1, 100) ~ (4, 101) => 0.243737
+(1, 100) ~ (4, 103) => 0.0172233
+(1, 100) ~ (4, 104) => 0.0642069
+(1, 101) ~ (4, 97) => 0.186806
+(1, 101) ~ (4, 98) => 0.0698479
+(1, 101) ~ (4, 101) => 0.0145914
+(1, 101) ~ (4, 102) => 0.169886
+(1, 101) ~ (4, 104) => 0.0198546
+(1, 101) ~ (4, 105) => 0.0549153
+(1, 102) ~ (4, 97) => 0.0264513
+(1, 102) ~ (4, 98) => 0.227328
+(1, 102) ~ (4, 99) => 0.0552972
+(1, 102) ~ (4, 102) => 0.0174065
+(1, 102) ~ (4, 103) => 0.143004
+(1, 102) ~ (4, 104) => 0.0106338
+(1, 102) ~ (4, 105) => 0.0158562
+(1, 102) ~ (4, 106) => 0.0333486
+(1, 103) ~ (4, 97) => 0.0171077
+(1, 103) ~ (4, 98) => 0.02843
+(1, 103) ~ (4, 99) => 0.235013
+(1, 103) ~ (4, 100) => 0.051633
+(1, 103) ~ (4, 103) => 0.021835
+(1, 103) ~ (4, 104) => 0.133981
+(1, 103) ~ (4, 107) => 0.0243301
+(1, 104) ~ (4, 98) => 0.0549373
+(1, 104) ~ (4, 99) => 0.0487433
+(1, 104) ~ (4, 100) => 0.243369
+(1, 104) ~ (4, 101) => 0.0490171
+(1, 104) ~ (4, 104) => 0.023226
+(1, 104) ~ (4, 105) => 0.137571
+(1, 104) ~ (4, 108) => 0.0230147
+(1, 105) ~ (4, 99) => 0.0694195
+(1, 105) ~ (4, 100) => 0.100641
+(1, 105) ~ (4, 101) => 0.305118
+(1, 105) ~ (4, 102) => 0.0501207
+(1, 105) ~ (4, 105) => 0.016448
+(1, 105) ~ (4, 106) => 0.130881
+(1, 105) ~ (4, 109) => 0.0160825
+(1, 106) ~ (4, 100) => 0.0763538
+(1, 106) ~ (4, 101) => 0.13899
+(1, 106) ~ (4, 102) => 0.340276
+(1, 106) ~ (4, 103) => 0.0430469
+(1, 106) ~ (4, 106) => 0.0156467
+(1, 106) ~ (4, 107) => 0.122439
+(1, 106) ~ (4, 110) => 0.0110702
+(1, 107) ~ (4, 101) => 0.0770901
+(1, 107) ~ (4, 102) => 0.165403
+(1, 107) ~ (4, 103) => 0.350391
+(1, 107) ~ (4, 104) => 0.0294617
+(1, 107) ~ (4, 107) => 0.0133297
+(1, 107) ~ (4, 108) => 0.11403
+(1, 108) ~ (4, 102) => 0.0777783
+(1, 108) ~ (4, 103) => 0.175477
+(1, 108) ~ (4, 104) => 0.346006
+(1, 108) ~ (4, 105) => 0.019019
+(1, 108) ~ (4, 108) => 0.0101178
+(1, 108) ~ (4, 109) => 0.112449
+(1, 109) ~ (4, 102) => 0.0115103
+(1, 109) ~ (4, 103) => 0.0754649
+(1, 109) ~ (4, 104) => 0.184384
+(1, 109) ~ (4, 105) => 0.366134
+(1, 109) ~ (4, 106) => 0.0187998
+(1, 109) ~ (4, 108) => 0.0144397
+(1, 109) ~ (4, 109) => 0.0104104
+(1, 109) ~ (4, 110) => 0.0923354
+(1, 110) ~ (4, 102) => 0.0105554
+(1, 110) ~ (4, 103) => 0.018598
+(1, 110) ~ (4, 104) => 0.08482
+(1, 110) ~ (4, 105) => 0.163357
+(1, 110) ~ (4, 106) => 0.354616
+(1, 110) ~ (4, 107) => 0.024419
+(1, 110) ~ (4, 109) => 0.0143632
+(1, 110) ~ (4, 110) => 0.0127876
+(1, 110) ~ (4, 111) => 0.0739786
+(1, 111) ~ (4, 101) => 0.0100543
+(1, 111) ~ (4, 102) => 0.011011
+(1, 111) ~ (4, 103) => 0.0108022
+(1, 111) ~ (4, 104) => 0.0210489
+(1, 111) ~ (4, 105) => 0.107488
+(1, 111) ~ (4, 106) => 0.156468
+(1, 111) ~ (4, 107) => 0.344211
+(1, 111) ~ (4, 108) => 0.028964
+(1, 111) ~ (4, 109) => 0.0157252
+(1, 111) ~ (4, 110) => 0.0153984
+(1, 111) ~ (4, 111) => 0.0146192
+(1, 111) ~ (4, 112) => 0.0620611
+(1, 112) ~ (4, 102) => 0.0101096
+(1, 112) ~ (4, 103) => 0.0153189
+(1, 112) ~ (4, 104) => 0.0115719
+(1, 112) ~ (4, 105) => 0.0241407
+(1, 112) ~ (4, 106) => 0.139366
+(1, 112) ~ (4, 107) => 0.123279
+(1, 112) ~ (4, 108) => 0.317682
+(1, 112) ~ (4, 109) => 0.0394395
+(1, 112) ~ (4, 110) => 0.0329493
+(1, 112) ~ (4, 111) => 0.0169077
+(1, 112) ~ (4, 112) => 0.0108278
+(1, 112) ~ (4, 113) => 0.0203938
+(1, 113) ~ (4, 104) => 0.0169738
+(1, 113) ~ (4, 105) => 0.0145148
+(1, 113) ~ (4, 106) => 0.0328665
+(1, 113) ~ (4, 107) => 0.183794
+(1, 113) ~ (4, 108) => 0.106871
+(1, 113) ~ (4, 109) => 0.306304
+(1, 113) ~ (4, 110) => 0.0499654
+(1, 113) ~ (4, 111) => 0.0489616
+(1, 113) ~ (4, 112) => 0.0182048
+(1, 113) ~ (4, 114) => 0.0126404
+(1, 114) ~ (4, 105) => 0.0196373
+(1, 114) ~ (4, 106) => 0.0189093
+(1, 114) ~ (4, 107) => 0.0348017
+(1, 114) ~ (4, 108) => 0.204208
+(1, 114) ~ (4, 109) => 0.0928616
+(1, 114) ~ (4, 110) => 0.301887
+(1, 114) ~ (4, 111) => 0.0619844
+(1, 114) ~ (4, 112) => 0.0507434
+(1, 115) ~ (4, 106) => 0.0234776
+(1, 115) ~ (4, 107) => 0.0194656
+(1, 115) ~ (4, 108) => 0.0292557
+(1, 115) ~ (4, 109) => 0.225941
+(1, 115) ~ (4, 110) => 0.0822337
+(1, 115) ~ (4, 111) => 0.303419
+(1, 115) ~ (4, 112) => 0.0589514
+(1, 115) ~ (4, 113) => 0.0315397
+(1, 116) ~ (4, 107) => 0.0243382
+(1, 116) ~ (4, 108) => 0.0149195
+(1, 116) ~ (4, 109) => 0.025185
+(1, 116) ~ (4, 110) => 0.255396
+(1, 116) ~ (4, 111) => 0.0752456
+(1, 116) ~ (4, 112) => 0.26281
+(1, 116) ~ (4, 113) => 0.0169398
+(1, 116) ~ (4, 114) => 0.0277386
+(1, 117) ~ (4, 108) => 0.0265524
+(1, 117) ~ (4, 109) => 0.0134732
+(1, 117) ~ (4, 110) => 0.0210341
+(1, 117) ~ (4, 111) => 0.28705
+(1, 117) ~ (4, 112) => 0.0616149
+(1, 117) ~ (4, 113) => 0.185533
+(1, 118) ~ (4, 108) => 0.0118386
+(1, 118) ~ (4, 109) => 0.0187851
+(1, 118) ~ (4, 110) => 0.0101858
+(1, 118) ~ (4, 111) => 0.0125236
+(1, 118) ~ (4, 112) => 0.390933
+(1, 118) ~ (4, 113) => 0.0518968
+(1, 118) ~ (4, 114) => 0.101888
+(1, 119) ~ (4, 113) => 0.641376
+(1, 119) ~ (4, 114) => 0.0313112
+(1, 120) ~ (4, 114) => 0.782546
+
+; gap posteriors
+(1, 0) ~ (4, -1) => 0.010722
+(1, 1) ~ (4, -1) => 0.01782
+(1, 2) ~ (4, -1) => 0.0344675
+(1, 3) ~ (4, -1) => 0.0311629
+(1, 4) ~ (4, -1) => 0.101642
+(1, 5) ~ (4, -1) => 0.0757117
+(1, 6) ~ (4, -1) => 0.0683185
+(1, 7) ~ (4, -1) => 0.0422703
+(1, 8) ~ (4, -1) => 0.038811
+(1, 9) ~ (4, -1) => 0.0380868
+(1, 10) ~ (4, -1) => 0.0336946
+(1, 11) ~ (4, -1) => 0.0490358
+(1, 12) ~ (4, -1) => 0.046435
+(1, 13) ~ (4, -1) => 0.0411231
+(1, 14) ~ (4, -1) => 0.0285672
+(1, 15) ~ (4, -1) => 0.0307478
+(1, 16) ~ (4, -1) => 0.0197996
+(1, 17) ~ (4, -1) => 0.0196693
+(1, 18) ~ (4, -1) => 0.024738
+(1, 19) ~ (4, -1) => 0.0229749
+(1, 20) ~ (4, -1) => 0.0183271
+(1, 21) ~ (4, -1) => 0.00887638
+(1, 22) ~ (4, -1) => 0.00795847
+(1, 23) ~ (4, -1) => 0.0100709
+(1, 24) ~ (4, -1) => 0.0110378
+(1, 25) ~ (4, -1) => 0.0147488
+(1, 26) ~ (4, -1) => 0.0146568
+(1, 27) ~ (4, -1) => 0.0113737
+(1, 28) ~ (4, -1) => 0.0093326
+(1, 29) ~ (4, -1) => 0.0051561
+(1, 30) ~ (4, -1) => 0.00215167
+(1, 31) ~ (4, -1) => 0.00209516
+(1, 32) ~ (4, -1) => 0.00215626
+(1, 33) ~ (4, -1) => 0.00205702
+(1, 34) ~ (4, -1) => 0.00253522
+(1, 35) ~ (4, -1) => 0.00389469
+(1, 36) ~ (4, -1) => 0.00374353
+(1, 37) ~ (4, -1) => 0.00358886
+(1, 38) ~ (4, -1) => 0.00510991
+(1, 39) ~ (4, -1) => 0.00699538
+(1, 40) ~ (4, -1) => 0.00867957
+(1, 41) ~ (4, -1) => 0.0115793
+(1, 42) ~ (4, -1) => 0.0113542
+(1, 43) ~ (4, -1) => 0.0155427
+(1, 44) ~ (4, -1) => 0.0141918
+(1, 45) ~ (4, -1) => 0.00639582
+(1, 46) ~ (4, -1) => 0.00434816
+(1, 47) ~ (4, -1) => 0.00275648
+(1, 48) ~ (4, -1) => 0.00125778
+(1, 49) ~ (4, -1) => 0.00233644
+(1, 50) ~ (4, -1) => 0.00392306
+(1, 51) ~ (4, -1) => 0.00470459
+(1, 52) ~ (4, -1) => 0.00551981
+(1, 53) ~ (4, -1) => 0.0077188
+(1, 54) ~ (4, -1) => 0.0131648
+(1, 55) ~ (4, -1) => 0.0291715
+(1, 56) ~ (4, -1) => 0.0304282
+(1, 57) ~ (4, -1) => 0.0372456
+(1, 58) ~ (4, -1) => 0.075767
+(1, 59) ~ (4, -1) => 0.0576277
+(1, 60) ~ (4, -1) => 0.0811823
+(1, 61) ~ (4, -1) => 0.0783001
+(1, 62) ~ (4, -1) => 0.0804816
+(1, 63) ~ (4, -1) => 0.0835261
+(1, 64) ~ (4, -1) => 0.0730034
+(1, 65) ~ (4, -1) => 0.0646522
+(1, 66) ~ (4, -1) => 0.0608361
+(1, 67) ~ (4, -1) => 0.0968458
+(1, 68) ~ (4, -1) => 0.119473
+(1, 69) ~ (4, -1) => 0.0938259
+(1, 70) ~ (4, -1) => 0.128666
+(1, 71) ~ (4, -1) => 0.241706
+(1, 72) ~ (4, -1) => 0.173796
+(1, 73) ~ (4, -1) => 0.0825055
+(1, 74) ~ (4, -1) => 0.109459
+(1, 75) ~ (4, -1) => 0.149407
+(1, 76) ~ (4, -1) => 0.132171
+(1, 77) ~ (4, -1) => 0.0581304
+(1, 78) ~ (4, -1) => 0.0382406
+(1, 79) ~ (4, -1) => 0.0240311
+(1, 80) ~ (4, -1) => 0.0231795
+(1, 81) ~ (4, -1) => 0.0429596
+(1, 82) ~ (4, -1) => 0.0619419
+(1, 83) ~ (4, -1) => 0.0430918
+(1, 84) ~ (4, -1) => 0.0259712
+(1, 85) ~ (4, -1) => 0.0221565
+(1, 86) ~ (4, -1) => 0.0171378
+(1, 87) ~ (4, -1) => 0.0194864
+(1, 88) ~ (4, -1) => 0.0223163
+(1, 89) ~ (4, -1) => 0.0259754
+(1, 90) ~ (4, -1) => 0.0305189
+(1, 91) ~ (4, -1) => 0.0484836
+(1, 92) ~ (4, -1) => 0.0594014
+(1, 93) ~ (4, -1) => 0.0651627
+(1, 94) ~ (4, -1) => 0.0798298
+(1, 95) ~ (4, -1) => 0.139268
+(1, 96) ~ (4, -1) => 0.343575
+(1, 97) ~ (4, -1) => 0.406257
+(1, 98) ~ (4, -1) => 0.436375
+(1, 99) ~ (4, -1) => 0.487049
+(1, 100) ~ (4, -1) => 0.540843
+(1, 101) ~ (4, -1) => 0.484099
+(1, 102) ~ (4, -1) => 0.470674
+(1, 103) ~ (4, -1) => 0.48767
+(1, 104) ~ (4, -1) => 0.420122
+(1, 105) ~ (4, -1) => 0.311289
+(1, 106) ~ (4, -1) => 0.252177
+(1, 107) ~ (4, -1) => 0.250294
+(1, 108) ~ (4, -1) => 0.259154
+(1, 109) ~ (4, -1) => 0.226521
+(1, 110) ~ (4, -1) => 0.242506
+(1, 111) ~ (4, -1) => 0.202148
+(1, 112) ~ (4, -1) => 0.238014
+(1, 113) ~ (4, -1) => 0.208904
+(1, 114) ~ (4, -1) => 0.214967
+(1, 115) ~ (4, -1) => 0.225716
+(1, 116) ~ (4, -1) => 0.297427
+(1, 117) ~ (4, -1) => 0.404742
+(1, 118) ~ (4, -1) => 0.401949
+(1, 119) ~ (4, -1) => 0.327312
+(1, 120) ~ (4, -1) => 0.217454
+
+(1, -1) ~ (4, 0) => 0.0221156
+(1, -1) ~ (4, 1) => 0.061354
+(1, -1) ~ (4, 2) => 0.0765463
+(1, -1) ~ (4, 3) => 0.0473499
+(1, -1) ~ (4, 4) => 0.0914107
+(1, -1) ~ (4, 5) => 0.199227
+(1, -1) ~ (4, 6) => 0.0763252
+(1, -1) ~ (4, 7) => 0.0537031
+(1, -1) ~ (4, 8) => 0.0592893
+(1, -1) ~ (4, 9) => 0.0987201
+(1, -1) ~ (4, 10) => 0.0993958
+(1, -1) ~ (4, 11) => 0.106496
+(1, -1) ~ (4, 12) => 0.125902
+(1, -1) ~ (4, 13) => 0.106117
+(1, -1) ~ (4, 14) => 0.118632
+(1, -1) ~ (4, 15) => 0.166901
+(1, -1) ~ (4, 16) => 0.13401
+(1, -1) ~ (4, 17) => 0.0641384
+(1, -1) ~ (4, 18) => 0.0321292
+(1, -1) ~ (4, 19) => 0.025158
+(1, -1) ~ (4, 20) => 0.0108784
+(1, -1) ~ (4, 21) => 0.0183271
+(1, -1) ~ (4, 22) => 0.00887638
+(1, -1) ~ (4, 23) => 0.00795847
+(1, -1) ~ (4, 24) => 0.0100709
+(1, -1) ~ (4, 25) => 0.0110378
+(1, -1) ~ (4, 26) => 0.0147488
+(1, -1) ~ (4, 27) => 0.0146568
+(1, -1) ~ (4, 28) => 0.0113737
+(1, -1) ~ (4, 29) => 0.0093326
+(1, -1) ~ (4, 30) => 0.0051561
+(1, -1) ~ (4, 31) => 0.00215167
+(1, -1) ~ (4, 32) => 0.00209516
+(1, -1) ~ (4, 33) => 0.00215626
+(1, -1) ~ (4, 34) => 0.00205702
+(1, -1) ~ (4, 35) => 0.00253522
+(1, -1) ~ (4, 36) => 0.00389469
+(1, -1) ~ (4, 37) => 0.00374353
+(1, -1) ~ (4, 38) => 0.00358886
+(1, -1) ~ (4, 39) => 0.00510991
+(1, -1) ~ (4, 40) => 0.00699538
+(1, -1) ~ (4, 41) => 0.00867957
+(1, -1) ~ (4, 42) => 0.0115793
+(1, -1) ~ (4, 43) => 0.0113542
+(1, -1) ~ (4, 44) => 0.0155427
+(1, -1) ~ (4, 45) => 0.0141918
+(1, -1) ~ (4, 46) => 0.00639582
+(1, -1) ~ (4, 47) => 0.00434816
+(1, -1) ~ (4, 48) => 0.00275648
+(1, -1) ~ (4, 49) => 0.00125778
+(1, -1) ~ (4, 50) => 0.00233644
+(1, -1) ~ (4, 51) => 0.00392306
+(1, -1) ~ (4, 52) => 0.00470459
+(1, -1) ~ (4, 53) => 0.00551981
+(1, -1) ~ (4, 54) => 0.0077188
+(1, -1) ~ (4, 55) => 0.0131648
+(1, -1) ~ (4, 56) => 0.0414066
+(1, -1) ~ (4, 57) => 0.0625783
+(1, -1) ~ (4, 58) => 0.13677
+(1, -1) ~ (4, 59) => 0.208416
+(1, -1) ~ (4, 60) => 0.274527
+(1, -1) ~ (4, 61) => 0.249817
+(1, -1) ~ (4, 62) => 0.243319
+(1, -1) ~ (4, 63) => 0.227787
+(1, -1) ~ (4, 64) => 0.187623
+(1, -1) ~ (4, 65) => 0.144364
+(1, -1) ~ (4, 66) => 0.110116
+(1, -1) ~ (4, 67) => 0.0717894
+(1, -1) ~ (4, 68) => 0.0884375
+(1, -1) ~ (4, 69) => 0.0748303
+(1, -1) ~ (4, 70) => 0.0379656
+(1, -1) ~ (4, 71) => 0.0299769
+(1, -1) ~ (4, 72) => 0.0366692
+(1, -1) ~ (4, 73) => 0.0375699
+(1, -1) ~ (4, 74) => 0.036289
+(1, -1) ~ (4, 75) => 0.0283476
+(1, -1) ~ (4, 76) => 0.0173725
+(1, -1) ~ (4, 77) => 0.0153177
+(1, -1) ~ (4, 78) => 0.0107867
+(1, -1) ~ (4, 79) => 0.0114756
+(1, -1) ~ (4, 80) => 0.0110753
+(1, -1) ~ (4, 81) => 0.0103727
+(1, -1) ~ (4, 82) => 0.0129161
+(1, -1) ~ (4, 83) => 0.0108335
+(1, -1) ~ (4, 84) => 0.00888711
+(1, -1) ~ (4, 85) => 0.0112291
+(1, -1) ~ (4, 86) => 0.0133122
+(1, -1) ~ (4, 87) => 0.0129793
+(1, -1) ~ (4, 88) => 0.0160275
+(1, -1) ~ (4, 89) => 0.020042
+(1, -1) ~ (4, 90) => 0.0234923
+(1, -1) ~ (4, 91) => 0.0276008
+(1, -1) ~ (4, 92) => 0.0341268
+(1, -1) ~ (4, 93) => 0.046653
+(1, -1) ~ (4, 94) => 0.0513096
+(1, -1) ~ (4, 95) => 0.0459653
+(1, -1) ~ (4, 96) => 0.0505307
+(1, -1) ~ (4, 97) => 0.0790939
+(1, -1) ~ (4, 98) => 0.0954511
+(1, -1) ~ (4, 99) => 0.107523
+(1, -1) ~ (4, 100) => 0.0971013
+(1, -1) ~ (4, 101) => 0.0997319
+(1, -1) ~ (4, 102) => 0.0643058
+(1, -1) ~ (4, 103) => 0.0673215
+(1, -1) ~ (4, 104) => 0.0538322
+(1, -1) ~ (4, 105) => 0.060919
+(1, -1) ~ (4, 106) => 0.07562
+(1, -1) ~ (4, 107) => 0.0855923
+(1, -1) ~ (4, 108) => 0.098106
+(1, -1) ~ (4, 109) => 0.108981
+(1, -1) ~ (4, 110) => 0.114757
+(1, -1) ~ (4, 111) => 0.10531
+(1, -1) ~ (4, 112) => 0.0838537
+(1, -1) ~ (4, 113) => 0.0523201
+(1, -1) ~ (4, 114) => 0.0438755
+
+; Sparse posterior probability matrix for sequences 2 and 3
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (3, 0) => 0.912219
+(2, 1) ~ (3, 0) => 0.0718007
+(2, 1) ~ (3, 1) => 0.769694
+(2, 1) ~ (3, 2) => 0.0110463
+(2, 2) ~ (3, 0) => 0.0104892
+(2, 2) ~ (3, 1) => 0.188178
+(2, 2) ~ (3, 2) => 0.351436
+(2, 2) ~ (3, 3) => 0.0113299
+(2, 3) ~ (3, 1) => 0.0137234
+(2, 3) ~ (3, 2) => 0.591679
+(2, 3) ~ (3, 3) => 0.175511
+(2, 3) ~ (3, 4) => 0.0151036
+(2, 4) ~ (3, 2) => 0.0132808
+(2, 4) ~ (3, 3) => 0.765129
+(2, 4) ~ (3, 4) => 0.158401
+(2, 4) ~ (3, 5) => 0.013829
+(2, 5) ~ (3, 2) => 0.0148175
+(2, 5) ~ (3, 4) => 0.782908
+(2, 5) ~ (3, 5) => 0.134097
+(2, 5) ~ (3, 6) => 0.0123352
+(2, 6) ~ (3, 3) => 0.0179582
+(2, 6) ~ (3, 4) => 0.0107126
+(2, 6) ~ (3, 5) => 0.810321
+(2, 6) ~ (3, 6) => 0.109905
+(2, 6) ~ (3, 7) => 0.0124712
+(2, 7) ~ (3, 4) => 0.0164818
+(2, 7) ~ (3, 5) => 0.010239
+(2, 7) ~ (3, 6) => 0.839631
+(2, 7) ~ (3, 7) => 0.0946232
+(2, 7) ~ (3, 8) => 0.012011
+(2, 8) ~ (3, 5) => 0.0138719
+(2, 8) ~ (3, 6) => 0.010994
+(2, 8) ~ (3, 7) => 0.855491
+(2, 8) ~ (3, 8) => 0.0805815
+(2, 8) ~ (3, 9) => 0.0118083
+(2, 9) ~ (3, 6) => 0.0117331
+(2, 9) ~ (3, 8) => 0.87597
+(2, 9) ~ (3, 9) => 0.0702489
+(2, 10) ~ (3, 7) => 0.0131188
+(2, 10) ~ (3, 9) => 0.881161
+(2, 10) ~ (3, 10) => 0.0775847
+(2, 11) ~ (3, 8) => 0.0139033
+(2, 11) ~ (3, 10) => 0.882278
+(2, 11) ~ (3, 11) => 0.0769188
+(2, 12) ~ (3, 9) => 0.0159977
+(2, 12) ~ (3, 11) => 0.87372
+(2, 12) ~ (3, 12) => 0.0763642
+(2, 13) ~ (3, 10) => 0.0188449
+(2, 13) ~ (3, 12) => 0.870258
+(2, 13) ~ (3, 13) => 0.0775476
+(2, 14) ~ (3, 11) => 0.0202707
+(2, 14) ~ (3, 13) => 0.86664
+(2, 14) ~ (3, 14) => 0.0748482
+(2, 15) ~ (3, 12) => 0.0219178
+(2, 15) ~ (3, 13) => 0.010943
+(2, 15) ~ (3, 14) => 0.869692
+(2, 15) ~ (3, 15) => 0.0689487
+(2, 16) ~ (3, 13) => 0.0232454
+(2, 16) ~ (3, 15) => 0.874295
+(2, 16) ~ (3, 16) => 0.0633501
+(2, 17) ~ (3, 14) => 0.0233048
+(2, 17) ~ (3, 16) => 0.88226
+(2, 17) ~ (3, 17) => 0.0538437
+(2, 18) ~ (3, 15) => 0.0217488
+(2, 18) ~ (3, 17) => 0.855545
+(2, 18) ~ (3, 18) => 0.0793593
+(2, 18) ~ (3, 19) => 0.0157072
+(2, 19) ~ (3, 16) => 0.0175444
+(2, 19) ~ (3, 17) => 0.0160561
+(2, 19) ~ (3, 18) => 0.817885
+(2, 19) ~ (3, 19) => 0.100913
+(2, 19) ~ (3, 20) => 0.0233638
+(2, 20) ~ (3, 17) => 0.0135937
+(2, 20) ~ (3, 18) => 0.0242672
+(2, 20) ~ (3, 19) => 0.789968
+(2, 20) ~ (3, 20) => 0.123207
+(2, 20) ~ (3, 21) => 0.0213565
+(2, 21) ~ (3, 19) => 0.0261828
+(2, 21) ~ (3, 20) => 0.694714
+(2, 21) ~ (3, 21) => 0.215251
+(2, 21) ~ (3, 22) => 0.0268549
+(2, 22) ~ (3, 20) => 0.0305857
+(2, 22) ~ (3, 21) => 0.587857
+(2, 22) ~ (3, 22) => 0.311666
+(2, 22) ~ (3, 23) => 0.0283362
+(2, 23) ~ (3, 21) => 0.0326522
+(2, 23) ~ (3, 22) => 0.395926
+(2, 23) ~ (3, 23) => 0.415452
+(2, 23) ~ (3, 24) => 0.0884368
+(2, 23) ~ (3, 25) => 0.0256445
+(2, 24) ~ (3, 22) => 0.0467456
+(2, 24) ~ (3, 23) => 0.340051
+(2, 24) ~ (3, 24) => 0.420047
+(2, 24) ~ (3, 25) => 0.105561
+(2, 24) ~ (3, 26) => 0.058892
+(2, 25) ~ (3, 23) => 0.0441939
+(2, 25) ~ (3, 24) => 0.303561
+(2, 25) ~ (3, 25) => 0.440929
+(2, 25) ~ (3, 26) => 0.111829
+(2, 25) ~ (3, 27) => 0.0681721
+(2, 26) ~ (3, 24) => 0.0282852
+(2, 26) ~ (3, 25) => 0.184632
+(2, 26) ~ (3, 26) => 0.531902
+(2, 26) ~ (3, 27) => 0.160047
+(2, 26) ~ (3, 28) => 0.0681182
+(2, 27) ~ (3, 25) => 0.0210367
+(2, 27) ~ (3, 26) => 0.0955383
+(2, 27) ~ (3, 27) => 0.541095
+(2, 27) ~ (3, 28) => 0.252434
+(2, 27) ~ (3, 29) => 0.0226225
+(2, 28) ~ (3, 26) => 0.016329
+(2, 28) ~ (3, 27) => 0.0430946
+(2, 28) ~ (3, 28) => 0.390886
+(2, 28) ~ (3, 29) => 0.511642
+(2, 28) ~ (3, 30) => 0.0169631
+(2, 29) ~ (3, 28) => 0.0248496
+(2, 29) ~ (3, 29) => 0.224394
+(2, 29) ~ (3, 30) => 0.705462
+(2, 30) ~ (3, 29) => 0.0269841
+(2, 30) ~ (3, 30) => 0.19096
+(2, 30) ~ (3, 31) => 0.753588
+(2, 30) ~ (3, 32) => 0.0108379
+(2, 31) ~ (3, 30) => 0.0184418
+(2, 31) ~ (3, 31) => 0.178088
+(2, 31) ~ (3, 32) => 0.778899
+(2, 31) ~ (3, 33) => 0.0110412
+(2, 32) ~ (3, 31) => 0.0144673
+(2, 32) ~ (3, 32) => 0.162407
+(2, 32) ~ (3, 33) => 0.802215
+(2, 32) ~ (3, 34) => 0.0104707
+(2, 33) ~ (3, 33) => 0.14551
+(2, 33) ~ (3, 34) => 0.825586
+(2, 33) ~ (3, 35) => 0.0103387
+(2, 34) ~ (3, 34) => 0.106713
+(2, 34) ~ (3, 35) => 0.873839
+(2, 34) ~ (3, 36) => 0.0106047
+(2, 35) ~ (3, 35) => 0.0873912
+(2, 35) ~ (3, 36) => 0.890685
+(2, 35) ~ (3, 37) => 0.0110911
+(2, 36) ~ (3, 36) => 0.073463
+(2, 36) ~ (3, 37) => 0.905275
+(2, 37) ~ (3, 37) => 0.0566876
+(2, 37) ~ (3, 38) => 0.914633
+(2, 37) ~ (3, 39) => 0.0175098
+(2, 38) ~ (3, 38) => 0.0483487
+(2, 38) ~ (3, 39) => 0.913967
+(2, 38) ~ (3, 40) => 0.0233346
+(2, 39) ~ (3, 39) => 0.0393131
+(2, 39) ~ (3, 40) => 0.91366
+(2, 39) ~ (3, 41) => 0.0280139
+(2, 40) ~ (3, 40) => 0.0290908
+(2, 40) ~ (3, 41) => 0.910376
+(2, 40) ~ (3, 42) => 0.029927
+(2, 40) ~ (3, 43) => 0.0173682
+(2, 41) ~ (3, 41) => 0.0159556
+(2, 41) ~ (3, 42) => 0.893686
+(2, 41) ~ (3, 43) => 0.0417165
+(2, 41) ~ (3, 44) => 0.0300805
+(2, 42) ~ (3, 42) => 0.0128435
+(2, 42) ~ (3, 43) => 0.816866
+(2, 42) ~ (3, 44) => 0.0747328
+(2, 42) ~ (3, 45) => 0.0766794
+(2, 43) ~ (3, 43) => 0.0112216
+(2, 43) ~ (3, 44) => 0.744483
+(2, 43) ~ (3, 45) => 0.0722127
+(2, 43) ~ (3, 46) => 0.155164
+(2, 44) ~ (3, 45) => 0.547748
+(2, 44) ~ (3, 46) => 0.0799809
+(2, 44) ~ (3, 47) => 0.342057
+(2, 45) ~ (3, 45) => 0.0131908
+(2, 45) ~ (3, 46) => 0.358146
+(2, 45) ~ (3, 47) => 0.0648093
+(2, 45) ~ (3, 48) => 0.536005
+(2, 46) ~ (3, 46) => 0.0194527
+(2, 46) ~ (3, 47) => 0.260014
+(2, 46) ~ (3, 48) => 0.054873
+(2, 46) ~ (3, 49) => 0.63219
+(2, 47) ~ (3, 47) => 0.0211202
+(2, 47) ~ (3, 48) => 0.138658
+(2, 47) ~ (3, 49) => 0.084201
+(2, 47) ~ (3, 50) => 0.715968
+(2, 48) ~ (3, 48) => 0.019805
+(2, 48) ~ (3, 49) => 0.106673
+(2, 48) ~ (3, 50) => 0.0803427
+(2, 48) ~ (3, 51) => 0.745385
+(2, 48) ~ (3, 52) => 0.0119975
+(2, 49) ~ (3, 49) => 0.0147538
+(2, 49) ~ (3, 50) => 0.0908894
+(2, 49) ~ (3, 51) => 0.0850807
+(2, 49) ~ (3, 52) => 0.744384
+(2, 49) ~ (3, 53) => 0.0202554
+(2, 49) ~ (3, 55) => 0.0164495
+(2, 50) ~ (3, 50) => 0.0109338
+(2, 50) ~ (3, 51) => 0.078519
+(2, 50) ~ (3, 52) => 0.0704142
+(2, 50) ~ (3, 53) => 0.759322
+(2, 50) ~ (3, 54) => 0.0248888
+(2, 50) ~ (3, 56) => 0.0221958
+(2, 51) ~ (3, 52) => 0.0530084
+(2, 51) ~ (3, 53) => 0.0598729
+(2, 51) ~ (3, 54) => 0.780695
+(2, 51) ~ (3, 55) => 0.0282813
+(2, 51) ~ (3, 57) => 0.0248568
+(2, 52) ~ (3, 51) => 0.017435
+(2, 52) ~ (3, 53) => 0.0564319
+(2, 52) ~ (3, 54) => 0.0421895
+(2, 52) ~ (3, 55) => 0.784995
+(2, 52) ~ (3, 56) => 0.0311489
+(2, 52) ~ (3, 58) => 0.0274959
+(2, 53) ~ (3, 52) => 0.0217949
+(2, 53) ~ (3, 54) => 0.0601851
+(2, 53) ~ (3, 55) => 0.0197095
+(2, 53) ~ (3, 56) => 0.795482
+(2, 53) ~ (3, 57) => 0.0109175
+(2, 53) ~ (3, 58) => 0.0115474
+(2, 53) ~ (3, 59) => 0.0255435
+(2, 54) ~ (3, 53) => 0.0216466
+(2, 54) ~ (3, 55) => 0.0722559
+(2, 54) ~ (3, 57) => 0.825877
+(2, 54) ~ (3, 59) => 0.0151793
+(2, 54) ~ (3, 60) => 0.0264456
+(2, 55) ~ (3, 54) => 0.0220394
+(2, 55) ~ (3, 56) => 0.0727696
+(2, 55) ~ (3, 58) => 0.820669
+(2, 55) ~ (3, 59) => 0.0113806
+(2, 55) ~ (3, 60) => 0.0123758
+(2, 55) ~ (3, 61) => 0.0274192
+(2, 56) ~ (3, 55) => 0.0236865
+(2, 56) ~ (3, 57) => 0.0732798
+(2, 56) ~ (3, 59) => 0.812937
+(2, 56) ~ (3, 60) => 0.0178522
+(2, 56) ~ (3, 61) => 0.0110424
+(2, 56) ~ (3, 62) => 0.0260317
+(2, 57) ~ (3, 56) => 0.0231383
+(2, 57) ~ (3, 58) => 0.0651512
+(2, 57) ~ (3, 59) => 0.0202254
+(2, 57) ~ (3, 60) => 0.762579
+(2, 57) ~ (3, 61) => 0.0260054
+(2, 57) ~ (3, 62) => 0.0104877
+(2, 57) ~ (3, 63) => 0.0237027
+(2, 58) ~ (3, 57) => 0.0228056
+(2, 58) ~ (3, 59) => 0.0582755
+(2, 58) ~ (3, 60) => 0.0709923
+(2, 58) ~ (3, 61) => 0.745487
+(2, 58) ~ (3, 62) => 0.0229806
+(2, 58) ~ (3, 63) => 0.0104964
+(2, 58) ~ (3, 64) => 0.0250778
+(2, 59) ~ (3, 58) => 0.0210501
+(2, 59) ~ (3, 60) => 0.0400063
+(2, 59) ~ (3, 61) => 0.103635
+(2, 59) ~ (3, 62) => 0.743213
+(2, 59) ~ (3, 63) => 0.0120093
+(2, 59) ~ (3, 65) => 0.0269394
+(2, 60) ~ (3, 59) => 0.0205336
+(2, 60) ~ (3, 61) => 0.0311801
+(2, 60) ~ (3, 62) => 0.114275
+(2, 60) ~ (3, 63) => 0.763172
+(2, 60) ~ (3, 64) => 0.0108669
+(2, 60) ~ (3, 66) => 0.029065
+(2, 61) ~ (3, 60) => 0.019203
+(2, 61) ~ (3, 62) => 0.0250228
+(2, 61) ~ (3, 63) => 0.121338
+(2, 61) ~ (3, 64) => 0.763225
+(2, 61) ~ (3, 66) => 0.0100375
+(2, 61) ~ (3, 67) => 0.0275168
+(2, 62) ~ (3, 61) => 0.017906
+(2, 62) ~ (3, 63) => 0.0198621
+(2, 62) ~ (3, 64) => 0.114397
+(2, 62) ~ (3, 65) => 0.755672
+(2, 62) ~ (3, 66) => 0.0231649
+(2, 62) ~ (3, 68) => 0.0247336
+(2, 63) ~ (3, 62) => 0.0138077
+(2, 63) ~ (3, 64) => 0.0175315
+(2, 63) ~ (3, 65) => 0.109107
+(2, 63) ~ (3, 66) => 0.763379
+(2, 63) ~ (3, 67) => 0.0410025
+(2, 63) ~ (3, 69) => 0.020784
+(2, 64) ~ (3, 63) => 0.0102547
+(2, 64) ~ (3, 65) => 0.0138672
+(2, 64) ~ (3, 66) => 0.0731854
+(2, 64) ~ (3, 67) => 0.783173
+(2, 64) ~ (3, 68) => 0.0575795
+(2, 64) ~ (3, 70) => 0.0189942
+(2, 65) ~ (3, 66) => 0.0133074
+(2, 65) ~ (3, 67) => 0.0481256
+(2, 65) ~ (3, 68) => 0.811987
+(2, 65) ~ (3, 69) => 0.0582157
+(2, 65) ~ (3, 71) => 0.0162578
+(2, 66) ~ (3, 67) => 0.0157743
+(2, 66) ~ (3, 68) => 0.0395827
+(2, 66) ~ (3, 69) => 0.823794
+(2, 66) ~ (3, 70) => 0.0556786
+(2, 66) ~ (3, 72) => 0.0171338
+(2, 67) ~ (3, 68) => 0.0193724
+(2, 67) ~ (3, 69) => 0.0282314
+(2, 67) ~ (3, 70) => 0.834363
+(2, 67) ~ (3, 71) => 0.0464193
+(2, 67) ~ (3, 73) => 0.0174638
+(2, 68) ~ (3, 69) => 0.0260141
+(2, 68) ~ (3, 70) => 0.0165242
+(2, 68) ~ (3, 71) => 0.85728
+(2, 68) ~ (3, 72) => 0.0310383
+(2, 68) ~ (3, 74) => 0.0175118
+(2, 69) ~ (3, 70) => 0.035459
+(2, 69) ~ (3, 71) => 0.0113658
+(2, 69) ~ (3, 72) => 0.865281
+(2, 69) ~ (3, 73) => 0.0221201
+(2, 69) ~ (3, 75) => 0.0172224
+(2, 70) ~ (3, 71) => 0.0417122
+(2, 70) ~ (3, 72) => 0.0152907
+(2, 70) ~ (3, 73) => 0.860113
+(2, 70) ~ (3, 74) => 0.0226685
+(2, 70) ~ (3, 76) => 0.0159944
+(2, 71) ~ (3, 72) => 0.0421178
+(2, 71) ~ (3, 73) => 0.0216645
+(2, 71) ~ (3, 74) => 0.84704
+(2, 71) ~ (3, 75) => 0.0211169
+(2, 71) ~ (3, 77) => 0.0148277
+(2, 72) ~ (3, 73) => 0.043654
+(2, 72) ~ (3, 74) => 0.0172267
+(2, 72) ~ (3, 75) => 0.836945
+(2, 72) ~ (3, 76) => 0.0194034
+(2, 72) ~ (3, 78) => 0.0132848
+(2, 73) ~ (3, 74) => 0.0580869
+(2, 73) ~ (3, 75) => 0.0187178
+(2, 73) ~ (3, 76) => 0.810266
+(2, 73) ~ (3, 77) => 0.0276538
+(2, 73) ~ (3, 79) => 0.0104439
+(2, 74) ~ (3, 75) => 0.0717605
+(2, 74) ~ (3, 76) => 0.0191459
+(2, 74) ~ (3, 77) => 0.757251
+(2, 74) ~ (3, 78) => 0.0426763
+(2, 74) ~ (3, 79) => 0.0117989
+(2, 74) ~ (3, 80) => 0.0154628
+(2, 75) ~ (3, 76) => 0.0948856
+(2, 75) ~ (3, 77) => 0.0178498
+(2, 75) ~ (3, 78) => 0.702191
+(2, 75) ~ (3, 79) => 0.0632593
+(2, 75) ~ (3, 81) => 0.0248046
+(2, 76) ~ (3, 77) => 0.128414
+(2, 76) ~ (3, 78) => 0.0112402
+(2, 76) ~ (3, 79) => 0.672104
+(2, 76) ~ (3, 80) => 0.0661465
+(2, 76) ~ (3, 82) => 0.0333699
+(2, 77) ~ (3, 78) => 0.164143
+(2, 77) ~ (3, 80) => 0.613724
+(2, 77) ~ (3, 81) => 0.0825015
+(2, 77) ~ (3, 83) => 0.0382622
+(2, 78) ~ (3, 79) => 0.195281
+(2, 78) ~ (3, 80) => 0.0185792
+(2, 78) ~ (3, 81) => 0.555859
+(2, 78) ~ (3, 82) => 0.0961757
+(2, 78) ~ (3, 84) => 0.0421843
+(2, 79) ~ (3, 80) => 0.215348
+(2, 79) ~ (3, 81) => 0.0349873
+(2, 79) ~ (3, 82) => 0.496042
+(2, 79) ~ (3, 83) => 0.0364031
+(2, 79) ~ (3, 85) => 0.0326168
+(2, 80) ~ (3, 80) => 0.0115117
+(2, 80) ~ (3, 81) => 0.223624
+(2, 80) ~ (3, 82) => 0.079929
+(2, 80) ~ (3, 83) => 0.337106
+(2, 80) ~ (3, 84) => 0.0106316
+(2, 80) ~ (3, 86) => 0.0192009
+(2, 81) ~ (3, 81) => 0.0131745
+(2, 81) ~ (3, 82) => 0.180289
+(2, 81) ~ (3, 83) => 0.333153
+(2, 81) ~ (3, 84) => 0.188807
+(2, 82) ~ (3, 83) => 0.19264
+(2, 82) ~ (3, 84) => 0.510794
+(2, 82) ~ (3, 85) => 0.0423436
+(2, 83) ~ (3, 84) => 0.134766
+(2, 83) ~ (3, 85) => 0.748091
+(2, 83) ~ (3, 86) => 0.0340299
+(2, 84) ~ (3, 85) => 0.124034
+(2, 84) ~ (3, 86) => 0.797623
+(2, 84) ~ (3, 87) => 0.0147967
+(2, 85) ~ (3, 86) => 0.103652
+(2, 85) ~ (3, 87) => 0.842524
+(2, 85) ~ (3, 88) => 0.0208894
+(2, 86) ~ (3, 87) => 0.0997144
+(2, 86) ~ (3, 88) => 0.845196
+(2, 86) ~ (3, 89) => 0.0234072
+(2, 86) ~ (3, 90) => 0.0107157
+(2, 87) ~ (3, 88) => 0.0930518
+(2, 87) ~ (3, 89) => 0.8471
+(2, 87) ~ (3, 90) => 0.0248629
+(2, 87) ~ (3, 91) => 0.0139739
+(2, 88) ~ (3, 89) => 0.0857533
+(2, 88) ~ (3, 90) => 0.849847
+(2, 88) ~ (3, 91) => 0.0253994
+(2, 88) ~ (3, 92) => 0.0172874
+(2, 89) ~ (3, 90) => 0.0779791
+(2, 89) ~ (3, 91) => 0.853474
+(2, 89) ~ (3, 92) => 0.0248887
+(2, 89) ~ (3, 93) => 0.020537
+(2, 90) ~ (3, 91) => 0.0690332
+(2, 90) ~ (3, 92) => 0.854971
+(2, 90) ~ (3, 93) => 0.0215933
+(2, 90) ~ (3, 94) => 0.0265344
+(2, 91) ~ (3, 92) => 0.0544033
+(2, 91) ~ (3, 93) => 0.838902
+(2, 91) ~ (3, 94) => 0.0154623
+(2, 91) ~ (3, 95) => 0.04098
+(2, 92) ~ (3, 92) => 0.0132734
+(2, 92) ~ (3, 93) => 0.0640387
+(2, 92) ~ (3, 94) => 0.81029
+(2, 92) ~ (3, 95) => 0.030015
+(2, 92) ~ (3, 96) => 0.0506843
+(2, 93) ~ (3, 93) => 0.0139586
+(2, 93) ~ (3, 94) => 0.066642
+(2, 93) ~ (3, 95) => 0.793257
+(2, 93) ~ (3, 96) => 0.0371655
+(2, 93) ~ (3, 97) => 0.0576045
+(2, 94) ~ (3, 94) => 0.0134106
+(2, 94) ~ (3, 95) => 0.0708252
+(2, 94) ~ (3, 96) => 0.777998
+(2, 94) ~ (3, 97) => 0.042573
+(2, 94) ~ (3, 98) => 0.0650598
+(2, 95) ~ (3, 95) => 0.0136072
+(2, 95) ~ (3, 96) => 0.0740319
+(2, 95) ~ (3, 97) => 0.767366
+(2, 95) ~ (3, 98) => 0.0473759
+(2, 95) ~ (3, 99) => 0.0732843
+(2, 96) ~ (3, 96) => 0.0126428
+(2, 96) ~ (3, 97) => 0.0727371
+(2, 96) ~ (3, 98) => 0.746456
+(2, 96) ~ (3, 99) => 0.0447085
+(2, 96) ~ (3, 100) => 0.0872262
+(2, 97) ~ (3, 97) => 0.01097
+(2, 97) ~ (3, 98) => 0.069651
+(2, 97) ~ (3, 99) => 0.664269
+(2, 97) ~ (3, 100) => 0.0886041
+(2, 97) ~ (3, 101) => 0.136258
+(2, 98) ~ (3, 99) => 0.0633581
+(2, 98) ~ (3, 100) => 0.638794
+(2, 98) ~ (3, 101) => 0.0972055
+(2, 98) ~ (3, 102) => 0.158956
+(2, 99) ~ (3, 100) => 0.0642447
+(2, 99) ~ (3, 101) => 0.608713
+(2, 99) ~ (3, 102) => 0.101072
+(2, 99) ~ (3, 103) => 0.179987
+(2, 99) ~ (3, 104) => 0.0134226
+(2, 100) ~ (3, 101) => 0.0628381
+(2, 100) ~ (3, 102) => 0.565253
+(2, 100) ~ (3, 103) => 0.0925793
+(2, 100) ~ (3, 104) => 0.22493
+(2, 100) ~ (3, 105) => 0.0201774
+(2, 101) ~ (3, 102) => 0.0582955
+(2, 101) ~ (3, 103) => 0.488531
+(2, 101) ~ (3, 104) => 0.088342
+(2, 101) ~ (3, 105) => 0.301908
+(2, 101) ~ (3, 106) => 0.0234782
+(2, 102) ~ (3, 103) => 0.0488188
+(2, 102) ~ (3, 104) => 0.442169
+(2, 102) ~ (3, 105) => 0.0861669
+(2, 102) ~ (3, 106) => 0.339663
+(2, 102) ~ (3, 107) => 0.0319856
+(2, 102) ~ (3, 108) => 0.0102129
+(2, 103) ~ (3, 104) => 0.0451189
+(2, 103) ~ (3, 105) => 0.417869
+(2, 103) ~ (3, 106) => 0.101878
+(2, 103) ~ (3, 107) => 0.330704
+(2, 103) ~ (3, 108) => 0.0556638
+(2, 103) ~ (3, 109) => 0.0128317
+(2, 104) ~ (3, 105) => 0.0390924
+(2, 104) ~ (3, 106) => 0.358106
+(2, 104) ~ (3, 107) => 0.150172
+(2, 104) ~ (3, 108) => 0.303106
+(2, 104) ~ (3, 109) => 0.0977888
+(2, 104) ~ (3, 110) => 0.013972
+(2, 105) ~ (3, 106) => 0.0274588
+(2, 105) ~ (3, 107) => 0.340064
+(2, 105) ~ (3, 108) => 0.167527
+(2, 105) ~ (3, 109) => 0.288065
+(2, 105) ~ (3, 110) => 0.118611
+(2, 105) ~ (3, 111) => 0.0163121
+(2, 105) ~ (3, 112) => 0.0110333
+(2, 106) ~ (3, 107) => 0.0219264
+(2, 106) ~ (3, 108) => 0.298204
+(2, 106) ~ (3, 109) => 0.196487
+(2, 106) ~ (3, 110) => 0.239676
+(2, 106) ~ (3, 111) => 0.174687
+(2, 106) ~ (3, 112) => 0.0226356
+(2, 106) ~ (3, 113) => 0.01682
+(2, 107) ~ (3, 108) => 0.0112795
+(2, 107) ~ (3, 109) => 0.267841
+(2, 107) ~ (3, 110) => 0.196018
+(2, 107) ~ (3, 111) => 0.198548
+(2, 107) ~ (3, 112) => 0.249279
+(2, 107) ~ (3, 113) => 0.0255195
+(2, 107) ~ (3, 114) => 0.0218508
+(2, 108) ~ (3, 110) => 0.193457
+(2, 108) ~ (3, 111) => 0.221388
+(2, 108) ~ (3, 112) => 0.179815
+(2, 108) ~ (3, 113) => 0.318613
+(2, 108) ~ (3, 114) => 0.0269196
+(2, 108) ~ (3, 115) => 0.0301377
+(2, 109) ~ (3, 111) => 0.139579
+(2, 109) ~ (3, 112) => 0.247642
+(2, 109) ~ (3, 113) => 0.143416
+(2, 109) ~ (3, 114) => 0.363755
+(2, 109) ~ (3, 115) => 0.0293932
+(2, 109) ~ (3, 116) => 0.0436318
+(2, 109) ~ (3, 117) => 0.0103051
+(2, 110) ~ (3, 112) => 0.106042
+(2, 110) ~ (3, 113) => 0.246516
+(2, 110) ~ (3, 114) => 0.0569842
+(2, 110) ~ (3, 115) => 0.449036
+(2, 110) ~ (3, 116) => 0.0339885
+(2, 110) ~ (3, 117) => 0.0626111
+(2, 111) ~ (3, 113) => 0.0552989
+(2, 111) ~ (3, 114) => 0.224447
+(2, 111) ~ (3, 115) => 0.0445831
+(2, 111) ~ (3, 116) => 0.410877
+(2, 111) ~ (3, 117) => 0.0744035
+(2, 111) ~ (3, 118) => 0.160586
+(2, 112) ~ (3, 114) => 0.0434332
+(2, 112) ~ (3, 115) => 0.175791
+(2, 112) ~ (3, 116) => 0.0534169
+(2, 112) ~ (3, 117) => 0.355902
+(2, 112) ~ (3, 118) => 0.095059
+(2, 112) ~ (3, 119) => 0.24442
+(2, 113) ~ (3, 115) => 0.0322391
+(2, 113) ~ (3, 116) => 0.132796
+(2, 113) ~ (3, 117) => 0.0568449
+(2, 113) ~ (3, 118) => 0.30053
+(2, 113) ~ (3, 119) => 0.106687
+(2, 113) ~ (3, 120) => 0.339605
+(2, 114) ~ (3, 116) => 0.0221525
+(2, 114) ~ (3, 117) => 0.0938424
+(2, 114) ~ (3, 118) => 0.0545654
+(2, 114) ~ (3, 119) => 0.243757
+(2, 114) ~ (3, 120) => 0.109812
+(2, 114) ~ (3, 121) => 0.447637
+(2, 115) ~ (3, 117) => 0.0127634
+(2, 115) ~ (3, 118) => 0.058171
+(2, 115) ~ (3, 119) => 0.0469398
+(2, 115) ~ (3, 120) => 0.187073
+(2, 115) ~ (3, 121) => 0.103177
+(2, 115) ~ (3, 122) => 0.569744
+(2, 116) ~ (3, 119) => 0.0363324
+(2, 116) ~ (3, 120) => 0.0337418
+(2, 116) ~ (3, 121) => 0.128479
+(2, 116) ~ (3, 122) => 0.0844861
+(2, 116) ~ (3, 123) => 0.697759
+
+; gap posteriors
+(2, 0) ~ (3, -1) => 0.0877809
+(2, 1) ~ (3, -1) => 0.147459
+(2, 2) ~ (3, -1) => 0.438567
+(2, 3) ~ (3, -1) => 0.203983
+(2, 4) ~ (3, -1) => 0.0493607
+(2, 5) ~ (3, -1) => 0.0558425
+(2, 6) ~ (3, -1) => 0.0386316
+(2, 7) ~ (3, -1) => 0.0270138
+(2, 8) ~ (3, -1) => 0.0272533
+(2, 9) ~ (3, -1) => 0.0420483
+(2, 10) ~ (3, -1) => 0.0281353
+(2, 11) ~ (3, -1) => 0.0269
+(2, 12) ~ (3, -1) => 0.033918
+(2, 13) ~ (3, -1) => 0.0333499
+(2, 14) ~ (3, -1) => 0.0382407
+(2, 15) ~ (3, -1) => 0.0284983
+(2, 16) ~ (3, -1) => 0.0391094
+(2, 17) ~ (3, -1) => 0.0405911
+(2, 18) ~ (3, -1) => 0.0276393
+(2, 19) ~ (3, -1) => 0.0242372
+(2, 20) ~ (3, -1) => 0.027607
+(2, 21) ~ (3, -1) => 0.0369975
+(2, 22) ~ (3, -1) => 0.0415553
+(2, 23) ~ (3, -1) => 0.0418888
+(2, 24) ~ (3, -1) => 0.0287031
+(2, 25) ~ (3, -1) => 0.0313156
+(2, 26) ~ (3, -1) => 0.0270151
+(2, 27) ~ (3, -1) => 0.067274
+(2, 28) ~ (3, -1) => 0.0210858
+(2, 29) ~ (3, -1) => 0.0452946
+(2, 30) ~ (3, -1) => 0.01763
+(2, 31) ~ (3, -1) => 0.01353
+(2, 32) ~ (3, -1) => 0.0104404
+(2, 33) ~ (3, -1) => 0.0185649
+(2, 34) ~ (3, -1) => 0.00884382
+(2, 35) ~ (3, -1) => 0.0108326
+(2, 36) ~ (3, -1) => 0.0212617
+(2, 37) ~ (3, -1) => 0.0111692
+(2, 38) ~ (3, -1) => 0.01435
+(2, 39) ~ (3, -1) => 0.0190129
+(2, 40) ~ (3, -1) => 0.0132385
+(2, 41) ~ (3, -1) => 0.0185611
+(2, 42) ~ (3, -1) => 0.0188782
+(2, 43) ~ (3, -1) => 0.0169189
+(2, 44) ~ (3, -1) => 0.0302144
+(2, 45) ~ (3, -1) => 0.0278494
+(2, 46) ~ (3, -1) => 0.0334706
+(2, 47) ~ (3, -1) => 0.0400531
+(2, 48) ~ (3, -1) => 0.0357975
+(2, 49) ~ (3, -1) => 0.028187
+(2, 50) ~ (3, -1) => 0.033726
+(2, 51) ~ (3, -1) => 0.0532859
+(2, 52) ~ (3, -1) => 0.0403041
+(2, 53) ~ (3, -1) => 0.0548203
+(2, 54) ~ (3, -1) => 0.0385958
+(2, 55) ~ (3, -1) => 0.033346
+(2, 56) ~ (3, -1) => 0.0351706
+(2, 57) ~ (3, -1) => 0.0687101
+(2, 58) ~ (3, -1) => 0.0438844
+(2, 59) ~ (3, -1) => 0.0531467
+(2, 60) ~ (3, -1) => 0.0309074
+(2, 61) ~ (3, -1) => 0.0336566
+(2, 62) ~ (3, -1) => 0.0442651
+(2, 63) ~ (3, -1) => 0.0343893
+(2, 64) ~ (3, -1) => 0.0429456
+(2, 65) ~ (3, -1) => 0.0521062
+(2, 66) ~ (3, -1) => 0.048037
+(2, 67) ~ (3, -1) => 0.0541499
+(2, 68) ~ (3, -1) => 0.0516318
+(2, 69) ~ (3, -1) => 0.0485513
+(2, 70) ~ (3, -1) => 0.0442208
+(2, 71) ~ (3, -1) => 0.053233
+(2, 72) ~ (3, -1) => 0.0694859
+(2, 73) ~ (3, -1) => 0.0748312
+(2, 74) ~ (3, -1) => 0.0819042
+(2, 75) ~ (3, -1) => 0.0970098
+(2, 76) ~ (3, -1) => 0.0887252
+(2, 77) ~ (3, -1) => 0.10137
+(2, 78) ~ (3, -1) => 0.091921
+(2, 79) ~ (3, -1) => 0.184603
+(2, 80) ~ (3, -1) => 0.317997
+(2, 81) ~ (3, -1) => 0.284577
+(2, 82) ~ (3, -1) => 0.254223
+(2, 83) ~ (3, -1) => 0.0831129
+(2, 84) ~ (3, -1) => 0.0635464
+(2, 85) ~ (3, -1) => 0.0329345
+(2, 86) ~ (3, -1) => 0.0209663
+(2, 87) ~ (3, -1) => 0.0210114
+(2, 88) ~ (3, -1) => 0.0217129
+(2, 89) ~ (3, -1) => 0.0231215
+(2, 90) ~ (3, -1) => 0.027868
+(2, 91) ~ (3, -1) => 0.0502525
+(2, 92) ~ (3, -1) => 0.0316988
+(2, 93) ~ (3, -1) => 0.0313728
+(2, 94) ~ (3, -1) => 0.0301334
+(2, 95) ~ (3, -1) => 0.0243352
+(2, 96) ~ (3, -1) => 0.0362296
+(2, 97) ~ (3, -1) => 0.0302476
+(2, 98) ~ (3, -1) => 0.0416869
+(2, 99) ~ (3, -1) => 0.0325608
+(2, 100) ~ (3, -1) => 0.0342223
+(2, 101) ~ (3, -1) => 0.0394444
+(2, 102) ~ (3, -1) => 0.0409836
+(2, 103) ~ (3, -1) => 0.0359349
+(2, 104) ~ (3, -1) => 0.0377625
+(2, 105) ~ (3, -1) => 0.0309289
+(2, 106) ~ (3, -1) => 0.0295646
+(2, 107) ~ (3, -1) => 0.0296637
+(2, 108) ~ (3, -1) => 0.0296693
+(2, 109) ~ (3, -1) => 0.0222767
+(2, 110) ~ (3, -1) => 0.0448225
+(2, 111) ~ (3, -1) => 0.0298049
+(2, 112) ~ (3, -1) => 0.0319781
+(2, 113) ~ (3, -1) => 0.0312987
+(2, 114) ~ (3, -1) => 0.0282332
+(2, 115) ~ (3, -1) => 0.0221325
+(2, 116) ~ (3, -1) => 0.019201
+
+(2, -1) ~ (3, 0) => 0.00549098
+(2, -1) ~ (3, 1) => 0.0284047
+(2, -1) ~ (3, 2) => 0.0177408
+(2, -1) ~ (3, 3) => 0.0300718
+(2, -1) ~ (3, 4) => 0.0163935
+(2, -1) ~ (3, 5) => 0.0176419
+(2, -1) ~ (3, 6) => 0.0154013
+(2, -1) ~ (3, 7) => 0.0242956
+(2, -1) ~ (3, 8) => 0.0175344
+(2, -1) ~ (3, 9) => 0.0207839
+(2, -1) ~ (3, 10) => 0.0212925
+(2, -1) ~ (3, 11) => 0.0290905
+(2, -1) ~ (3, 12) => 0.0314603
+(2, -1) ~ (3, 13) => 0.0216237
+(2, -1) ~ (3, 14) => 0.0321548
+(2, -1) ~ (3, 15) => 0.0350075
+(2, -1) ~ (3, 16) => 0.0368452
+(2, -1) ~ (3, 17) => 0.0609611
+(2, -1) ~ (3, 18) => 0.0784882
+(2, -1) ~ (3, 19) => 0.0672284
+(2, -1) ~ (3, 20) => 0.12813
+(2, -1) ~ (3, 21) => 0.142884
+(2, -1) ~ (3, 22) => 0.218807
+(2, -1) ~ (3, 23) => 0.171967
+(2, -1) ~ (3, 24) => 0.15967
+(2, -1) ~ (3, 25) => 0.222197
+(2, -1) ~ (3, 26) => 0.18551
+(2, -1) ~ (3, 27) => 0.187592
+(2, -1) ~ (3, 28) => 0.263713
+(2, -1) ~ (3, 29) => 0.214358
+(2, -1) ~ (3, 30) => 0.0681732
+(2, -1) ~ (3, 31) => 0.0538566
+(2, -1) ~ (3, 32) => 0.0478567
+(2, -1) ~ (3, 33) => 0.0412337
+(2, -1) ~ (3, 34) => 0.0572303
+(2, -1) ~ (3, 35) => 0.0284314
+(2, -1) ~ (3, 36) => 0.0252472
+(2, -1) ~ (3, 37) => 0.026946
+(2, -1) ~ (3, 38) => 0.0370179
+(2, -1) ~ (3, 39) => 0.0292104
+(2, -1) ~ (3, 40) => 0.0339145
+(2, -1) ~ (3, 41) => 0.0456549
+(2, -1) ~ (3, 42) => 0.0635432
+(2, -1) ~ (3, 43) => 0.112828
+(2, -1) ~ (3, 44) => 0.150704
+(2, -1) ~ (3, 45) => 0.290169
+(2, -1) ~ (3, 46) => 0.387257
+(2, -1) ~ (3, 47) => 0.312
+(2, -1) ~ (3, 48) => 0.250659
+(2, -1) ~ (3, 49) => 0.162182
+(2, -1) ~ (3, 50) => 0.101866
+(2, -1) ~ (3, 51) => 0.0735808
+(2, -1) ~ (3, 52) => 0.0984006
+(2, -1) ~ (3, 53) => 0.082471
+(2, -1) ~ (3, 54) => 0.0700025
+(2, -1) ~ (3, 55) => 0.0546228
+(2, -1) ~ (3, 56) => 0.0552658
+(2, -1) ~ (3, 57) => 0.0422634
+(2, -1) ~ (3, 58) => 0.0540859
+(2, -1) ~ (3, 59) => 0.0359253
+(2, -1) ~ (3, 60) => 0.0505454
+(2, -1) ~ (3, 61) => 0.0373247
+(2, -1) ~ (3, 62) => 0.0441815
+(2, -1) ~ (3, 63) => 0.0391645
+(2, -1) ~ (3, 64) => 0.068902
+(2, -1) ~ (3, 65) => 0.0944152
+(2, -1) ~ (3, 66) => 0.0878613
+(2, -1) ~ (3, 67) => 0.0844075
+(2, -1) ~ (3, 68) => 0.0467444
+(2, -1) ~ (3, 69) => 0.0429611
+(2, -1) ~ (3, 70) => 0.0389809
+(2, -1) ~ (3, 71) => 0.0269651
+(2, -1) ~ (3, 72) => 0.0291381
+(2, -1) ~ (3, 73) => 0.0349843
+(2, -1) ~ (3, 74) => 0.0374661
+(2, -1) ~ (3, 75) => 0.0342372
+(2, -1) ~ (3, 76) => 0.0403042
+(2, -1) ~ (3, 77) => 0.0540031
+(2, -1) ~ (3, 78) => 0.066465
+(2, -1) ~ (3, 79) => 0.0471131
+(2, -1) ~ (3, 80) => 0.0592285
+(2, -1) ~ (3, 81) => 0.0650489
+(2, -1) ~ (3, 82) => 0.114195
+(2, -1) ~ (3, 83) => 0.062436
+(2, -1) ~ (3, 84) => 0.112817
+(2, -1) ~ (3, 85) => 0.0529147
+(2, -1) ~ (3, 86) => 0.0454942
+(2, -1) ~ (3, 87) => 0.042965
+(2, -1) ~ (3, 88) => 0.0408624
+(2, -1) ~ (3, 89) => 0.0437396
+(2, -1) ~ (3, 90) => 0.0365953
+(2, -1) ~ (3, 91) => 0.0381197
+(2, -1) ~ (3, 92) => 0.0351761
+(2, -1) ~ (3, 93) => 0.0409706
+(2, -1) ~ (3, 94) => 0.0676607
+(2, -1) ~ (3, 95) => 0.0513159
+(2, -1) ~ (3, 96) => 0.0474775
+(2, -1) ~ (3, 97) => 0.0487498
+(2, -1) ~ (3, 98) => 0.0714575
+(2, -1) ~ (3, 99) => 0.15438
+(2, -1) ~ (3, 100) => 0.121131
+(2, -1) ~ (3, 101) => 0.0949849
+(2, -1) ~ (3, 102) => 0.116424
+(2, -1) ~ (3, 103) => 0.190084
+(2, -1) ~ (3, 104) => 0.186017
+(2, -1) ~ (3, 105) => 0.134786
+(2, -1) ~ (3, 106) => 0.149416
+(2, -1) ~ (3, 107) => 0.125148
+(2, -1) ~ (3, 108) => 0.154007
+(2, -1) ~ (3, 109) => 0.136986
+(2, -1) ~ (3, 110) => 0.238266
+(2, -1) ~ (3, 111) => 0.249486
+(2, -1) ~ (3, 112) => 0.183553
+(2, -1) ~ (3, 113) => 0.193816
+(2, -1) ~ (3, 114) => 0.262609
+(2, -1) ~ (3, 115) => 0.23882
+(2, -1) ~ (3, 116) => 0.303138
+(2, -1) ~ (3, 117) => 0.333328
+(2, -1) ~ (3, 118) => 0.331089
+(2, -1) ~ (3, 119) => 0.321864
+(2, -1) ~ (3, 120) => 0.329769
+(2, -1) ~ (3, 121) => 0.320706
+(2, -1) ~ (3, 122) => 0.34577
+(2, -1) ~ (3, 123) => 0.302241
+
+; Sparse posterior probability matrix for sequences 2 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (4, 0) => 0.999973
+(2, 1) ~ (4, 1) => 0.999959
+(2, 2) ~ (4, 2) => 0.999958
+(2, 3) ~ (4, 3) => 0.999941
+(2, 4) ~ (4, 4) => 0.999919
+(2, 5) ~ (4, 5) => 0.999891
+(2, 6) ~ (4, 6) => 0.99981
+(2, 7) ~ (4, 7) => 0.999116
+(2, 8) ~ (4, 8) => 0.998434
+(2, 9) ~ (4, 9) => 0.995901
+(2, 10) ~ (4, 10) => 0.996327
+(2, 11) ~ (4, 11) => 0.997881
+(2, 12) ~ (4, 12) => 0.999732
+(2, 13) ~ (4, 13) => 0.999802
+(2, 14) ~ (4, 14) => 0.99983
+(2, 15) ~ (4, 15) => 0.999743
+(2, 16) ~ (4, 16) => 0.999785
+(2, 17) ~ (4, 17) => 0.999937
+(2, 18) ~ (4, 18) => 0.999951
+(2, 19) ~ (4, 19) => 0.999927
+(2, 20) ~ (4, 20) => 0.999795
+(2, 21) ~ (4, 21) => 0.999275
+(2, 22) ~ (4, 22) => 0.996451
+(2, 23) ~ (4, 23) => 0.873754
+(2, 23) ~ (4, 25) => 0.125035
+(2, 24) ~ (4, 24) => 0.829152
+(2, 24) ~ (4, 26) => 0.169029
+(2, 25) ~ (4, 25) => 0.783438
+(2, 25) ~ (4, 27) => 0.212918
+(2, 26) ~ (4, 26) => 0.737339
+(2, 26) ~ (4, 28) => 0.256707
+(2, 27) ~ (4, 27) => 0.392799
+(2, 27) ~ (4, 29) => 0.596058
+(2, 28) ~ (4, 28) => 0.0543627
+(2, 28) ~ (4, 30) => 0.941193
+(2, 29) ~ (4, 29) => 0.0102944
+(2, 29) ~ (4, 31) => 0.98758
+(2, 30) ~ (4, 32) => 0.987631
+(2, 31) ~ (4, 33) => 0.987558
+(2, 32) ~ (4, 34) => 0.987287
+(2, 33) ~ (4, 35) => 0.98688
+(2, 34) ~ (4, 36) => 0.98644
+(2, 35) ~ (4, 37) => 0.98908
+(2, 36) ~ (4, 38) => 0.991073
+(2, 37) ~ (4, 39) => 0.992566
+(2, 38) ~ (4, 40) => 0.993351
+(2, 39) ~ (4, 41) => 0.994015
+(2, 40) ~ (4, 42) => 0.994746
+(2, 41) ~ (4, 43) => 0.995839
+(2, 42) ~ (4, 44) => 0.977547
+(2, 42) ~ (4, 45) => 0.0182142
+(2, 43) ~ (4, 45) => 0.948504
+(2, 43) ~ (4, 46) => 0.0438593
+(2, 44) ~ (4, 46) => 0.80689
+(2, 44) ~ (4, 47) => 0.172119
+(2, 44) ~ (4, 48) => 0.0151122
+(2, 45) ~ (4, 47) => 0.66376
+(2, 45) ~ (4, 48) => 0.298734
+(2, 45) ~ (4, 49) => 0.0254432
+(2, 46) ~ (4, 48) => 0.535235
+(2, 46) ~ (4, 49) => 0.426938
+(2, 46) ~ (4, 50) => 0.0156811
+(2, 47) ~ (4, 49) => 0.18341
+(2, 47) ~ (4, 50) => 0.793797
+(2, 48) ~ (4, 50) => 0.0546794
+(2, 48) ~ (4, 51) => 0.937541
+(2, 49) ~ (4, 51) => 0.038142
+(2, 49) ~ (4, 52) => 0.955037
+(2, 50) ~ (4, 52) => 0.0214529
+(2, 50) ~ (4, 53) => 0.972652
+(2, 51) ~ (4, 54) => 0.990151
+(2, 52) ~ (4, 55) => 0.987688
+(2, 53) ~ (4, 56) => 0.984835
+(2, 54) ~ (4, 57) => 0.981194
+(2, 55) ~ (4, 58) => 0.98758
+(2, 56) ~ (4, 59) => 0.992328
+(2, 57) ~ (4, 60) => 0.994514
+(2, 58) ~ (4, 61) => 0.995624
+(2, 59) ~ (4, 62) => 0.995867
+(2, 60) ~ (4, 63) => 0.995137
+(2, 61) ~ (4, 64) => 0.994339
+(2, 62) ~ (4, 65) => 0.985782
+(2, 62) ~ (4, 66) => 0.0116691
+(2, 63) ~ (4, 66) => 0.974591
+(2, 63) ~ (4, 67) => 0.0177516
+(2, 64) ~ (4, 67) => 0.974288
+(2, 64) ~ (4, 68) => 0.0150426
+(2, 65) ~ (4, 68) => 0.981646
+(2, 65) ~ (4, 69) => 0.0111215
+(2, 66) ~ (4, 69) => 0.987026
+(2, 67) ~ (4, 70) => 0.991489
+(2, 68) ~ (4, 71) => 0.992768
+(2, 69) ~ (4, 72) => 0.994095
+(2, 70) ~ (4, 73) => 0.999045
+(2, 71) ~ (4, 74) => 0.999827
+(2, 72) ~ (4, 75) => 0.999803
+(2, 73) ~ (4, 76) => 0.999569
+(2, 74) ~ (4, 77) => 0.994798
+(2, 75) ~ (4, 78) => 0.988805
+(2, 76) ~ (4, 79) => 0.98439
+(2, 77) ~ (4, 80) => 0.972567
+(2, 78) ~ (4, 80) => 0.0140551
+(2, 78) ~ (4, 81) => 0.973198
+(2, 79) ~ (4, 81) => 0.0106253
+(2, 79) ~ (4, 82) => 0.984992
+(2, 80) ~ (4, 83) => 0.99094
+(2, 81) ~ (4, 84) => 0.998216
+(2, 82) ~ (4, 85) => 0.998343
+(2, 83) ~ (4, 86) => 0.995831
+(2, 84) ~ (4, 87) => 0.987651
+(2, 85) ~ (4, 88) => 0.960698
+(2, 86) ~ (4, 88) => 0.0132651
+(2, 86) ~ (4, 89) => 0.934129
+(2, 87) ~ (4, 88) => 0.0117123
+(2, 87) ~ (4, 89) => 0.0214743
+(2, 87) ~ (4, 90) => 0.90714
+(2, 87) ~ (4, 91) => 0.0102037
+(2, 88) ~ (4, 89) => 0.0203423
+(2, 88) ~ (4, 90) => 0.028983
+(2, 88) ~ (4, 91) => 0.81782
+(2, 88) ~ (4, 92) => 0.0113718
+(2, 89) ~ (4, 90) => 0.0288114
+(2, 89) ~ (4, 91) => 0.0301506
+(2, 89) ~ (4, 92) => 0.718794
+(2, 90) ~ (4, 91) => 0.031314
+(2, 90) ~ (4, 92) => 0.0267699
+(2, 90) ~ (4, 93) => 0.49835
+(2, 90) ~ (4, 96) => 0.0143709
+(2, 91) ~ (4, 90) => 0.0107846
+(2, 91) ~ (4, 92) => 0.0292316
+(2, 91) ~ (4, 94) => 0.17252
+(2, 91) ~ (4, 97) => 0.137018
+(2, 92) ~ (4, 91) => 0.0963423
+(2, 92) ~ (4, 92) => 0.0186512
+(2, 92) ~ (4, 93) => 0.165762
+(2, 92) ~ (4, 95) => 0.0926958
+(2, 92) ~ (4, 98) => 0.136725
+(2, 93) ~ (4, 92) => 0.18046
+(2, 93) ~ (4, 93) => 0.0293981
+(2, 93) ~ (4, 94) => 0.287231
+(2, 93) ~ (4, 96) => 0.0173829
+(2, 93) ~ (4, 99) => 0.135975
+(2, 94) ~ (4, 93) => 0.259966
+(2, 94) ~ (4, 94) => 0.0223073
+(2, 94) ~ (4, 95) => 0.37379
+(2, 94) ~ (4, 100) => 0.134254
+(2, 95) ~ (4, 94) => 0.313548
+(2, 95) ~ (4, 95) => 0.0147214
+(2, 95) ~ (4, 96) => 0.481227
+(2, 95) ~ (4, 101) => 0.1299
+(2, 96) ~ (4, 95) => 0.281428
+(2, 96) ~ (4, 96) => 0.0126401
+(2, 96) ~ (4, 97) => 0.489366
+(2, 96) ~ (4, 98) => 0.0191972
+(2, 96) ~ (4, 102) => 0.0159534
+(2, 97) ~ (4, 96) => 0.284253
+(2, 97) ~ (4, 97) => 0.0158498
+(2, 97) ~ (4, 98) => 0.434571
+(2, 97) ~ (4, 99) => 0.0206082
+(2, 97) ~ (4, 103) => 0.0114567
+(2, 98) ~ (4, 97) => 0.302922
+(2, 98) ~ (4, 98) => 0.0213778
+(2, 98) ~ (4, 99) => 0.380668
+(2, 98) ~ (4, 100) => 0.0200138
+(2, 99) ~ (4, 98) => 0.351583
+(2, 99) ~ (4, 99) => 0.0246088
+(2, 99) ~ (4, 100) => 0.323652
+(2, 99) ~ (4, 101) => 0.0153151
+(2, 100) ~ (4, 98) => 0.0132709
+(2, 100) ~ (4, 99) => 0.400242
+(2, 100) ~ (4, 100) => 0.0251155
+(2, 100) ~ (4, 101) => 0.192022
+(2, 100) ~ (4, 102) => 0.0236002
+(2, 101) ~ (4, 99) => 0.0189444
+(2, 101) ~ (4, 100) => 0.448056
+(2, 101) ~ (4, 101) => 0.0137732
+(2, 101) ~ (4, 102) => 0.106586
+(2, 101) ~ (4, 103) => 0.0152306
+(2, 102) ~ (4, 100) => 0.0239723
+(2, 102) ~ (4, 101) => 0.47956
+(2, 102) ~ (4, 103) => 0.0140131
+(2, 103) ~ (4, 101) => 0.136731
+(2, 103) ~ (4, 102) => 0.397817
+(2, 103) ~ (4, 104) => 0.0100579
+(2, 104) ~ (4, 102) => 0.410569
+(2, 104) ~ (4, 103) => 0.305299
+(2, 105) ~ (4, 103) => 0.610093
+(2, 105) ~ (4, 104) => 0.206547
+(2, 106) ~ (4, 104) => 0.737252
+(2, 106) ~ (4, 105) => 0.107586
+(2, 107) ~ (4, 105) => 0.863061
+(2, 108) ~ (4, 106) => 0.990022
+(2, 109) ~ (4, 107) => 0.99527
+(2, 110) ~ (4, 108) => 0.999439
+(2, 111) ~ (4, 109) => 0.999211
+(2, 112) ~ (4, 110) => 0.998805
+(2, 113) ~ (4, 111) => 0.998975
+(2, 114) ~ (4, 112) => 0.999288
+(2, 115) ~ (4, 113) => 0.999372
+(2, 116) ~ (4, 114) => 0.999479
+
+; gap posteriors
+(2, 0) ~ (4, -1) => 0.0001
+(2, 1) ~ (4, -1) => 0.0001
+(2, 2) ~ (4, -1) => 0.0001
+(2, 3) ~ (4, -1) => 0.0001
+(2, 4) ~ (4, -1) => 0.0001
+(2, 5) ~ (4, -1) => 0.000109017
+(2, 6) ~ (4, -1) => 0.000190377
+(2, 7) ~ (4, -1) => 0.000883937
+(2, 8) ~ (4, -1) => 0.00156647
+(2, 9) ~ (4, -1) => 0.00409913
+(2, 10) ~ (4, -1) => 0.00367343
+(2, 11) ~ (4, -1) => 0.00211948
+(2, 12) ~ (4, -1) => 0.000268221
+(2, 13) ~ (4, -1) => 0.000198305
+(2, 14) ~ (4, -1) => 0.000169575
+(2, 15) ~ (4, -1) => 0.000256658
+(2, 16) ~ (4, -1) => 0.000214875
+(2, 17) ~ (4, -1) => 0.0001
+(2, 18) ~ (4, -1) => 0.0001
+(2, 19) ~ (4, -1) => 0.0001
+(2, 20) ~ (4, -1) => 0.000204742
+(2, 21) ~ (4, -1) => 0.000725269
+(2, 22) ~ (4, -1) => 0.00354856
+(2, 23) ~ (4, -1) => 0.0012116
+(2, 24) ~ (4, -1) => 0.00181881
+(2, 25) ~ (4, -1) => 0.00364436
+(2, 26) ~ (4, -1) => 0.00595394
+(2, 27) ~ (4, -1) => 0.0111427
+(2, 28) ~ (4, -1) => 0.00444442
+(2, 29) ~ (4, -1) => 0.00212574
+(2, 30) ~ (4, -1) => 0.0123688
+(2, 31) ~ (4, -1) => 0.0124415
+(2, 32) ~ (4, -1) => 0.0127129
+(2, 33) ~ (4, -1) => 0.0131204
+(2, 34) ~ (4, -1) => 0.0135601
+(2, 35) ~ (4, -1) => 0.0109202
+(2, 36) ~ (4, -1) => 0.00892693
+(2, 37) ~ (4, -1) => 0.00743407
+(2, 38) ~ (4, -1) => 0.00664937
+(2, 39) ~ (4, -1) => 0.00598472
+(2, 40) ~ (4, -1) => 0.00525385
+(2, 41) ~ (4, -1) => 0.0041607
+(2, 42) ~ (4, -1) => 0.00423832
+(2, 43) ~ (4, -1) => 0.00763632
+(2, 44) ~ (4, -1) => 0.00587854
+(2, 45) ~ (4, -1) => 0.0120628
+(2, 46) ~ (4, -1) => 0.0221453
+(2, 47) ~ (4, -1) => 0.0227933
+(2, 48) ~ (4, -1) => 0.00777984
+(2, 49) ~ (4, -1) => 0.00682092
+(2, 50) ~ (4, -1) => 0.0058952
+(2, 51) ~ (4, -1) => 0.00984943
+(2, 52) ~ (4, -1) => 0.0123124
+(2, 53) ~ (4, -1) => 0.0151654
+(2, 54) ~ (4, -1) => 0.0188055
+(2, 55) ~ (4, -1) => 0.0124199
+(2, 56) ~ (4, -1) => 0.00767189
+(2, 57) ~ (4, -1) => 0.00548559
+(2, 58) ~ (4, -1) => 0.0043757
+(2, 59) ~ (4, -1) => 0.00413293
+(2, 60) ~ (4, -1) => 0.00486308
+(2, 61) ~ (4, -1) => 0.00566137
+(2, 62) ~ (4, -1) => 0.00254938
+(2, 63) ~ (4, -1) => 0.00765711
+(2, 64) ~ (4, -1) => 0.0106697
+(2, 65) ~ (4, -1) => 0.00723239
+(2, 66) ~ (4, -1) => 0.012974
+(2, 67) ~ (4, -1) => 0.00851142
+(2, 68) ~ (4, -1) => 0.00723213
+(2, 69) ~ (4, -1) => 0.00590456
+(2, 70) ~ (4, -1) => 0.000954747
+(2, 71) ~ (4, -1) => 0.000173271
+(2, 72) ~ (4, -1) => 0.000196636
+(2, 73) ~ (4, -1) => 0.000430703
+(2, 74) ~ (4, -1) => 0.00520182
+(2, 75) ~ (4, -1) => 0.0111952
+(2, 76) ~ (4, -1) => 0.0156104
+(2, 77) ~ (4, -1) => 0.027433
+(2, 78) ~ (4, -1) => 0.012747
+(2, 79) ~ (4, -1) => 0.00438237
+(2, 80) ~ (4, -1) => 0.00905997
+(2, 81) ~ (4, -1) => 0.00178385
+(2, 82) ~ (4, -1) => 0.00165653
+(2, 83) ~ (4, -1) => 0.00416887
+(2, 84) ~ (4, -1) => 0.0123487
+(2, 85) ~ (4, -1) => 0.0393024
+(2, 86) ~ (4, -1) => 0.052606
+(2, 87) ~ (4, -1) => 0.04947
+(2, 88) ~ (4, -1) => 0.121483
+(2, 89) ~ (4, -1) => 0.222244
+(2, 90) ~ (4, -1) => 0.429195
+(2, 91) ~ (4, -1) => 0.650446
+(2, 92) ~ (4, -1) => 0.489823
+(2, 93) ~ (4, -1) => 0.349553
+(2, 94) ~ (4, -1) => 0.209683
+(2, 95) ~ (4, -1) => 0.0606034
+(2, 96) ~ (4, -1) => 0.181415
+(2, 97) ~ (4, -1) => 0.233262
+(2, 98) ~ (4, -1) => 0.275018
+(2, 99) ~ (4, -1) => 0.284841
+(2, 100) ~ (4, -1) => 0.345749
+(2, 101) ~ (4, -1) => 0.39741
+(2, 102) ~ (4, -1) => 0.482455
+(2, 103) ~ (4, -1) => 0.455395
+(2, 104) ~ (4, -1) => 0.284132
+(2, 105) ~ (4, -1) => 0.18336
+(2, 106) ~ (4, -1) => 0.155162
+(2, 107) ~ (4, -1) => 0.136939
+(2, 108) ~ (4, -1) => 0.00997782
+(2, 109) ~ (4, -1) => 0.00472993
+(2, 110) ~ (4, -1) => 0.00056082
+(2, 111) ~ (4, -1) => 0.000788987
+(2, 112) ~ (4, -1) => 0.00119466
+(2, 113) ~ (4, -1) => 0.00102484
+(2, 114) ~ (4, -1) => 0.000711977
+(2, 115) ~ (4, -1) => 0.000628114
+(2, 116) ~ (4, -1) => 0.000520766
+
+(2, -1) ~ (4, 0) => 0.0001
+(2, -1) ~ (4, 1) => 0.0001
+(2, -1) ~ (4, 2) => 0.0001
+(2, -1) ~ (4, 3) => 0.0001
+(2, -1) ~ (4, 4) => 0.0001
+(2, -1) ~ (4, 5) => 0.000109017
+(2, -1) ~ (4, 6) => 0.000190377
+(2, -1) ~ (4, 7) => 0.000883937
+(2, -1) ~ (4, 8) => 0.00156647
+(2, -1) ~ (4, 9) => 0.00409913
+(2, -1) ~ (4, 10) => 0.00367343
+(2, -1) ~ (4, 11) => 0.00211948
+(2, -1) ~ (4, 12) => 0.000268221
+(2, -1) ~ (4, 13) => 0.000198305
+(2, -1) ~ (4, 14) => 0.000169575
+(2, -1) ~ (4, 15) => 0.000256658
+(2, -1) ~ (4, 16) => 0.000214875
+(2, -1) ~ (4, 17) => 0.0001
+(2, -1) ~ (4, 18) => 0.0001
+(2, -1) ~ (4, 19) => 0.0001
+(2, -1) ~ (4, 20) => 0.000204742
+(2, -1) ~ (4, 21) => 0.000725269
+(2, -1) ~ (4, 22) => 0.00354856
+(2, -1) ~ (4, 23) => 0.126246
+(2, -1) ~ (4, 24) => 0.170848
+(2, -1) ~ (4, 25) => 0.0915277
+(2, -1) ~ (4, 26) => 0.093632
+(2, -1) ~ (4, 27) => 0.394283
+(2, -1) ~ (4, 28) => 0.68893
+(2, -1) ~ (4, 29) => 0.393647
+(2, -1) ~ (4, 30) => 0.0588071
+(2, -1) ~ (4, 31) => 0.0124201
+(2, -1) ~ (4, 32) => 0.0123688
+(2, -1) ~ (4, 33) => 0.0124415
+(2, -1) ~ (4, 34) => 0.0127129
+(2, -1) ~ (4, 35) => 0.0131204
+(2, -1) ~ (4, 36) => 0.0135601
+(2, -1) ~ (4, 37) => 0.0109202
+(2, -1) ~ (4, 38) => 0.00892693
+(2, -1) ~ (4, 39) => 0.00743407
+(2, -1) ~ (4, 40) => 0.00664937
+(2, -1) ~ (4, 41) => 0.00598472
+(2, -1) ~ (4, 42) => 0.00525385
+(2, -1) ~ (4, 43) => 0.0041607
+(2, -1) ~ (4, 44) => 0.0224525
+(2, -1) ~ (4, 45) => 0.0332814
+(2, -1) ~ (4, 46) => 0.14925
+(2, -1) ~ (4, 47) => 0.164121
+(2, -1) ~ (4, 48) => 0.150918
+(2, -1) ~ (4, 49) => 0.364208
+(2, -1) ~ (4, 50) => 0.135843
+(2, -1) ~ (4, 51) => 0.0243172
+(2, -1) ~ (4, 52) => 0.02351
+(2, -1) ~ (4, 53) => 0.0273482
+(2, -1) ~ (4, 54) => 0.00984943
+(2, -1) ~ (4, 55) => 0.0123124
+(2, -1) ~ (4, 56) => 0.0151654
+(2, -1) ~ (4, 57) => 0.0188055
+(2, -1) ~ (4, 58) => 0.0124199
+(2, -1) ~ (4, 59) => 0.00767189
+(2, -1) ~ (4, 60) => 0.00548559
+(2, -1) ~ (4, 61) => 0.0043757
+(2, -1) ~ (4, 62) => 0.00413293
+(2, -1) ~ (4, 63) => 0.00486308
+(2, -1) ~ (4, 64) => 0.00566137
+(2, -1) ~ (4, 65) => 0.0142184
+(2, -1) ~ (4, 66) => 0.0137397
+(2, -1) ~ (4, 67) => 0.00796068
+(2, -1) ~ (4, 68) => 0.00331122
+(2, -1) ~ (4, 69) => 0.00185251
+(2, -1) ~ (4, 70) => 0.00851142
+(2, -1) ~ (4, 71) => 0.00723213
+(2, -1) ~ (4, 72) => 0.00590456
+(2, -1) ~ (4, 73) => 0.000954747
+(2, -1) ~ (4, 74) => 0.000173271
+(2, -1) ~ (4, 75) => 0.000196636
+(2, -1) ~ (4, 76) => 0.000430703
+(2, -1) ~ (4, 77) => 0.00520182
+(2, -1) ~ (4, 78) => 0.0111952
+(2, -1) ~ (4, 79) => 0.0156104
+(2, -1) ~ (4, 80) => 0.0133779
+(2, -1) ~ (4, 81) => 0.0161768
+(2, -1) ~ (4, 82) => 0.0150077
+(2, -1) ~ (4, 83) => 0.00905997
+(2, -1) ~ (4, 84) => 0.00178385
+(2, -1) ~ (4, 85) => 0.00165653
+(2, -1) ~ (4, 86) => 0.00416887
+(2, -1) ~ (4, 87) => 0.0123487
+(2, -1) ~ (4, 88) => 0.014325
+(2, -1) ~ (4, 89) => 0.0240546
+(2, -1) ~ (4, 90) => 0.0242813
+(2, -1) ~ (4, 91) => 0.0141692
+(2, -1) ~ (4, 92) => 0.0147225
+(2, -1) ~ (4, 93) => 0.0465231
+(2, -1) ~ (4, 94) => 0.204394
+(2, -1) ~ (4, 95) => 0.237364
+(2, -1) ~ (4, 96) => 0.190126
+(2, -1) ~ (4, 97) => 0.0548435
+(2, -1) ~ (4, 98) => 0.0232749
+(2, -1) ~ (4, 99) => 0.0189537
+(2, -1) ~ (4, 100) => 0.0249357
+(2, -1) ~ (4, 101) => 0.0326982
+(2, -1) ~ (4, 102) => 0.0454752
+(2, -1) ~ (4, 103) => 0.0439081
+(2, -1) ~ (4, 104) => 0.0461428
+(2, -1) ~ (4, 105) => 0.0293524
+(2, -1) ~ (4, 106) => 0.00997782
+(2, -1) ~ (4, 107) => 0.00472993
+(2, -1) ~ (4, 108) => 0.00056082
+(2, -1) ~ (4, 109) => 0.000788987
+(2, -1) ~ (4, 110) => 0.00119466
+(2, -1) ~ (4, 111) => 0.00102484
+(2, -1) ~ (4, 112) => 0.000711977
+(2, -1) ~ (4, 113) => 0.000628114
+(2, -1) ~ (4, 114) => 0.000520766
+
+; Sparse posterior probability matrix for sequences 3 and 4
+; Format is:
+; (sequence_1, position_1) ~ (sequence_2, position_2) => prob
+; which means that (sequence_1, position_1) is aligned to (sequence_2, position_2) with probability prob.
+; (sequence_1, position_1) ~ (sequence_2, -1) => prob
+; means that (sequence_1, position_1) is aligned to a gap in sequence_2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(3, 0) ~ (4, 0) => 0.945854
+(3, 0) ~ (4, 1) => 0.0426255
+(3, 1) ~ (4, 1) => 0.795816
+(3, 1) ~ (4, 2) => 0.155864
+(3, 1) ~ (4, 4) => 0.0250491
+(3, 2) ~ (4, 2) => 0.467306
+(3, 2) ~ (4, 3) => 0.455764
+(3, 2) ~ (4, 5) => 0.0474358
+(3, 3) ~ (4, 3) => 0.386836
+(3, 3) ~ (4, 4) => 0.523777
+(3, 3) ~ (4, 6) => 0.0519108
+(3, 4) ~ (4, 4) => 0.362349
+(3, 4) ~ (4, 5) => 0.544462
+(3, 4) ~ (4, 7) => 0.0504517
+(3, 5) ~ (4, 3) => 0.0139722
+(3, 5) ~ (4, 5) => 0.345338
+(3, 5) ~ (4, 6) => 0.560174
+(3, 5) ~ (4, 8) => 0.0468764
+(3, 6) ~ (4, 4) => 0.0135466
+(3, 6) ~ (4, 6) => 0.275592
+(3, 6) ~ (4, 7) => 0.630428
+(3, 6) ~ (4, 9) => 0.0439859
+(3, 7) ~ (4, 5) => 0.0140046
+(3, 7) ~ (4, 7) => 0.251357
+(3, 7) ~ (4, 8) => 0.65331
+(3, 7) ~ (4, 10) => 0.0412024
+(3, 8) ~ (4, 6) => 0.0132128
+(3, 8) ~ (4, 8) => 0.227269
+(3, 8) ~ (4, 9) => 0.678214
+(3, 8) ~ (4, 11) => 0.041237
+(3, 9) ~ (4, 7) => 0.0122744
+(3, 9) ~ (4, 8) => 0.0106347
+(3, 9) ~ (4, 9) => 0.209395
+(3, 9) ~ (4, 10) => 0.699971
+(3, 9) ~ (4, 12) => 0.0419998
+(3, 10) ~ (4, 10) => 0.192676
+(3, 10) ~ (4, 11) => 0.725324
+(3, 10) ~ (4, 13) => 0.0423334
+(3, 11) ~ (4, 11) => 0.174253
+(3, 11) ~ (4, 12) => 0.745647
+(3, 11) ~ (4, 14) => 0.0411201
+(3, 12) ~ (4, 12) => 0.161506
+(3, 12) ~ (4, 13) => 0.760658
+(3, 12) ~ (4, 15) => 0.0396721
+(3, 13) ~ (4, 13) => 0.144054
+(3, 13) ~ (4, 14) => 0.783233
+(3, 13) ~ (4, 16) => 0.0367266
+(3, 14) ~ (4, 14) => 0.131933
+(3, 14) ~ (4, 15) => 0.801345
+(3, 14) ~ (4, 17) => 0.0335606
+(3, 15) ~ (4, 15) => 0.0770446
+(3, 15) ~ (4, 16) => 0.867081
+(3, 15) ~ (4, 18) => 0.02941
+(3, 16) ~ (4, 16) => 0.0220656
+(3, 16) ~ (4, 17) => 0.932208
+(3, 16) ~ (4, 19) => 0.0244371
+(3, 17) ~ (4, 18) => 0.953203
+(3, 17) ~ (4, 20) => 0.0176096
+(3, 18) ~ (4, 19) => 0.960417
+(3, 18) ~ (4, 21) => 0.0106505
+(3, 19) ~ (4, 20) => 0.973707
+(3, 20) ~ (4, 21) => 0.982371
+(3, 21) ~ (4, 22) => 0.990437
+(3, 22) ~ (4, 23) => 0.991209
+(3, 23) ~ (4, 24) => 0.989302
+(3, 24) ~ (4, 25) => 0.98866
+(3, 25) ~ (4, 26) => 0.985898
+(3, 26) ~ (4, 27) => 0.985762
+(3, 27) ~ (4, 28) => 0.988663
+(3, 28) ~ (4, 29) => 0.990445
+(3, 29) ~ (4, 30) => 0.994917
+(3, 30) ~ (4, 31) => 0.997697
+(3, 31) ~ (4, 32) => 0.998128
+(3, 32) ~ (4, 33) => 0.998343
+(3, 33) ~ (4, 34) => 0.998602
+(3, 34) ~ (4, 35) => 0.998642
+(3, 35) ~ (4, 36) => 0.998354
+(3, 36) ~ (4, 37) => 0.998399
+(3, 37) ~ (4, 38) => 0.99846
+(3, 38) ~ (4, 39) => 0.997966
+(3, 39) ~ (4, 40) => 0.997336
+(3, 40) ~ (4, 41) => 0.996804
+(3, 41) ~ (4, 42) => 0.996123
+(3, 42) ~ (4, 43) => 0.996323
+(3, 43) ~ (4, 44) => 0.994871
+(3, 44) ~ (4, 45) => 0.995513
+(3, 45) ~ (4, 46) => 0.997885
+(3, 46) ~ (4, 47) => 0.998502
+(3, 47) ~ (4, 48) => 0.998968
+(3, 48) ~ (4, 49) => 0.999365
+(3, 49) ~ (4, 50) => 0.998898
+(3, 50) ~ (4, 51) => 0.998161
+(3, 51) ~ (4, 52) => 0.997877
+(3, 52) ~ (4, 53) => 0.99736
+(3, 53) ~ (4, 54) => 0.996798
+(3, 54) ~ (4, 55) => 0.995089
+(3, 55) ~ (4, 56) => 0.989176
+(3, 56) ~ (4, 57) => 0.980898
+(3, 57) ~ (4, 58) => 0.964716
+(3, 58) ~ (4, 57) => 0.0112644
+(3, 58) ~ (4, 59) => 0.917136
+(3, 59) ~ (4, 58) => 0.0151822
+(3, 59) ~ (4, 59) => 0.0331795
+(3, 59) ~ (4, 60) => 0.906763
+(3, 60) ~ (4, 59) => 0.0172214
+(3, 60) ~ (4, 60) => 0.0328876
+(3, 60) ~ (4, 61) => 0.907386
+(3, 61) ~ (4, 60) => 0.0158207
+(3, 61) ~ (4, 61) => 0.0332385
+(3, 61) ~ (4, 62) => 0.908808
+(3, 62) ~ (4, 61) => 0.0111186
+(3, 62) ~ (4, 62) => 0.0366779
+(3, 62) ~ (4, 63) => 0.896399
+(3, 63) ~ (4, 63) => 0.048936
+(3, 63) ~ (4, 64) => 0.891003
+(3, 64) ~ (4, 64) => 0.0514905
+(3, 64) ~ (4, 65) => 0.866675
+(3, 65) ~ (4, 65) => 0.0595006
+(3, 65) ~ (4, 66) => 0.851418
+(3, 66) ~ (4, 63) => 0.0103388
+(3, 66) ~ (4, 66) => 0.0703233
+(3, 66) ~ (4, 67) => 0.838538
+(3, 67) ~ (4, 64) => 0.0110753
+(3, 67) ~ (4, 67) => 0.0855752
+(3, 67) ~ (4, 68) => 0.827057
+(3, 68) ~ (4, 65) => 0.0131414
+(3, 68) ~ (4, 68) => 0.0919022
+(3, 68) ~ (4, 69) => 0.827332
+(3, 69) ~ (4, 66) => 0.0123491
+(3, 69) ~ (4, 69) => 0.0914567
+(3, 69) ~ (4, 70) => 0.824847
+(3, 70) ~ (4, 66) => 0.01044
+(3, 70) ~ (4, 69) => 0.0106506
+(3, 70) ~ (4, 70) => 0.0785519
+(3, 70) ~ (4, 71) => 0.839885
+(3, 71) ~ (4, 71) => 0.075831
+(3, 71) ~ (4, 72) => 0.848594
+(3, 72) ~ (4, 72) => 0.0610588
+(3, 72) ~ (4, 73) => 0.867971
+(3, 73) ~ (4, 73) => 0.0583565
+(3, 73) ~ (4, 74) => 0.881993
+(3, 74) ~ (4, 74) => 0.0589104
+(3, 74) ~ (4, 75) => 0.883948
+(3, 75) ~ (4, 75) => 0.0594331
+(3, 75) ~ (4, 76) => 0.894058
+(3, 76) ~ (4, 76) => 0.0500623
+(3, 76) ~ (4, 77) => 0.913804
+(3, 77) ~ (4, 77) => 0.0167174
+(3, 77) ~ (4, 78) => 0.958807
+(3, 78) ~ (4, 79) => 0.969092
+(3, 79) ~ (4, 80) => 0.97535
+(3, 80) ~ (4, 81) => 0.978705
+(3, 81) ~ (4, 82) => 0.978817
+(3, 82) ~ (4, 83) => 0.980909
+(3, 83) ~ (4, 84) => 0.986672
+(3, 84) ~ (4, 85) => 0.989259
+(3, 85) ~ (4, 86) => 0.99417
+(3, 86) ~ (4, 87) => 0.99593
+(3, 87) ~ (4, 88) => 0.996226
+(3, 88) ~ (4, 89) => 0.995842
+(3, 89) ~ (4, 90) => 0.995441
+(3, 90) ~ (4, 91) => 0.995144
+(3, 91) ~ (4, 92) => 0.9949
+(3, 92) ~ (4, 93) => 0.994437
+(3, 93) ~ (4, 94) => 0.993155
+(3, 94) ~ (4, 95) => 0.987908
+(3, 95) ~ (4, 96) => 0.959974
+(3, 96) ~ (4, 96) => 0.0100734
+(3, 96) ~ (4, 97) => 0.894489
+(3, 97) ~ (4, 97) => 0.0160087
+(3, 97) ~ (4, 98) => 0.83905
+(3, 97) ~ (4, 99) => 0.0104844
+(3, 98) ~ (4, 98) => 0.0209899
+(3, 98) ~ (4, 99) => 0.752437
+(3, 98) ~ (4, 100) => 0.0146597
+(3, 98) ~ (4, 101) => 0.0110792
+(3, 99) ~ (4, 99) => 0.0232331
+(3, 99) ~ (4, 100) => 0.680563
+(3, 99) ~ (4, 101) => 0.0187207
+(3, 100) ~ (4, 100) => 0.024573
+(3, 100) ~ (4, 101) => 0.637979
+(3, 100) ~ (4, 102) => 0.0229808
+(3, 101) ~ (4, 99) => 0.0151721
+(3, 101) ~ (4, 101) => 0.0202249
+(3, 101) ~ (4, 102) => 0.627795
+(3, 101) ~ (4, 103) => 0.0217507
+(3, 102) ~ (4, 99) => 0.0115034
+(3, 102) ~ (4, 100) => 0.0170404
+(3, 102) ~ (4, 102) => 0.0207155
+(3, 102) ~ (4, 103) => 0.612061
+(3, 102) ~ (4, 104) => 0.0188836
+(3, 103) ~ (4, 96) => 0.014009
+(3, 103) ~ (4, 97) => 0.0126966
+(3, 103) ~ (4, 100) => 0.0124264
+(3, 103) ~ (4, 101) => 0.0152207
+(3, 103) ~ (4, 103) => 0.0197261
+(3, 103) ~ (4, 104) => 0.582355
+(3, 103) ~ (4, 105) => 0.0175385
+(3, 104) ~ (4, 97) => 0.046542
+(3, 104) ~ (4, 98) => 0.0183285
+(3, 104) ~ (4, 99) => 0.0110259
+(3, 104) ~ (4, 101) => 0.0172575
+(3, 104) ~ (4, 102) => 0.0103727
+(3, 104) ~ (4, 104) => 0.0237605
+(3, 104) ~ (4, 105) => 0.45921
+(3, 104) ~ (4, 106) => 0.0100269
+(3, 105) ~ (4, 98) => 0.0651734
+(3, 105) ~ (4, 99) => 0.0178034
+(3, 105) ~ (4, 100) => 0.0149463
+(3, 105) ~ (4, 102) => 0.0173608
+(3, 105) ~ (4, 105) => 0.0190767
+(3, 105) ~ (4, 106) => 0.161179
+(3, 106) ~ (4, 99) => 0.112586
+(3, 106) ~ (4, 100) => 0.010777
+(3, 106) ~ (4, 101) => 0.0151981
+(3, 106) ~ (4, 102) => 0.0101708
+(3, 106) ~ (4, 103) => 0.0157665
+(3, 106) ~ (4, 106) => 0.0232581
+(3, 106) ~ (4, 107) => 0.101162
+(3, 107) ~ (4, 100) => 0.170215
+(3, 107) ~ (4, 102) => 0.0141334
+(3, 107) ~ (4, 103) => 0.0169848
+(3, 107) ~ (4, 104) => 0.0151281
+(3, 107) ~ (4, 106) => 0.0225332
+(3, 107) ~ (4, 107) => 0.0214484
+(3, 107) ~ (4, 108) => 0.0540949
+(3, 108) ~ (4, 101) => 0.205178
+(3, 108) ~ (4, 103) => 0.0114623
+(3, 108) ~ (4, 104) => 0.0216287
+(3, 108) ~ (4, 105) => 0.0167529
+(3, 108) ~ (4, 107) => 0.0432399
+(3, 108) ~ (4, 108) => 0.0275386
+(3, 108) ~ (4, 109) => 0.0188665
+(3, 109) ~ (4, 102) => 0.219284
+(3, 109) ~ (4, 104) => 0.0115448
+(3, 109) ~ (4, 105) => 0.0161419
+(3, 109) ~ (4, 108) => 0.0571243
+(3, 109) ~ (4, 109) => 0.0218307
+(3, 110) ~ (4, 101) => 0.0100538
+(3, 110) ~ (4, 103) => 0.229731
+(3, 110) ~ (4, 105) => 0.0133349
+(3, 110) ~ (4, 106) => 0.0174424
+(3, 110) ~ (4, 109) => 0.0726479
+(3, 110) ~ (4, 110) => 0.0224208
+(3, 111) ~ (4, 102) => 0.011391
+(3, 111) ~ (4, 103) => 0.0115524
+(3, 111) ~ (4, 104) => 0.247555
+(3, 111) ~ (4, 105) => 0.0118101
+(3, 111) ~ (4, 106) => 0.0431518
+(3, 111) ~ (4, 107) => 0.0162422
+(3, 111) ~ (4, 110) => 0.0749089
+(3, 111) ~ (4, 111) => 0.0192234
+(3, 112) ~ (4, 103) => 0.0130666
+(3, 112) ~ (4, 104) => 0.0173198
+(3, 112) ~ (4, 105) => 0.362588
+(3, 112) ~ (4, 106) => 0.0517833
+(3, 112) ~ (4, 107) => 0.0559057
+(3, 112) ~ (4, 108) => 0.0152714
+(3, 112) ~ (4, 111) => 0.0702002
+(3, 112) ~ (4, 112) => 0.0176271
+(3, 113) ~ (4, 104) => 0.0159644
+(3, 113) ~ (4, 105) => 0.0230932
+(3, 113) ~ (4, 106) => 0.54455
+(3, 113) ~ (4, 107) => 0.0513713
+(3, 113) ~ (4, 108) => 0.0523564
+(3, 113) ~ (4, 112) => 0.0552967
+(3, 113) ~ (4, 113) => 0.0118596
+(3, 114) ~ (4, 105) => 0.0195209
+(3, 114) ~ (4, 106) => 0.0320723
+(3, 114) ~ (4, 107) => 0.565311
+(3, 114) ~ (4, 108) => 0.0318232
+(3, 114) ~ (4, 109) => 0.0400198
+(3, 114) ~ (4, 110) => 0.0106425
+(3, 114) ~ (4, 113) => 0.0130769
+(3, 115) ~ (4, 106) => 0.0476536
+(3, 115) ~ (4, 107) => 0.0367843
+(3, 115) ~ (4, 108) => 0.59805
+(3, 115) ~ (4, 109) => 0.0249412
+(3, 115) ~ (4, 110) => 0.0241695
+(3, 116) ~ (4, 107) => 0.062439
+(3, 116) ~ (4, 108) => 0.0414171
+(3, 116) ~ (4, 109) => 0.573227
+(3, 116) ~ (4, 110) => 0.0273273
+(3, 116) ~ (4, 111) => 0.0143928
+(3, 117) ~ (4, 108) => 0.0822867
+(3, 117) ~ (4, 109) => 0.0602625
+(3, 117) ~ (4, 110) => 0.541956
+(3, 117) ~ (4, 111) => 0.0212016
+(3, 118) ~ (4, 109) => 0.14572
+(3, 118) ~ (4, 110) => 0.0712549
+(3, 118) ~ (4, 111) => 0.415964
+(3, 118) ~ (4, 112) => 0.018113
+(3, 119) ~ (4, 110) => 0.189877
+(3, 119) ~ (4, 111) => 0.0669625
+(3, 119) ~ (4, 112) => 0.326683
+(3, 119) ~ (4, 113) => 0.0163307
+(3, 120) ~ (4, 111) => 0.35028
+(3, 120) ~ (4, 112) => 0.0580825
+(3, 120) ~ (4, 113) => 0.239895
+(3, 120) ~ (4, 114) => 0.0109029
+(3, 121) ~ (4, 112) => 0.485271
+(3, 121) ~ (4, 113) => 0.0473759
+(3, 121) ~ (4, 114) => 0.15221
+(3, 122) ~ (4, 113) => 0.646363
+(3, 122) ~ (4, 114) => 0.0324235
+(3, 123) ~ (4, 114) => 0.768876
+
+; gap posteriors
+(3, 0) ~ (4, -1) => 0.011521
+(3, 1) ~ (4, -1) => 0.0232715
+(3, 2) ~ (4, -1) => 0.0294944
+(3, 3) ~ (4, -1) => 0.0374758
+(3, 4) ~ (4, -1) => 0.0427377
+(3, 5) ~ (4, -1) => 0.0336394
+(3, 6) ~ (4, -1) => 0.0364479
+(3, 7) ~ (4, -1) => 0.040126
+(3, 8) ~ (4, -1) => 0.0400677
+(3, 9) ~ (4, -1) => 0.0257251
+(3, 10) ~ (4, -1) => 0.0396668
+(3, 11) ~ (4, -1) => 0.0389797
+(3, 12) ~ (4, -1) => 0.0381644
+(3, 13) ~ (4, -1) => 0.0359863
+(3, 14) ~ (4, -1) => 0.0331617
+(3, 15) ~ (4, -1) => 0.0264647
+(3, 16) ~ (4, -1) => 0.0212889
+(3, 17) ~ (4, -1) => 0.0291869
+(3, 18) ~ (4, -1) => 0.0289326
+(3, 19) ~ (4, -1) => 0.026293
+(3, 20) ~ (4, -1) => 0.0176294
+(3, 21) ~ (4, -1) => 0.00956285
+(3, 22) ~ (4, -1) => 0.00879073
+(3, 23) ~ (4, -1) => 0.010698
+(3, 24) ~ (4, -1) => 0.0113403
+(3, 25) ~ (4, -1) => 0.0141022
+(3, 26) ~ (4, -1) => 0.0142379
+(3, 27) ~ (4, -1) => 0.0113373
+(3, 28) ~ (4, -1) => 0.00955504
+(3, 29) ~ (4, -1) => 0.00508314
+(3, 30) ~ (4, -1) => 0.00230259
+(3, 31) ~ (4, -1) => 0.00187194
+(3, 32) ~ (4, -1) => 0.00165713
+(3, 33) ~ (4, -1) => 0.00139844
+(3, 34) ~ (4, -1) => 0.00135821
+(3, 35) ~ (4, -1) => 0.00164616
+(3, 36) ~ (4, -1) => 0.00160104
+(3, 37) ~ (4, -1) => 0.00153983
+(3, 38) ~ (4, -1) => 0.00203383
+(3, 39) ~ (4, -1) => 0.00266433
+(3, 40) ~ (4, -1) => 0.00319564
+(3, 41) ~ (4, -1) => 0.00387728
+(3, 42) ~ (4, -1) => 0.00367743
+(3, 43) ~ (4, -1) => 0.00512922
+(3, 44) ~ (4, -1) => 0.00448745
+(3, 45) ~ (4, -1) => 0.00211495
+(3, 46) ~ (4, -1) => 0.00149804
+(3, 47) ~ (4, -1) => 0.00103152
+(3, 48) ~ (4, -1) => 0.000635028
+(3, 49) ~ (4, -1) => 0.00110245
+(3, 50) ~ (4, -1) => 0.00183916
+(3, 51) ~ (4, -1) => 0.00212258
+(3, 52) ~ (4, -1) => 0.00264025
+(3, 53) ~ (4, -1) => 0.00320232
+(3, 54) ~ (4, -1) => 0.00491136
+(3, 55) ~ (4, -1) => 0.0108238
+(3, 56) ~ (4, -1) => 0.0191017
+(3, 57) ~ (4, -1) => 0.0352843
+(3, 58) ~ (4, -1) => 0.0715998
+(3, 59) ~ (4, -1) => 0.0448753
+(3, 60) ~ (4, -1) => 0.042505
+(3, 61) ~ (4, -1) => 0.0421329
+(3, 62) ~ (4, -1) => 0.0558043
+(3, 63) ~ (4, -1) => 0.0600608
+(3, 64) ~ (4, -1) => 0.081835
+(3, 65) ~ (4, -1) => 0.0890811
+(3, 66) ~ (4, -1) => 0.0807998
+(3, 67) ~ (4, -1) => 0.0762923
+(3, 68) ~ (4, -1) => 0.0676247
+(3, 69) ~ (4, -1) => 0.0713468
+(3, 70) ~ (4, -1) => 0.0604725
+(3, 71) ~ (4, -1) => 0.0755754
+(3, 72) ~ (4, -1) => 0.0709699
+(3, 73) ~ (4, -1) => 0.0596501
+(3, 74) ~ (4, -1) => 0.0571417
+(3, 75) ~ (4, -1) => 0.0465088
+(3, 76) ~ (4, -1) => 0.0361339
+(3, 77) ~ (4, -1) => 0.0244761
+(3, 78) ~ (4, -1) => 0.0309075
+(3, 79) ~ (4, -1) => 0.0246496
+(3, 80) ~ (4, -1) => 0.0212947
+(3, 81) ~ (4, -1) => 0.0211834
+(3, 82) ~ (4, -1) => 0.019091
+(3, 83) ~ (4, -1) => 0.0133281
+(3, 84) ~ (4, -1) => 0.010741
+(3, 85) ~ (4, -1) => 0.00583035
+(3, 86) ~ (4, -1) => 0.0040701
+(3, 87) ~ (4, -1) => 0.00377399
+(3, 88) ~ (4, -1) => 0.0041579
+(3, 89) ~ (4, -1) => 0.00455886
+(3, 90) ~ (4, -1) => 0.00485605
+(3, 91) ~ (4, -1) => 0.00510013
+(3, 92) ~ (4, -1) => 0.0055626
+(3, 93) ~ (4, -1) => 0.00684518
+(3, 94) ~ (4, -1) => 0.0120923
+(3, 95) ~ (4, -1) => 0.0400258
+(3, 96) ~ (4, -1) => 0.095438
+(3, 97) ~ (4, -1) => 0.134457
+(3, 98) ~ (4, -1) => 0.200834
+(3, 99) ~ (4, -1) => 0.277483
+(3, 100) ~ (4, -1) => 0.314468
+(3, 101) ~ (4, -1) => 0.315057
+(3, 102) ~ (4, -1) => 0.319796
+(3, 103) ~ (4, -1) => 0.326027
+(3, 104) ~ (4, -1) => 0.403476
+(3, 105) ~ (4, -1) => 0.70446
+(3, 106) ~ (4, -1) => 0.711082
+(3, 107) ~ (4, -1) => 0.685463
+(3, 108) ~ (4, -1) => 0.655333
+(3, 109) ~ (4, -1) => 0.674074
+(3, 110) ~ (4, -1) => 0.634369
+(3, 111) ~ (4, -1) => 0.564165
+(3, 112) ~ (4, -1) => 0.396238
+(3, 113) ~ (4, -1) => 0.245508
+(3, 114) ~ (4, -1) => 0.287533
+(3, 115) ~ (4, -1) => 0.268401
+(3, 116) ~ (4, -1) => 0.281197
+(3, 117) ~ (4, -1) => 0.294293
+(3, 118) ~ (4, -1) => 0.348948
+(3, 119) ~ (4, -1) => 0.400146
+(3, 120) ~ (4, -1) => 0.34084
+(3, 121) ~ (4, -1) => 0.315143
+(3, 122) ~ (4, -1) => 0.321213
+(3, 123) ~ (4, -1) => 0.231124
+
+(3, -1) ~ (4, 0) => 0.0541465
+(3, -1) ~ (4, 1) => 0.161559
+(3, -1) ~ (4, 2) => 0.37683
+(3, -1) ~ (4, 3) => 0.143428
+(3, -1) ~ (4, 4) => 0.0752784
+(3, -1) ~ (4, 5) => 0.04876
+(3, -1) ~ (4, 6) => 0.09911
+(3, -1) ~ (4, 7) => 0.0554892
+(3, -1) ~ (4, 8) => 0.0619105
+(3, -1) ~ (4, 9) => 0.0684057
+(3, -1) ~ (4, 10) => 0.0661505
+(3, -1) ~ (4, 11) => 0.0591855
+(3, -1) ~ (4, 12) => 0.0508474
+(3, -1) ~ (4, 13) => 0.0529554
+(3, -1) ~ (4, 14) => 0.0437136
+(3, -1) ~ (4, 15) => 0.0819385
+(3, -1) ~ (4, 16) => 0.074127
+(3, -1) ~ (4, 17) => 0.0342311
+(3, -1) ~ (4, 18) => 0.0173865
+(3, -1) ~ (4, 19) => 0.015146
+(3, -1) ~ (4, 20) => 0.0086835
+(3, -1) ~ (4, 21) => 0.00697899
+(3, -1) ~ (4, 22) => 0.00956285
+(3, -1) ~ (4, 23) => 0.00879073
+(3, -1) ~ (4, 24) => 0.010698
+(3, -1) ~ (4, 25) => 0.0113403
+(3, -1) ~ (4, 26) => 0.0141022
+(3, -1) ~ (4, 27) => 0.0142379
+(3, -1) ~ (4, 28) => 0.0113373
+(3, -1) ~ (4, 29) => 0.00955504
+(3, -1) ~ (4, 30) => 0.00508314
+(3, -1) ~ (4, 31) => 0.00230259
+(3, -1) ~ (4, 32) => 0.00187194
+(3, -1) ~ (4, 33) => 0.00165713
+(3, -1) ~ (4, 34) => 0.00139844
+(3, -1) ~ (4, 35) => 0.00135821
+(3, -1) ~ (4, 36) => 0.00164616
+(3, -1) ~ (4, 37) => 0.00160104
+(3, -1) ~ (4, 38) => 0.00153983
+(3, -1) ~ (4, 39) => 0.00203383
+(3, -1) ~ (4, 40) => 0.00266433
+(3, -1) ~ (4, 41) => 0.00319564
+(3, -1) ~ (4, 42) => 0.00387728
+(3, -1) ~ (4, 43) => 0.00367743
+(3, -1) ~ (4, 44) => 0.00512922
+(3, -1) ~ (4, 45) => 0.00448745
+(3, -1) ~ (4, 46) => 0.00211495
+(3, -1) ~ (4, 47) => 0.00149804
+(3, -1) ~ (4, 48) => 0.00103152
+(3, -1) ~ (4, 49) => 0.000635028
+(3, -1) ~ (4, 50) => 0.00110245
+(3, -1) ~ (4, 51) => 0.00183916
+(3, -1) ~ (4, 52) => 0.00212258
+(3, -1) ~ (4, 53) => 0.00264025
+(3, -1) ~ (4, 54) => 0.00320232
+(3, -1) ~ (4, 55) => 0.00491136
+(3, -1) ~ (4, 56) => 0.0108238
+(3, -1) ~ (4, 57) => 0.00783731
+(3, -1) ~ (4, 58) => 0.0201021
+(3, -1) ~ (4, 59) => 0.0324633
+(3, -1) ~ (4, 60) => 0.0445287
+(3, -1) ~ (4, 61) => 0.0482569
+(3, -1) ~ (4, 62) => 0.0545141
+(3, -1) ~ (4, 63) => 0.044326
+(3, -1) ~ (4, 64) => 0.046431
+(3, -1) ~ (4, 65) => 0.0606835
+(3, -1) ~ (4, 66) => 0.0554693
+(3, -1) ~ (4, 67) => 0.0758867
+(3, -1) ~ (4, 68) => 0.0810406
+(3, -1) ~ (4, 69) => 0.0705609
+(3, -1) ~ (4, 70) => 0.0966008
+(3, -1) ~ (4, 71) => 0.0842841
+(3, -1) ~ (4, 72) => 0.0903475
+(3, -1) ~ (4, 73) => 0.0736722
+(3, -1) ~ (4, 74) => 0.0590962
+(3, -1) ~ (4, 75) => 0.056619
+(3, -1) ~ (4, 76) => 0.0558796
+(3, -1) ~ (4, 77) => 0.0694788
+(3, -1) ~ (4, 78) => 0.0411935
+(3, -1) ~ (4, 79) => 0.0309075
+(3, -1) ~ (4, 80) => 0.0246496
+(3, -1) ~ (4, 81) => 0.0212947
+(3, -1) ~ (4, 82) => 0.0211834
+(3, -1) ~ (4, 83) => 0.019091
+(3, -1) ~ (4, 84) => 0.0133281
+(3, -1) ~ (4, 85) => 0.010741
+(3, -1) ~ (4, 86) => 0.00583035
+(3, -1) ~ (4, 87) => 0.0040701
+(3, -1) ~ (4, 88) => 0.00377399
+(3, -1) ~ (4, 89) => 0.0041579
+(3, -1) ~ (4, 90) => 0.00455886
+(3, -1) ~ (4, 91) => 0.00485605
+(3, -1) ~ (4, 92) => 0.00510013
+(3, -1) ~ (4, 93) => 0.0055626
+(3, -1) ~ (4, 94) => 0.00684518
+(3, -1) ~ (4, 95) => 0.0120923
+(3, -1) ~ (4, 96) => 0.0159435
+(3, -1) ~ (4, 97) => 0.0302641
+(3, -1) ~ (4, 98) => 0.056458
+(3, -1) ~ (4, 99) => 0.0457553
+(3, -1) ~ (4, 100) => 0.0547993
+(3, -1) ~ (4, 101) => 0.0490888
+(3, -1) ~ (4, 102) => 0.0457956
+(3, -1) ~ (4, 103) => 0.0478987
+(3, -1) ~ (4, 104) => 0.0458594
+(3, -1) ~ (4, 105) => 0.0409329
+(3, -1) ~ (4, 106) => 0.0463488
+(3, -1) ~ (4, 107) => 0.0460968
+(3, -1) ~ (4, 108) => 0.0400374
+(3, -1) ~ (4, 109) => 0.0424846
+(3, -1) ~ (4, 110) => 0.0374424
+(3, -1) ~ (4, 111) => 0.0417758
+(3, -1) ~ (4, 112) => 0.0389267
+(3, -1) ~ (4, 113) => 0.0250984
+(3, -1) ~ (4, 114) => 0.0355872
+
diff --git a/examples/U5.aln1.mfa b/examples/U5.aln1.mfa
new file mode 100644
index 0000000..ff012e0
--- /dev/null
+++ b/examples/U5.aln1.mfa
@@ -0,0 +1,11 @@
+>AC005719.2-130462_130570
+U-ACUCUGGUUUCUCUUCAAUUGUCGAAUAAAUCUUUCGCCUUUUACUAAAGAUUUCCGUGGAGAGGAACA-CUCUAAUGAGUCUAAACUCAAUUUUU----------------------GUAUGACCUG---GCU
+>AC000104.1-17376_17496
+AG-CCAUGUGGUGAGCACAU--AGCGAACUAUUCUUUCGCCUUUUACUAAAGAAUACCGUGUGCUCUCCACGCUA---AGUGGCAUACGCCUAUUUUUGGAGGG--U--UCCCACUUUAC----UGUGG-GUCCCA
+>AC009948.3-27597_27481
+AUACUCUGGAUUCUCUUCAG--AUC--AUAUAUCUUUUGCCUUUUAUUAGA-AUUUCUAGAGAGAGGAUAAAUUA---UGAGUUUGUAGCCAGUUUUUUCUUUGC-UUUU--UAUUU-UU----GGCAGG---GUU
+>AL606646.3-46909_46786
+AG-CUGCGCAGUGGGCACAA--AGCGAACUAUUCUUUCGCCUUUUACUAAAGAAUACCGUGUGCACGCUGCAAAU---AGCAGCAUACUCUAAUUUUUUGAGGGGA-UUUCCUAUCUAAG----GACAA-ACCCCA
+>M23811.1-5_119
+AUACUCUGGUUUCUCUUCAG--AUCGUAUAAAUCUUUCCCCUUUCANCAAAGAUUUCCGUGGAGAGGAACAACUC---UGAGUCUUAAACCAAUUUUUUGAGCCUU-GU--------UCC----GGCAAG---GCU
+
diff --git a/examples/U5.aln1.reference.mfa b/examples/U5.aln1.reference.mfa
new file mode 100644
index 0000000..8a2b50c
--- /dev/null
+++ b/examples/U5.aln1.reference.mfa
@@ -0,0 +1,20 @@
+>AC005719.2-130462_130570
+-UACUCUGGUUUCUCUUCAAUUGUCGAAUAAAUCUUUCGCCUUUUACUAA
+AGAUUUCCGUGGAGAGGAACACUCUAAUGAGUCUAAACUCAAUUUUUGUA
+UGAC--------CU-----------GGCU
+>AC000104.1-17376_17496
+AGCCAU-GUGGUGAGCACA--UAGCGAACUAUUCUUUCGCCUUUUACUAA
+AGAAUACCGUGUGCUCUCCAC-GCUAA-GUGGCAUACGCCUAUUUUUGGA
+GGGUUCCCAC--UUUACUG-UGGGUCCCA
+>AC009948.3-27597_27481
+AUACUCUGGAUUCUCUUCA--GAUC--AUAUAUCUUUUGCCUUUUAUUAG
+A-AUUUCUAGAGAGAGGAUAA-AUUAU-GAGUUUGUAGCCAGUUUUUUCU
+UUGCUUUUUAU-UUUU----GGCAGGGUU
+>AL606646.3-46909_46786
+AGCUGC-GCAGUGGGCACA--AAGCGAACUAUUCUUUCGCCUUUUACUAA
+AGAAUACCGUGUGCACGCUGC-AAAUA-GCAGCAUACUCUAAUUUUUUGA
+GGGGAUUUCCUAUCUAAGGACAAACCCCA
+>M23811.1-5_119
+AUACUCUGGUUUCUCUUCA--GAUCGUAUAAAUCUUUCCCCUUUCANCAA
+AGAUUUCCGUGGAGAGGAACA-ACUCU-GAGUCUUAAACCAAUUUUUUGA
+-GCCUUGUU---CC------GGCAAGGCU
diff --git a/examples/U5.aln1.reference.stock b/examples/U5.aln1.reference.stock
new file mode 100644
index 0000000..76ba45b
--- /dev/null
+++ b/examples/U5.aln1.reference.stock
@@ -0,0 +1,13 @@
+# STOCKHOLM 1.0
+M23811.1-5_119 AUACUCUGGUUUCUCUUCA--GAUCGUAUAAAUCUUUCCCCUUUCANCAAAGAUUUCCGUGGAGAGGAACA-ACUCU-GAGUCUUAAACCAAUUUUUUGA-GCCUUGUU---CC------GGCAAGGCU
+#=GR M23811.1-5_119 SS --<<<<--<<<<<<<<<<<----------<<<<<<<<----------->>>>>>>>--->>>>>>>>>>>-------->>>>-----------------<-<<<<<<--------------->>>>>>>
+AC005719.2-130462_130570 -UACUCUGGUUUCUCUUCAAUUGUCGAAUAAAUCUUUCGCCUUUUACUAAAGAUUUCCGUGGAGAGGAACACUCUAAUGAGUCUAAACUCAAUUUUUGUAUGAC--------CU-----------GGCU
+#=GR AC005719.2-130462_130570 SS --<<<<--<<<<<<<<<<<----------<<<<<<<<----------->>>>>>>>--->>>>>>>>>>>-------->>>>-----------------<-<<<--------------------->>>>
+AL606646.3-46909_46786 AGCUGC-GCAGUGGGCACA--AAGCGAACUAUUCUUUCGCCUUUUACUAAAGAAUACCGUGUGCACGCUGC-AAAUA-GCAGCAUACUCUAAUUUUUUGAGGGGAUUUCCUAUCUAAGGACAAACCCCA
+#=GR AL606646.3-46909_46786 SS --<<<<--<<<<<<<<<<<----------<<<<<<<<----------->>>>>>>>--->>>>>>>>>>>-------->>>>-----------------<-<<<<<<--------------->>>>>>>
+AC000104.1-17376_17496 AGCCAU-GUGGUGAGCACA--UAGCGAACUAUUCUUUCGCCUUUUACUAAAGAAUACCGUGUGCUCUCCAC-GCUAA-GUGGCAUACGCCUAUUUUUGGAGGGUUCCCAC--UUUACUG-UGGGUCCCA
+#=GR AC000104.1-17376_17496 SS --<<<<--<<<<<<<<<<<----------<<<<<<<<----------->>>>>>>>--->>>>>>>>>>>-------->>>>-----------------<-<<<<<<--------------->>>>>>>
+AC009948.3-27597_27481 AUACUCUGGAUUCUCUUCA--GAUC--AUAUAUCUUUUGCCUUUUAUUAGA-AUUUCUAGAGAGAGGAUAA-AUUAU-GAGUUUGUAGCCAGUUUUUUCUUUGCUUUUUAU-UUUU----GGCAGGGUU
+#=GR AC009948.3-27597_27481 SS --<<<<--<<<<<<<<<<<----------<<<<-<<<----------->>>->>>>--->>>>>>>>>>>-------->>>>-----------------<-<<<<<<--------------->>>>>>>
+#=GC SS_cons ..<<<<..<<<<<<<<<<<..........<<<<<<<<...........>>>>>>>>...>>>>>>>>>>>........>>>>.................<.<<<<<<...............>>>>>>>
+//
diff --git a/examples/U5.aln1.stock b/examples/U5.aln1.stock
new file mode 100644
index 0000000..a99dcdb
--- /dev/null
+++ b/examples/U5.aln1.stock
@@ -0,0 +1,9 @@
+# STOCKHOLM 1.0
+#=GF Accuracy 0.673907
+AC005719.2-130462_130570 U-ACUCUGGUUUCUCUUCAAUUGUCGAAUAAAUCUUUCGCCUUUUACUAAAGAUUUCCGUGGAGAGGAACA-CUCUAAUGAGUCUAAACUCAAUUUUU----------------------GUAUGACCUG---GCU
+AC000104.1-17376_17496 AG-CCAUGUGGUGAGCACAU--AGCGAACUAUUCUUUCGCCUUUUACUAAAGAAUACCGUGUGCUCUCCACGCUA---AGUGGCAUACGCCUAUUUUUGGAGGG--U--UCCCACUUUAC----UGUGG-GUCCCA
+AC009948.3-27597_27481 AUACUCUGGAUUCUCUUCAG--AUC--AUAUAUCUUUUGCCUUUUAUUAGA-AUUUCUAGAGAGAGGAUAAAUUA---UGAGUUUGUAGCCAGUUUUUUCUUUGC-UUUU--UAUUU-UU----GGCAGG---GUU
+AL606646.3-46909_46786 AG-CUGCGCAGUGGGCACAA--AGCGAACUAUUCUUUCGCCUUUUACUAAAGAAUACCGUGUGCACGCUGCAAAU---AGCAGCAUACUCUAAUUUUUUGAGGGGA-UUUCCUAUCUAAG----GACAA-ACCCCA
+M23811.1-5_119 AUACUCUGGUUUCUCUUCAG--AUCGUAUAAAUCUUUCCCCUUUCANCAAAGAUUUCCGUGGAGAGGAACAACUC---UGAGUCUUAAACCAAUUUUUUGAGCCUU-GU--------UCC----GGCAAG---GCU
+#=GC Accuracy 7657777777777777777634678777777899999999999999998878777787777655555555454552325667777777777877776676665554444555666554551111555555555678
+//
diff --git a/examples/tRNA.aln1.fasta b/examples/tRNA.aln1.fasta
new file mode 100644
index 0000000..37b3984
--- /dev/null
+++ b/examples/tRNA.aln1.fasta
@@ -0,0 +1,15 @@
+>AE004843.1-4972_4900
+GCUCAUGUAGCUCAGUUGGUAGAGCACACCCUUGGUAAGGGUGAGGUCAG
+CGGUUCAAAUCCGCUCAUGAGCU
+>Z82044.1-16031_16103
+GCGGUUGUGGCGAAGUGGUUAACGCACCAGAUUGUGGCUCUGGCACUCGU
+GGGUUCGAUUCCCAUCAAUCGCC
+>M83762.1-1031_1093
+GCUUUAAAAGCUUUGCUGAAGCAACGGCCUUGUAAGUCGUAGAAAACUAU
+ACGUUUUAAAGCU
+>AB042432.1-14140_14072
+GUUUCUGUAGUUGAAUUACAACGAUGAUUUUUCAUGUCAUUGGUCGCAGU
+UGAAUGCUGUGUAGAAAUA
+>AC008670.6-83725_83795
+ACUUUUAAAGGAUAACAGCCAUCCGUUGGUCUUAGGCCCCAAAAAUUUUG
+GUGCAACUCCAAAUAAAAGUA
diff --git a/examples/tRNA.aln1.fasta.gui b/examples/tRNA.aln1.fasta.gui
new file mode 100644
index 0000000..271a87e
--- /dev/null
+++ b/examples/tRNA.aln1.fasta.gui
@@ -0,0 +1,636 @@
+; Initial DAG
+; Format is:
+; column: (sequence, position)
+; sequence is 0-based and position is 0-based
+
+0: (0, 0)
+1: (1, 0)
+2: (2, 0)
+3: (3, 0)
+4: (4, 0)
+5: (0, 1)
+6: (1, 1)
+7: (2, 1)
+8: (3, 1)
+9: (4, 1)
+10: (0, 2)
+11: (1, 2)
+12: (2, 2)
+13: (3, 2)
+14: (4, 2)
+15: (0, 3)
+16: (1, 3)
+17: (2, 3)
+18: (3, 3)
+19: (4, 3)
+20: (0, 4)
+21: (1, 4)
+22: (2, 4)
+23: (3, 4)
+24: (4, 4)
+25: (0, 5)
+26: (1, 5)
+27: (2, 5)
+28: (3, 5)
+29: (4, 5)
+30: (0, 6)
+31: (1, 6)
+32: (2, 6)
+33: (3, 6)
+34: (4, 6)
+35: (0, 7)
+36: (1, 7)
+37: (2, 7)
+38: (3, 7)
+39: (4, 7)
+40: (0, 8)
+41: (1, 8)
+42: (2, 8)
+43: (3, 8)
+44: (4, 8)
+45: (0, 9)
+46: (1, 9)
+47: (2, 9)
+48: (3, 9)
+49: (4, 9)
+50: (0, 10)
+51: (1, 10)
+52: (2, 10)
+53: (3, 10)
+54: (4, 10)
+55: (0, 11)
+56: (1, 11)
+57: (2, 11)
+58: (3, 11)
+59: (4, 11)
+60: (0, 12)
+61: (1, 12)
+62: (2, 12)
+63: (3, 12)
+64: (4, 12)
+65: (0, 13)
+66: (1, 13)
+67: (2, 13)
+68: (3, 13)
+69: (4, 13)
+70: (0, 14)
+71: (1, 14)
+72: (2, 14)
+73: (3, 14)
+74: (4, 14)
+75: (0, 15)
+76: (1, 15)
+77: (2, 15)
+78: (3, 15)
+79: (4, 15)
+80: (0, 16)
+81: (1, 16)
+82: (2, 16)
+83: (3, 16)
+84: (4, 16)
+85: (0, 17)
+86: (1, 17)
+87: (2, 17)
+88: (3, 17)
+89: (4, 17)
+90: (0, 18)
+91: (1, 18)
+92: (2, 18)
+93: (3, 18)
+94: (4, 18)
+95: (0, 19)
+96: (1, 19)
+97: (2, 19)
+98: (3, 19)
+99: (4, 19)
+100: (0, 20)
+101: (1, 20)
+102: (2, 20)
+103: (3, 20)
+104: (4, 20)
+105: (0, 21)
+106: (1, 21)
+107: (2, 21)
+108: (3, 21)
+109: (4, 21)
+110: (0, 22)
+111: (1, 22)
+112: (2, 22)
+113: (3, 22)
+114: (4, 22)
+115: (0, 23)
+116: (1, 23)
+117: (2, 23)
+118: (3, 23)
+119: (4, 23)
+120: (0, 24)
+121: (1, 24)
+122: (2, 24)
+123: (3, 24)
+124: (4, 24)
+125: (0, 25)
+126: (1, 25)
+127: (2, 25)
+128: (3, 25)
+129: (4, 25)
+130: (0, 26)
+131: (1, 26)
+132: (2, 26)
+133: (3, 26)
+134: (4, 26)
+135: (0, 27)
+136: (1, 27)
+137: (2, 27)
+138: (3, 27)
+139: (4, 27)
+140: (0, 28)
+141: (1, 28)
+142: (2, 28)
+143: (3, 28)
+144: (4, 28)
+145: (0, 29)
+146: (1, 29)
+147: (2, 29)
+148: (3, 29)
+149: (4, 29)
+150: (0, 30)
+151: (1, 30)
+152: (2, 30)
+153: (3, 30)
+154: (4, 30)
+155: (0, 31)
+156: (1, 31)
+157: (2, 31)
+158: (3, 31)
+159: (4, 31)
+160: (0, 32)
+161: (1, 32)
+162: (2, 32)
+163: (3, 32)
+164: (4, 32)
+165: (0, 33)
+166: (1, 33)
+167: (2, 33)
+168: (3, 33)
+169: (4, 33)
+170: (0, 34)
+171: (1, 34)
+172: (2, 34)
+173: (3, 34)
+174: (4, 34)
+175: (0, 35)
+176: (1, 35)
+177: (2, 35)
+178: (3, 35)
+179: (4, 35)
+180: (0, 36)
+181: (1, 36)
+182: (2, 36)
+183: (3, 36)
+184: (4, 36)
+185: (0, 37)
+186: (1, 37)
+187: (2, 37)
+188: (3, 37)
+189: (4, 37)
+190: (0, 38)
+191: (1, 38)
+192: (2, 38)
+193: (3, 38)
+194: (4, 38)
+195: (0, 39)
+196: (1, 39)
+197: (2, 39)
+198: (3, 39)
+199: (4, 39)
+200: (0, 40)
+201: (1, 40)
+202: (2, 40)
+203: (3, 40)
+204: (4, 40)
+205: (0, 41)
+206: (1, 41)
+207: (2, 41)
+208: (3, 41)
+209: (4, 41)
+210: (0, 42)
+211: (1, 42)
+212: (2, 42)
+213: (3, 42)
+214: (4, 42)
+215: (0, 43)
+216: (1, 43)
+217: (2, 43)
+218: (3, 43)
+219: (4, 43)
+220: (0, 44)
+221: (1, 44)
+222: (2, 44)
+223: (3, 44)
+224: (4, 44)
+225: (0, 45)
+226: (1, 45)
+227: (2, 45)
+228: (3, 45)
+229: (4, 45)
+230: (0, 46)
+231: (1, 46)
+232: (2, 46)
+233: (3, 46)
+234: (4, 46)
+235: (0, 47)
+236: (1, 47)
+237: (2, 47)
+238: (3, 47)
+239: (4, 47)
+240: (0, 48)
+241: (1, 48)
+242: (2, 48)
+243: (3, 48)
+244: (4, 48)
+245: (0, 49)
+246: (1, 49)
+247: (2, 49)
+248: (3, 49)
+249: (4, 49)
+250: (0, 50)
+251: (1, 50)
+252: (2, 50)
+253: (3, 50)
+254: (4, 50)
+255: (0, 51)
+256: (1, 51)
+257: (2, 51)
+258: (3, 51)
+259: (4, 51)
+260: (0, 52)
+261: (1, 52)
+262: (2, 52)
+263: (3, 52)
+264: (4, 52)
+265: (0, 53)
+266: (1, 53)
+267: (2, 53)
+268: (3, 53)
+269: (4, 53)
+270: (0, 54)
+271: (1, 54)
+272: (2, 54)
+273: (3, 54)
+274: (4, 54)
+275: (0, 55)
+276: (1, 55)
+277: (2, 55)
+278: (3, 55)
+279: (4, 55)
+280: (0, 56)
+281: (1, 56)
+282: (2, 56)
+283: (3, 56)
+284: (4, 56)
+285: (0, 57)
+286: (1, 57)
+287: (2, 57)
+288: (3, 57)
+289: (4, 57)
+290: (0, 58)
+291: (1, 58)
+292: (2, 58)
+293: (3, 58)
+294: (4, 58)
+295: (0, 59)
+296: (1, 59)
+297: (2, 59)
+298: (3, 59)
+299: (4, 59)
+300: (0, 60)
+301: (1, 60)
+302: (2, 60)
+303: (3, 60)
+304: (4, 60)
+305: (0, 61)
+306: (1, 61)
+307: (2, 61)
+308: (3, 61)
+309: (4, 61)
+310: (0, 62)
+311: (1, 62)
+312: (2, 62)
+313: (3, 62)
+314: (4, 62)
+315: (0, 63)
+316: (1, 63)
+317: (3, 63)
+318: (4, 63)
+319: (0, 64)
+320: (1, 64)
+321: (3, 64)
+322: (4, 64)
+323: (0, 65)
+324: (1, 65)
+325: (3, 65)
+326: (4, 65)
+327: (0, 66)
+328: (1, 66)
+329: (3, 66)
+330: (4, 66)
+331: (0, 67)
+332: (1, 67)
+333: (3, 67)
+334: (4, 67)
+335: (0, 68)
+336: (1, 68)
+337: (3, 68)
+338: (4, 68)
+339: (0, 69)
+340: (1, 69)
+341: (4, 69)
+342: (0, 70)
+343: (1, 70)
+344: (4, 70)
+345: (0, 71)
+346: (1, 71)
+347: (0, 72)
+348: (1, 72)
+
+; Merges (added edges)
+; Format is:
+; source_column -> dest_column
+; (new accuracy is source_column_accuracy + dest_column_accuracy + accuracy_change)
+; (note that all accuracies are unnormalized)
+
+1 -> 0
+51 -> 50
+271 -> 270
+276 -> 275
+6 -> 5
+301 -> 300
+66 -> 65
+56 -> 55
+46 -> 45
+71 -> 70
+266 -> 265
+61 -> 60
+41 -> 40
+306 -> 305
+296 -> 295
+281 -> 280
+36 -> 35
+76 -> 75
+261 -> 260
+286 -> 285
+31 -> 30
+291 -> 290
+11 -> 10
+81 -> 80
+311 -> 310
+96 -> 95
+86 -> 85
+320 -> 319
+26 -> 25
+91 -> 90
+316 -> 315
+256 -> 255
+101 -> 100
+16 -> 15
+116 -> 115
+21 -> 20
+121 -> 120
+324 -> 323
+106 -> 105
+111 -> 110
+251 -> 250
+126 -> 125
+156 -> 155
+246 -> 245
+131 -> 130
+241 -> 240
+151 -> 150
+236 -> 235
+161 -> 160
+136 -> 135
+146 -> 145
+141 -> 140
+328 -> 327
+231 -> 230
+348 -> 347
+343 -> 342
+166 -> 165
+346 -> 345
+340 -> 339
+336 -> 335
+332 -> 331
+226 -> 225
+171 -> 170
+221 -> 220
+216 -> 215
+211 -> 210
+176 -> 175
+181 -> 180
+186 -> 185
+206 -> 205
+191 -> 190
+201 -> 200
+196 -> 195
+3 -> 2
+344 -> 337
+341 -> 333
+338 -> 329
+334 -> 325
+330 -> 321
+313 -> 322
+326 -> 317
+123 -> 122
+318 -> 308
+4 -> 1
+128 -> 127
+8 -> 7
+118 -> 117
+314 -> 303
+113 -> 112
+108 -> 107
+309 -> 298
+133 -> 132
+103 -> 102
+304 -> 293
+83 -> 82
+78 -> 77
+13 -> 12
+98 -> 97
+299 -> 288
+88 -> 87
+53 -> 52
+268 -> 279
+294 -> 283
+48 -> 47
+273 -> 284
+93 -> 92
+289 -> 278
+274 -> 263
+238 -> 249
+18 -> 17
+73 -> 72
+243 -> 254
+58 -> 57
+218 -> 229
+43 -> 42
+224 -> 213
+244 -> 233
+248 -> 259
+223 -> 234
+219 -> 208
+239 -> 228
+68 -> 67
+9 -> 6
+38 -> 37
+63 -> 62
+214 -> 203
+269 -> 258
+4 -> 3
+23 -> 22
+33 -> 32
+209 -> 198
+264 -> 253
+28 -> 27
+138 -> 137
+204 -> 193
+143 -> 142
+199 -> 188
+9 -> 8
+14 -> 11
+348 -> 312
+194 -> 183
+19 -> 16
+346 -> 307
+148 -> 147
+189 -> 178
+24 -> 21
+39 -> 36
+34 -> 31
+44 -> 41
+14 -> 13
+29 -> 26
+184 -> 173
+346 -> 341
+49 -> 46
+153 -> 152
+343 -> 338
+179 -> 168
+19 -> 18
+348 -> 344
+54 -> 51
+59 -> 56
+24 -> 23
+158 -> 157
+163 -> 162
+29 -> 28
+340 -> 334
+64 -> 61
+343 -> 302
+306 -> 299
+332 -> 326
+328 -> 313
+304 -> 311
+34 -> 33
+324 -> 318
+39 -> 38
+301 -> 294
+309 -> 316
+79 -> 76
+74 -> 71
+69 -> 66
+296 -> 289
+291 -> 273
+84 -> 81
+44 -> 43
+336 -> 330
+320 -> 314
+89 -> 86
+286 -> 268
+49 -> 48
+281 -> 274
+340 -> 297
+54 -> 53
+151 -> 149
+161 -> 159
+276 -> 269
+156 -> 154
+94 -> 91
+166 -> 164
+99 -> 96
+336 -> 292
+171 -> 169
+271 -> 264
+146 -> 144
+59 -> 58
+332 -> 287
+266 -> 248
+176 -> 174
+136 -> 134
+141 -> 139
+104 -> 101
+114 -> 111
+261 -> 243
+328 -> 282
+131 -> 129
+64 -> 63
+79 -> 78
+324 -> 277
+256 -> 238
+126 -> 124
+74 -> 73
+109 -> 106
+197 -> 209
+204 -> 192
+69 -> 68
+121 -> 119
+199 -> 187
+84 -> 83
+320 -> 272
+202 -> 214
+194 -> 182
+251 -> 244
+236 -> 218
+309 -> 267
+246 -> 239
+189 -> 177
+304 -> 262
+207 -> 219
+89 -> 88
+184 -> 172
+241 -> 223
+306 -> 257
+179 -> 167
+231 -> 224
+94 -> 93
+116 -> 103
+181 -> 179
+301 -> 252
+186 -> 184
+199 -> 201
+123 -> 136
+204 -> 206
+191 -> 189
+143 -> 156
+148 -> 161
+212 -> 231
+196 -> 194
+99 -> 98
+108 -> 121
+151 -> 138
+146 -> 133
+197 -> 211
+221 -> 207
+176 -> 163
+153 -> 166
+216 -> 202
+141 -> 128
+131 -> 118
+296 -> 247
+126 -> 113
+171 -> 158
+217 -> 236
+291 -> 242
+222 -> 241
+286 -> 237
+227 -> 246
diff --git a/examples/tRNA.aln1.fasta.probs b/examples/tRNA.aln1.fasta.probs
new file mode 100644
index 0000000..42bc4a8
--- /dev/null
+++ b/examples/tRNA.aln1.fasta.probs
@@ -0,0 +1,3731 @@
+; Sparse posterior probability matrix for sequences 0 and 1
+; Format is:
+; (0, position_1) ~ (1, position_2) => prob
+; which means that (0, position_1) is aligned to (1, position_2) with probability prob.
+; (0, position_1) ~ (1, -1) => prob
+; means that (0, position_1) is aligned to a gap in 1 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (1, 0) => 0.999999
+(0, 1) ~ (1, 1) => 0.999998
+(0, 2) ~ (1, 2) => 0.999995
+(0, 3) ~ (1, 3) => 0.999994
+(0, 4) ~ (1, 4) => 0.999993
+(0, 5) ~ (1, 5) => 0.999995
+(0, 6) ~ (1, 6) => 0.999996
+(0, 7) ~ (1, 7) => 0.999997
+(0, 8) ~ (1, 8) => 0.999997
+(0, 9) ~ (1, 9) => 0.999998
+(0, 10) ~ (1, 10) => 0.999998
+(0, 11) ~ (1, 11) => 0.999998
+(0, 12) ~ (1, 12) => 0.999998
+(0, 13) ~ (1, 13) => 0.999998
+(0, 14) ~ (1, 14) => 0.999998
+(0, 15) ~ (1, 15) => 0.999997
+(0, 16) ~ (1, 16) => 0.999995
+(0, 17) ~ (1, 17) => 0.999995
+(0, 18) ~ (1, 18) => 0.999994
+(0, 19) ~ (1, 19) => 0.999995
+(0, 20) ~ (1, 20) => 0.999994
+(0, 21) ~ (1, 21) => 0.999992
+(0, 22) ~ (1, 22) => 0.999992
+(0, 23) ~ (1, 23) => 0.999993
+(0, 24) ~ (1, 24) => 0.999993
+(0, 25) ~ (1, 25) => 0.999991
+(0, 26) ~ (1, 26) => 0.999989
+(0, 27) ~ (1, 27) => 0.999986
+(0, 28) ~ (1, 28) => 0.999985
+(0, 29) ~ (1, 29) => 0.999985
+(0, 30) ~ (1, 30) => 0.999988
+(0, 31) ~ (1, 31) => 0.99999
+(0, 32) ~ (1, 32) => 0.999988
+(0, 33) ~ (1, 33) => 0.999982
+(0, 34) ~ (1, 34) => 0.999972
+(0, 35) ~ (1, 35) => 0.999963
+(0, 36) ~ (1, 36) => 0.999959
+(0, 37) ~ (1, 37) => 0.999958
+(0, 38) ~ (1, 38) => 0.999955
+(0, 39) ~ (1, 39) => 0.999953
+(0, 40) ~ (1, 40) => 0.999954
+(0, 41) ~ (1, 41) => 0.999956
+(0, 42) ~ (1, 42) => 0.999963
+(0, 43) ~ (1, 43) => 0.999967
+(0, 44) ~ (1, 44) => 0.999968
+(0, 45) ~ (1, 45) => 0.999975
+(0, 46) ~ (1, 46) => 0.999985
+(0, 47) ~ (1, 47) => 0.999988
+(0, 48) ~ (1, 48) => 0.999988
+(0, 49) ~ (1, 49) => 0.999989
+(0, 50) ~ (1, 50) => 0.999991
+(0, 51) ~ (1, 51) => 0.999994
+(0, 52) ~ (1, 52) => 0.999996
+(0, 53) ~ (1, 53) => 0.999998
+(0, 54) ~ (1, 54) => 0.999998
+(0, 55) ~ (1, 55) => 0.999998
+(0, 56) ~ (1, 56) => 0.999997
+(0, 57) ~ (1, 57) => 0.999996
+(0, 58) ~ (1, 58) => 0.999996
+(0, 59) ~ (1, 59) => 0.999997
+(0, 60) ~ (1, 60) => 0.999998
+(0, 61) ~ (1, 61) => 0.999997
+(0, 62) ~ (1, 62) => 0.999995
+(0, 63) ~ (1, 63) => 0.999994
+(0, 64) ~ (1, 64) => 0.999995
+(0, 65) ~ (1, 65) => 0.999993
+(0, 66) ~ (1, 66) => 0.999985
+(0, 67) ~ (1, 67) => 0.999977
+(0, 68) ~ (1, 68) => 0.999977
+(0, 69) ~ (1, 69) => 0.999979
+(0, 70) ~ (1, 70) => 0.999982
+(0, 71) ~ (1, 71) => 0.999981
+(0, 72) ~ (1, 72) => 0.999982
+
+; gap posteriors
+(0, 0) ~ (1, -1) => 0.0001
+(0, 1) ~ (1, -1) => 0.0001
+(0, 2) ~ (1, -1) => 0.0001
+(0, 3) ~ (1, -1) => 0.0001
+(0, 4) ~ (1, -1) => 0.0001
+(0, 5) ~ (1, -1) => 0.0001
+(0, 6) ~ (1, -1) => 0.0001
+(0, 7) ~ (1, -1) => 0.0001
+(0, 8) ~ (1, -1) => 0.0001
+(0, 9) ~ (1, -1) => 0.0001
+(0, 10) ~ (1, -1) => 0.0001
+(0, 11) ~ (1, -1) => 0.0001
+(0, 12) ~ (1, -1) => 0.0001
+(0, 13) ~ (1, -1) => 0.0001
+(0, 14) ~ (1, -1) => 0.0001
+(0, 15) ~ (1, -1) => 0.0001
+(0, 16) ~ (1, -1) => 0.0001
+(0, 17) ~ (1, -1) => 0.0001
+(0, 18) ~ (1, -1) => 0.0001
+(0, 19) ~ (1, -1) => 0.0001
+(0, 20) ~ (1, -1) => 0.0001
+(0, 21) ~ (1, -1) => 0.0001
+(0, 22) ~ (1, -1) => 0.0001
+(0, 23) ~ (1, -1) => 0.0001
+(0, 24) ~ (1, -1) => 0.0001
+(0, 25) ~ (1, -1) => 0.0001
+(0, 26) ~ (1, -1) => 0.0001
+(0, 27) ~ (1, -1) => 0.0001
+(0, 28) ~ (1, -1) => 0.0001
+(0, 29) ~ (1, -1) => 0.0001
+(0, 30) ~ (1, -1) => 0.0001
+(0, 31) ~ (1, -1) => 0.0001
+(0, 32) ~ (1, -1) => 0.0001
+(0, 33) ~ (1, -1) => 0.0001
+(0, 34) ~ (1, -1) => 0.0001
+(0, 35) ~ (1, -1) => 0.0001
+(0, 36) ~ (1, -1) => 0.0001
+(0, 37) ~ (1, -1) => 0.0001
+(0, 38) ~ (1, -1) => 0.0001
+(0, 39) ~ (1, -1) => 0.0001
+(0, 40) ~ (1, -1) => 0.0001
+(0, 41) ~ (1, -1) => 0.0001
+(0, 42) ~ (1, -1) => 0.0001
+(0, 43) ~ (1, -1) => 0.0001
+(0, 44) ~ (1, -1) => 0.0001
+(0, 45) ~ (1, -1) => 0.0001
+(0, 46) ~ (1, -1) => 0.0001
+(0, 47) ~ (1, -1) => 0.0001
+(0, 48) ~ (1, -1) => 0.0001
+(0, 49) ~ (1, -1) => 0.0001
+(0, 50) ~ (1, -1) => 0.0001
+(0, 51) ~ (1, -1) => 0.0001
+(0, 52) ~ (1, -1) => 0.0001
+(0, 53) ~ (1, -1) => 0.0001
+(0, 54) ~ (1, -1) => 0.0001
+(0, 55) ~ (1, -1) => 0.0001
+(0, 56) ~ (1, -1) => 0.0001
+(0, 57) ~ (1, -1) => 0.0001
+(0, 58) ~ (1, -1) => 0.0001
+(0, 59) ~ (1, -1) => 0.0001
+(0, 60) ~ (1, -1) => 0.0001
+(0, 61) ~ (1, -1) => 0.0001
+(0, 62) ~ (1, -1) => 0.0001
+(0, 63) ~ (1, -1) => 0.0001
+(0, 64) ~ (1, -1) => 0.0001
+(0, 65) ~ (1, -1) => 0.0001
+(0, 66) ~ (1, -1) => 0.0001
+(0, 67) ~ (1, -1) => 0.0001
+(0, 68) ~ (1, -1) => 0.0001
+(0, 69) ~ (1, -1) => 0.0001
+(0, 70) ~ (1, -1) => 0.0001
+(0, 71) ~ (1, -1) => 0.0001
+(0, 72) ~ (1, -1) => 0.0001
+
+(0, -1) ~ (1, 0) => 0.0001
+(0, -1) ~ (1, 1) => 0.0001
+(0, -1) ~ (1, 2) => 0.0001
+(0, -1) ~ (1, 3) => 0.0001
+(0, -1) ~ (1, 4) => 0.0001
+(0, -1) ~ (1, 5) => 0.0001
+(0, -1) ~ (1, 6) => 0.0001
+(0, -1) ~ (1, 7) => 0.0001
+(0, -1) ~ (1, 8) => 0.0001
+(0, -1) ~ (1, 9) => 0.0001
+(0, -1) ~ (1, 10) => 0.0001
+(0, -1) ~ (1, 11) => 0.0001
+(0, -1) ~ (1, 12) => 0.0001
+(0, -1) ~ (1, 13) => 0.0001
+(0, -1) ~ (1, 14) => 0.0001
+(0, -1) ~ (1, 15) => 0.0001
+(0, -1) ~ (1, 16) => 0.0001
+(0, -1) ~ (1, 17) => 0.0001
+(0, -1) ~ (1, 18) => 0.0001
+(0, -1) ~ (1, 19) => 0.0001
+(0, -1) ~ (1, 20) => 0.0001
+(0, -1) ~ (1, 21) => 0.0001
+(0, -1) ~ (1, 22) => 0.0001
+(0, -1) ~ (1, 23) => 0.0001
+(0, -1) ~ (1, 24) => 0.0001
+(0, -1) ~ (1, 25) => 0.0001
+(0, -1) ~ (1, 26) => 0.0001
+(0, -1) ~ (1, 27) => 0.0001
+(0, -1) ~ (1, 28) => 0.0001
+(0, -1) ~ (1, 29) => 0.0001
+(0, -1) ~ (1, 30) => 0.0001
+(0, -1) ~ (1, 31) => 0.0001
+(0, -1) ~ (1, 32) => 0.0001
+(0, -1) ~ (1, 33) => 0.0001
+(0, -1) ~ (1, 34) => 0.0001
+(0, -1) ~ (1, 35) => 0.0001
+(0, -1) ~ (1, 36) => 0.0001
+(0, -1) ~ (1, 37) => 0.0001
+(0, -1) ~ (1, 38) => 0.0001
+(0, -1) ~ (1, 39) => 0.0001
+(0, -1) ~ (1, 40) => 0.0001
+(0, -1) ~ (1, 41) => 0.0001
+(0, -1) ~ (1, 42) => 0.0001
+(0, -1) ~ (1, 43) => 0.0001
+(0, -1) ~ (1, 44) => 0.0001
+(0, -1) ~ (1, 45) => 0.0001
+(0, -1) ~ (1, 46) => 0.0001
+(0, -1) ~ (1, 47) => 0.0001
+(0, -1) ~ (1, 48) => 0.0001
+(0, -1) ~ (1, 49) => 0.0001
+(0, -1) ~ (1, 50) => 0.0001
+(0, -1) ~ (1, 51) => 0.0001
+(0, -1) ~ (1, 52) => 0.0001
+(0, -1) ~ (1, 53) => 0.0001
+(0, -1) ~ (1, 54) => 0.0001
+(0, -1) ~ (1, 55) => 0.0001
+(0, -1) ~ (1, 56) => 0.0001
+(0, -1) ~ (1, 57) => 0.0001
+(0, -1) ~ (1, 58) => 0.0001
+(0, -1) ~ (1, 59) => 0.0001
+(0, -1) ~ (1, 60) => 0.0001
+(0, -1) ~ (1, 61) => 0.0001
+(0, -1) ~ (1, 62) => 0.0001
+(0, -1) ~ (1, 63) => 0.0001
+(0, -1) ~ (1, 64) => 0.0001
+(0, -1) ~ (1, 65) => 0.0001
+(0, -1) ~ (1, 66) => 0.0001
+(0, -1) ~ (1, 67) => 0.0001
+(0, -1) ~ (1, 68) => 0.0001
+(0, -1) ~ (1, 69) => 0.0001
+(0, -1) ~ (1, 70) => 0.0001
+(0, -1) ~ (1, 71) => 0.0001
+(0, -1) ~ (1, 72) => 0.0001
+
+; Sparse posterior probability matrix for sequences 0 and 2
+; Format is:
+; (0, position_1) ~ (2, position_2) => prob
+; which means that (0, position_1) is aligned to (2, position_2) with probability prob.
+; (0, position_1) ~ (2, -1) => prob
+; means that (0, position_1) is aligned to a gap in 2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (2, 0) => 0.999724
+(0, 1) ~ (2, 1) => 0.998259
+(0, 2) ~ (2, 2) => 0.994262
+(0, 3) ~ (2, 3) => 0.989699
+(0, 4) ~ (2, 4) => 0.984788
+(0, 5) ~ (2, 5) => 0.98371
+(0, 6) ~ (2, 6) => 0.984832
+(0, 7) ~ (2, 7) => 0.986823
+(0, 8) ~ (2, 8) => 0.990154
+(0, 9) ~ (2, 9) => 0.993648
+(0, 10) ~ (2, 10) => 0.992968
+(0, 11) ~ (2, 11) => 0.97876
+(0, 12) ~ (2, 12) => 0.921718
+(0, 13) ~ (2, 13) => 0.887071
+(0, 14) ~ (2, 14) => 0.871222
+(0, 15) ~ (2, 12) => 0.0582702
+(0, 15) ~ (2, 15) => 0.849592
+(0, 15) ~ (2, 18) => 0.0100661
+(0, 16) ~ (2, 13) => 0.0887852
+(0, 16) ~ (2, 16) => 0.823034
+(0, 17) ~ (2, 14) => 0.101264
+(0, 17) ~ (2, 17) => 0.772626
+(0, 17) ~ (2, 20) => 0.0101951
+(0, 18) ~ (2, 15) => 0.111043
+(0, 18) ~ (2, 17) => 0.0266189
+(0, 18) ~ (2, 18) => 0.634374
+(0, 18) ~ (2, 20) => 0.0130161
+(0, 19) ~ (2, 15) => 0.0101311
+(0, 19) ~ (2, 16) => 0.130759
+(0, 19) ~ (2, 18) => 0.0390973
+(0, 19) ~ (2, 19) => 0.511963
+(0, 19) ~ (2, 21) => 0.014438
+(0, 19) ~ (2, 22) => 0.0108856
+(0, 20) ~ (2, 16) => 0.0118631
+(0, 20) ~ (2, 17) => 0.146939
+(0, 20) ~ (2, 18) => 0.0396141
+(0, 20) ~ (2, 19) => 0.0482135
+(0, 20) ~ (2, 20) => 0.410275
+(0, 20) ~ (2, 22) => 0.0168449
+(0, 20) ~ (2, 23) => 0.0104926
+(0, 21) ~ (2, 17) => 0.0164278
+(0, 21) ~ (2, 18) => 0.217703
+(0, 21) ~ (2, 19) => 0.0659514
+(0, 21) ~ (2, 20) => 0.0485805
+(0, 21) ~ (2, 21) => 0.360963
+(0, 21) ~ (2, 23) => 0.0107928
+(0, 22) ~ (2, 18) => 0.0175471
+(0, 22) ~ (2, 19) => 0.292626
+(0, 22) ~ (2, 20) => 0.090073
+(0, 22) ~ (2, 21) => 0.0254846
+(0, 22) ~ (2, 22) => 0.338077
+(0, 23) ~ (2, 19) => 0.0151479
+(0, 23) ~ (2, 20) => 0.351957
+(0, 23) ~ (2, 21) => 0.127763
+(0, 23) ~ (2, 22) => 0.0214119
+(0, 23) ~ (2, 23) => 0.278308
+(0, 24) ~ (2, 21) => 0.35012
+(0, 24) ~ (2, 22) => 0.184091
+(0, 24) ~ (2, 23) => 0.0102155
+(0, 24) ~ (2, 24) => 0.230821
+(0, 25) ~ (2, 20) => 0.0163298
+(0, 25) ~ (2, 22) => 0.223097
+(0, 25) ~ (2, 23) => 0.381562
+(0, 25) ~ (2, 25) => 0.159674
+(0, 26) ~ (2, 21) => 0.0275944
+(0, 26) ~ (2, 22) => 0.0131233
+(0, 26) ~ (2, 23) => 0.0808135
+(0, 26) ~ (2, 24) => 0.560693
+(0, 26) ~ (2, 25) => 0.0229938
+(0, 26) ~ (2, 26) => 0.0856582
+(0, 26) ~ (2, 27) => 0.0132148
+(0, 27) ~ (2, 22) => 0.0282464
+(0, 27) ~ (2, 23) => 0.0326558
+(0, 27) ~ (2, 24) => 0.0448551
+(0, 27) ~ (2, 25) => 0.621584
+(0, 27) ~ (2, 26) => 0.0519631
+(0, 27) ~ (2, 27) => 0.0247191
+(0, 28) ~ (2, 23) => 0.024229
+(0, 28) ~ (2, 24) => 0.0391592
+(0, 28) ~ (2, 25) => 0.0415402
+(0, 28) ~ (2, 26) => 0.674947
+(0, 28) ~ (2, 27) => 0.0693055
+(0, 28) ~ (2, 28) => 0.0241231
+(0, 29) ~ (2, 24) => 0.0185494
+(0, 29) ~ (2, 26) => 0.0432005
+(0, 29) ~ (2, 27) => 0.773768
+(0, 29) ~ (2, 28) => 0.0661617
+(0, 29) ~ (2, 29) => 0.0184992
+(0, 30) ~ (2, 27) => 0.0597814
+(0, 30) ~ (2, 28) => 0.79759
+(0, 30) ~ (2, 29) => 0.0537858
+(0, 30) ~ (2, 30) => 0.0134248
+(0, 31) ~ (2, 28) => 0.062305
+(0, 31) ~ (2, 29) => 0.788477
+(0, 31) ~ (2, 30) => 0.0418489
+(0, 31) ~ (2, 32) => 0.0152908
+(0, 32) ~ (2, 29) => 0.0799714
+(0, 32) ~ (2, 30) => 0.756954
+(0, 32) ~ (2, 33) => 0.017271
+(0, 33) ~ (2, 30) => 0.0917165
+(0, 33) ~ (2, 31) => 0.634551
+(0, 33) ~ (2, 34) => 0.0191927
+(0, 34) ~ (2, 31) => 0.175789
+(0, 34) ~ (2, 32) => 0.400881
+(0, 34) ~ (2, 33) => 0.0207365
+(0, 34) ~ (2, 35) => 0.0223507
+(0, 35) ~ (2, 30) => 0.0147897
+(0, 35) ~ (2, 32) => 0.229849
+(0, 35) ~ (2, 33) => 0.313607
+(0, 35) ~ (2, 34) => 0.0222486
+(0, 35) ~ (2, 36) => 0.020426
+(0, 36) ~ (2, 31) => 0.0205284
+(0, 36) ~ (2, 32) => 0.071508
+(0, 36) ~ (2, 33) => 0.204588
+(0, 36) ~ (2, 34) => 0.245642
+(0, 36) ~ (2, 35) => 0.023337
+(0, 36) ~ (2, 37) => 0.0109347
+(0, 37) ~ (2, 30) => 0.0116018
+(0, 37) ~ (2, 32) => 0.0423532
+(0, 37) ~ (2, 33) => 0.110317
+(0, 37) ~ (2, 34) => 0.172453
+(0, 37) ~ (2, 35) => 0.161916
+(0, 37) ~ (2, 36) => 0.0341586
+(0, 38) ~ (2, 31) => 0.0235705
+(0, 38) ~ (2, 33) => 0.051835
+(0, 38) ~ (2, 34) => 0.140796
+(0, 38) ~ (2, 35) => 0.128513
+(0, 38) ~ (2, 36) => 0.138184
+(0, 38) ~ (2, 37) => 0.0419751
+(0, 39) ~ (2, 32) => 0.0284375
+(0, 39) ~ (2, 34) => 0.0605162
+(0, 39) ~ (2, 35) => 0.177165
+(0, 39) ~ (2, 36) => 0.056401
+(0, 39) ~ (2, 37) => 0.133565
+(0, 39) ~ (2, 38) => 0.0645766
+(0, 39) ~ (2, 40) => 0.0138348
+(0, 40) ~ (2, 31) => 0.0398725
+(0, 40) ~ (2, 33) => 0.0382519
+(0, 40) ~ (2, 35) => 0.0703581
+(0, 40) ~ (2, 36) => 0.188482
+(0, 40) ~ (2, 37) => 0.0221293
+(0, 40) ~ (2, 38) => 0.140343
+(0, 40) ~ (2, 39) => 0.0662712
+(0, 40) ~ (2, 41) => 0.0153682
+(0, 41) ~ (2, 32) => 0.0639644
+(0, 41) ~ (2, 34) => 0.0479564
+(0, 41) ~ (2, 36) => 0.0646349
+(0, 41) ~ (2, 37) => 0.215527
+(0, 41) ~ (2, 39) => 0.128938
+(0, 41) ~ (2, 40) => 0.076872
+(0, 41) ~ (2, 42) => 0.0144392
+(0, 42) ~ (2, 32) => 0.0304373
+(0, 42) ~ (2, 33) => 0.059531
+(0, 42) ~ (2, 35) => 0.0595085
+(0, 42) ~ (2, 37) => 0.0261667
+(0, 42) ~ (2, 38) => 0.250169
+(0, 42) ~ (2, 40) => 0.0911969
+(0, 42) ~ (2, 41) => 0.0914186
+(0, 42) ~ (2, 43) => 0.0136913
+(0, 43) ~ (2, 33) => 0.0837669
+(0, 43) ~ (2, 34) => 0.0562082
+(0, 43) ~ (2, 36) => 0.0614359
+(0, 43) ~ (2, 38) => 0.012928
+(0, 43) ~ (2, 39) => 0.253133
+(0, 43) ~ (2, 40) => 0.0173352
+(0, 43) ~ (2, 41) => 0.0589634
+(0, 43) ~ (2, 42) => 0.0964243
+(0, 43) ~ (2, 44) => 0.0126652
+(0, 44) ~ (2, 34) => 0.132966
+(0, 44) ~ (2, 35) => 0.0482587
+(0, 44) ~ (2, 37) => 0.0630964
+(0, 44) ~ (2, 40) => 0.26258
+(0, 44) ~ (2, 41) => 0.0226665
+(0, 44) ~ (2, 42) => 0.0471306
+(0, 44) ~ (2, 43) => 0.0955452
+(0, 44) ~ (2, 45) => 0.0107377
+(0, 45) ~ (2, 31) => 0.017201
+(0, 45) ~ (2, 35) => 0.196908
+(0, 45) ~ (2, 36) => 0.0319099
+(0, 45) ~ (2, 38) => 0.07081
+(0, 45) ~ (2, 41) => 0.271162
+(0, 45) ~ (2, 42) => 0.0205864
+(0, 45) ~ (2, 43) => 0.0353805
+(0, 45) ~ (2, 44) => 0.0941144
+(0, 46) ~ (2, 32) => 0.0253401
+(0, 46) ~ (2, 36) => 0.241181
+(0, 46) ~ (2, 37) => 0.031351
+(0, 46) ~ (2, 39) => 0.0664009
+(0, 46) ~ (2, 42) => 0.260711
+(0, 46) ~ (2, 43) => 0.0179568
+(0, 46) ~ (2, 44) => 0.0215948
+(0, 46) ~ (2, 45) => 0.0931938
+(0, 47) ~ (2, 33) => 0.0275964
+(0, 47) ~ (2, 37) => 0.246739
+(0, 47) ~ (2, 38) => 0.029932
+(0, 47) ~ (2, 39) => 0.0204301
+(0, 47) ~ (2, 40) => 0.0498507
+(0, 47) ~ (2, 43) => 0.251047
+(0, 47) ~ (2, 44) => 0.0135477
+(0, 47) ~ (2, 46) => 0.0926613
+(0, 48) ~ (2, 34) => 0.0334336
+(0, 48) ~ (2, 37) => 0.0116868
+(0, 48) ~ (2, 38) => 0.193955
+(0, 48) ~ (2, 39) => 0.0456215
+(0, 48) ~ (2, 40) => 0.0421049
+(0, 48) ~ (2, 41) => 0.0410816
+(0, 48) ~ (2, 42) => 0.0123284
+(0, 48) ~ (2, 44) => 0.254717
+(0, 48) ~ (2, 45) => 0.0123801
+(0, 48) ~ (2, 47) => 0.0667051
+(0, 49) ~ (2, 35) => 0.0389983
+(0, 49) ~ (2, 38) => 0.0422504
+(0, 49) ~ (2, 39) => 0.177682
+(0, 49) ~ (2, 40) => 0.0594786
+(0, 49) ~ (2, 41) => 0.0511579
+(0, 49) ~ (2, 42) => 0.0388787
+(0, 49) ~ (2, 43) => 0.0135967
+(0, 49) ~ (2, 45) => 0.252676
+(0, 49) ~ (2, 48) => 0.0456863
+(0, 50) ~ (2, 36) => 0.0415821
+(0, 50) ~ (2, 39) => 0.050177
+(0, 50) ~ (2, 40) => 0.181601
+(0, 50) ~ (2, 41) => 0.0671565
+(0, 50) ~ (2, 42) => 0.0472804
+(0, 50) ~ (2, 43) => 0.0351595
+(0, 50) ~ (2, 44) => 0.0129426
+(0, 50) ~ (2, 46) => 0.248721
+(0, 50) ~ (2, 49) => 0.0291422
+(0, 51) ~ (2, 37) => 0.0420335
+(0, 51) ~ (2, 40) => 0.0512515
+(0, 51) ~ (2, 41) => 0.192155
+(0, 51) ~ (2, 42) => 0.0946379
+(0, 51) ~ (2, 43) => 0.0492776
+(0, 51) ~ (2, 44) => 0.0356747
+(0, 51) ~ (2, 45) => 0.0148672
+(0, 51) ~ (2, 47) => 0.174671
+(0, 51) ~ (2, 50) => 0.0178835
+(0, 52) ~ (2, 38) => 0.0515219
+(0, 52) ~ (2, 41) => 0.0516903
+(0, 52) ~ (2, 42) => 0.189746
+(0, 52) ~ (2, 43) => 0.124305
+(0, 52) ~ (2, 44) => 0.0495705
+(0, 52) ~ (2, 45) => 0.0354658
+(0, 52) ~ (2, 46) => 0.0152973
+(0, 52) ~ (2, 48) => 0.151707
+(0, 53) ~ (2, 39) => 0.0545825
+(0, 53) ~ (2, 42) => 0.0452449
+(0, 53) ~ (2, 43) => 0.187371
+(0, 53) ~ (2, 44) => 0.15197
+(0, 53) ~ (2, 45) => 0.0487567
+(0, 53) ~ (2, 46) => 0.0329965
+(0, 53) ~ (2, 47) => 0.0290346
+(0, 53) ~ (2, 49) => 0.133888
+(0, 54) ~ (2, 40) => 0.0535747
+(0, 54) ~ (2, 43) => 0.0385975
+(0, 54) ~ (2, 44) => 0.184618
+(0, 54) ~ (2, 45) => 0.18189
+(0, 54) ~ (2, 46) => 0.0464012
+(0, 54) ~ (2, 47) => 0.0365166
+(0, 54) ~ (2, 48) => 0.023408
+(0, 54) ~ (2, 50) => 0.1125
+(0, 55) ~ (2, 41) => 0.0520236
+(0, 55) ~ (2, 44) => 0.0314222
+(0, 55) ~ (2, 45) => 0.182111
+(0, 55) ~ (2, 46) => 0.211635
+(0, 55) ~ (2, 47) => 0.0502179
+(0, 55) ~ (2, 48) => 0.0192955
+(0, 55) ~ (2, 49) => 0.0183962
+(0, 55) ~ (2, 51) => 0.0807924
+(0, 56) ~ (2, 42) => 0.054673
+(0, 56) ~ (2, 45) => 0.0300687
+(0, 56) ~ (2, 46) => 0.192478
+(0, 56) ~ (2, 47) => 0.178491
+(0, 56) ~ (2, 48) => 0.0411804
+(0, 56) ~ (2, 49) => 0.0126608
+(0, 56) ~ (2, 50) => 0.014626
+(0, 56) ~ (2, 52) => 0.0444692
+(0, 57) ~ (2, 43) => 0.0546273
+(0, 57) ~ (2, 46) => 0.0107941
+(0, 57) ~ (2, 47) => 0.330134
+(0, 57) ~ (2, 48) => 0.143113
+(0, 57) ~ (2, 49) => 0.0270833
+(0, 57) ~ (2, 50) => 0.0108142
+(0, 57) ~ (2, 53) => 0.0317131
+(0, 58) ~ (2, 44) => 0.0521404
+(0, 58) ~ (2, 48) => 0.462548
+(0, 58) ~ (2, 49) => 0.102628
+(0, 58) ~ (2, 50) => 0.0228717
+(0, 58) ~ (2, 54) => 0.0236598
+(0, 59) ~ (2, 45) => 0.0486479
+(0, 59) ~ (2, 49) => 0.579688
+(0, 59) ~ (2, 50) => 0.0901317
+(0, 59) ~ (2, 55) => 0.0201023
+(0, 60) ~ (2, 46) => 0.0474697
+(0, 60) ~ (2, 50) => 0.645043
+(0, 60) ~ (2, 51) => 0.0615694
+(0, 60) ~ (2, 56) => 0.0147287
+(0, 61) ~ (2, 47) => 0.0335597
+(0, 61) ~ (2, 51) => 0.789701
+(0, 61) ~ (2, 52) => 0.0265989
+(0, 62) ~ (2, 48) => 0.0279606
+(0, 62) ~ (2, 52) => 0.869536
+(0, 62) ~ (2, 53) => 0.0204472
+(0, 63) ~ (2, 49) => 0.0240568
+(0, 63) ~ (2, 53) => 0.887267
+(0, 63) ~ (2, 54) => 0.0216905
+(0, 64) ~ (2, 50) => 0.0199529
+(0, 64) ~ (2, 54) => 0.900811
+(0, 64) ~ (2, 55) => 0.0230221
+(0, 65) ~ (2, 51) => 0.0177709
+(0, 65) ~ (2, 55) => 0.90596
+(0, 65) ~ (2, 56) => 0.0223452
+(0, 66) ~ (2, 52) => 0.0115729
+(0, 66) ~ (2, 56) => 0.91626
+(0, 66) ~ (2, 57) => 0.0194429
+(0, 67) ~ (2, 56) => 0.010609
+(0, 67) ~ (2, 57) => 0.932905
+(0, 67) ~ (2, 58) => 0.0135614
+(0, 68) ~ (2, 58) => 0.954925
+(0, 69) ~ (2, 59) => 0.974332
+(0, 70) ~ (2, 60) => 0.990845
+(0, 71) ~ (2, 61) => 0.997531
+(0, 72) ~ (2, 62) => 0.998506
+
+; gap posteriors
+(0, 0) ~ (2, -1) => 0.000275612
+(0, 1) ~ (2, -1) => 0.00174129
+(0, 2) ~ (2, -1) => 0.00573754
+(0, 3) ~ (2, -1) => 0.010301
+(0, 4) ~ (2, -1) => 0.0152116
+(0, 5) ~ (2, -1) => 0.0162897
+(0, 6) ~ (2, -1) => 0.015168
+(0, 7) ~ (2, -1) => 0.0131771
+(0, 8) ~ (2, -1) => 0.00984573
+(0, 9) ~ (2, -1) => 0.00635201
+(0, 10) ~ (2, -1) => 0.0070315
+(0, 11) ~ (2, -1) => 0.0212397
+(0, 12) ~ (2, -1) => 0.078282
+(0, 13) ~ (2, -1) => 0.112929
+(0, 14) ~ (2, -1) => 0.128778
+(0, 15) ~ (2, -1) => 0.082072
+(0, 16) ~ (2, -1) => 0.0881804
+(0, 17) ~ (2, -1) => 0.115915
+(0, 18) ~ (2, -1) => 0.214949
+(0, 19) ~ (2, -1) => 0.282726
+(0, 20) ~ (2, -1) => 0.315758
+(0, 21) ~ (2, -1) => 0.279582
+(0, 22) ~ (2, -1) => 0.236192
+(0, 23) ~ (2, -1) => 0.205413
+(0, 24) ~ (2, -1) => 0.224752
+(0, 25) ~ (2, -1) => 0.219337
+(0, 26) ~ (2, -1) => 0.195909
+(0, 27) ~ (2, -1) => 0.195977
+(0, 28) ~ (2, -1) => 0.126696
+(0, 29) ~ (2, -1) => 0.0798208
+(0, 30) ~ (2, -1) => 0.0754177
+(0, 31) ~ (2, -1) => 0.0920783
+(0, 32) ~ (2, -1) => 0.145803
+(0, 33) ~ (2, -1) => 0.254539
+(0, 34) ~ (2, -1) => 0.380242
+(0, 35) ~ (2, -1) => 0.39908
+(0, 36) ~ (2, -1) => 0.423462
+(0, 37) ~ (2, -1) => 0.4672
+(0, 38) ~ (2, -1) => 0.475126
+(0, 39) ~ (2, -1) => 0.465504
+(0, 40) ~ (2, -1) => 0.418923
+(0, 41) ~ (2, -1) => 0.387668
+(0, 42) ~ (2, -1) => 0.377881
+(0, 43) ~ (2, -1) => 0.34714
+(0, 44) ~ (2, -1) => 0.317019
+(0, 45) ~ (2, -1) => 0.261928
+(0, 46) ~ (2, -1) => 0.242271
+(0, 47) ~ (2, -1) => 0.268196
+(0, 48) ~ (2, -1) => 0.285986
+(0, 49) ~ (2, -1) => 0.279595
+(0, 50) ~ (2, -1) => 0.286238
+(0, 51) ~ (2, -1) => 0.327548
+(0, 52) ~ (2, -1) => 0.330696
+(0, 53) ~ (2, -1) => 0.316156
+(0, 54) ~ (2, -1) => 0.322494
+(0, 55) ~ (2, -1) => 0.354106
+(0, 56) ~ (2, -1) => 0.431354
+(0, 57) ~ (2, -1) => 0.391721
+(0, 58) ~ (2, -1) => 0.336152
+(0, 59) ~ (2, -1) => 0.26143
+(0, 60) ~ (2, -1) => 0.231189
+(0, 61) ~ (2, -1) => 0.150141
+(0, 62) ~ (2, -1) => 0.0820566
+(0, 63) ~ (2, -1) => 0.066986
+(0, 64) ~ (2, -1) => 0.0562138
+(0, 65) ~ (2, -1) => 0.0539238
+(0, 66) ~ (2, -1) => 0.0527242
+(0, 67) ~ (2, -1) => 0.0429246
+(0, 68) ~ (2, -1) => 0.0450748
+(0, 69) ~ (2, -1) => 0.0256681
+(0, 70) ~ (2, -1) => 0.00915456
+(0, 71) ~ (2, -1) => 0.002469
+(0, 72) ~ (2, -1) => 0.00149399
+
+(0, -1) ~ (2, 0) => 0.000275612
+(0, -1) ~ (2, 1) => 0.00174129
+(0, -1) ~ (2, 2) => 0.00573754
+(0, -1) ~ (2, 3) => 0.010301
+(0, -1) ~ (2, 4) => 0.0152116
+(0, -1) ~ (2, 5) => 0.0162897
+(0, -1) ~ (2, 6) => 0.015168
+(0, -1) ~ (2, 7) => 0.0131771
+(0, -1) ~ (2, 8) => 0.00984573
+(0, -1) ~ (2, 9) => 0.00635201
+(0, -1) ~ (2, 10) => 0.0070315
+(0, -1) ~ (2, 11) => 0.0212397
+(0, -1) ~ (2, 12) => 0.0200118
+(0, -1) ~ (2, 13) => 0.0241438
+(0, -1) ~ (2, 14) => 0.0275133
+(0, -1) ~ (2, 15) => 0.0292348
+(0, -1) ~ (2, 16) => 0.0343431
+(0, -1) ~ (2, 17) => 0.0373887
+(0, -1) ~ (2, 18) => 0.0415987
+(0, -1) ~ (2, 19) => 0.0660981
+(0, -1) ~ (2, 20) => 0.0595737
+(0, -1) ~ (2, 21) => 0.0936376
+(0, -1) ~ (2, 22) => 0.164222
+(0, -1) ~ (2, 23) => 0.170931
+(0, -1) ~ (2, 24) => 0.105922
+(0, -1) ~ (2, 25) => 0.154209
+(0, -1) ~ (2, 26) => 0.144231
+(0, -1) ~ (2, 27) => 0.0592109
+(0, -1) ~ (2, 28) => 0.0498198
+(0, -1) ~ (2, 29) => 0.0592668
+(0, -1) ~ (2, 30) => 0.0696642
+(0, -1) ~ (2, 31) => 0.0884868
+(0, -1) ~ (2, 32) => 0.0919386
+(0, -1) ~ (2, 33) => 0.0724985
+(0, -1) ~ (2, 34) => 0.0685876
+(0, -1) ~ (2, 35) => 0.0726866
+(0, -1) ~ (2, 36) => 0.121605
+(0, -1) ~ (2, 37) => 0.154795
+(0, -1) ~ (2, 38) => 0.143514
+(0, -1) ~ (2, 39) => 0.136763
+(0, -1) ~ (2, 40) => 0.10032
+(0, -1) ~ (2, 41) => 0.0851562
+(0, -1) ~ (2, 42) => 0.0779182
+(0, -1) ~ (2, 43) => 0.0834449
+(0, -1) ~ (2, 44) => 0.0850222
+(0, -1) ~ (2, 45) => 0.089206
+(0, -1) ~ (2, 46) => 0.101546
+(0, -1) ~ (2, 47) => 0.100671
+(0, -1) ~ (2, 48) => 0.0851012
+(0, -1) ~ (2, 49) => 0.0724566
+(0, -1) ~ (2, 50) => 0.066177
+(0, -1) ~ (2, 51) => 0.0501667
+(0, -1) ~ (2, 52) => 0.0478234
+(0, -1) ~ (2, 53) => 0.060573
+(0, -1) ~ (2, 54) => 0.0538386
+(0, -1) ~ (2, 55) => 0.0509156
+(0, -1) ~ (2, 56) => 0.036057
+(0, -1) ~ (2, 57) => 0.0476521
+(0, -1) ~ (2, 58) => 0.0315134
+(0, -1) ~ (2, 59) => 0.0256681
+(0, -1) ~ (2, 60) => 0.00915456
+(0, -1) ~ (2, 61) => 0.002469
+(0, -1) ~ (2, 62) => 0.00149399
+
+; Sparse posterior probability matrix for sequences 0 and 3
+; Format is:
+; (0, position_1) ~ (3, position_2) => prob
+; which means that (0, position_1) is aligned to (3, position_2) with probability prob.
+; (0, position_1) ~ (3, -1) => prob
+; means that (0, position_1) is aligned to a gap in 3 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (3, 0) => 0.999868
+(0, 1) ~ (3, 1) => 0.999554
+(0, 2) ~ (3, 2) => 0.999334
+(0, 3) ~ (3, 3) => 0.999235
+(0, 4) ~ (3, 4) => 0.999279
+(0, 5) ~ (3, 5) => 0.999524
+(0, 6) ~ (3, 6) => 0.999585
+(0, 7) ~ (3, 7) => 0.999572
+(0, 8) ~ (3, 8) => 0.999311
+(0, 9) ~ (3, 9) => 0.998955
+(0, 10) ~ (3, 10) => 0.99825
+(0, 11) ~ (3, 11) => 0.997211
+(0, 12) ~ (3, 12) => 0.996337
+(0, 13) ~ (3, 13) => 0.99552
+(0, 14) ~ (3, 14) => 0.993473
+(0, 15) ~ (3, 15) => 0.988359
+(0, 16) ~ (3, 16) => 0.976493
+(0, 17) ~ (3, 17) => 0.928737
+(0, 18) ~ (3, 17) => 0.0325857
+(0, 18) ~ (3, 18) => 0.855379
+(0, 18) ~ (3, 19) => 0.0148667
+(0, 19) ~ (3, 17) => 0.0110468
+(0, 19) ~ (3, 18) => 0.0543214
+(0, 19) ~ (3, 19) => 0.721971
+(0, 19) ~ (3, 20) => 0.0169913
+(0, 20) ~ (3, 17) => 0.0143884
+(0, 20) ~ (3, 18) => 0.047874
+(0, 20) ~ (3, 19) => 0.13454
+(0, 20) ~ (3, 20) => 0.690495
+(0, 20) ~ (3, 21) => 0.0206943
+(0, 21) ~ (3, 18) => 0.0172511
+(0, 21) ~ (3, 19) => 0.0933079
+(0, 21) ~ (3, 20) => 0.148898
+(0, 21) ~ (3, 21) => 0.646272
+(0, 21) ~ (3, 22) => 0.030991
+(0, 22) ~ (3, 19) => 0.0201563
+(0, 22) ~ (3, 20) => 0.107175
+(0, 22) ~ (3, 21) => 0.167541
+(0, 22) ~ (3, 22) => 0.604437
+(0, 22) ~ (3, 23) => 0.0351532
+(0, 23) ~ (3, 20) => 0.0189054
+(0, 23) ~ (3, 21) => 0.118466
+(0, 23) ~ (3, 22) => 0.192156
+(0, 23) ~ (3, 23) => 0.594313
+(0, 23) ~ (3, 24) => 0.027865
+(0, 24) ~ (3, 21) => 0.0168377
+(0, 24) ~ (3, 22) => 0.131108
+(0, 24) ~ (3, 23) => 0.195914
+(0, 24) ~ (3, 24) => 0.540339
+(0, 24) ~ (3, 25) => 0.0282492
+(0, 25) ~ (3, 23) => 0.137636
+(0, 25) ~ (3, 24) => 0.264318
+(0, 25) ~ (3, 25) => 0.209762
+(0, 25) ~ (3, 26) => 0.0367611
+(0, 26) ~ (3, 24) => 0.122203
+(0, 26) ~ (3, 25) => 0.610714
+(0, 26) ~ (3, 26) => 0.0458083
+(0, 26) ~ (3, 27) => 0.0310703
+(0, 27) ~ (3, 25) => 0.0343706
+(0, 27) ~ (3, 26) => 0.868687
+(0, 27) ~ (3, 27) => 0.0307455
+(0, 27) ~ (3, 28) => 0.0212694
+(0, 28) ~ (3, 26) => 0.0153008
+(0, 28) ~ (3, 27) => 0.911727
+(0, 28) ~ (3, 28) => 0.0305757
+(0, 28) ~ (3, 29) => 0.0197958
+(0, 29) ~ (3, 27) => 0.0154065
+(0, 29) ~ (3, 28) => 0.923867
+(0, 29) ~ (3, 29) => 0.0282678
+(0, 29) ~ (3, 30) => 0.0180916
+(0, 30) ~ (3, 28) => 0.0148131
+(0, 30) ~ (3, 29) => 0.928523
+(0, 30) ~ (3, 30) => 0.025473
+(0, 30) ~ (3, 31) => 0.0151869
+(0, 31) ~ (3, 29) => 0.0138116
+(0, 31) ~ (3, 30) => 0.931348
+(0, 31) ~ (3, 31) => 0.0204346
+(0, 32) ~ (3, 30) => 0.0119587
+(0, 32) ~ (3, 31) => 0.930356
+(0, 32) ~ (3, 32) => 0.0112762
+(0, 33) ~ (3, 32) => 0.913441
+(0, 34) ~ (3, 33) => 0.886764
+(0, 34) ~ (3, 35) => 0.0140674
+(0, 35) ~ (3, 31) => 0.0101124
+(0, 35) ~ (3, 34) => 0.860442
+(0, 35) ~ (3, 36) => 0.0174668
+(0, 36) ~ (3, 32) => 0.0147431
+(0, 36) ~ (3, 35) => 0.757718
+(0, 36) ~ (3, 37) => 0.017365
+(0, 37) ~ (3, 32) => 0.0104763
+(0, 37) ~ (3, 33) => 0.0191068
+(0, 37) ~ (3, 35) => 0.0137239
+(0, 37) ~ (3, 36) => 0.724875
+(0, 37) ~ (3, 37) => 0.0101107
+(0, 37) ~ (3, 38) => 0.0150061
+(0, 38) ~ (3, 33) => 0.0167235
+(0, 38) ~ (3, 34) => 0.0206122
+(0, 38) ~ (3, 35) => 0.0170961
+(0, 38) ~ (3, 36) => 0.0213794
+(0, 38) ~ (3, 37) => 0.693712
+(0, 39) ~ (3, 32) => 0.0187956
+(0, 39) ~ (3, 34) => 0.022139
+(0, 39) ~ (3, 35) => 0.0437584
+(0, 39) ~ (3, 36) => 0.0153575
+(0, 39) ~ (3, 37) => 0.0362792
+(0, 39) ~ (3, 38) => 0.640753
+(0, 40) ~ (3, 33) => 0.032433
+(0, 40) ~ (3, 35) => 0.0639345
+(0, 40) ~ (3, 36) => 0.0480517
+(0, 40) ~ (3, 37) => 0.0171286
+(0, 40) ~ (3, 38) => 0.0482781
+(0, 40) ~ (3, 39) => 0.583542
+(0, 41) ~ (3, 34) => 0.0464326
+(0, 41) ~ (3, 36) => 0.0763925
+(0, 41) ~ (3, 37) => 0.059493
+(0, 41) ~ (3, 38) => 0.0148169
+(0, 41) ~ (3, 39) => 0.0572248
+(0, 41) ~ (3, 40) => 0.556763
+(0, 42) ~ (3, 35) => 0.0563854
+(0, 42) ~ (3, 37) => 0.0673534
+(0, 42) ~ (3, 38) => 0.110734
+(0, 42) ~ (3, 39) => 0.0229042
+(0, 42) ~ (3, 40) => 0.0357203
+(0, 42) ~ (3, 41) => 0.360305
+(0, 43) ~ (3, 36) => 0.0588889
+(0, 43) ~ (3, 38) => 0.0604748
+(0, 43) ~ (3, 39) => 0.157368
+(0, 43) ~ (3, 40) => 0.0370634
+(0, 43) ~ (3, 41) => 0.0199648
+(0, 43) ~ (3, 42) => 0.161219
+(0, 44) ~ (3, 37) => 0.0629392
+(0, 44) ~ (3, 39) => 0.0344668
+(0, 44) ~ (3, 40) => 0.217001
+(0, 44) ~ (3, 41) => 0.0728361
+(0, 44) ~ (3, 42) => 0.0230368
+(0, 44) ~ (3, 43) => 0.0615437
+(0, 45) ~ (3, 38) => 0.065582
+(0, 45) ~ (3, 40) => 0.0132727
+(0, 45) ~ (3, 41) => 0.424589
+(0, 45) ~ (3, 42) => 0.0956251
+(0, 45) ~ (3, 44) => 0.0521909
+(0, 46) ~ (3, 39) => 0.0683149
+(0, 46) ~ (3, 41) => 0.0103489
+(0, 46) ~ (3, 42) => 0.607405
+(0, 46) ~ (3, 43) => 0.0793701
+(0, 46) ~ (3, 45) => 0.0409314
+(0, 47) ~ (3, 40) => 0.0592941
+(0, 47) ~ (3, 43) => 0.768465
+(0, 47) ~ (3, 44) => 0.059465
+(0, 47) ~ (3, 46) => 0.0361746
+(0, 48) ~ (3, 41) => 0.048867
+(0, 48) ~ (3, 44) => 0.813133
+(0, 48) ~ (3, 45) => 0.0197414
+(0, 48) ~ (3, 47) => 0.0310433
+(0, 49) ~ (3, 42) => 0.0437046
+(0, 49) ~ (3, 45) => 0.874886
+(0, 49) ~ (3, 48) => 0.0237211
+(0, 50) ~ (3, 43) => 0.0375795
+(0, 50) ~ (3, 46) => 0.900147
+(0, 50) ~ (3, 49) => 0.0160224
+(0, 51) ~ (3, 44) => 0.0216162
+(0, 51) ~ (3, 47) => 0.9279
+(0, 52) ~ (3, 45) => 0.0116906
+(0, 52) ~ (3, 47) => 0.0112825
+(0, 52) ~ (3, 48) => 0.946085
+(0, 53) ~ (3, 48) => 0.0128174
+(0, 53) ~ (3, 49) => 0.963231
+(0, 54) ~ (3, 49) => 0.015348
+(0, 54) ~ (3, 50) => 0.972575
+(0, 55) ~ (3, 50) => 0.0172364
+(0, 55) ~ (3, 51) => 0.973723
+(0, 56) ~ (3, 51) => 0.0160667
+(0, 56) ~ (3, 52) => 0.97698
+(0, 57) ~ (3, 52) => 0.0177774
+(0, 57) ~ (3, 53) => 0.976109
+(0, 58) ~ (3, 53) => 0.0190756
+(0, 58) ~ (3, 54) => 0.97426
+(0, 59) ~ (3, 54) => 0.0182465
+(0, 59) ~ (3, 55) => 0.977275
+(0, 60) ~ (3, 56) => 0.98739
+(0, 61) ~ (3, 57) => 0.993847
+(0, 62) ~ (3, 58) => 0.996528
+(0, 63) ~ (3, 59) => 0.997048
+(0, 64) ~ (3, 60) => 0.997148
+(0, 65) ~ (3, 61) => 0.998164
+(0, 66) ~ (3, 62) => 0.998541
+(0, 67) ~ (3, 63) => 0.997815
+(0, 68) ~ (3, 64) => 0.997719
+(0, 69) ~ (3, 65) => 0.998095
+(0, 70) ~ (3, 66) => 0.998485
+(0, 71) ~ (3, 67) => 0.998721
+(0, 72) ~ (3, 68) => 0.998798
+
+; gap posteriors
+(0, 0) ~ (3, -1) => 0.000132024
+(0, 1) ~ (3, -1) => 0.000445604
+(0, 2) ~ (3, -1) => 0.00066638
+(0, 3) ~ (3, -1) => 0.000764966
+(0, 4) ~ (3, -1) => 0.000720799
+(0, 5) ~ (3, -1) => 0.000475764
+(0, 6) ~ (3, -1) => 0.000415146
+(0, 7) ~ (3, -1) => 0.000428081
+(0, 8) ~ (3, -1) => 0.00068903
+(0, 9) ~ (3, -1) => 0.00104487
+(0, 10) ~ (3, -1) => 0.00174987
+(0, 11) ~ (3, -1) => 0.0027886
+(0, 12) ~ (3, -1) => 0.0036633
+(0, 13) ~ (3, -1) => 0.00448018
+(0, 14) ~ (3, -1) => 0.00652683
+(0, 15) ~ (3, -1) => 0.0116414
+(0, 16) ~ (3, -1) => 0.0235071
+(0, 17) ~ (3, -1) => 0.0712631
+(0, 18) ~ (3, -1) => 0.0971687
+(0, 19) ~ (3, -1) => 0.19567
+(0, 20) ~ (3, -1) => 0.092008
+(0, 21) ~ (3, -1) => 0.0632803
+(0, 22) ~ (3, -1) => 0.0655384
+(0, 23) ~ (3, -1) => 0.0482949
+(0, 24) ~ (3, -1) => 0.0875526
+(0, 25) ~ (3, -1) => 0.351522
+(0, 26) ~ (3, -1) => 0.190204
+(0, 27) ~ (3, -1) => 0.0449275
+(0, 28) ~ (3, -1) => 0.0226006
+(0, 29) ~ (3, -1) => 0.0143671
+(0, 30) ~ (3, -1) => 0.0160044
+(0, 31) ~ (3, -1) => 0.0344054
+(0, 32) ~ (3, -1) => 0.0464087
+(0, 33) ~ (3, -1) => 0.0865594
+(0, 34) ~ (3, -1) => 0.0991687
+(0, 35) ~ (3, -1) => 0.111979
+(0, 36) ~ (3, -1) => 0.210174
+(0, 37) ~ (3, -1) => 0.206701
+(0, 38) ~ (3, -1) => 0.230477
+(0, 39) ~ (3, -1) => 0.222917
+(0, 40) ~ (3, -1) => 0.206632
+(0, 41) ~ (3, -1) => 0.188877
+(0, 42) ~ (3, -1) => 0.346598
+(0, 43) ~ (3, -1) => 0.505021
+(0, 44) ~ (3, -1) => 0.528176
+(0, 45) ~ (3, -1) => 0.34874
+(0, 46) ~ (3, -1) => 0.19363
+(0, 47) ~ (3, -1) => 0.0766014
+(0, 48) ~ (3, -1) => 0.0872151
+(0, 49) ~ (3, -1) => 0.0576887
+(0, 50) ~ (3, -1) => 0.0462513
+(0, 51) ~ (3, -1) => 0.0504838
+(0, 52) ~ (3, -1) => 0.0309421
+(0, 53) ~ (3, -1) => 0.0239515
+(0, 54) ~ (3, -1) => 0.0120769
+(0, 55) ~ (3, -1) => 0.00904036
+(0, 56) ~ (3, -1) => 0.00695324
+(0, 57) ~ (3, -1) => 0.00611335
+(0, 58) ~ (3, -1) => 0.00666398
+(0, 59) ~ (3, -1) => 0.00447881
+(0, 60) ~ (3, -1) => 0.01261
+(0, 61) ~ (3, -1) => 0.00615257
+(0, 62) ~ (3, -1) => 0.00347233
+(0, 63) ~ (3, -1) => 0.0029515
+(0, 64) ~ (3, -1) => 0.00285226
+(0, 65) ~ (3, -1) => 0.00183558
+(0, 66) ~ (3, -1) => 0.00145894
+(0, 67) ~ (3, -1) => 0.00218451
+(0, 68) ~ (3, -1) => 0.00228107
+(0, 69) ~ (3, -1) => 0.0019049
+(0, 70) ~ (3, -1) => 0.00151461
+(0, 71) ~ (3, -1) => 0.00127912
+(0, 72) ~ (3, -1) => 0.00120163
+
+(0, -1) ~ (3, 0) => 0.000132024
+(0, -1) ~ (3, 1) => 0.000445604
+(0, -1) ~ (3, 2) => 0.00066638
+(0, -1) ~ (3, 3) => 0.000764966
+(0, -1) ~ (3, 4) => 0.000720799
+(0, -1) ~ (3, 5) => 0.000475764
+(0, -1) ~ (3, 6) => 0.000415146
+(0, -1) ~ (3, 7) => 0.000428081
+(0, -1) ~ (3, 8) => 0.00068903
+(0, -1) ~ (3, 9) => 0.00104487
+(0, -1) ~ (3, 10) => 0.00174987
+(0, -1) ~ (3, 11) => 0.0027886
+(0, -1) ~ (3, 12) => 0.0036633
+(0, -1) ~ (3, 13) => 0.00448018
+(0, -1) ~ (3, 14) => 0.00652683
+(0, -1) ~ (3, 15) => 0.0116414
+(0, -1) ~ (3, 16) => 0.0235071
+(0, -1) ~ (3, 17) => 0.0132422
+(0, -1) ~ (3, 18) => 0.0251746
+(0, -1) ~ (3, 19) => 0.0151578
+(0, -1) ~ (3, 20) => 0.0175357
+(0, -1) ~ (3, 21) => 0.0301902
+(0, -1) ~ (3, 22) => 0.0413084
+(0, -1) ~ (3, 23) => 0.0369834
+(0, -1) ~ (3, 24) => 0.0452749
+(0, -1) ~ (3, 25) => 0.116903
+(0, -1) ~ (3, 26) => 0.0334428
+(0, -1) ~ (3, 27) => 0.0110505
+(0, -1) ~ (3, 28) => 0.00947493
+(0, -1) ~ (3, 29) => 0.00960221
+(0, -1) ~ (3, 30) => 0.0131282
+(0, -1) ~ (3, 31) => 0.0239097
+(0, -1) ~ (3, 32) => 0.0312681
+(0, -1) ~ (3, 33) => 0.0449728
+(0, -1) ~ (3, 34) => 0.050374
+(0, -1) ~ (3, 35) => 0.0333168
+(0, -1) ~ (3, 36) => 0.0375886
+(0, -1) ~ (3, 37) => 0.0356192
+(0, -1) ~ (3, 38) => 0.0443555
+(0, -1) ~ (3, 39) => 0.0761793
+(0, -1) ~ (3, 40) => 0.0808852
+(0, -1) ~ (3, 41) => 0.0630895
+(0, -1) ~ (3, 42) => 0.0690095
+(0, -1) ~ (3, 43) => 0.0530418
+(0, -1) ~ (3, 44) => 0.0535947
+(0, -1) ~ (3, 45) => 0.0527511
+(0, -1) ~ (3, 46) => 0.0636786
+(0, -1) ~ (3, 47) => 0.0297743
+(0, -1) ~ (3, 48) => 0.0173768
+(0, -1) ~ (3, 49) => 0.00539852
+(0, -1) ~ (3, 50) => 0.0101885
+(0, -1) ~ (3, 51) => 0.0102101
+(0, -1) ~ (3, 52) => 0.00524251
+(0, -1) ~ (3, 53) => 0.00481516
+(0, -1) ~ (3, 54) => 0.00749309
+(0, -1) ~ (3, 55) => 0.0227253
+(0, -1) ~ (3, 56) => 0.01261
+(0, -1) ~ (3, 57) => 0.00615257
+(0, -1) ~ (3, 58) => 0.00347233
+(0, -1) ~ (3, 59) => 0.0029515
+(0, -1) ~ (3, 60) => 0.00285226
+(0, -1) ~ (3, 61) => 0.00183558
+(0, -1) ~ (3, 62) => 0.00145894
+(0, -1) ~ (3, 63) => 0.00218451
+(0, -1) ~ (3, 64) => 0.00228107
+(0, -1) ~ (3, 65) => 0.0019049
+(0, -1) ~ (3, 66) => 0.00151461
+(0, -1) ~ (3, 67) => 0.00127912
+(0, -1) ~ (3, 68) => 0.00120163
+
+; Sparse posterior probability matrix for sequences 0 and 4
+; Format is:
+; (0, position_1) ~ (4, position_2) => prob
+; which means that (0, position_1) is aligned to (4, position_2) with probability prob.
+; (0, position_1) ~ (4, -1) => prob
+; means that (0, position_1) is aligned to a gap in 4 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(0, 0) ~ (4, 0) => 0.999514
+(0, 1) ~ (4, 1) => 0.998516
+(0, 2) ~ (4, 2) => 0.997281
+(0, 3) ~ (4, 3) => 0.995841
+(0, 4) ~ (4, 4) => 0.994201
+(0, 5) ~ (4, 5) => 0.993769
+(0, 6) ~ (4, 6) => 0.993297
+(0, 7) ~ (4, 7) => 0.992672
+(0, 8) ~ (4, 8) => 0.992009
+(0, 9) ~ (4, 9) => 0.990084
+(0, 10) ~ (4, 10) => 0.985447
+(0, 11) ~ (4, 11) => 0.98106
+(0, 12) ~ (4, 12) => 0.975757
+(0, 13) ~ (4, 13) => 0.958052
+(0, 14) ~ (4, 14) => 0.93861
+(0, 14) ~ (4, 15) => 0.0147639
+(0, 15) ~ (4, 14) => 0.0126409
+(0, 15) ~ (4, 15) => 0.912625
+(0, 15) ~ (4, 16) => 0.0257896
+(0, 16) ~ (4, 15) => 0.0185846
+(0, 16) ~ (4, 16) => 0.894391
+(0, 16) ~ (4, 17) => 0.0308256
+(0, 17) ~ (4, 16) => 0.0242979
+(0, 17) ~ (4, 17) => 0.857031
+(0, 17) ~ (4, 18) => 0.0570543
+(0, 18) ~ (4, 17) => 0.0281106
+(0, 18) ~ (4, 18) => 0.791574
+(0, 18) ~ (4, 19) => 0.100693
+(0, 19) ~ (4, 18) => 0.0298682
+(0, 19) ~ (4, 19) => 0.728809
+(0, 19) ~ (4, 20) => 0.145172
+(0, 19) ~ (4, 21) => 0.0101754
+(0, 20) ~ (4, 17) => 0.0109799
+(0, 20) ~ (4, 19) => 0.0332834
+(0, 20) ~ (4, 20) => 0.696943
+(0, 20) ~ (4, 21) => 0.166937
+(0, 21) ~ (4, 18) => 0.0174621
+(0, 21) ~ (4, 20) => 0.0345769
+(0, 21) ~ (4, 21) => 0.618242
+(0, 21) ~ (4, 22) => 0.235162
+(0, 22) ~ (4, 19) => 0.0239593
+(0, 22) ~ (4, 20) => 0.0101096
+(0, 22) ~ (4, 21) => 0.0329467
+(0, 22) ~ (4, 22) => 0.588253
+(0, 22) ~ (4, 23) => 0.26687
+(0, 23) ~ (4, 18) => 0.0128343
+(0, 23) ~ (4, 20) => 0.0289404
+(0, 23) ~ (4, 22) => 0.0314561
+(0, 23) ~ (4, 23) => 0.559074
+(0, 23) ~ (4, 24) => 0.298491
+(0, 24) ~ (4, 19) => 0.0182627
+(0, 24) ~ (4, 21) => 0.0336418
+(0, 24) ~ (4, 22) => 0.0110812
+(0, 24) ~ (4, 23) => 0.03092
+(0, 24) ~ (4, 24) => 0.541415
+(0, 24) ~ (4, 25) => 0.315487
+(0, 25) ~ (4, 20) => 0.0202519
+(0, 25) ~ (4, 22) => 0.0331185
+(0, 25) ~ (4, 23) => 0.0107767
+(0, 25) ~ (4, 24) => 0.0274971
+(0, 25) ~ (4, 25) => 0.53752
+(0, 25) ~ (4, 26) => 0.318873
+(0, 26) ~ (4, 21) => 0.0213842
+(0, 26) ~ (4, 23) => 0.0324301
+(0, 26) ~ (4, 25) => 0.0268448
+(0, 26) ~ (4, 26) => 0.536632
+(0, 26) ~ (4, 27) => 0.324565
+(0, 27) ~ (4, 21) => 0.0104048
+(0, 27) ~ (4, 22) => 0.0203407
+(0, 27) ~ (4, 24) => 0.0295516
+(0, 27) ~ (4, 26) => 0.0226638
+(0, 27) ~ (4, 27) => 0.520972
+(0, 27) ~ (4, 28) => 0.343537
+(0, 27) ~ (4, 29) => 0.0114994
+(0, 28) ~ (4, 22) => 0.0129635
+(0, 28) ~ (4, 23) => 0.0188873
+(0, 28) ~ (4, 25) => 0.0278172
+(0, 28) ~ (4, 27) => 0.01552
+(0, 28) ~ (4, 28) => 0.509783
+(0, 28) ~ (4, 29) => 0.368894
+(0, 28) ~ (4, 30) => 0.013488
+(0, 29) ~ (4, 23) => 0.0142972
+(0, 29) ~ (4, 24) => 0.0162591
+(0, 29) ~ (4, 26) => 0.0239518
+(0, 29) ~ (4, 28) => 0.0119455
+(0, 29) ~ (4, 29) => 0.512726
+(0, 29) ~ (4, 30) => 0.379499
+(0, 29) ~ (4, 31) => 0.0141546
+(0, 30) ~ (4, 24) => 0.0152735
+(0, 30) ~ (4, 25) => 0.0153808
+(0, 30) ~ (4, 27) => 0.0193743
+(0, 30) ~ (4, 29) => 0.0113134
+(0, 30) ~ (4, 30) => 0.512265
+(0, 30) ~ (4, 31) => 0.386834
+(0, 30) ~ (4, 32) => 0.0144186
+(0, 31) ~ (4, 25) => 0.0173578
+(0, 31) ~ (4, 26) => 0.0140679
+(0, 31) ~ (4, 28) => 0.0179109
+(0, 31) ~ (4, 31) => 0.508472
+(0, 31) ~ (4, 32) => 0.391715
+(0, 31) ~ (4, 33) => 0.0138223
+(0, 32) ~ (4, 26) => 0.0184863
+(0, 32) ~ (4, 27) => 0.0120909
+(0, 32) ~ (4, 29) => 0.0183136
+(0, 32) ~ (4, 32) => 0.502458
+(0, 32) ~ (4, 33) => 0.394539
+(0, 32) ~ (4, 34) => 0.0129449
+(0, 33) ~ (4, 27) => 0.0195599
+(0, 33) ~ (4, 28) => 0.0118155
+(0, 33) ~ (4, 30) => 0.0179152
+(0, 33) ~ (4, 33) => 0.490753
+(0, 33) ~ (4, 34) => 0.395656
+(0, 33) ~ (4, 35) => 0.0148373
+(0, 34) ~ (4, 28) => 0.0190948
+(0, 34) ~ (4, 29) => 0.0103769
+(0, 34) ~ (4, 31) => 0.0176846
+(0, 34) ~ (4, 34) => 0.476603
+(0, 34) ~ (4, 35) => 0.391058
+(0, 34) ~ (4, 36) => 0.0153786
+(0, 35) ~ (4, 29) => 0.017431
+(0, 35) ~ (4, 30) => 0.0101261
+(0, 35) ~ (4, 31) => 0.010376
+(0, 35) ~ (4, 32) => 0.0197472
+(0, 35) ~ (4, 33) => 0.0131514
+(0, 35) ~ (4, 34) => 0.0105301
+(0, 35) ~ (4, 35) => 0.438519
+(0, 35) ~ (4, 36) => 0.358745
+(0, 35) ~ (4, 37) => 0.0167357
+(0, 36) ~ (4, 30) => 0.0152305
+(0, 36) ~ (4, 31) => 0.010468
+(0, 36) ~ (4, 32) => 0.0126431
+(0, 36) ~ (4, 33) => 0.0209446
+(0, 36) ~ (4, 34) => 0.0195897
+(0, 36) ~ (4, 35) => 0.017062
+(0, 36) ~ (4, 36) => 0.417176
+(0, 36) ~ (4, 37) => 0.332704
+(0, 36) ~ (4, 38) => 0.0170539
+(0, 37) ~ (4, 31) => 0.0117718
+(0, 37) ~ (4, 32) => 0.0112397
+(0, 37) ~ (4, 33) => 0.0166754
+(0, 37) ~ (4, 34) => 0.0198598
+(0, 37) ~ (4, 35) => 0.0477904
+(0, 37) ~ (4, 36) => 0.0281445
+(0, 37) ~ (4, 37) => 0.393131
+(0, 37) ~ (4, 38) => 0.305903
+(0, 37) ~ (4, 39) => 0.0168858
+(0, 38) ~ (4, 33) => 0.0124444
+(0, 38) ~ (4, 34) => 0.0182892
+(0, 38) ~ (4, 35) => 0.023384
+(0, 38) ~ (4, 36) => 0.0950097
+(0, 38) ~ (4, 37) => 0.0361916
+(0, 38) ~ (4, 38) => 0.367469
+(0, 38) ~ (4, 39) => 0.278029
+(0, 38) ~ (4, 40) => 0.0157316
+(0, 39) ~ (4, 34) => 0.0124835
+(0, 39) ~ (4, 35) => 0.01799
+(0, 39) ~ (4, 36) => 0.0214553
+(0, 39) ~ (4, 37) => 0.141615
+(0, 39) ~ (4, 38) => 0.0441001
+(0, 39) ~ (4, 39) => 0.342546
+(0, 39) ~ (4, 40) => 0.245489
+(0, 39) ~ (4, 41) => 0.0134022
+(0, 40) ~ (4, 35) => 0.0115237
+(0, 40) ~ (4, 36) => 0.0147978
+(0, 40) ~ (4, 37) => 0.0191242
+(0, 40) ~ (4, 38) => 0.194733
+(0, 40) ~ (4, 39) => 0.0516583
+(0, 40) ~ (4, 40) => 0.312011
+(0, 40) ~ (4, 41) => 0.211869
+(0, 40) ~ (4, 42) => 0.0108932
+(0, 41) ~ (4, 37) => 0.0114752
+(0, 41) ~ (4, 38) => 0.0164653
+(0, 41) ~ (4, 39) => 0.252944
+(0, 41) ~ (4, 40) => 0.0575781
+(0, 41) ~ (4, 41) => 0.280072
+(0, 41) ~ (4, 42) => 0.180025
+(0, 42) ~ (4, 39) => 0.0135825
+(0, 42) ~ (4, 40) => 0.325667
+(0, 42) ~ (4, 41) => 0.0643341
+(0, 42) ~ (4, 42) => 0.256768
+(0, 42) ~ (4, 43) => 0.154878
+(0, 43) ~ (4, 40) => 0.0123884
+(0, 43) ~ (4, 41) => 0.394095
+(0, 43) ~ (4, 42) => 0.0690658
+(0, 43) ~ (4, 43) => 0.232745
+(0, 43) ~ (4, 44) => 0.130116
+(0, 44) ~ (4, 41) => 0.0106287
+(0, 44) ~ (4, 42) => 0.452426
+(0, 44) ~ (4, 43) => 0.0709358
+(0, 44) ~ (4, 44) => 0.206051
+(0, 44) ~ (4, 45) => 0.0984956
+(0, 45) ~ (4, 43) => 0.507375
+(0, 45) ~ (4, 44) => 0.0718677
+(0, 45) ~ (4, 45) => 0.172093
+(0, 45) ~ (4, 46) => 0.0927931
+(0, 46) ~ (4, 44) => 0.564698
+(0, 46) ~ (4, 45) => 0.0694848
+(0, 46) ~ (4, 46) => 0.166909
+(0, 46) ~ (4, 47) => 0.0913847
+(0, 47) ~ (4, 45) => 0.637546
+(0, 47) ~ (4, 46) => 0.0648203
+(0, 47) ~ (4, 47) => 0.153889
+(0, 47) ~ (4, 48) => 0.0820016
+(0, 48) ~ (4, 46) => 0.654355
+(0, 48) ~ (4, 47) => 0.0454965
+(0, 48) ~ (4, 48) => 0.0825864
+(0, 48) ~ (4, 49) => 0.0714093
+(0, 49) ~ (4, 47) => 0.689994
+(0, 49) ~ (4, 48) => 0.0132113
+(0, 49) ~ (4, 49) => 0.0595504
+(0, 49) ~ (4, 50) => 0.0713961
+(0, 50) ~ (4, 48) => 0.806874
+(0, 50) ~ (4, 50) => 0.0355284
+(0, 50) ~ (4, 51) => 0.0704155
+(0, 51) ~ (4, 49) => 0.849007
+(0, 51) ~ (4, 51) => 0.0251387
+(0, 51) ~ (4, 52) => 0.0660731
+(0, 52) ~ (4, 50) => 0.876333
+(0, 52) ~ (4, 52) => 0.0229833
+(0, 52) ~ (4, 53) => 0.0447138
+(0, 53) ~ (4, 51) => 0.89111
+(0, 53) ~ (4, 54) => 0.0355685
+(0, 54) ~ (4, 52) => 0.898423
+(0, 54) ~ (4, 55) => 0.0284183
+(0, 55) ~ (4, 53) => 0.934729
+(0, 55) ~ (4, 56) => 0.0228447
+(0, 56) ~ (4, 54) => 0.949109
+(0, 56) ~ (4, 57) => 0.0111105
+(0, 57) ~ (4, 55) => 0.959562
+(0, 58) ~ (4, 56) => 0.965689
+(0, 59) ~ (4, 57) => 0.978606
+(0, 60) ~ (4, 58) => 0.985098
+(0, 61) ~ (4, 59) => 0.988442
+(0, 62) ~ (4, 60) => 0.990037
+(0, 63) ~ (4, 61) => 0.990973
+(0, 64) ~ (4, 62) => 0.994206
+(0, 65) ~ (4, 63) => 0.996555
+(0, 66) ~ (4, 64) => 0.997557
+(0, 67) ~ (4, 65) => 0.997882
+(0, 68) ~ (4, 66) => 0.99823
+(0, 69) ~ (4, 67) => 0.998604
+(0, 70) ~ (4, 68) => 0.999028
+(0, 71) ~ (4, 69) => 0.999454
+(0, 72) ~ (4, 70) => 0.999603
+
+; gap posteriors
+(0, 0) ~ (4, -1) => 0.000485778
+(0, 1) ~ (4, -1) => 0.00148392
+(0, 2) ~ (4, -1) => 0.00271869
+(0, 3) ~ (4, -1) => 0.00415862
+(0, 4) ~ (4, -1) => 0.0057987
+(0, 5) ~ (4, -1) => 0.00623131
+(0, 6) ~ (4, -1) => 0.00670302
+(0, 7) ~ (4, -1) => 0.00732833
+(0, 8) ~ (4, -1) => 0.00799137
+(0, 9) ~ (4, -1) => 0.00991583
+(0, 10) ~ (4, -1) => 0.0145533
+(0, 11) ~ (4, -1) => 0.0189404
+(0, 12) ~ (4, -1) => 0.0242434
+(0, 13) ~ (4, -1) => 0.0419483
+(0, 14) ~ (4, -1) => 0.0466256
+(0, 15) ~ (4, -1) => 0.0489447
+(0, 16) ~ (4, -1) => 0.0561989
+(0, 17) ~ (4, -1) => 0.0616167
+(0, 18) ~ (4, -1) => 0.0796226
+(0, 19) ~ (4, -1) => 0.0859755
+(0, 20) ~ (4, -1) => 0.0918564
+(0, 21) ~ (4, -1) => 0.0945573
+(0, 22) ~ (4, -1) => 0.0778609
+(0, 23) ~ (4, -1) => 0.0692046
+(0, 24) ~ (4, -1) => 0.0491916
+(0, 25) ~ (4, -1) => 0.0519622
+(0, 26) ~ (4, -1) => 0.0581443
+(0, 27) ~ (4, -1) => 0.0410307
+(0, 28) ~ (4, -1) => 0.0326463
+(0, 29) ~ (4, -1) => 0.0271674
+(0, 30) ~ (4, -1) => 0.0251403
+(0, 31) ~ (4, -1) => 0.0366544
+(0, 32) ~ (4, -1) => 0.0411676
+(0, 33) ~ (4, -1) => 0.0494631
+(0, 34) ~ (4, -1) => 0.0698045
+(0, 35) ~ (4, -1) => 0.104638
+(0, 36) ~ (4, -1) => 0.137128
+(0, 37) ~ (4, -1) => 0.148598
+(0, 38) ~ (4, -1) => 0.153452
+(0, 39) ~ (4, -1) => 0.160919
+(0, 40) ~ (4, -1) => 0.173389
+(0, 41) ~ (4, -1) => 0.20144
+(0, 42) ~ (4, -1) => 0.18477
+(0, 43) ~ (4, -1) => 0.161589
+(0, 44) ~ (4, -1) => 0.161462
+(0, 45) ~ (4, -1) => 0.155872
+(0, 46) ~ (4, -1) => 0.107523
+(0, 47) ~ (4, -1) => 0.0617432
+(0, 48) ~ (4, -1) => 0.146152
+(0, 49) ~ (4, -1) => 0.165848
+(0, 50) ~ (4, -1) => 0.0871824
+(0, 51) ~ (4, -1) => 0.0597811
+(0, 52) ~ (4, -1) => 0.0559696
+(0, 53) ~ (4, -1) => 0.0733211
+(0, 54) ~ (4, -1) => 0.0731589
+(0, 55) ~ (4, -1) => 0.0424263
+(0, 56) ~ (4, -1) => 0.03978
+(0, 57) ~ (4, -1) => 0.0404378
+(0, 58) ~ (4, -1) => 0.0343113
+(0, 59) ~ (4, -1) => 0.0213943
+(0, 60) ~ (4, -1) => 0.0149022
+(0, 61) ~ (4, -1) => 0.011558
+(0, 62) ~ (4, -1) => 0.00996262
+(0, 63) ~ (4, -1) => 0.00902694
+(0, 64) ~ (4, -1) => 0.00579423
+(0, 65) ~ (4, -1) => 0.00344515
+(0, 66) ~ (4, -1) => 0.00244266
+(0, 67) ~ (4, -1) => 0.00211805
+(0, 68) ~ (4, -1) => 0.00176966
+(0, 69) ~ (4, -1) => 0.00139618
+(0, 70) ~ (4, -1) => 0.00097239
+(0, 71) ~ (4, -1) => 0.000545561
+(0, 72) ~ (4, -1) => 0.000396788
+
+(0, -1) ~ (4, 0) => 0.000485778
+(0, -1) ~ (4, 1) => 0.00148392
+(0, -1) ~ (4, 2) => 0.00271869
+(0, -1) ~ (4, 3) => 0.00415862
+(0, -1) ~ (4, 4) => 0.0057987
+(0, -1) ~ (4, 5) => 0.00623131
+(0, -1) ~ (4, 6) => 0.00670302
+(0, -1) ~ (4, 7) => 0.00732833
+(0, -1) ~ (4, 8) => 0.00799137
+(0, -1) ~ (4, 9) => 0.00991583
+(0, -1) ~ (4, 10) => 0.0145533
+(0, -1) ~ (4, 11) => 0.0189404
+(0, -1) ~ (4, 12) => 0.0242434
+(0, -1) ~ (4, 13) => 0.0419483
+(0, -1) ~ (4, 14) => 0.0487487
+(0, -1) ~ (4, 15) => 0.0540268
+(0, -1) ~ (4, 16) => 0.0555215
+(0, -1) ~ (4, 17) => 0.0730528
+(0, -1) ~ (4, 18) => 0.0912071
+(0, -1) ~ (4, 19) => 0.0949929
+(0, -1) ~ (4, 20) => 0.0640061
+(0, -1) ~ (4, 21) => 0.106268
+(0, -1) ~ (4, 22) => 0.0676255
+(0, -1) ~ (4, 23) => 0.0667446
+(0, -1) ~ (4, 24) => 0.0715125
+(0, -1) ~ (4, 25) => 0.0595916
+(0, -1) ~ (4, 26) => 0.0653252
+(0, -1) ~ (4, 27) => 0.087918
+(0, -1) ~ (4, 28) => 0.085913
+(0, -1) ~ (4, 29) => 0.0494456
+(0, -1) ~ (4, 30) => 0.0514761
+(0, -1) ~ (4, 31) => 0.040239
+(0, -1) ~ (4, 32) => 0.0477791
+(0, -1) ~ (4, 33) => 0.0376703
+(0, -1) ~ (4, 34) => 0.0340439
+(0, -1) ~ (4, 35) => 0.0378354
+(0, -1) ~ (4, 36) => 0.0492928
+(0, -1) ~ (4, 37) => 0.0490222
+(0, -1) ~ (4, 38) => 0.0542755
+(0, -1) ~ (4, 39) => 0.0443546
+(0, -1) ~ (4, 40) => 0.0311347
+(0, -1) ~ (4, 41) => 0.0255986
+(0, -1) ~ (4, 42) => 0.0308209
+(0, -1) ~ (4, 43) => 0.0340663
+(0, -1) ~ (4, 44) => 0.0272668
+(0, -1) ~ (4, 45) => 0.0223807
+(0, -1) ~ (4, 46) => 0.021122
+(0, -1) ~ (4, 47) => 0.0192357
+(0, -1) ~ (4, 48) => 0.015327
+(0, -1) ~ (4, 49) => 0.0200332
+(0, -1) ~ (4, 50) => 0.0167421
+(0, -1) ~ (4, 51) => 0.0133354
+(0, -1) ~ (4, 52) => 0.0125208
+(0, -1) ~ (4, 53) => 0.0205573
+(0, -1) ~ (4, 54) => 0.015322
+(0, -1) ~ (4, 55) => 0.0120195
+(0, -1) ~ (4, 56) => 0.0114666
+(0, -1) ~ (4, 57) => 0.0102838
+(0, -1) ~ (4, 58) => 0.0149022
+(0, -1) ~ (4, 59) => 0.011558
+(0, -1) ~ (4, 60) => 0.00996262
+(0, -1) ~ (4, 61) => 0.00902694
+(0, -1) ~ (4, 62) => 0.00579423
+(0, -1) ~ (4, 63) => 0.00344515
+(0, -1) ~ (4, 64) => 0.00244266
+(0, -1) ~ (4, 65) => 0.00211805
+(0, -1) ~ (4, 66) => 0.00176966
+(0, -1) ~ (4, 67) => 0.00139618
+(0, -1) ~ (4, 68) => 0.00097239
+(0, -1) ~ (4, 69) => 0.000545561
+(0, -1) ~ (4, 70) => 0.000396788
+
+; Sparse posterior probability matrix for sequences 1 and 2
+; Format is:
+; (1, position_1) ~ (2, position_2) => prob
+; which means that (1, position_1) is aligned to (2, position_2) with probability prob.
+; (1, position_1) ~ (2, -1) => prob
+; means that (1, position_1) is aligned to a gap in 2 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (2, 0) => 0.999094
+(1, 1) ~ (2, 1) => 0.997448
+(1, 2) ~ (2, 2) => 0.986767
+(1, 3) ~ (2, 3) => 0.978374
+(1, 4) ~ (2, 4) => 0.972173
+(1, 5) ~ (2, 5) => 0.964819
+(1, 6) ~ (2, 6) => 0.95891
+(1, 7) ~ (2, 7) => 0.955012
+(1, 8) ~ (2, 8) => 0.95247
+(1, 9) ~ (2, 9) => 0.951644
+(1, 10) ~ (2, 10) => 0.943464
+(1, 11) ~ (2, 11) => 0.782914
+(1, 12) ~ (2, 12) => 0.623542
+(1, 13) ~ (2, 10) => 0.0112665
+(1, 13) ~ (2, 13) => 0.565875
+(1, 14) ~ (2, 11) => 0.139013
+(1, 14) ~ (2, 12) => 0.0175483
+(1, 14) ~ (2, 14) => 0.54091
+(1, 15) ~ (2, 12) => 0.268444
+(1, 15) ~ (2, 13) => 0.0187597
+(1, 15) ~ (2, 15) => 0.502274
+(1, 16) ~ (2, 13) => 0.314698
+(1, 16) ~ (2, 14) => 0.0140877
+(1, 16) ~ (2, 16) => 0.460893
+(1, 16) ~ (2, 17) => 0.0108112
+(1, 17) ~ (2, 14) => 0.343784
+(1, 17) ~ (2, 17) => 0.430631
+(1, 18) ~ (2, 15) => 0.366036
+(1, 18) ~ (2, 18) => 0.29449
+(1, 19) ~ (2, 16) => 0.381954
+(1, 19) ~ (2, 19) => 0.163511
+(1, 20) ~ (2, 17) => 0.38833
+(1, 20) ~ (2, 19) => 0.0138335
+(1, 20) ~ (2, 20) => 0.0530408
+(1, 21) ~ (2, 12) => 0.0134113
+(1, 21) ~ (2, 14) => 0.0102321
+(1, 21) ~ (2, 18) => 0.480316
+(1, 21) ~ (2, 20) => 0.0148497
+(1, 21) ~ (2, 21) => 0.0205532
+(1, 22) ~ (2, 13) => 0.0258397
+(1, 22) ~ (2, 15) => 0.0174053
+(1, 22) ~ (2, 16) => 0.0245665
+(1, 22) ~ (2, 19) => 0.57662
+(1, 22) ~ (2, 21) => 0.0182654
+(1, 22) ~ (2, 22) => 0.0182623
+(1, 23) ~ (2, 14) => 0.0349297
+(1, 23) ~ (2, 16) => 0.0145924
+(1, 23) ~ (2, 17) => 0.0414316
+(1, 23) ~ (2, 20) => 0.661132
+(1, 23) ~ (2, 22) => 0.012064
+(1, 23) ~ (2, 23) => 0.0160862
+(1, 24) ~ (2, 15) => 0.0390256
+(1, 24) ~ (2, 17) => 0.0127681
+(1, 24) ~ (2, 18) => 0.050498
+(1, 24) ~ (2, 19) => 0.0149119
+(1, 24) ~ (2, 21) => 0.657612
+(1, 24) ~ (2, 24) => 0.0143432
+(1, 25) ~ (2, 16) => 0.0340814
+(1, 25) ~ (2, 18) => 0.0123949
+(1, 25) ~ (2, 19) => 0.058215
+(1, 25) ~ (2, 20) => 0.0186699
+(1, 25) ~ (2, 22) => 0.58866
+(1, 25) ~ (2, 23) => 0.0109872
+(1, 26) ~ (2, 16) => 0.0135688
+(1, 26) ~ (2, 17) => 0.0333154
+(1, 26) ~ (2, 19) => 0.0111839
+(1, 26) ~ (2, 20) => 0.0655114
+(1, 26) ~ (2, 21) => 0.0272406
+(1, 26) ~ (2, 23) => 0.527228
+(1, 26) ~ (2, 24) => 0.0138852
+(1, 27) ~ (2, 15) => 0.0109047
+(1, 27) ~ (2, 17) => 0.0219079
+(1, 27) ~ (2, 18) => 0.0345236
+(1, 27) ~ (2, 21) => 0.0698108
+(1, 27) ~ (2, 22) => 0.022402
+(1, 27) ~ (2, 24) => 0.459169
+(1, 28) ~ (2, 16) => 0.010307
+(1, 28) ~ (2, 18) => 0.0369566
+(1, 28) ~ (2, 19) => 0.0349588
+(1, 28) ~ (2, 22) => 0.048518
+(1, 28) ~ (2, 23) => 0.0140514
+(1, 28) ~ (2, 25) => 0.11556
+(1, 29) ~ (2, 17) => 0.0110613
+(1, 29) ~ (2, 19) => 0.0530166
+(1, 29) ~ (2, 20) => 0.0350594
+(1, 29) ~ (2, 23) => 0.0263944
+(1, 29) ~ (2, 25) => 0.0119736
+(1, 29) ~ (2, 26) => 0.0670001
+(1, 30) ~ (2, 20) => 0.0739915
+(1, 30) ~ (2, 21) => 0.011643
+(1, 30) ~ (2, 27) => 0.0129328
+(1, 31) ~ (2, 21) => 0.135111
+(1, 31) ~ (2, 22) => 0.0115332
+(1, 31) ~ (2, 23) => 0.011898
+(1, 32) ~ (2, 22) => 0.22652
+(1, 32) ~ (2, 24) => 0.0121469
+(1, 33) ~ (2, 23) => 0.3225
+(1, 33) ~ (2, 25) => 0.0126822
+(1, 34) ~ (2, 24) => 0.449264
+(1, 35) ~ (2, 25) => 0.81488
+(1, 36) ~ (2, 25) => 0.0113769
+(1, 36) ~ (2, 26) => 0.888401
+(1, 37) ~ (2, 26) => 0.0113593
+(1, 37) ~ (2, 27) => 0.939763
+(1, 38) ~ (2, 27) => 0.0152703
+(1, 38) ~ (2, 28) => 0.938306
+(1, 39) ~ (2, 28) => 0.0202989
+(1, 39) ~ (2, 29) => 0.941099
+(1, 40) ~ (2, 29) => 0.0186615
+(1, 40) ~ (2, 30) => 0.947784
+(1, 41) ~ (2, 30) => 0.0164206
+(1, 41) ~ (2, 31) => 0.952835
+(1, 42) ~ (2, 31) => 0.015842
+(1, 42) ~ (2, 32) => 0.952413
+(1, 43) ~ (2, 32) => 0.0129773
+(1, 43) ~ (2, 33) => 0.954789
+(1, 44) ~ (2, 33) => 0.0101037
+(1, 44) ~ (2, 34) => 0.958371
+(1, 45) ~ (2, 35) => 0.959456
+(1, 46) ~ (2, 36) => 0.965329
+(1, 46) ~ (2, 37) => 0.0111856
+(1, 47) ~ (2, 37) => 0.964527
+(1, 47) ~ (2, 38) => 0.015778
+(1, 48) ~ (2, 38) => 0.944404
+(1, 48) ~ (2, 39) => 0.0345369
+(1, 49) ~ (2, 39) => 0.897005
+(1, 49) ~ (2, 40) => 0.0749715
+(1, 50) ~ (2, 40) => 0.831309
+(1, 50) ~ (2, 41) => 0.130936
+(1, 51) ~ (2, 41) => 0.798738
+(1, 51) ~ (2, 42) => 0.154102
+(1, 52) ~ (2, 41) => 0.0132142
+(1, 52) ~ (2, 42) => 0.725309
+(1, 52) ~ (2, 43) => 0.209116
+(1, 53) ~ (2, 42) => 0.0150667
+(1, 53) ~ (2, 43) => 0.655637
+(1, 53) ~ (2, 44) => 0.265498
+(1, 54) ~ (2, 43) => 0.015162
+(1, 54) ~ (2, 44) => 0.589069
+(1, 54) ~ (2, 45) => 0.322512
+(1, 55) ~ (2, 44) => 0.0140719
+(1, 55) ~ (2, 45) => 0.524877
+(1, 55) ~ (2, 46) => 0.380721
+(1, 55) ~ (2, 51) => 0.0100137
+(1, 56) ~ (2, 45) => 0.0137075
+(1, 56) ~ (2, 46) => 0.500871
+(1, 56) ~ (2, 47) => 0.384918
+(1, 56) ~ (2, 52) => 0.0103494
+(1, 57) ~ (2, 45) => 0.0100424
+(1, 57) ~ (2, 46) => 0.0112021
+(1, 57) ~ (2, 47) => 0.509806
+(1, 57) ~ (2, 48) => 0.366433
+(1, 58) ~ (2, 44) => 0.0105319
+(1, 58) ~ (2, 47) => 0.015009
+(1, 58) ~ (2, 48) => 0.536204
+(1, 58) ~ (2, 49) => 0.346334
+(1, 59) ~ (2, 45) => 0.0123206
+(1, 59) ~ (2, 48) => 0.0156557
+(1, 59) ~ (2, 49) => 0.565172
+(1, 59) ~ (2, 50) => 0.324536
+(1, 60) ~ (2, 46) => 0.0144696
+(1, 60) ~ (2, 49) => 0.0164832
+(1, 60) ~ (2, 50) => 0.591594
+(1, 60) ~ (2, 51) => 0.306718
+(1, 61) ~ (2, 47) => 0.0122717
+(1, 61) ~ (2, 50) => 0.0177466
+(1, 61) ~ (2, 51) => 0.616943
+(1, 61) ~ (2, 52) => 0.282094
+(1, 62) ~ (2, 48) => 0.0114546
+(1, 62) ~ (2, 51) => 0.0197631
+(1, 62) ~ (2, 52) => 0.63336
+(1, 62) ~ (2, 53) => 0.260882
+(1, 62) ~ (2, 54) => 0.0103619
+(1, 63) ~ (2, 49) => 0.0104938
+(1, 63) ~ (2, 52) => 0.0170966
+(1, 63) ~ (2, 53) => 0.654907
+(1, 63) ~ (2, 54) => 0.215816
+(1, 63) ~ (2, 55) => 0.0109924
+(1, 64) ~ (2, 50) => 0.0100197
+(1, 64) ~ (2, 53) => 0.0170993
+(1, 64) ~ (2, 54) => 0.703137
+(1, 64) ~ (2, 55) => 0.201086
+(1, 64) ~ (2, 56) => 0.0125242
+(1, 65) ~ (2, 54) => 0.0149272
+(1, 65) ~ (2, 55) => 0.723008
+(1, 65) ~ (2, 56) => 0.181918
+(1, 65) ~ (2, 57) => 0.01143
+(1, 66) ~ (2, 55) => 0.0117348
+(1, 66) ~ (2, 56) => 0.74943
+(1, 66) ~ (2, 57) => 0.137998
+(1, 67) ~ (2, 57) => 0.805113
+(1, 67) ~ (2, 58) => 0.0939498
+(1, 68) ~ (2, 58) => 0.860193
+(1, 68) ~ (2, 59) => 0.0510018
+(1, 69) ~ (2, 59) => 0.918843
+(1, 69) ~ (2, 60) => 0.0142735
+(1, 70) ~ (2, 60) => 0.971603
+(1, 71) ~ (2, 61) => 0.987802
+(1, 72) ~ (2, 62) => 0.989852
+
+; gap posteriors
+(1, 0) ~ (2, -1) => 0.000905573
+(1, 1) ~ (2, -1) => 0.00255185
+(1, 2) ~ (2, -1) => 0.0132332
+(1, 3) ~ (2, -1) => 0.0216258
+(1, 4) ~ (2, -1) => 0.0278274
+(1, 5) ~ (2, -1) => 0.0351809
+(1, 6) ~ (2, -1) => 0.0410896
+(1, 7) ~ (2, -1) => 0.0449879
+(1, 8) ~ (2, -1) => 0.0475303
+(1, 9) ~ (2, -1) => 0.0483561
+(1, 10) ~ (2, -1) => 0.0565364
+(1, 11) ~ (2, -1) => 0.217086
+(1, 12) ~ (2, -1) => 0.376458
+(1, 13) ~ (2, -1) => 0.422859
+(1, 14) ~ (2, -1) => 0.302529
+(1, 15) ~ (2, -1) => 0.210523
+(1, 16) ~ (2, -1) => 0.19951
+(1, 17) ~ (2, -1) => 0.225584
+(1, 18) ~ (2, -1) => 0.339474
+(1, 19) ~ (2, -1) => 0.454535
+(1, 20) ~ (2, -1) => 0.544796
+(1, 21) ~ (2, -1) => 0.460637
+(1, 22) ~ (2, -1) => 0.319041
+(1, 23) ~ (2, -1) => 0.219764
+(1, 24) ~ (2, -1) => 0.210841
+(1, 25) ~ (2, -1) => 0.276991
+(1, 26) ~ (2, -1) => 0.308066
+(1, 27) ~ (2, -1) => 0.381282
+(1, 28) ~ (2, -1) => 0.739648
+(1, 29) ~ (2, -1) => 0.795495
+(1, 30) ~ (2, -1) => 0.901433
+(1, 31) ~ (2, -1) => 0.841457
+(1, 32) ~ (2, -1) => 0.761333
+(1, 33) ~ (2, -1) => 0.664818
+(1, 34) ~ (2, -1) => 0.550736
+(1, 35) ~ (2, -1) => 0.18512
+(1, 36) ~ (2, -1) => 0.100222
+(1, 37) ~ (2, -1) => 0.0488778
+(1, 38) ~ (2, -1) => 0.0464234
+(1, 39) ~ (2, -1) => 0.0386017
+(1, 40) ~ (2, -1) => 0.0335548
+(1, 41) ~ (2, -1) => 0.0307443
+(1, 42) ~ (2, -1) => 0.0317452
+(1, 43) ~ (2, -1) => 0.0322342
+(1, 44) ~ (2, -1) => 0.0315252
+(1, 45) ~ (2, -1) => 0.0405439
+(1, 46) ~ (2, -1) => 0.0234852
+(1, 47) ~ (2, -1) => 0.0196954
+(1, 48) ~ (2, -1) => 0.0210589
+(1, 49) ~ (2, -1) => 0.0280236
+(1, 50) ~ (2, -1) => 0.0377551
+(1, 51) ~ (2, -1) => 0.0471599
+(1, 52) ~ (2, -1) => 0.052361
+(1, 53) ~ (2, -1) => 0.0637985
+(1, 54) ~ (2, -1) => 0.073257
+(1, 55) ~ (2, -1) => 0.0703172
+(1, 56) ~ (2, -1) => 0.0901538
+(1, 57) ~ (2, -1) => 0.102516
+(1, 58) ~ (2, -1) => 0.0919218
+(1, 59) ~ (2, -1) => 0.0823148
+(1, 60) ~ (2, -1) => 0.0707349
+(1, 61) ~ (2, -1) => 0.0709448
+(1, 62) ~ (2, -1) => 0.0641783
+(1, 63) ~ (2, -1) => 0.0906945
+(1, 64) ~ (2, -1) => 0.0561339
+(1, 65) ~ (2, -1) => 0.0687169
+(1, 66) ~ (2, -1) => 0.100837
+(1, 67) ~ (2, -1) => 0.100937
+(1, 68) ~ (2, -1) => 0.0888056
+(1, 69) ~ (2, -1) => 0.0668831
+(1, 70) ~ (2, -1) => 0.0283966
+(1, 71) ~ (2, -1) => 0.0121977
+(1, 72) ~ (2, -1) => 0.0101479
+
+(1, -1) ~ (2, 0) => 0.000905573
+(1, -1) ~ (2, 1) => 0.00255185
+(1, -1) ~ (2, 2) => 0.0132332
+(1, -1) ~ (2, 3) => 0.0216258
+(1, -1) ~ (2, 4) => 0.0278274
+(1, -1) ~ (2, 5) => 0.0351809
+(1, -1) ~ (2, 6) => 0.0410896
+(1, -1) ~ (2, 7) => 0.0449879
+(1, -1) ~ (2, 8) => 0.0475303
+(1, -1) ~ (2, 9) => 0.0483561
+(1, -1) ~ (2, 10) => 0.0452699
+(1, -1) ~ (2, 11) => 0.0780733
+(1, -1) ~ (2, 12) => 0.0770544
+(1, -1) ~ (2, 13) => 0.0748279
+(1, -1) ~ (2, 14) => 0.0560563
+(1, -1) ~ (2, 15) => 0.0643543
+(1, -1) ~ (2, 16) => 0.0600374
+(1, -1) ~ (2, 17) => 0.0497433
+(1, -1) ~ (2, 18) => 0.0908208
+(1, -1) ~ (2, 19) => 0.0737488
+(1, -1) ~ (2, 20) => 0.0777454
+(1, -1) ~ (2, 21) => 0.0597632
+(1, -1) ~ (2, 22) => 0.0720404
+(1, -1) ~ (2, 23) => 0.0708541
+(1, -1) ~ (2, 24) => 0.0511919
+(1, -1) ~ (2, 25) => 0.0335279
+(1, -1) ~ (2, 26) => 0.0332396
+(1, -1) ~ (2, 27) => 0.032034
+(1, -1) ~ (2, 28) => 0.0413947
+(1, -1) ~ (2, 29) => 0.0402391
+(1, -1) ~ (2, 30) => 0.0357957
+(1, -1) ~ (2, 31) => 0.0313229
+(1, -1) ~ (2, 32) => 0.0346099
+(1, -1) ~ (2, 33) => 0.0351078
+(1, -1) ~ (2, 34) => 0.0416289
+(1, -1) ~ (2, 35) => 0.0405439
+(1, -1) ~ (2, 36) => 0.0346707
+(1, -1) ~ (2, 37) => 0.0242878
+(1, -1) ~ (2, 38) => 0.0398179
+(1, -1) ~ (2, 39) => 0.0684582
+(1, -1) ~ (2, 40) => 0.0937197
+(1, -1) ~ (2, 41) => 0.0571113
+(1, -1) ~ (2, 42) => 0.105523
+(1, -1) ~ (2, 43) => 0.120085
+(1, -1) ~ (2, 44) => 0.12083
+(1, -1) ~ (2, 45) => 0.116541
+(1, -1) ~ (2, 46) => 0.0927367
+(1, -1) ~ (2, 47) => 0.077995
+(1, -1) ~ (2, 48) => 0.0702529
+(1, -1) ~ (2, 49) => 0.0615169
+(1, -1) ~ (2, 50) => 0.0561027
+(1, -1) ~ (2, 51) => 0.0465621
+(1, -1) ~ (2, 52) => 0.0571002
+(1, -1) ~ (2, 53) => 0.0671119
+(1, -1) ~ (2, 54) => 0.0557581
+(1, -1) ~ (2, 55) => 0.0531792
+(1, -1) ~ (2, 56) => 0.0561283
+(1, -1) ~ (2, 57) => 0.0454589
+(1, -1) ~ (2, 58) => 0.0458576
+(1, -1) ~ (2, 59) => 0.0301548
+(1, -1) ~ (2, 60) => 0.0141231
+(1, -1) ~ (2, 61) => 0.0121977
+(1, -1) ~ (2, 62) => 0.0101479
+
+; Sparse posterior probability matrix for sequences 1 and 3
+; Format is:
+; (1, position_1) ~ (3, position_2) => prob
+; which means that (1, position_1) is aligned to (3, position_2) with probability prob.
+; (1, position_1) ~ (3, -1) => prob
+; means that (1, position_1) is aligned to a gap in 3 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (3, 0) => 0.995396
+(1, 1) ~ (3, 1) => 0.990391
+(1, 2) ~ (3, 2) => 0.985028
+(1, 3) ~ (3, 3) => 0.981486
+(1, 4) ~ (3, 4) => 0.978827
+(1, 5) ~ (3, 5) => 0.97648
+(1, 6) ~ (3, 6) => 0.972703
+(1, 7) ~ (3, 4) => 0.0115628
+(1, 7) ~ (3, 7) => 0.967717
+(1, 8) ~ (3, 5) => 0.0135615
+(1, 8) ~ (3, 8) => 0.959045
+(1, 9) ~ (3, 6) => 0.0163987
+(1, 9) ~ (3, 9) => 0.949696
+(1, 10) ~ (3, 7) => 0.0190044
+(1, 10) ~ (3, 10) => 0.937617
+(1, 10) ~ (3, 11) => 0.0129853
+(1, 11) ~ (3, 8) => 0.0211865
+(1, 11) ~ (3, 11) => 0.910826
+(1, 11) ~ (3, 12) => 0.0157986
+(1, 12) ~ (3, 9) => 0.023134
+(1, 12) ~ (3, 12) => 0.881964
+(1, 12) ~ (3, 13) => 0.0158382
+(1, 13) ~ (3, 10) => 0.0266981
+(1, 13) ~ (3, 12) => 0.0105404
+(1, 13) ~ (3, 13) => 0.844069
+(1, 13) ~ (3, 14) => 0.0148972
+(1, 14) ~ (3, 11) => 0.0439572
+(1, 14) ~ (3, 13) => 0.0126215
+(1, 14) ~ (3, 14) => 0.815765
+(1, 14) ~ (3, 15) => 0.0138622
+(1, 15) ~ (3, 11) => 0.0104431
+(1, 15) ~ (3, 12) => 0.0608694
+(1, 15) ~ (3, 14) => 0.0112314
+(1, 15) ~ (3, 15) => 0.78086
+(1, 15) ~ (3, 16) => 0.0134008
+(1, 16) ~ (3, 12) => 0.0109899
+(1, 16) ~ (3, 13) => 0.0983563
+(1, 16) ~ (3, 15) => 0.0179452
+(1, 16) ~ (3, 16) => 0.739521
+(1, 16) ~ (3, 17) => 0.0113865
+(1, 17) ~ (3, 13) => 0.0104095
+(1, 17) ~ (3, 14) => 0.125531
+(1, 17) ~ (3, 16) => 0.026547
+(1, 17) ~ (3, 17) => 0.703378
+(1, 18) ~ (3, 15) => 0.151156
+(1, 18) ~ (3, 16) => 0.0111796
+(1, 18) ~ (3, 17) => 0.034269
+(1, 18) ~ (3, 18) => 0.629933
+(1, 19) ~ (3, 15) => 0.0108788
+(1, 19) ~ (3, 16) => 0.174132
+(1, 19) ~ (3, 18) => 0.0721763
+(1, 19) ~ (3, 19) => 0.477315
+(1, 19) ~ (3, 21) => 0.0153414
+(1, 20) ~ (3, 16) => 0.01192
+(1, 20) ~ (3, 17) => 0.189344
+(1, 20) ~ (3, 18) => 0.0114817
+(1, 20) ~ (3, 19) => 0.0996167
+(1, 20) ~ (3, 20) => 0.420865
+(1, 20) ~ (3, 22) => 0.0172597
+(1, 21) ~ (3, 17) => 0.0189469
+(1, 21) ~ (3, 18) => 0.20813
+(1, 21) ~ (3, 19) => 0.0268727
+(1, 21) ~ (3, 20) => 0.100019
+(1, 21) ~ (3, 21) => 0.371805
+(1, 21) ~ (3, 22) => 0.0109161
+(1, 21) ~ (3, 23) => 0.0192062
+(1, 22) ~ (3, 18) => 0.0247649
+(1, 22) ~ (3, 19) => 0.301992
+(1, 22) ~ (3, 20) => 0.0263423
+(1, 22) ~ (3, 21) => 0.0976981
+(1, 22) ~ (3, 22) => 0.363576
+(1, 22) ~ (3, 23) => 0.0116817
+(1, 22) ~ (3, 24) => 0.0184189
+(1, 23) ~ (3, 19) => 0.0252746
+(1, 23) ~ (3, 20) => 0.35478
+(1, 23) ~ (3, 21) => 0.0269343
+(1, 23) ~ (3, 22) => 0.0801417
+(1, 23) ~ (3, 23) => 0.359805
+(1, 23) ~ (3, 24) => 0.0124989
+(1, 23) ~ (3, 25) => 0.0163924
+(1, 24) ~ (3, 18) => 0.011919
+(1, 24) ~ (3, 20) => 0.0199273
+(1, 24) ~ (3, 21) => 0.390984
+(1, 24) ~ (3, 22) => 0.038907
+(1, 24) ~ (3, 23) => 0.0517075
+(1, 24) ~ (3, 24) => 0.348992
+(1, 24) ~ (3, 25) => 0.0137934
+(1, 24) ~ (3, 26) => 0.0130414
+(1, 25) ~ (3, 19) => 0.0129538
+(1, 25) ~ (3, 21) => 0.0148458
+(1, 25) ~ (3, 22) => 0.403158
+(1, 25) ~ (3, 23) => 0.0561948
+(1, 25) ~ (3, 24) => 0.0273747
+(1, 25) ~ (3, 25) => 0.329881
+(1, 25) ~ (3, 26) => 0.0169664
+(1, 25) ~ (3, 27) => 0.0105858
+(1, 26) ~ (3, 20) => 0.01294
+(1, 26) ~ (3, 21) => 0.0118539
+(1, 26) ~ (3, 22) => 0.0161972
+(1, 26) ~ (3, 23) => 0.418513
+(1, 26) ~ (3, 24) => 0.0706186
+(1, 26) ~ (3, 25) => 0.0222531
+(1, 26) ~ (3, 26) => 0.311964
+(1, 26) ~ (3, 27) => 0.0183467
+(1, 26) ~ (3, 28) => 0.0103098
+(1, 27) ~ (3, 21) => 0.0131638
+(1, 27) ~ (3, 22) => 0.0118709
+(1, 27) ~ (3, 23) => 0.0183417
+(1, 27) ~ (3, 24) => 0.44009
+(1, 27) ~ (3, 25) => 0.0747324
+(1, 27) ~ (3, 26) => 0.0175087
+(1, 27) ~ (3, 27) => 0.300328
+(1, 27) ~ (3, 28) => 0.0161952
+(1, 28) ~ (3, 22) => 0.0121037
+(1, 28) ~ (3, 23) => 0.0126842
+(1, 28) ~ (3, 24) => 0.0212302
+(1, 28) ~ (3, 25) => 0.445472
+(1, 28) ~ (3, 26) => 0.0814102
+(1, 28) ~ (3, 27) => 0.0138388
+(1, 28) ~ (3, 28) => 0.267678
+(1, 29) ~ (3, 23) => 0.0111073
+(1, 29) ~ (3, 24) => 0.012566
+(1, 29) ~ (3, 25) => 0.0339763
+(1, 29) ~ (3, 26) => 0.453241
+(1, 29) ~ (3, 27) => 0.085766
+(1, 29) ~ (3, 28) => 0.0147963
+(1, 29) ~ (3, 29) => 0.25958
+(1, 30) ~ (3, 25) => 0.0125012
+(1, 30) ~ (3, 26) => 0.041281
+(1, 30) ~ (3, 27) => 0.450709
+(1, 30) ~ (3, 28) => 0.0867804
+(1, 30) ~ (3, 29) => 0.0116203
+(1, 30) ~ (3, 30) => 0.252879
+(1, 31) ~ (3, 26) => 0.0113047
+(1, 31) ~ (3, 27) => 0.0465356
+(1, 31) ~ (3, 28) => 0.47938
+(1, 31) ~ (3, 29) => 0.0979211
+(1, 31) ~ (3, 30) => 0.0128137
+(1, 31) ~ (3, 31) => 0.256682
+(1, 32) ~ (3, 26) => 0.0108535
+(1, 32) ~ (3, 27) => 0.0139025
+(1, 32) ~ (3, 28) => 0.0458842
+(1, 32) ~ (3, 29) => 0.486734
+(1, 32) ~ (3, 30) => 0.103579
+(1, 32) ~ (3, 31) => 0.0112588
+(1, 32) ~ (3, 32) => 0.257243
+(1, 33) ~ (3, 27) => 0.0166269
+(1, 33) ~ (3, 28) => 0.0141723
+(1, 33) ~ (3, 29) => 0.04278
+(1, 33) ~ (3, 30) => 0.489511
+(1, 33) ~ (3, 31) => 0.103811
+(1, 33) ~ (3, 33) => 0.254368
+(1, 34) ~ (3, 28) => 0.0219532
+(1, 34) ~ (3, 29) => 0.0143756
+(1, 34) ~ (3, 30) => 0.03998
+(1, 34) ~ (3, 31) => 0.492067
+(1, 34) ~ (3, 32) => 0.105331
+(1, 34) ~ (3, 34) => 0.246016
+(1, 35) ~ (3, 29) => 0.0255324
+(1, 35) ~ (3, 30) => 0.0135853
+(1, 35) ~ (3, 31) => 0.0350078
+(1, 35) ~ (3, 32) => 0.4903
+(1, 35) ~ (3, 33) => 0.0987823
+(1, 35) ~ (3, 34) => 0.0161749
+(1, 35) ~ (3, 35) => 0.235413
+(1, 36) ~ (3, 30) => 0.0296384
+(1, 36) ~ (3, 31) => 0.010736
+(1, 36) ~ (3, 32) => 0.0177727
+(1, 36) ~ (3, 33) => 0.52432
+(1, 36) ~ (3, 34) => 0.0860192
+(1, 36) ~ (3, 35) => 0.0234103
+(1, 36) ~ (3, 36) => 0.212867
+(1, 37) ~ (3, 31) => 0.034319
+(1, 37) ~ (3, 33) => 0.0167545
+(1, 37) ~ (3, 34) => 0.543198
+(1, 37) ~ (3, 35) => 0.0778639
+(1, 37) ~ (3, 36) => 0.0273952
+(1, 37) ~ (3, 37) => 0.196289
+(1, 38) ~ (3, 32) => 0.0377224
+(1, 38) ~ (3, 34) => 0.0174039
+(1, 38) ~ (3, 35) => 0.555875
+(1, 38) ~ (3, 36) => 0.0659105
+(1, 38) ~ (3, 37) => 0.0275898
+(1, 38) ~ (3, 38) => 0.177806
+(1, 38) ~ (3, 39) => 0.0101026
+(1, 39) ~ (3, 33) => 0.0394619
+(1, 39) ~ (3, 35) => 0.0129644
+(1, 39) ~ (3, 36) => 0.594134
+(1, 39) ~ (3, 37) => 0.0510767
+(1, 39) ~ (3, 38) => 0.0271276
+(1, 39) ~ (3, 39) => 0.175218
+(1, 39) ~ (3, 40) => 0.0109782
+(1, 40) ~ (3, 34) => 0.0419389
+(1, 40) ~ (3, 36) => 0.0112319
+(1, 40) ~ (3, 37) => 0.62399
+(1, 40) ~ (3, 38) => 0.0328705
+(1, 40) ~ (3, 39) => 0.0265368
+(1, 40) ~ (3, 40) => 0.169942
+(1, 40) ~ (3, 41) => 0.0114618
+(1, 41) ~ (3, 35) => 0.0430015
+(1, 41) ~ (3, 38) => 0.660358
+(1, 41) ~ (3, 39) => 0.0296371
+(1, 41) ~ (3, 40) => 0.0233448
+(1, 41) ~ (3, 41) => 0.161792
+(1, 41) ~ (3, 42) => 0.0149258
+(1, 42) ~ (3, 36) => 0.0428936
+(1, 42) ~ (3, 39) => 0.669817
+(1, 42) ~ (3, 40) => 0.0264389
+(1, 42) ~ (3, 41) => 0.0214453
+(1, 42) ~ (3, 42) => 0.149187
+(1, 42) ~ (3, 43) => 0.0175046
+(1, 43) ~ (3, 37) => 0.0431126
+(1, 43) ~ (3, 40) => 0.682826
+(1, 43) ~ (3, 41) => 0.0247335
+(1, 43) ~ (3, 42) => 0.0168342
+(1, 43) ~ (3, 43) => 0.12862
+(1, 43) ~ (3, 44) => 0.0206483
+(1, 44) ~ (3, 38) => 0.0433083
+(1, 44) ~ (3, 41) => 0.691843
+(1, 44) ~ (3, 42) => 0.0244189
+(1, 44) ~ (3, 43) => 0.0125934
+(1, 44) ~ (3, 44) => 0.101424
+(1, 44) ~ (3, 45) => 0.02514
+(1, 45) ~ (3, 39) => 0.0423174
+(1, 45) ~ (3, 42) => 0.704015
+(1, 45) ~ (3, 43) => 0.0230706
+(1, 45) ~ (3, 44) => 0.0153593
+(1, 45) ~ (3, 45) => 0.096491
+(1, 45) ~ (3, 46) => 0.0253639
+(1, 46) ~ (3, 40) => 0.040037
+(1, 46) ~ (3, 43) => 0.725074
+(1, 46) ~ (3, 44) => 0.0185435
+(1, 46) ~ (3, 45) => 0.0139109
+(1, 46) ~ (3, 46) => 0.0932612
+(1, 46) ~ (3, 47) => 0.0240035
+(1, 47) ~ (3, 41) => 0.0358536
+(1, 47) ~ (3, 44) => 0.742786
+(1, 47) ~ (3, 45) => 0.01195
+(1, 47) ~ (3, 46) => 0.0152377
+(1, 47) ~ (3, 47) => 0.0851979
+(1, 47) ~ (3, 48) => 0.0262604
+(1, 48) ~ (3, 42) => 0.0328576
+(1, 48) ~ (3, 43) => 0.0135657
+(1, 48) ~ (3, 45) => 0.746086
+(1, 48) ~ (3, 47) => 0.0133431
+(1, 48) ~ (3, 48) => 0.0797635
+(1, 48) ~ (3, 49) => 0.0294528
+(1, 49) ~ (3, 43) => 0.0280398
+(1, 49) ~ (3, 44) => 0.019162
+(1, 49) ~ (3, 45) => 0.0162065
+(1, 49) ~ (3, 46) => 0.734722
+(1, 49) ~ (3, 49) => 0.0725957
+(1, 49) ~ (3, 50) => 0.0333288
+(1, 50) ~ (3, 44) => 0.0163408
+(1, 50) ~ (3, 45) => 0.0248054
+(1, 50) ~ (3, 46) => 0.0400117
+(1, 50) ~ (3, 47) => 0.669056
+(1, 50) ~ (3, 50) => 0.0639796
+(1, 50) ~ (3, 51) => 0.0362032
+(1, 51) ~ (3, 45) => 0.0105474
+(1, 51) ~ (3, 46) => 0.0199165
+(1, 51) ~ (3, 47) => 0.127149
+(1, 51) ~ (3, 48) => 0.600043
+(1, 51) ~ (3, 51) => 0.0578059
+(1, 51) ~ (3, 52) => 0.0382132
+(1, 52) ~ (3, 47) => 0.0288882
+(1, 52) ~ (3, 48) => 0.20295
+(1, 52) ~ (3, 49) => 0.518334
+(1, 52) ~ (3, 52) => 0.048736
+(1, 52) ~ (3, 53) => 0.0391005
+(1, 53) ~ (3, 48) => 0.0341356
+(1, 53) ~ (3, 49) => 0.271832
+(1, 53) ~ (3, 50) => 0.462479
+(1, 53) ~ (3, 53) => 0.0339093
+(1, 53) ~ (3, 54) => 0.038158
+(1, 54) ~ (3, 49) => 0.0551342
+(1, 54) ~ (3, 50) => 0.318716
+(1, 54) ~ (3, 51) => 0.403304
+(1, 54) ~ (3, 52) => 0.0130531
+(1, 54) ~ (3, 53) => 0.0116799
+(1, 54) ~ (3, 54) => 0.0279478
+(1, 54) ~ (3, 55) => 0.0343756
+(1, 55) ~ (3, 50) => 0.0696785
+(1, 55) ~ (3, 51) => 0.362204
+(1, 55) ~ (3, 52) => 0.37353
+(1, 55) ~ (3, 53) => 0.0220372
+(1, 55) ~ (3, 54) => 0.0161689
+(1, 55) ~ (3, 55) => 0.0183638
+(1, 55) ~ (3, 56) => 0.0334753
+(1, 56) ~ (3, 51) => 0.0805352
+(1, 56) ~ (3, 52) => 0.391937
+(1, 56) ~ (3, 53) => 0.356031
+(1, 56) ~ (3, 54) => 0.0284829
+(1, 56) ~ (3, 55) => 0.0183179
+(1, 56) ~ (3, 57) => 0.0311126
+(1, 57) ~ (3, 52) => 0.082601
+(1, 57) ~ (3, 53) => 0.409511
+(1, 57) ~ (3, 54) => 0.320715
+(1, 57) ~ (3, 55) => 0.0370158
+(1, 57) ~ (3, 56) => 0.0157029
+(1, 57) ~ (3, 58) => 0.0290831
+(1, 58) ~ (3, 53) => 0.0836298
+(1, 58) ~ (3, 54) => 0.424384
+(1, 58) ~ (3, 55) => 0.318713
+(1, 58) ~ (3, 56) => 0.0398674
+(1, 58) ~ (3, 57) => 0.0186446
+(1, 58) ~ (3, 59) => 0.0258257
+(1, 59) ~ (3, 54) => 0.0994068
+(1, 59) ~ (3, 55) => 0.41132
+(1, 59) ~ (3, 56) => 0.334235
+(1, 59) ~ (3, 57) => 0.0396993
+(1, 59) ~ (3, 58) => 0.019212
+(1, 59) ~ (3, 60) => 0.0210773
+(1, 60) ~ (3, 55) => 0.103516
+(1, 60) ~ (3, 56) => 0.414033
+(1, 60) ~ (3, 57) => 0.341186
+(1, 60) ~ (3, 58) => 0.0363834
+(1, 60) ~ (3, 59) => 0.0226094
+(1, 60) ~ (3, 61) => 0.0183042
+(1, 61) ~ (3, 56) => 0.106281
+(1, 61) ~ (3, 57) => 0.415867
+(1, 61) ~ (3, 58) => 0.342795
+(1, 61) ~ (3, 59) => 0.0342202
+(1, 61) ~ (3, 60) => 0.0236904
+(1, 61) ~ (3, 62) => 0.0151772
+(1, 62) ~ (3, 57) => 0.108796
+(1, 62) ~ (3, 58) => 0.410822
+(1, 62) ~ (3, 59) => 0.350547
+(1, 62) ~ (3, 60) => 0.026028
+(1, 62) ~ (3, 61) => 0.0242796
+(1, 62) ~ (3, 63) => 0.012299
+(1, 63) ~ (3, 58) => 0.108405
+(1, 63) ~ (3, 59) => 0.413771
+(1, 63) ~ (3, 60) => 0.337751
+(1, 63) ~ (3, 61) => 0.0138994
+(1, 63) ~ (3, 62) => 0.0230785
+(1, 64) ~ (3, 59) => 0.102746
+(1, 64) ~ (3, 60) => 0.448018
+(1, 64) ~ (3, 61) => 0.303239
+(1, 64) ~ (3, 62) => 0.0123941
+(1, 64) ~ (3, 63) => 0.0203131
+(1, 65) ~ (3, 60) => 0.0698707
+(1, 65) ~ (3, 61) => 0.533674
+(1, 65) ~ (3, 62) => 0.262921
+(1, 65) ~ (3, 63) => 0.016051
+(1, 65) ~ (3, 64) => 0.0206803
+(1, 66) ~ (3, 61) => 0.0550442
+(1, 66) ~ (3, 62) => 0.590582
+(1, 66) ~ (3, 63) => 0.228459
+(1, 66) ~ (3, 64) => 0.0193094
+(1, 66) ~ (3, 65) => 0.018637
+(1, 67) ~ (3, 62) => 0.0533169
+(1, 67) ~ (3, 63) => 0.631199
+(1, 67) ~ (3, 64) => 0.194184
+(1, 67) ~ (3, 65) => 0.0169158
+(1, 67) ~ (3, 66) => 0.0145392
+(1, 68) ~ (3, 63) => 0.0484263
+(1, 68) ~ (3, 64) => 0.673038
+(1, 68) ~ (3, 65) => 0.103311
+(1, 68) ~ (3, 66) => 0.0109832
+(1, 68) ~ (3, 67) => 0.0111111
+(1, 69) ~ (3, 64) => 0.0443406
+(1, 69) ~ (3, 65) => 0.785169
+(1, 69) ~ (3, 66) => 0.0659399
+(1, 69) ~ (3, 67) => 0.0105862
+(1, 70) ~ (3, 65) => 0.0381781
+(1, 70) ~ (3, 66) => 0.850399
+(1, 70) ~ (3, 67) => 0.0439482
+(1, 71) ~ (3, 66) => 0.0283484
+(1, 71) ~ (3, 67) => 0.894354
+(1, 71) ~ (3, 68) => 0.0300751
+(1, 72) ~ (3, 67) => 0.0237847
+(1, 72) ~ (3, 68) => 0.923415
+
+; gap posteriors
+(1, 0) ~ (3, -1) => 0.00460368
+(1, 1) ~ (3, -1) => 0.00960892
+(1, 2) ~ (3, -1) => 0.0149716
+(1, 3) ~ (3, -1) => 0.0185144
+(1, 4) ~ (3, -1) => 0.0211734
+(1, 5) ~ (3, -1) => 0.0235199
+(1, 6) ~ (3, -1) => 0.0272967
+(1, 7) ~ (3, -1) => 0.0207204
+(1, 8) ~ (3, -1) => 0.0273939
+(1, 9) ~ (3, -1) => 0.0339053
+(1, 10) ~ (3, -1) => 0.0303934
+(1, 11) ~ (3, -1) => 0.052189
+(1, 12) ~ (3, -1) => 0.0790636
+(1, 13) ~ (3, -1) => 0.103795
+(1, 14) ~ (3, -1) => 0.113794
+(1, 15) ~ (3, -1) => 0.123195
+(1, 16) ~ (3, -1) => 0.121801
+(1, 17) ~ (3, -1) => 0.134134
+(1, 18) ~ (3, -1) => 0.173462
+(1, 19) ~ (3, -1) => 0.250156
+(1, 20) ~ (3, -1) => 0.249512
+(1, 21) ~ (3, -1) => 0.244104
+(1, 22) ~ (3, -1) => 0.155526
+(1, 23) ~ (3, -1) => 0.124173
+(1, 24) ~ (3, -1) => 0.110728
+(1, 25) ~ (3, -1) => 0.12804
+(1, 26) ~ (3, -1) => 0.107004
+(1, 27) ~ (3, -1) => 0.10777
+(1, 28) ~ (3, -1) => 0.145583
+(1, 29) ~ (3, -1) => 0.128967
+(1, 30) ~ (3, -1) => 0.14423
+(1, 31) ~ (3, -1) => 0.0953625
+(1, 32) ~ (3, -1) => 0.0705453
+(1, 33) ~ (3, -1) => 0.0787321
+(1, 34) ~ (3, -1) => 0.0802766
+(1, 35) ~ (3, -1) => 0.0852045
+(1, 36) ~ (3, -1) => 0.0952369
+(1, 37) ~ (3, -1) => 0.10418
+(1, 38) ~ (3, -1) => 0.10759
+(1, 39) ~ (3, -1) => 0.0890398
+(1, 40) ~ (3, -1) => 0.0820279
+(1, 41) ~ (3, -1) => 0.0669413
+(1, 42) ~ (3, -1) => 0.072714
+(1, 43) ~ (3, -1) => 0.0832253
+(1, 44) ~ (3, -1) => 0.101272
+(1, 45) ~ (3, -1) => 0.0933826
+(1, 46) ~ (3, -1) => 0.0851695
+(1, 47) ~ (3, -1) => 0.0827143
+(1, 48) ~ (3, -1) => 0.0849315
+(1, 49) ~ (3, -1) => 0.0959448
+(1, 50) ~ (3, -1) => 0.149604
+(1, 51) ~ (3, -1) => 0.146325
+(1, 52) ~ (3, -1) => 0.161991
+(1, 53) ~ (3, -1) => 0.159486
+(1, 54) ~ (3, -1) => 0.13579
+(1, 55) ~ (3, -1) => 0.104543
+(1, 56) ~ (3, -1) => 0.0935837
+(1, 57) ~ (3, -1) => 0.105371
+(1, 58) ~ (3, -1) => 0.0889355
+(1, 59) ~ (3, -1) => 0.0750498
+(1, 60) ~ (3, -1) => 0.0639688
+(1, 61) ~ (3, -1) => 0.0619684
+(1, 62) ~ (3, -1) => 0.0672282
+(1, 63) ~ (3, -1) => 0.103096
+(1, 64) ~ (3, -1) => 0.113289
+(1, 65) ~ (3, -1) => 0.0968023
+(1, 66) ~ (3, -1) => 0.0879686
+(1, 67) ~ (3, -1) => 0.0898454
+(1, 68) ~ (3, -1) => 0.15313
+(1, 69) ~ (3, -1) => 0.0939643
+(1, 70) ~ (3, -1) => 0.0674745
+(1, 71) ~ (3, -1) => 0.047223
+(1, 72) ~ (3, -1) => 0.0528007
+
+(1, -1) ~ (3, 0) => 0.00460368
+(1, -1) ~ (3, 1) => 0.00960892
+(1, -1) ~ (3, 2) => 0.0149716
+(1, -1) ~ (3, 3) => 0.0185144
+(1, -1) ~ (3, 4) => 0.00961064
+(1, -1) ~ (3, 5) => 0.0099584
+(1, -1) ~ (3, 6) => 0.0108979
+(1, -1) ~ (3, 7) => 0.0132788
+(1, -1) ~ (3, 8) => 0.0197689
+(1, -1) ~ (3, 9) => 0.0271701
+(1, -1) ~ (3, 10) => 0.0356849
+(1, -1) ~ (3, 11) => 0.0217885
+(1, -1) ~ (3, 12) => 0.0198375
+(1, -1) ~ (3, 13) => 0.0187054
+(1, -1) ~ (3, 14) => 0.0325754
+(1, -1) ~ (3, 15) => 0.0252975
+(1, -1) ~ (3, 16) => 0.0232991
+(1, -1) ~ (3, 17) => 0.0426747
+(1, -1) ~ (3, 18) => 0.0415947
+(1, -1) ~ (3, 19) => 0.0559758
+(1, -1) ~ (3, 20) => 0.0651271
+(1, -1) ~ (3, 21) => 0.0573729
+(1, -1) ~ (3, 22) => 0.0458691
+(1, -1) ~ (3, 23) => 0.0407588
+(1, -1) ~ (3, 24) => 0.0482111
+(1, -1) ~ (3, 25) => 0.050998
+(1, -1) ~ (3, 26) => 0.0424293
+(1, -1) ~ (3, 27) => 0.043361
+(1, -1) ~ (3, 28) => 0.0428509
+(1, -1) ~ (3, 29) => 0.0614567
+(1, -1) ~ (3, 30) => 0.058014
+(1, -1) ~ (3, 31) => 0.0561184
+(1, -1) ~ (3, 32) => 0.0916308
+(1, -1) ~ (3, 33) => 0.0663138
+(1, -1) ~ (3, 34) => 0.0492484
+(1, -1) ~ (3, 35) => 0.0514725
+(1, -1) ~ (3, 36) => 0.0455687
+(1, -1) ~ (3, 37) => 0.057942
+(1, -1) ~ (3, 38) => 0.0585302
+(1, -1) ~ (3, 39) => 0.0463716
+(1, -1) ~ (3, 40) => 0.0464333
+(1, -1) ~ (3, 41) => 0.0528705
+(1, -1) ~ (3, 42) => 0.0577614
+(1, -1) ~ (3, 43) => 0.0515314
+(1, -1) ~ (3, 44) => 0.0657357
+(1, -1) ~ (3, 45) => 0.054863
+(1, -1) ~ (3, 46) => 0.0714867
+(1, -1) ~ (3, 47) => 0.0523624
+(1, -1) ~ (3, 48) => 0.0568473
+(1, -1) ~ (3, 49) => 0.052651
+(1, -1) ~ (3, 50) => 0.051819
+(1, -1) ~ (3, 51) => 0.0599482
+(1, -1) ~ (3, 52) => 0.0519298
+(1, -1) ~ (3, 53) => 0.0441015
+(1, -1) ~ (3, 54) => 0.0447369
+(1, -1) ~ (3, 55) => 0.0583776
+(1, -1) ~ (3, 56) => 0.056406
+(1, -1) ~ (3, 57) => 0.0446942
+(1, -1) ~ (3, 58) => 0.0532994
+(1, -1) ~ (3, 59) => 0.050281
+(1, -1) ~ (3, 60) => 0.0735643
+(1, -1) ~ (3, 61) => 0.0515588
+(1, -1) ~ (3, 62) => 0.04253
+(1, -1) ~ (3, 63) => 0.043253
+(1, -1) ~ (3, 64) => 0.0484475
+(1, -1) ~ (3, 65) => 0.0377892
+(1, -1) ~ (3, 66) => 0.0297902
+(1, -1) ~ (3, 67) => 0.0162162
+(1, -1) ~ (3, 68) => 0.0465104
+
+; Sparse posterior probability matrix for sequences 1 and 4
+; Format is:
+; (1, position_1) ~ (4, position_2) => prob
+; which means that (1, position_1) is aligned to (4, position_2) with probability prob.
+; (1, position_1) ~ (4, -1) => prob
+; means that (1, position_1) is aligned to a gap in 4 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(1, 0) ~ (4, 0) => 0.9997
+(1, 1) ~ (4, 1) => 0.998453
+(1, 2) ~ (4, 2) => 0.994036
+(1, 3) ~ (4, 3) => 0.990408
+(1, 4) ~ (4, 4) => 0.988165
+(1, 5) ~ (4, 5) => 0.986209
+(1, 6) ~ (4, 6) => 0.982967
+(1, 6) ~ (4, 7) => 0.0100327
+(1, 7) ~ (4, 7) => 0.978678
+(1, 7) ~ (4, 8) => 0.0119843
+(1, 8) ~ (4, 8) => 0.976071
+(1, 8) ~ (4, 9) => 0.0141077
+(1, 9) ~ (4, 9) => 0.973414
+(1, 9) ~ (4, 10) => 0.0162018
+(1, 10) ~ (4, 10) => 0.969108
+(1, 10) ~ (4, 11) => 0.0152438
+(1, 11) ~ (4, 11) => 0.972431
+(1, 11) ~ (4, 12) => 0.012889
+(1, 12) ~ (4, 12) => 0.976003
+(1, 13) ~ (4, 13) => 0.984501
+(1, 14) ~ (4, 14) => 0.990905
+(1, 15) ~ (4, 15) => 0.997242
+(1, 16) ~ (4, 16) => 0.997814
+(1, 17) ~ (4, 17) => 0.997782
+(1, 18) ~ (4, 18) => 0.995086
+(1, 19) ~ (4, 19) => 0.991604
+(1, 20) ~ (4, 20) => 0.911543
+(1, 21) ~ (4, 20) => 0.081885
+(1, 21) ~ (4, 21) => 0.830548
+(1, 22) ~ (4, 21) => 0.157179
+(1, 22) ~ (4, 22) => 0.785469
+(1, 22) ~ (4, 23) => 0.0137291
+(1, 23) ~ (4, 22) => 0.18888
+(1, 23) ~ (4, 23) => 0.0844835
+(1, 23) ~ (4, 24) => 0.0231893
+(1, 24) ~ (4, 23) => 0.879762
+(1, 24) ~ (4, 24) => 0.0510101
+(1, 24) ~ (4, 25) => 0.0155857
+(1, 25) ~ (4, 24) => 0.914978
+(1, 25) ~ (4, 25) => 0.0301128
+(1, 26) ~ (4, 25) => 0.941345
+(1, 26) ~ (4, 26) => 0.0216416
+(1, 27) ~ (4, 26) => 0.956951
+(1, 27) ~ (4, 27) => 0.0115729
+(1, 28) ~ (4, 26) => 0.0109663
+(1, 28) ~ (4, 27) => 0.966065
+(1, 29) ~ (4, 27) => 0.0159347
+(1, 29) ~ (4, 28) => 0.974505
+(1, 30) ~ (4, 28) => 0.0161725
+(1, 30) ~ (4, 29) => 0.97449
+(1, 31) ~ (4, 29) => 0.0190305
+(1, 31) ~ (4, 30) => 0.977209
+(1, 32) ~ (4, 30) => 0.0194295
+(1, 32) ~ (4, 31) => 0.976426
+(1, 33) ~ (4, 31) => 0.0191771
+(1, 33) ~ (4, 32) => 0.975558
+(1, 34) ~ (4, 32) => 0.0195985
+(1, 34) ~ (4, 33) => 0.976658
+(1, 35) ~ (4, 33) => 0.0175109
+(1, 35) ~ (4, 34) => 0.98082
+(1, 36) ~ (4, 34) => 0.01437
+(1, 36) ~ (4, 35) => 0.984299
+(1, 37) ~ (4, 35) => 0.0109015
+(1, 37) ~ (4, 36) => 0.985344
+(1, 38) ~ (4, 36) => 0.0119291
+(1, 38) ~ (4, 37) => 0.982136
+(1, 39) ~ (4, 37) => 0.0136494
+(1, 39) ~ (4, 38) => 0.979989
+(1, 40) ~ (4, 38) => 0.0144306
+(1, 40) ~ (4, 39) => 0.977198
+(1, 41) ~ (4, 39) => 0.01581
+(1, 41) ~ (4, 40) => 0.947786
+(1, 42) ~ (4, 40) => 0.0428728
+(1, 42) ~ (4, 41) => 0.917917
+(1, 43) ~ (4, 41) => 0.0696512
+(1, 43) ~ (4, 42) => 0.880536
+(1, 43) ~ (4, 43) => 0.0110859
+(1, 44) ~ (4, 42) => 0.104454
+(1, 44) ~ (4, 43) => 0.851407
+(1, 44) ~ (4, 44) => 0.0123777
+(1, 45) ~ (4, 43) => 0.131508
+(1, 45) ~ (4, 44) => 0.814437
+(1, 45) ~ (4, 45) => 0.0125995
+(1, 46) ~ (4, 44) => 0.166203
+(1, 46) ~ (4, 45) => 0.755124
+(1, 46) ~ (4, 46) => 0.0124186
+(1, 47) ~ (4, 45) => 0.224856
+(1, 47) ~ (4, 46) => 0.69205
+(1, 47) ~ (4, 47) => 0.0106718
+(1, 48) ~ (4, 46) => 0.287558
+(1, 48) ~ (4, 47) => 0.591345
+(1, 49) ~ (4, 47) => 0.390257
+(1, 49) ~ (4, 48) => 0.534056
+(1, 50) ~ (4, 48) => 0.451092
+(1, 50) ~ (4, 49) => 0.43122
+(1, 51) ~ (4, 49) => 0.555362
+(1, 51) ~ (4, 50) => 0.328075
+(1, 51) ~ (4, 51) => 0.010077
+(1, 52) ~ (4, 50) => 0.65686
+(1, 52) ~ (4, 51) => 0.22068
+(1, 52) ~ (4, 52) => 0.0147259
+(1, 53) ~ (4, 51) => 0.758032
+(1, 53) ~ (4, 52) => 0.161636
+(1, 54) ~ (4, 52) => 0.815324
+(1, 54) ~ (4, 53) => 0.10525
+(1, 55) ~ (4, 53) => 0.883556
+(1, 55) ~ (4, 54) => 0.0684677
+(1, 56) ~ (4, 54) => 0.92492
+(1, 56) ~ (4, 55) => 0.0400275
+(1, 57) ~ (4, 55) => 0.955228
+(1, 57) ~ (4, 56) => 0.0105455
+(1, 58) ~ (4, 56) => 0.984308
+(1, 58) ~ (4, 57) => 0.0105717
+(1, 59) ~ (4, 57) => 0.983824
+(1, 59) ~ (4, 58) => 0.010638
+(1, 60) ~ (4, 58) => 0.983863
+(1, 60) ~ (4, 59) => 0.0107324
+(1, 61) ~ (4, 59) => 0.983473
+(1, 61) ~ (4, 60) => 0.0107019
+(1, 62) ~ (4, 60) => 0.982547
+(1, 62) ~ (4, 61) => 0.0113025
+(1, 63) ~ (4, 61) => 0.982421
+(1, 63) ~ (4, 62) => 0.0119239
+(1, 64) ~ (4, 62) => 0.982245
+(1, 64) ~ (4, 63) => 0.0113742
+(1, 65) ~ (4, 63) => 0.984131
+(1, 66) ~ (4, 64) => 0.986408
+(1, 67) ~ (4, 65) => 0.98779
+(1, 68) ~ (4, 66) => 0.989351
+(1, 69) ~ (4, 67) => 0.993642
+(1, 70) ~ (4, 68) => 0.996821
+(1, 71) ~ (4, 69) => 0.99803
+(1, 72) ~ (4, 70) => 0.998733
+
+; gap posteriors
+(1, 0) ~ (4, -1) => 0.000300169
+(1, 1) ~ (4, -1) => 0.00154728
+(1, 2) ~ (4, -1) => 0.00596356
+(1, 3) ~ (4, -1) => 0.00959235
+(1, 4) ~ (4, -1) => 0.0118346
+(1, 5) ~ (4, -1) => 0.0137908
+(1, 6) ~ (4, -1) => 0.00700056
+(1, 7) ~ (4, -1) => 0.00933819
+(1, 8) ~ (4, -1) => 0.00982151
+(1, 9) ~ (4, -1) => 0.0103839
+(1, 10) ~ (4, -1) => 0.0156481
+(1, 11) ~ (4, -1) => 0.0146795
+(1, 12) ~ (4, -1) => 0.0239967
+(1, 13) ~ (4, -1) => 0.0154991
+(1, 14) ~ (4, -1) => 0.00909489
+(1, 15) ~ (4, -1) => 0.00275785
+(1, 16) ~ (4, -1) => 0.00218636
+(1, 17) ~ (4, -1) => 0.00221789
+(1, 18) ~ (4, -1) => 0.00491434
+(1, 19) ~ (4, -1) => 0.00839573
+(1, 20) ~ (4, -1) => 0.0884575
+(1, 21) ~ (4, -1) => 0.0875668
+(1, 22) ~ (4, -1) => 0.0436231
+(1, 23) ~ (4, -1) => 0.703447
+(1, 24) ~ (4, -1) => 0.053642
+(1, 25) ~ (4, -1) => 0.0549091
+(1, 26) ~ (4, -1) => 0.0370133
+(1, 27) ~ (4, -1) => 0.0314757
+(1, 28) ~ (4, -1) => 0.0229687
+(1, 29) ~ (4, -1) => 0.00956059
+(1, 30) ~ (4, -1) => 0.00933713
+(1, 31) ~ (4, -1) => 0.00376034
+(1, 32) ~ (4, -1) => 0.00414461
+(1, 33) ~ (4, -1) => 0.00526446
+(1, 34) ~ (4, -1) => 0.00374305
+(1, 35) ~ (4, -1) => 0.00166941
+(1, 36) ~ (4, -1) => 0.00133061
+(1, 37) ~ (4, -1) => 0.00375503
+(1, 38) ~ (4, -1) => 0.00593489
+(1, 39) ~ (4, -1) => 0.00636154
+(1, 40) ~ (4, -1) => 0.00837189
+(1, 41) ~ (4, -1) => 0.0364044
+(1, 42) ~ (4, -1) => 0.0392098
+(1, 43) ~ (4, -1) => 0.0387269
+(1, 44) ~ (4, -1) => 0.0317611
+(1, 45) ~ (4, -1) => 0.0414552
+(1, 46) ~ (4, -1) => 0.0662551
+(1, 47) ~ (4, -1) => 0.0724223
+(1, 48) ~ (4, -1) => 0.121097
+(1, 49) ~ (4, -1) => 0.0756867
+(1, 50) ~ (4, -1) => 0.117688
+(1, 51) ~ (4, -1) => 0.106486
+(1, 52) ~ (4, -1) => 0.107734
+(1, 53) ~ (4, -1) => 0.0803325
+(1, 54) ~ (4, -1) => 0.0794263
+(1, 55) ~ (4, -1) => 0.0479762
+(1, 56) ~ (4, -1) => 0.035052
+(1, 57) ~ (4, -1) => 0.0342262
+(1, 58) ~ (4, -1) => 0.00512001
+(1, 59) ~ (4, -1) => 0.005538
+(1, 60) ~ (4, -1) => 0.00540488
+(1, 61) ~ (4, -1) => 0.00582494
+(1, 62) ~ (4, -1) => 0.00615006
+(1, 63) ~ (4, -1) => 0.00565557
+(1, 64) ~ (4, -1) => 0.00638068
+(1, 65) ~ (4, -1) => 0.015869
+(1, 66) ~ (4, -1) => 0.0135918
+(1, 67) ~ (4, -1) => 0.0122096
+(1, 68) ~ (4, -1) => 0.0106486
+(1, 69) ~ (4, -1) => 0.00635767
+(1, 70) ~ (4, -1) => 0.00317913
+(1, 71) ~ (4, -1) => 0.00197041
+(1, 72) ~ (4, -1) => 0.00126714
+
+(1, -1) ~ (4, 0) => 0.000300169
+(1, -1) ~ (4, 1) => 0.00154728
+(1, -1) ~ (4, 2) => 0.00596356
+(1, -1) ~ (4, 3) => 0.00959235
+(1, -1) ~ (4, 4) => 0.0118346
+(1, -1) ~ (4, 5) => 0.0137908
+(1, -1) ~ (4, 6) => 0.0170333
+(1, -1) ~ (4, 7) => 0.0112898
+(1, -1) ~ (4, 8) => 0.0119449
+(1, -1) ~ (4, 9) => 0.0124781
+(1, -1) ~ (4, 10) => 0.01469
+(1, -1) ~ (4, 11) => 0.0123247
+(1, -1) ~ (4, 12) => 0.0111076
+(1, -1) ~ (4, 13) => 0.0154991
+(1, -1) ~ (4, 14) => 0.00909489
+(1, -1) ~ (4, 15) => 0.00275785
+(1, -1) ~ (4, 16) => 0.00218636
+(1, -1) ~ (4, 17) => 0.00221789
+(1, -1) ~ (4, 18) => 0.00491434
+(1, -1) ~ (4, 19) => 0.00839573
+(1, -1) ~ (4, 20) => 0.00657246
+(1, -1) ~ (4, 21) => 0.0122733
+(1, -1) ~ (4, 22) => 0.0256506
+(1, -1) ~ (4, 23) => 0.0220253
+(1, -1) ~ (4, 24) => 0.0108224
+(1, -1) ~ (4, 25) => 0.0129564
+(1, -1) ~ (4, 26) => 0.0104407
+(1, -1) ~ (4, 27) => 0.00642735
+(1, -1) ~ (4, 28) => 0.00932278
+(1, -1) ~ (4, 29) => 0.00647917
+(1, -1) ~ (4, 30) => 0.00336128
+(1, -1) ~ (4, 31) => 0.00439699
+(1, -1) ~ (4, 32) => 0.00484306
+(1, -1) ~ (4, 33) => 0.00583074
+(1, -1) ~ (4, 34) => 0.00481027
+(1, -1) ~ (4, 35) => 0.00479911
+(1, -1) ~ (4, 36) => 0.00272742
+(1, -1) ~ (4, 37) => 0.00421452
+(1, -1) ~ (4, 38) => 0.00558037
+(1, -1) ~ (4, 39) => 0.00699246
+(1, -1) ~ (4, 40) => 0.00934161
+(1, -1) ~ (4, 41) => 0.0124315
+(1, -1) ~ (4, 42) => 0.0150102
+(1, -1) ~ (4, 43) => 0.00599855
+(1, -1) ~ (4, 44) => 0.0069824
+(1, -1) ~ (4, 45) => 0.00742133
+(1, -1) ~ (4, 46) => 0.00797325
+(1, -1) ~ (4, 47) => 0.00772557
+(1, -1) ~ (4, 48) => 0.0148522
+(1, -1) ~ (4, 49) => 0.0134176
+(1, -1) ~ (4, 50) => 0.0150655
+(1, -1) ~ (4, 51) => 0.0112107
+(1, -1) ~ (4, 52) => 0.00831461
+(1, -1) ~ (4, 53) => 0.011194
+(1, -1) ~ (4, 54) => 0.00661182
+(1, -1) ~ (4, 55) => 0.00474423
+(1, -1) ~ (4, 56) => 0.00514627
+(1, -1) ~ (4, 57) => 0.00560421
+(1, -1) ~ (4, 58) => 0.0054993
+(1, -1) ~ (4, 59) => 0.00579447
+(1, -1) ~ (4, 60) => 0.00675058
+(1, -1) ~ (4, 61) => 0.00627697
+(1, -1) ~ (4, 62) => 0.005831
+(1, -1) ~ (4, 63) => 0.00449479
+(1, -1) ~ (4, 64) => 0.0135918
+(1, -1) ~ (4, 65) => 0.0122096
+(1, -1) ~ (4, 66) => 0.0106486
+(1, -1) ~ (4, 67) => 0.00635767
+(1, -1) ~ (4, 68) => 0.00317913
+(1, -1) ~ (4, 69) => 0.00197041
+(1, -1) ~ (4, 70) => 0.00126714
+
+; Sparse posterior probability matrix for sequences 2 and 3
+; Format is:
+; (2, position_1) ~ (3, position_2) => prob
+; which means that (2, position_1) is aligned to (3, position_2) with probability prob.
+; (2, position_1) ~ (3, -1) => prob
+; means that (2, position_1) is aligned to a gap in 3 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (3, 0) => 0.999947
+(2, 1) ~ (3, 1) => 0.999575
+(2, 2) ~ (3, 2) => 0.999214
+(2, 3) ~ (3, 3) => 0.99887
+(2, 4) ~ (3, 4) => 0.99831
+(2, 5) ~ (3, 5) => 0.998182
+(2, 6) ~ (3, 6) => 0.99829
+(2, 7) ~ (3, 7) => 0.998429
+(2, 8) ~ (3, 8) => 0.998767
+(2, 9) ~ (3, 9) => 0.999066
+(2, 10) ~ (3, 10) => 0.999117
+(2, 11) ~ (3, 11) => 0.998802
+(2, 12) ~ (3, 12) => 0.998399
+(2, 13) ~ (3, 13) => 0.998518
+(2, 14) ~ (3, 14) => 0.998869
+(2, 15) ~ (3, 15) => 0.999238
+(2, 16) ~ (3, 16) => 0.999264
+(2, 17) ~ (3, 17) => 0.999154
+(2, 18) ~ (3, 18) => 0.999025
+(2, 19) ~ (3, 19) => 0.99917
+(2, 20) ~ (3, 20) => 0.999306
+(2, 21) ~ (3, 21) => 0.999472
+(2, 22) ~ (3, 22) => 0.999481
+(2, 23) ~ (3, 23) => 0.999569
+(2, 24) ~ (3, 24) => 0.999641
+(2, 25) ~ (3, 25) => 0.999579
+(2, 26) ~ (3, 26) => 0.999351
+(2, 27) ~ (3, 27) => 0.998136
+(2, 28) ~ (3, 28) => 0.996861
+(2, 29) ~ (3, 29) => 0.992417
+(2, 30) ~ (3, 30) => 0.987346
+(2, 31) ~ (3, 31) => 0.975394
+(2, 31) ~ (3, 38) => 0.015923
+(2, 32) ~ (3, 32) => 0.973891
+(2, 32) ~ (3, 39) => 0.0176899
+(2, 33) ~ (3, 33) => 0.973302
+(2, 33) ~ (3, 40) => 0.0185581
+(2, 34) ~ (3, 34) => 0.971226
+(2, 34) ~ (3, 41) => 0.0198995
+(2, 35) ~ (3, 35) => 0.969745
+(2, 35) ~ (3, 42) => 0.0210121
+(2, 36) ~ (3, 36) => 0.967632
+(2, 36) ~ (3, 43) => 0.0217485
+(2, 37) ~ (3, 37) => 0.964778
+(2, 37) ~ (3, 44) => 0.0223772
+(2, 38) ~ (3, 38) => 0.953399
+(2, 38) ~ (3, 45) => 0.0214184
+(2, 39) ~ (3, 39) => 0.93942
+(2, 39) ~ (3, 46) => 0.0200209
+(2, 39) ~ (3, 49) => 0.0161367
+(2, 40) ~ (3, 40) => 0.918972
+(2, 40) ~ (3, 47) => 0.0203095
+(2, 40) ~ (3, 50) => 0.0222161
+(2, 41) ~ (3, 41) => 0.899034
+(2, 41) ~ (3, 44) => 0.0102455
+(2, 41) ~ (3, 45) => 0.0119202
+(2, 41) ~ (3, 48) => 0.019201
+(2, 41) ~ (3, 51) => 0.0290967
+(2, 42) ~ (3, 42) => 0.803096
+(2, 42) ~ (3, 45) => 0.0837254
+(2, 42) ~ (3, 46) => 0.0143956
+(2, 42) ~ (3, 49) => 0.0166466
+(2, 42) ~ (3, 50) => 0.0127695
+(2, 42) ~ (3, 52) => 0.035725
+(2, 43) ~ (3, 43) => 0.703701
+(2, 43) ~ (3, 46) => 0.157502
+(2, 43) ~ (3, 47) => 0.020418
+(2, 43) ~ (3, 50) => 0.0149749
+(2, 43) ~ (3, 51) => 0.0245522
+(2, 43) ~ (3, 53) => 0.0401055
+(2, 44) ~ (3, 44) => 0.57052
+(2, 44) ~ (3, 47) => 0.279577
+(2, 44) ~ (3, 48) => 0.0221508
+(2, 44) ~ (3, 51) => 0.0140063
+(2, 44) ~ (3, 52) => 0.0338077
+(2, 44) ~ (3, 54) => 0.042243
+(2, 45) ~ (3, 45) => 0.527121
+(2, 45) ~ (3, 48) => 0.321751
+(2, 45) ~ (3, 49) => 0.0217577
+(2, 45) ~ (3, 52) => 0.0125016
+(2, 45) ~ (3, 53) => 0.0372461
+(2, 45) ~ (3, 55) => 0.0441308
+(2, 46) ~ (3, 46) => 0.483585
+(2, 46) ~ (3, 49) => 0.363802
+(2, 46) ~ (3, 50) => 0.0227212
+(2, 46) ~ (3, 54) => 0.0389651
+(2, 46) ~ (3, 56) => 0.0453491
+(2, 47) ~ (3, 47) => 0.429915
+(2, 47) ~ (3, 50) => 0.384198
+(2, 47) ~ (3, 51) => 0.0191817
+(2, 47) ~ (3, 53) => 0.0319531
+(2, 47) ~ (3, 55) => 0.0377027
+(2, 47) ~ (3, 57) => 0.0444744
+(2, 48) ~ (3, 48) => 0.393476
+(2, 48) ~ (3, 51) => 0.385334
+(2, 48) ~ (3, 52) => 0.0188001
+(2, 48) ~ (3, 53) => 0.019089
+(2, 48) ~ (3, 54) => 0.0562167
+(2, 48) ~ (3, 56) => 0.0380848
+(2, 48) ~ (3, 58) => 0.0425972
+(2, 49) ~ (3, 49) => 0.351502
+(2, 49) ~ (3, 52) => 0.384086
+(2, 49) ~ (3, 53) => 0.0152873
+(2, 49) ~ (3, 54) => 0.0242159
+(2, 49) ~ (3, 55) => 0.091456
+(2, 49) ~ (3, 57) => 0.0412649
+(2, 49) ~ (3, 59) => 0.0407586
+(2, 50) ~ (3, 50) => 0.211871
+(2, 50) ~ (3, 53) => 0.392184
+(2, 50) ~ (3, 54) => 0.010663
+(2, 50) ~ (3, 55) => 0.0236556
+(2, 50) ~ (3, 56) => 0.227295
+(2, 50) ~ (3, 58) => 0.0429079
+(2, 50) ~ (3, 60) => 0.03873
+(2, 51) ~ (3, 51) => 0.0266461
+(2, 51) ~ (3, 54) => 0.359766
+(2, 51) ~ (3, 56) => 0.0140821
+(2, 51) ~ (3, 57) => 0.48286
+(2, 51) ~ (3, 59) => 0.0437669
+(2, 51) ~ (3, 61) => 0.0315115
+(2, 52) ~ (3, 52) => 0.0222039
+(2, 52) ~ (3, 55) => 0.316429
+(2, 52) ~ (3, 58) => 0.547264
+(2, 52) ~ (3, 60) => 0.0418991
+(2, 52) ~ (3, 62) => 0.023413
+(2, 53) ~ (3, 53) => 0.0176828
+(2, 53) ~ (3, 56) => 0.26957
+(2, 53) ~ (3, 59) => 0.601712
+(2, 53) ~ (3, 61) => 0.0324992
+(2, 54) ~ (3, 54) => 0.0158207
+(2, 54) ~ (3, 57) => 0.25143
+(2, 54) ~ (3, 60) => 0.624199
+(2, 54) ~ (3, 62) => 0.0226157
+(2, 55) ~ (3, 58) => 0.172852
+(2, 55) ~ (3, 61) => 0.727637
+(2, 55) ~ (3, 63) => 0.0129581
+(2, 56) ~ (3, 59) => 0.156297
+(2, 56) ~ (3, 61) => 0.0112923
+(2, 56) ~ (3, 62) => 0.765054
+(2, 56) ~ (3, 64) => 0.0101235
+(2, 57) ~ (3, 60) => 0.112502
+(2, 57) ~ (3, 62) => 0.0111839
+(2, 57) ~ (3, 63) => 0.836895
+(2, 58) ~ (3, 61) => 0.0697027
+(2, 58) ~ (3, 64) => 0.892758
+(2, 59) ~ (3, 62) => 0.0478014
+(2, 59) ~ (3, 65) => 0.923074
+(2, 60) ~ (3, 63) => 0.026092
+(2, 60) ~ (3, 66) => 0.951758
+(2, 61) ~ (3, 67) => 0.982544
+(2, 62) ~ (3, 68) => 0.98509
+
+; gap posteriors
+(2, 0) ~ (3, -1) => 0.0001
+(2, 1) ~ (3, -1) => 0.000425398
+(2, 2) ~ (3, -1) => 0.000786066
+(2, 3) ~ (3, -1) => 0.00112969
+(2, 4) ~ (3, -1) => 0.00168991
+(2, 5) ~ (3, -1) => 0.00181818
+(2, 6) ~ (3, -1) => 0.00170982
+(2, 7) ~ (3, -1) => 0.00157106
+(2, 8) ~ (3, -1) => 0.0012331
+(2, 9) ~ (3, -1) => 0.000933766
+(2, 10) ~ (3, -1) => 0.000883043
+(2, 11) ~ (3, -1) => 0.00119829
+(2, 12) ~ (3, -1) => 0.0016014
+(2, 13) ~ (3, -1) => 0.00148249
+(2, 14) ~ (3, -1) => 0.00113052
+(2, 15) ~ (3, -1) => 0.000762403
+(2, 16) ~ (3, -1) => 0.000735939
+(2, 17) ~ (3, -1) => 0.000846386
+(2, 18) ~ (3, -1) => 0.000974774
+(2, 19) ~ (3, -1) => 0.000830472
+(2, 20) ~ (3, -1) => 0.000693679
+(2, 21) ~ (3, -1) => 0.000527978
+(2, 22) ~ (3, -1) => 0.00051868
+(2, 23) ~ (3, -1) => 0.000430584
+(2, 24) ~ (3, -1) => 0.000358582
+(2, 25) ~ (3, -1) => 0.000420928
+(2, 26) ~ (3, -1) => 0.000649154
+(2, 27) ~ (3, -1) => 0.00186402
+(2, 28) ~ (3, -1) => 0.0031389
+(2, 29) ~ (3, -1) => 0.00758296
+(2, 30) ~ (3, -1) => 0.0126536
+(2, 31) ~ (3, -1) => 0.00868261
+(2, 32) ~ (3, -1) => 0.00841863
+(2, 33) ~ (3, -1) => 0.00813985
+(2, 34) ~ (3, -1) => 0.00887471
+(2, 35) ~ (3, -1) => 0.00924337
+(2, 36) ~ (3, -1) => 0.0106191
+(2, 37) ~ (3, -1) => 0.0128444
+(2, 38) ~ (3, -1) => 0.0251826
+(2, 39) ~ (3, -1) => 0.0244229
+(2, 40) ~ (3, -1) => 0.0385019
+(2, 41) ~ (3, -1) => 0.0305023
+(2, 42) ~ (3, -1) => 0.0336419
+(2, 43) ~ (3, -1) => 0.0387467
+(2, 44) ~ (3, -1) => 0.0376953
+(2, 45) ~ (3, -1) => 0.035491
+(2, 46) ~ (3, -1) => 0.0455778
+(2, 47) ~ (3, -1) => 0.0525756
+(2, 48) ~ (3, -1) => 0.0464022
+(2, 49) ~ (3, -1) => 0.0514287
+(2, 50) ~ (3, -1) => 0.0526932
+(2, 51) ~ (3, -1) => 0.041367
+(2, 52) ~ (3, -1) => 0.0487913
+(2, 53) ~ (3, -1) => 0.0785365
+(2, 54) ~ (3, -1) => 0.0859343
+(2, 55) ~ (3, -1) => 0.0865522
+(2, 56) ~ (3, -1) => 0.0572338
+(2, 57) ~ (3, -1) => 0.0394192
+(2, 58) ~ (3, -1) => 0.037539
+(2, 59) ~ (3, -1) => 0.0291246
+(2, 60) ~ (3, -1) => 0.0221495
+(2, 61) ~ (3, -1) => 0.0174562
+(2, 62) ~ (3, -1) => 0.0149099
+
+(2, -1) ~ (3, 0) => 0.0001
+(2, -1) ~ (3, 1) => 0.000425398
+(2, -1) ~ (3, 2) => 0.000786066
+(2, -1) ~ (3, 3) => 0.00112969
+(2, -1) ~ (3, 4) => 0.00168991
+(2, -1) ~ (3, 5) => 0.00181818
+(2, -1) ~ (3, 6) => 0.00170982
+(2, -1) ~ (3, 7) => 0.00157106
+(2, -1) ~ (3, 8) => 0.0012331
+(2, -1) ~ (3, 9) => 0.000933766
+(2, -1) ~ (3, 10) => 0.000883043
+(2, -1) ~ (3, 11) => 0.00119829
+(2, -1) ~ (3, 12) => 0.0016014
+(2, -1) ~ (3, 13) => 0.00148249
+(2, -1) ~ (3, 14) => 0.00113052
+(2, -1) ~ (3, 15) => 0.000762403
+(2, -1) ~ (3, 16) => 0.000735939
+(2, -1) ~ (3, 17) => 0.000846386
+(2, -1) ~ (3, 18) => 0.000974774
+(2, -1) ~ (3, 19) => 0.000830472
+(2, -1) ~ (3, 20) => 0.000693679
+(2, -1) ~ (3, 21) => 0.000527978
+(2, -1) ~ (3, 22) => 0.00051868
+(2, -1) ~ (3, 23) => 0.000430584
+(2, -1) ~ (3, 24) => 0.000358582
+(2, -1) ~ (3, 25) => 0.000420928
+(2, -1) ~ (3, 26) => 0.000649154
+(2, -1) ~ (3, 27) => 0.00186402
+(2, -1) ~ (3, 28) => 0.0031389
+(2, -1) ~ (3, 29) => 0.00758296
+(2, -1) ~ (3, 30) => 0.0126536
+(2, -1) ~ (3, 31) => 0.0246056
+(2, -1) ~ (3, 32) => 0.0261086
+(2, -1) ~ (3, 33) => 0.026698
+(2, -1) ~ (3, 34) => 0.0287742
+(2, -1) ~ (3, 35) => 0.0302554
+(2, -1) ~ (3, 36) => 0.0323676
+(2, -1) ~ (3, 37) => 0.0352216
+(2, -1) ~ (3, 38) => 0.030678
+(2, -1) ~ (3, 39) => 0.0428905
+(2, -1) ~ (3, 40) => 0.0624694
+(2, -1) ~ (3, 41) => 0.0810661
+(2, -1) ~ (3, 42) => 0.175892
+(2, -1) ~ (3, 43) => 0.274551
+(2, -1) ~ (3, 44) => 0.396857
+(2, -1) ~ (3, 45) => 0.355815
+(2, -1) ~ (3, 46) => 0.324496
+(2, -1) ~ (3, 47) => 0.249781
+(2, -1) ~ (3, 48) => 0.243421
+(2, -1) ~ (3, 49) => 0.230155
+(2, -1) ~ (3, 50) => 0.33125
+(2, -1) ~ (3, 51) => 0.501183
+(2, -1) ~ (3, 52) => 0.492875
+(2, -1) ~ (3, 53) => 0.446452
+(2, -1) ~ (3, 54) => 0.452109
+(2, -1) ~ (3, 55) => 0.486626
+(2, -1) ~ (3, 56) => 0.405619
+(2, -1) ~ (3, 57) => 0.17997
+(2, -1) ~ (3, 58) => 0.194379
+(2, -1) ~ (3, 59) => 0.157466
+(2, -1) ~ (3, 60) => 0.18267
+(2, -1) ~ (3, 61) => 0.127357
+(2, -1) ~ (3, 62) => 0.129932
+(2, -1) ~ (3, 63) => 0.124055
+(2, -1) ~ (3, 64) => 0.0971181
+(2, -1) ~ (3, 65) => 0.076926
+(2, -1) ~ (3, 66) => 0.0482416
+(2, -1) ~ (3, 67) => 0.0174562
+(2, -1) ~ (3, 68) => 0.0149099
+
+; Sparse posterior probability matrix for sequences 2 and 4
+; Format is:
+; (2, position_1) ~ (4, position_2) => prob
+; which means that (2, position_1) is aligned to (4, position_2) with probability prob.
+; (2, position_1) ~ (4, -1) => prob
+; means that (2, position_1) is aligned to a gap in 4 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(2, 0) ~ (4, 0) => 0.998542
+(2, 1) ~ (4, 1) => 0.995426
+(2, 2) ~ (4, 2) => 0.988666
+(2, 3) ~ (4, 3) => 0.9822
+(2, 4) ~ (4, 4) => 0.976237
+(2, 4) ~ (4, 5) => 0.011716
+(2, 5) ~ (4, 5) => 0.970037
+(2, 5) ~ (4, 6) => 0.0135695
+(2, 6) ~ (4, 6) => 0.969056
+(2, 6) ~ (4, 7) => 0.0128288
+(2, 7) ~ (4, 7) => 0.967063
+(2, 7) ~ (4, 8) => 0.0117285
+(2, 8) ~ (4, 8) => 0.961482
+(2, 8) ~ (4, 10) => 0.0113458
+(2, 9) ~ (4, 9) => 0.945805
+(2, 9) ~ (4, 11) => 0.0200771
+(2, 10) ~ (4, 10) => 0.917843
+(2, 10) ~ (4, 12) => 0.0322421
+(2, 11) ~ (4, 11) => 0.898282
+(2, 11) ~ (4, 13) => 0.0360191
+(2, 12) ~ (4, 12) => 0.875037
+(2, 12) ~ (4, 14) => 0.03943
+(2, 13) ~ (4, 13) => 0.839135
+(2, 13) ~ (4, 15) => 0.0426612
+(2, 13) ~ (4, 16) => 0.0126761
+(2, 14) ~ (4, 14) => 0.791557
+(2, 14) ~ (4, 16) => 0.0512953
+(2, 14) ~ (4, 17) => 0.0182511
+(2, 15) ~ (4, 15) => 0.752944
+(2, 15) ~ (4, 17) => 0.0601359
+(2, 15) ~ (4, 18) => 0.0200182
+(2, 16) ~ (4, 13) => 0.0143305
+(2, 16) ~ (4, 14) => 0.0207263
+(2, 16) ~ (4, 16) => 0.626354
+(2, 16) ~ (4, 18) => 0.107548
+(2, 16) ~ (4, 19) => 0.0164787
+(2, 16) ~ (4, 26) => 0.0135834
+(2, 17) ~ (4, 14) => 0.0194406
+(2, 17) ~ (4, 15) => 0.034932
+(2, 17) ~ (4, 17) => 0.488906
+(2, 17) ~ (4, 19) => 0.201939
+(2, 17) ~ (4, 20) => 0.0127226
+(2, 17) ~ (4, 27) => 0.0163895
+(2, 18) ~ (4, 15) => 0.0234762
+(2, 18) ~ (4, 16) => 0.0780552
+(2, 18) ~ (4, 18) => 0.194741
+(2, 18) ~ (4, 20) => 0.428106
+(2, 18) ~ (4, 21) => 0.0118382
+(2, 18) ~ (4, 28) => 0.0185021
+(2, 19) ~ (4, 10) => 0.0133417
+(2, 19) ~ (4, 13) => 0.0139654
+(2, 19) ~ (4, 16) => 0.0487628
+(2, 19) ~ (4, 17) => 0.0960511
+(2, 19) ~ (4, 19) => 0.118091
+(2, 19) ~ (4, 20) => 0.0149224
+(2, 19) ~ (4, 21) => 0.464154
+(2, 19) ~ (4, 29) => 0.0207406
+(2, 20) ~ (4, 11) => 0.0194049
+(2, 20) ~ (4, 14) => 0.016594
+(2, 20) ~ (4, 17) => 0.0584456
+(2, 20) ~ (4, 18) => 0.139877
+(2, 20) ~ (4, 20) => 0.0892666
+(2, 20) ~ (4, 22) => 0.490776
+(2, 20) ~ (4, 30) => 0.0225482
+(2, 21) ~ (4, 12) => 0.0283802
+(2, 21) ~ (4, 15) => 0.0199346
+(2, 21) ~ (4, 18) => 0.0615525
+(2, 21) ~ (4, 19) => 0.173024
+(2, 21) ~ (4, 21) => 0.0478844
+(2, 21) ~ (4, 23) => 0.528753
+(2, 21) ~ (4, 31) => 0.0254757
+(2, 22) ~ (4, 13) => 0.0395842
+(2, 22) ~ (4, 16) => 0.0218912
+(2, 22) ~ (4, 19) => 0.0538685
+(2, 22) ~ (4, 20) => 0.180307
+(2, 22) ~ (4, 22) => 0.0236441
+(2, 22) ~ (4, 24) => 0.545339
+(2, 22) ~ (4, 32) => 0.0289556
+(2, 23) ~ (4, 14) => 0.0456339
+(2, 23) ~ (4, 17) => 0.0208566
+(2, 23) ~ (4, 20) => 0.0535287
+(2, 23) ~ (4, 21) => 0.168727
+(2, 23) ~ (4, 23) => 0.010217
+(2, 23) ~ (4, 25) => 0.565428
+(2, 23) ~ (4, 31) => 0.0102546
+(2, 23) ~ (4, 33) => 0.0325792
+(2, 24) ~ (4, 15) => 0.0482736
+(2, 24) ~ (4, 18) => 0.0218967
+(2, 24) ~ (4, 21) => 0.0416151
+(2, 24) ~ (4, 22) => 0.157218
+(2, 24) ~ (4, 23) => 0.0106472
+(2, 24) ~ (4, 26) => 0.588907
+(2, 24) ~ (4, 32) => 0.0122367
+(2, 24) ~ (4, 34) => 0.0283261
+(2, 25) ~ (4, 16) => 0.0499502
+(2, 25) ~ (4, 19) => 0.0197446
+(2, 25) ~ (4, 22) => 0.0277653
+(2, 25) ~ (4, 23) => 0.118998
+(2, 25) ~ (4, 27) => 0.62122
+(2, 25) ~ (4, 33) => 0.0131312
+(2, 25) ~ (4, 34) => 0.0316962
+(2, 25) ~ (4, 35) => 0.0298539
+(2, 26) ~ (4, 17) => 0.0527431
+(2, 26) ~ (4, 20) => 0.0187036
+(2, 26) ~ (4, 23) => 0.0206173
+(2, 26) ~ (4, 24) => 0.10183
+(2, 26) ~ (4, 28) => 0.629162
+(2, 26) ~ (4, 34) => 0.0134891
+(2, 26) ~ (4, 35) => 0.0435539
+(2, 26) ~ (4, 36) => 0.0292252
+(2, 27) ~ (4, 18) => 0.0545301
+(2, 27) ~ (4, 21) => 0.0165803
+(2, 27) ~ (4, 23) => 0.0149166
+(2, 27) ~ (4, 24) => 0.0168673
+(2, 27) ~ (4, 25) => 0.0685298
+(2, 27) ~ (4, 29) => 0.611743
+(2, 27) ~ (4, 30) => 0.0193867
+(2, 27) ~ (4, 35) => 0.0121248
+(2, 27) ~ (4, 36) => 0.0525759
+(2, 27) ~ (4, 37) => 0.0312284
+(2, 28) ~ (4, 19) => 0.0536277
+(2, 28) ~ (4, 22) => 0.0149467
+(2, 28) ~ (4, 24) => 0.0165919
+(2, 28) ~ (4, 25) => 0.0180463
+(2, 28) ~ (4, 26) => 0.0384618
+(2, 28) ~ (4, 28) => 0.0159832
+(2, 28) ~ (4, 29) => 0.013103
+(2, 28) ~ (4, 30) => 0.60593
+(2, 28) ~ (4, 31) => 0.0227669
+(2, 28) ~ (4, 36) => 0.0144775
+(2, 28) ~ (4, 37) => 0.0556122
+(2, 28) ~ (4, 38) => 0.0311845
+(2, 28) ~ (4, 39) => 0.0107012
+(2, 29) ~ (4, 20) => 0.048755
+(2, 29) ~ (4, 25) => 0.0264382
+(2, 29) ~ (4, 26) => 0.0184859
+(2, 29) ~ (4, 28) => 0.0110817
+(2, 29) ~ (4, 29) => 0.0453943
+(2, 29) ~ (4, 30) => 0.0174069
+(2, 29) ~ (4, 31) => 0.572724
+(2, 29) ~ (4, 32) => 0.0257223
+(2, 29) ~ (4, 37) => 0.015401
+(2, 29) ~ (4, 38) => 0.0567127
+(2, 29) ~ (4, 39) => 0.0286675
+(2, 29) ~ (4, 40) => 0.0111553
+(2, 30) ~ (4, 21) => 0.0412323
+(2, 30) ~ (4, 23) => 0.0151097
+(2, 30) ~ (4, 26) => 0.0289787
+(2, 30) ~ (4, 27) => 0.0123347
+(2, 30) ~ (4, 29) => 0.0321478
+(2, 30) ~ (4, 30) => 0.0536235
+(2, 30) ~ (4, 31) => 0.0235189
+(2, 30) ~ (4, 32) => 0.40967
+(2, 30) ~ (4, 33) => 0.0225321
+(2, 30) ~ (4, 38) => 0.0181489
+(2, 30) ~ (4, 39) => 0.061002
+(2, 30) ~ (4, 40) => 0.0271024
+(2, 30) ~ (4, 41) => 0.0108536
+(2, 31) ~ (4, 22) => 0.028064
+(2, 31) ~ (4, 24) => 0.0264322
+(2, 31) ~ (4, 27) => 0.0269888
+(2, 31) ~ (4, 28) => 0.0158611
+(2, 31) ~ (4, 30) => 0.0415634
+(2, 31) ~ (4, 31) => 0.069801
+(2, 31) ~ (4, 32) => 0.0137445
+(2, 31) ~ (4, 33) => 0.200735
+(2, 31) ~ (4, 34) => 0.0193556
+(2, 31) ~ (4, 39) => 0.0241224
+(2, 31) ~ (4, 40) => 0.0699924
+(2, 31) ~ (4, 41) => 0.0249167
+(2, 31) ~ (4, 42) => 0.0105018
+(2, 32) ~ (4, 23) => 0.0136887
+(2, 32) ~ (4, 25) => 0.0282818
+(2, 32) ~ (4, 29) => 0.0114172
+(2, 32) ~ (4, 31) => 0.0589819
+(2, 32) ~ (4, 32) => 0.258287
+(2, 32) ~ (4, 33) => 0.0422695
+(2, 32) ~ (4, 34) => 0.0996642
+(2, 32) ~ (4, 40) => 0.0349906
+(2, 32) ~ (4, 41) => 0.0800872
+(2, 32) ~ (4, 42) => 0.0236234
+(2, 32) ~ (4, 43) => 0.0105396
+(2, 33) ~ (4, 26) => 0.0272326
+(2, 33) ~ (4, 32) => 0.0678857
+(2, 33) ~ (4, 33) => 0.419549
+(2, 33) ~ (4, 34) => 0.0618204
+(2, 33) ~ (4, 35) => 0.0860165
+(2, 33) ~ (4, 41) => 0.0373187
+(2, 33) ~ (4, 42) => 0.0834393
+(2, 33) ~ (4, 43) => 0.0225148
+(2, 33) ~ (4, 44) => 0.0104026
+(2, 34) ~ (4, 27) => 0.0278057
+(2, 34) ~ (4, 33) => 0.088788
+(2, 34) ~ (4, 34) => 0.477058
+(2, 34) ~ (4, 35) => 0.0675444
+(2, 34) ~ (4, 36) => 0.0774371
+(2, 34) ~ (4, 42) => 0.0371009
+(2, 34) ~ (4, 43) => 0.0842122
+(2, 34) ~ (4, 44) => 0.0201752
+(2, 35) ~ (4, 28) => 0.0286754
+(2, 35) ~ (4, 34) => 0.0837725
+(2, 35) ~ (4, 35) => 0.506085
+(2, 35) ~ (4, 36) => 0.0747323
+(2, 35) ~ (4, 37) => 0.0764505
+(2, 35) ~ (4, 43) => 0.0355005
+(2, 35) ~ (4, 44) => 0.0828104
+(2, 35) ~ (4, 45) => 0.0136008
+(2, 36) ~ (4, 29) => 0.027168
+(2, 36) ~ (4, 35) => 0.0643335
+(2, 36) ~ (4, 36) => 0.510644
+(2, 36) ~ (4, 37) => 0.0893118
+(2, 36) ~ (4, 38) => 0.0813454
+(2, 36) ~ (4, 44) => 0.0324763
+(2, 36) ~ (4, 45) => 0.0769031
+(2, 36) ~ (4, 46) => 0.0122441
+(2, 36) ~ (4, 47) => 0.0117149
+(2, 36) ~ (4, 48) => 0.017039
+(2, 37) ~ (4, 30) => 0.0229957
+(2, 37) ~ (4, 36) => 0.0706496
+(2, 37) ~ (4, 37) => 0.510045
+(2, 37) ~ (4, 38) => 0.100204
+(2, 37) ~ (4, 39) => 0.0855251
+(2, 37) ~ (4, 45) => 0.029787
+(2, 37) ~ (4, 46) => 0.0661604
+(2, 37) ~ (4, 48) => 0.0135499
+(2, 37) ~ (4, 49) => 0.0269367
+(2, 38) ~ (4, 31) => 0.0175032
+(2, 38) ~ (4, 37) => 0.0700266
+(2, 38) ~ (4, 38) => 0.500383
+(2, 38) ~ (4, 39) => 0.105014
+(2, 38) ~ (4, 40) => 0.0818513
+(2, 38) ~ (4, 46) => 0.0234666
+(2, 38) ~ (4, 47) => 0.045906
+(2, 38) ~ (4, 49) => 0.0131891
+(2, 38) ~ (4, 50) => 0.0505568
+(2, 39) ~ (4, 32) => 0.0174012
+(2, 39) ~ (4, 38) => 0.0729988
+(2, 39) ~ (4, 39) => 0.495093
+(2, 39) ~ (4, 40) => 0.111376
+(2, 39) ~ (4, 41) => 0.0786771
+(2, 39) ~ (4, 47) => 0.0283747
+(2, 39) ~ (4, 48) => 0.0460581
+(2, 39) ~ (4, 51) => 0.0545152
+(2, 40) ~ (4, 33) => 0.0162995
+(2, 40) ~ (4, 39) => 0.076679
+(2, 40) ~ (4, 40) => 0.493329
+(2, 40) ~ (4, 41) => 0.114089
+(2, 40) ~ (4, 42) => 0.0766321
+(2, 40) ~ (4, 48) => 0.0278742
+(2, 40) ~ (4, 49) => 0.0420016
+(2, 40) ~ (4, 51) => 0.0110042
+(2, 40) ~ (4, 52) => 0.0547848
+(2, 41) ~ (4, 34) => 0.0116131
+(2, 41) ~ (4, 40) => 0.0914023
+(2, 41) ~ (4, 41) => 0.473634
+(2, 41) ~ (4, 42) => 0.111796
+(2, 41) ~ (4, 43) => 0.0713917
+(2, 41) ~ (4, 49) => 0.0269032
+(2, 41) ~ (4, 50) => 0.0395052
+(2, 41) ~ (4, 52) => 0.0132486
+(2, 41) ~ (4, 53) => 0.0566103
+(2, 42) ~ (4, 40) => 0.010478
+(2, 42) ~ (4, 41) => 0.119968
+(2, 42) ~ (4, 42) => 0.468146
+(2, 42) ~ (4, 43) => 0.114051
+(2, 42) ~ (4, 44) => 0.0674412
+(2, 42) ~ (4, 49) => 0.0116669
+(2, 42) ~ (4, 50) => 0.0207721
+(2, 42) ~ (4, 51) => 0.0295392
+(2, 42) ~ (4, 53) => 0.012907
+(2, 42) ~ (4, 54) => 0.0614878
+(2, 43) ~ (4, 41) => 0.0117239
+(2, 43) ~ (4, 42) => 0.131597
+(2, 43) ~ (4, 43) => 0.455075
+(2, 43) ~ (4, 44) => 0.110172
+(2, 43) ~ (4, 45) => 0.0534491
+(2, 43) ~ (4, 50) => 0.0282732
+(2, 43) ~ (4, 51) => 0.0164233
+(2, 43) ~ (4, 52) => 0.0210911
+(2, 43) ~ (4, 53) => 0.0203271
+(2, 43) ~ (4, 54) => 0.0161768
+(2, 43) ~ (4, 55) => 0.0610701
+(2, 44) ~ (4, 42) => 0.0112944
+(2, 44) ~ (4, 43) => 0.139226
+(2, 44) ~ (4, 44) => 0.421492
+(2, 44) ~ (4, 45) => 0.0887165
+(2, 44) ~ (4, 46) => 0.040336
+(2, 44) ~ (4, 51) => 0.0649874
+(2, 44) ~ (4, 52) => 0.0112763
+(2, 44) ~ (4, 53) => 0.0119737
+(2, 44) ~ (4, 54) => 0.053519
+(2, 44) ~ (4, 55) => 0.0155204
+(2, 44) ~ (4, 56) => 0.0574473
+(2, 45) ~ (4, 44) => 0.142093
+(2, 45) ~ (4, 45) => 0.338973
+(2, 45) ~ (4, 46) => 0.077569
+(2, 45) ~ (4, 47) => 0.0328013
+(2, 45) ~ (4, 49) => 0.0101379
+(2, 45) ~ (4, 51) => 0.0124482
+(2, 45) ~ (4, 52) => 0.136998
+(2, 45) ~ (4, 54) => 0.0126651
+(2, 45) ~ (4, 55) => 0.0692334
+(2, 45) ~ (4, 56) => 0.0110808
+(2, 45) ~ (4, 57) => 0.0585642
+(2, 46) ~ (4, 45) => 0.128081
+(2, 46) ~ (4, 46) => 0.266793
+(2, 46) ~ (4, 47) => 0.066356
+(2, 46) ~ (4, 48) => 0.0234567
+(2, 46) ~ (4, 50) => 0.012666
+(2, 46) ~ (4, 52) => 0.0160433
+(2, 46) ~ (4, 53) => 0.241252
+(2, 46) ~ (4, 54) => 0.0103079
+(2, 46) ~ (4, 56) => 0.0726072
+(2, 46) ~ (4, 58) => 0.0620953
+(2, 47) ~ (4, 46) => 0.11423
+(2, 47) ~ (4, 47) => 0.204916
+(2, 47) ~ (4, 48) => 0.054265
+(2, 47) ~ (4, 49) => 0.0122485
+(2, 47) ~ (4, 51) => 0.0217386
+(2, 47) ~ (4, 53) => 0.0281462
+(2, 47) ~ (4, 54) => 0.278594
+(2, 47) ~ (4, 55) => 0.0621101
+(2, 47) ~ (4, 57) => 0.0578478
+(2, 47) ~ (4, 59) => 0.0566805
+(2, 48) ~ (4, 47) => 0.0887885
+(2, 48) ~ (4, 48) => 0.113481
+(2, 48) ~ (4, 49) => 0.0294213
+(2, 48) ~ (4, 50) => 0.0277509
+(2, 48) ~ (4, 52) => 0.0240366
+(2, 48) ~ (4, 53) => 0.0183568
+(2, 48) ~ (4, 54) => 0.0513192
+(2, 48) ~ (4, 55) => 0.316657
+(2, 48) ~ (4, 56) => 0.113577
+(2, 48) ~ (4, 58) => 0.039584
+(2, 48) ~ (4, 60) => 0.0580738
+(2, 49) ~ (4, 47) => 0.010221
+(2, 49) ~ (4, 48) => 0.0671802
+(2, 49) ~ (4, 49) => 0.031381
+(2, 49) ~ (4, 51) => 0.0425332
+(2, 49) ~ (4, 53) => 0.0248722
+(2, 49) ~ (4, 54) => 0.0435647
+(2, 49) ~ (4, 55) => 0.0433843
+(2, 49) ~ (4, 56) => 0.288596
+(2, 49) ~ (4, 57) => 0.256565
+(2, 49) ~ (4, 59) => 0.0262983
+(2, 49) ~ (4, 61) => 0.050732
+(2, 50) ~ (4, 49) => 0.0370334
+(2, 50) ~ (4, 50) => 0.0265945
+(2, 50) ~ (4, 52) => 0.0411731
+(2, 50) ~ (4, 54) => 0.0251351
+(2, 50) ~ (4, 55) => 0.0520817
+(2, 50) ~ (4, 56) => 0.0309156
+(2, 50) ~ (4, 57) => 0.281636
+(2, 50) ~ (4, 58) => 0.329423
+(2, 50) ~ (4, 60) => 0.0218362
+(2, 50) ~ (4, 62) => 0.0427575
+(2, 51) ~ (4, 51) => 0.0206836
+(2, 51) ~ (4, 53) => 0.0389724
+(2, 51) ~ (4, 56) => 0.0332808
+(2, 51) ~ (4, 57) => 0.0210553
+(2, 51) ~ (4, 58) => 0.261659
+(2, 51) ~ (4, 59) => 0.481388
+(2, 51) ~ (4, 63) => 0.0250212
+(2, 52) ~ (4, 52) => 0.017403
+(2, 52) ~ (4, 54) => 0.0313144
+(2, 52) ~ (4, 58) => 0.0163025
+(2, 52) ~ (4, 59) => 0.226902
+(2, 52) ~ (4, 60) => 0.569504
+(2, 52) ~ (4, 64) => 0.0147197
+(2, 53) ~ (4, 53) => 0.0109879
+(2, 53) ~ (4, 55) => 0.0228179
+(2, 53) ~ (4, 59) => 0.0133433
+(2, 53) ~ (4, 60) => 0.208012
+(2, 53) ~ (4, 61) => 0.63705
+(2, 54) ~ (4, 56) => 0.0137268
+(2, 54) ~ (4, 60) => 0.0124162
+(2, 54) ~ (4, 61) => 0.188405
+(2, 54) ~ (4, 62) => 0.690922
+(2, 55) ~ (4, 61) => 0.010233
+(2, 55) ~ (4, 62) => 0.16719
+(2, 55) ~ (4, 63) => 0.746819
+(2, 56) ~ (4, 63) => 0.148808
+(2, 56) ~ (4, 64) => 0.792702
+(2, 57) ~ (4, 64) => 0.126001
+(2, 57) ~ (4, 65) => 0.839467
+(2, 58) ~ (4, 65) => 0.101762
+(2, 58) ~ (4, 66) => 0.875193
+(2, 59) ~ (4, 66) => 0.0770482
+(2, 59) ~ (4, 67) => 0.907624
+(2, 60) ~ (4, 67) => 0.0518415
+(2, 60) ~ (4, 68) => 0.938915
+(2, 61) ~ (4, 68) => 0.0344177
+(2, 61) ~ (4, 69) => 0.959284
+(2, 62) ~ (4, 69) => 0.0276166
+(2, 62) ~ (4, 70) => 0.96798
+
+; gap posteriors
+(2, 0) ~ (4, -1) => 0.00145835
+(2, 1) ~ (4, -1) => 0.00457394
+(2, 2) ~ (4, -1) => 0.0113339
+(2, 3) ~ (4, -1) => 0.0178
+(2, 4) ~ (4, -1) => 0.0120469
+(2, 5) ~ (4, -1) => 0.0163938
+(2, 6) ~ (4, -1) => 0.0181152
+(2, 7) ~ (4, -1) => 0.0212082
+(2, 8) ~ (4, -1) => 0.0271727
+(2, 9) ~ (4, -1) => 0.034118
+(2, 10) ~ (4, -1) => 0.0499147
+(2, 11) ~ (4, -1) => 0.0656988
+(2, 12) ~ (4, -1) => 0.0855329
+(2, 13) ~ (4, -1) => 0.105528
+(2, 14) ~ (4, -1) => 0.138896
+(2, 15) ~ (4, -1) => 0.166902
+(2, 16) ~ (4, -1) => 0.200979
+(2, 17) ~ (4, -1) => 0.22567
+(2, 18) ~ (4, -1) => 0.245282
+(2, 19) ~ (4, -1) => 0.209971
+(2, 20) ~ (4, -1) => 0.163088
+(2, 21) ~ (4, -1) => 0.114996
+(2, 22) ~ (4, -1) => 0.106411
+(2, 23) ~ (4, -1) => 0.0927752
+(2, 24) ~ (4, -1) => 0.0908801
+(2, 25) ~ (4, -1) => 0.08764
+(2, 26) ~ (4, -1) => 0.090675
+(2, 27) ~ (4, -1) => 0.101518
+(2, 28) ~ (4, -1) => 0.0885668
+(2, 29) ~ (4, -1) => 0.122055
+(2, 30) ~ (4, -1) => 0.243746
+(2, 31) ~ (4, -1) => 0.427921
+(2, 32) ~ (4, -1) => 0.338169
+(2, 33) ~ (4, -1) => 0.183821
+(2, 34) ~ (4, -1) => 0.119878
+(2, 35) ~ (4, -1) => 0.0983728
+(2, 36) ~ (4, -1) => 0.0768198
+(2, 37) ~ (4, -1) => 0.0741467
+(2, 38) ~ (4, -1) => 0.0921037
+(2, 39) ~ (4, -1) => 0.0955057
+(2, 40) ~ (4, -1) => 0.0873058
+(2, 41) ~ (4, -1) => 0.103895
+(2, 42) ~ (4, -1) => 0.0835427
+(2, 43) ~ (4, -1) => 0.0746221
+(2, 44) ~ (4, -1) => 0.0842112
+(2, 45) ~ (4, -1) => 0.0974357
+(2, 46) ~ (4, -1) => 0.100342
+(2, 47) ~ (4, -1) => 0.109223
+(2, 48) ~ (4, -1) => 0.118954
+(2, 49) ~ (4, -1) => 0.114672
+(2, 50) ~ (4, -1) => 0.111414
+(2, 51) ~ (4, -1) => 0.117939
+(2, 52) ~ (4, -1) => 0.123854
+(2, 53) ~ (4, -1) => 0.10779
+(2, 54) ~ (4, -1) => 0.0945296
+(2, 55) ~ (4, -1) => 0.0757575
+(2, 56) ~ (4, -1) => 0.0584903
+(2, 57) ~ (4, -1) => 0.0345322
+(2, 58) ~ (4, -1) => 0.0230455
+(2, 59) ~ (4, -1) => 0.0153277
+(2, 60) ~ (4, -1) => 0.00924337
+(2, 61) ~ (4, -1) => 0.00629866
+(2, 62) ~ (4, -1) => 0.00440294
+
+(2, -1) ~ (4, 0) => 0.00145835
+(2, -1) ~ (4, 1) => 0.00457394
+(2, -1) ~ (4, 2) => 0.0113339
+(2, -1) ~ (4, 3) => 0.0178
+(2, -1) ~ (4, 4) => 0.0237629
+(2, -1) ~ (4, 5) => 0.0182473
+(2, -1) ~ (4, 6) => 0.0173745
+(2, -1) ~ (4, 7) => 0.0201079
+(2, -1) ~ (4, 8) => 0.02679
+(2, -1) ~ (4, 9) => 0.054195
+(2, -1) ~ (4, 10) => 0.0574693
+(2, -1) ~ (4, 11) => 0.0622358
+(2, -1) ~ (4, 12) => 0.0643405
+(2, -1) ~ (4, 13) => 0.0569663
+(2, -1) ~ (4, 14) => 0.0666182
+(2, -1) ~ (4, 15) => 0.0777789
+(2, -1) ~ (4, 16) => 0.111015
+(2, -1) ~ (4, 17) => 0.204611
+(2, -1) ~ (4, 18) => 0.399836
+(2, -1) ~ (4, 19) => 0.363226
+(2, -1) ~ (4, 20) => 0.153688
+(2, -1) ~ (4, 21) => 0.207969
+(2, -1) ~ (4, 22) => 0.257586
+(2, -1) ~ (4, 23) => 0.267052
+(2, -1) ~ (4, 24) => 0.29294
+(2, -1) ~ (4, 25) => 0.293276
+(2, -1) ~ (4, 26) => 0.284351
+(2, -1) ~ (4, 27) => 0.295261
+(2, -1) ~ (4, 28) => 0.280734
+(2, -1) ~ (4, 29) => 0.238287
+(2, -1) ~ (4, 30) => 0.216545
+(2, -1) ~ (4, 31) => 0.198974
+(2, -1) ~ (4, 32) => 0.166097
+(2, -1) ~ (4, 33) => 0.164116
+(2, -1) ~ (4, 34) => 0.173205
+(2, -1) ~ (4, 35) => 0.190488
+(2, -1) ~ (4, 36) => 0.170258
+(2, -1) ~ (4, 37) => 0.151924
+(2, -1) ~ (4, 38) => 0.139023
+(2, -1) ~ (4, 39) => 0.113196
+(2, -1) ~ (4, 40) => 0.0683219
+(2, -1) ~ (4, 41) => 0.0487309
+(2, -1) ~ (4, 42) => 0.0458689
+(2, -1) ~ (4, 43) => 0.0674903
+(2, -1) ~ (4, 44) => 0.112937
+(2, -1) ~ (4, 45) => 0.27049
+(2, -1) ~ (4, 46) => 0.399201
+(2, -1) ~ (4, 47) => 0.510922
+(2, -1) ~ (4, 48) => 0.637096
+(2, -1) ~ (4, 49) => 0.75908
+(2, -1) ~ (4, 50) => 0.793881
+(2, -1) ~ (4, 51) => 0.726127
+(2, -1) ~ (4, 52) => 0.663945
+(2, -1) ~ (4, 53) => 0.535594
+(2, -1) ~ (4, 54) => 0.415915
+(2, -1) ~ (4, 55) => 0.357125
+(2, -1) ~ (4, 56) => 0.378768
+(2, -1) ~ (4, 57) => 0.324332
+(2, -1) ~ (4, 58) => 0.290936
+(2, -1) ~ (4, 59) => 0.195387
+(2, -1) ~ (4, 60) => 0.130158
+(2, -1) ~ (4, 61) => 0.11358
+(2, -1) ~ (4, 62) => 0.0991303
+(2, -1) ~ (4, 63) => 0.0793515
+(2, -1) ~ (4, 64) => 0.0665778
+(2, -1) ~ (4, 65) => 0.0587713
+(2, -1) ~ (4, 66) => 0.0477591
+(2, -1) ~ (4, 67) => 0.0405344
+(2, -1) ~ (4, 68) => 0.0266672
+(2, -1) ~ (4, 69) => 0.0130997
+(2, -1) ~ (4, 70) => 0.0320196
+
+; Sparse posterior probability matrix for sequences 3 and 4
+; Format is:
+; (3, position_1) ~ (4, position_2) => prob
+; which means that (3, position_1) is aligned to (4, position_2) with probability prob.
+; (3, position_1) ~ (4, -1) => prob
+; means that (3, position_1) is aligned to a gap in 4 with probability prob.
+; sequence is 0-based and position is 0-based
+
+; match posteriors
+(3, 0) ~ (4, 0) => 0.997285
+(3, 1) ~ (4, 1) => 0.992992
+(3, 2) ~ (4, 2) => 0.988812
+(3, 3) ~ (4, 3) => 0.983294
+(3, 4) ~ (4, 4) => 0.971159
+(3, 5) ~ (4, 5) => 0.964403
+(3, 6) ~ (4, 6) => 0.932676
+(3, 7) ~ (4, 4) => 0.0138149
+(3, 7) ~ (4, 7) => 0.901384
+(3, 8) ~ (4, 5) => 0.0165789
+(3, 8) ~ (4, 8) => 0.871325
+(3, 9) ~ (4, 6) => 0.0441118
+(3, 9) ~ (4, 9) => 0.80773
+(3, 10) ~ (4, 7) => 0.0721722
+(3, 10) ~ (4, 10) => 0.742859
+(3, 10) ~ (4, 11) => 0.0103132
+(3, 11) ~ (4, 8) => 0.101789
+(3, 11) ~ (4, 11) => 0.722337
+(3, 11) ~ (4, 12) => 0.0104381
+(3, 12) ~ (4, 9) => 0.164341
+(3, 12) ~ (4, 12) => 0.712839
+(3, 13) ~ (4, 10) => 0.225053
+(3, 13) ~ (4, 13) => 0.709947
+(3, 14) ~ (4, 11) => 0.245643
+(3, 14) ~ (4, 14) => 0.703531
+(3, 15) ~ (4, 12) => 0.25589
+(3, 15) ~ (4, 15) => 0.695015
+(3, 16) ~ (4, 13) => 0.258876
+(3, 16) ~ (4, 16) => 0.685029
+(3, 17) ~ (4, 14) => 0.265331
+(3, 17) ~ (4, 17) => 0.676414
+(3, 17) ~ (4, 18) => 0.0128501
+(3, 18) ~ (4, 12) => 0.0104514
+(3, 18) ~ (4, 15) => 0.271436
+(3, 18) ~ (4, 18) => 0.655436
+(3, 18) ~ (4, 19) => 0.0279704
+(3, 19) ~ (4, 13) => 0.0112605
+(3, 19) ~ (4, 16) => 0.277563
+(3, 19) ~ (4, 19) => 0.620308
+(3, 19) ~ (4, 20) => 0.0424477
+(3, 19) ~ (4, 21) => 0.0149749
+(3, 20) ~ (4, 14) => 0.0118974
+(3, 20) ~ (4, 17) => 0.277555
+(3, 20) ~ (4, 20) => 0.596722
+(3, 20) ~ (4, 21) => 0.0403282
+(3, 20) ~ (4, 22) => 0.0436599
+(3, 21) ~ (4, 15) => 0.0122614
+(3, 21) ~ (4, 18) => 0.268807
+(3, 21) ~ (4, 21) => 0.373359
+(3, 21) ~ (4, 22) => 0.0585173
+(3, 21) ~ (4, 23) => 0.259138
+(3, 22) ~ (4, 16) => 0.0126356
+(3, 22) ~ (4, 19) => 0.259571
+(3, 22) ~ (4, 22) => 0.233008
+(3, 22) ~ (4, 23) => 0.066998
+(3, 22) ~ (4, 24) => 0.397471
+(3, 23) ~ (4, 17) => 0.0128529
+(3, 23) ~ (4, 20) => 0.25384
+(3, 23) ~ (4, 23) => 0.149743
+(3, 23) ~ (4, 24) => 0.0764351
+(3, 23) ~ (4, 25) => 0.476947
+(3, 24) ~ (4, 18) => 0.0117948
+(3, 24) ~ (4, 21) => 0.164833
+(3, 24) ~ (4, 24) => 0.0405693
+(3, 24) ~ (4, 25) => 0.0595401
+(3, 24) ~ (4, 26) => 0.697766
+(3, 25) ~ (4, 19) => 0.0109566
+(3, 25) ~ (4, 22) => 0.0747387
+(3, 25) ~ (4, 25) => 0.0173782
+(3, 25) ~ (4, 26) => 0.0392685
+(3, 25) ~ (4, 27) => 0.834523
+(3, 26) ~ (4, 20) => 0.010506
+(3, 26) ~ (4, 23) => 0.0238937
+(3, 26) ~ (4, 27) => 0.029038
+(3, 26) ~ (4, 28) => 0.913101
+(3, 27) ~ (4, 24) => 0.0125322
+(3, 27) ~ (4, 28) => 0.0173845
+(3, 27) ~ (4, 29) => 0.942428
+(3, 28) ~ (4, 25) => 0.0100139
+(3, 28) ~ (4, 29) => 0.0150017
+(3, 28) ~ (4, 30) => 0.952637
+(3, 29) ~ (4, 30) => 0.011663
+(3, 29) ~ (4, 31) => 0.963971
+(3, 30) ~ (4, 32) => 0.971813
+(3, 31) ~ (4, 33) => 0.975934
+(3, 32) ~ (4, 34) => 0.981038
+(3, 33) ~ (4, 35) => 0.985724
+(3, 34) ~ (4, 36) => 0.989666
+(3, 35) ~ (4, 37) => 0.991388
+(3, 36) ~ (4, 38) => 0.99414
+(3, 37) ~ (4, 39) => 0.996371
+(3, 38) ~ (4, 40) => 0.998076
+(3, 39) ~ (4, 41) => 0.998239
+(3, 40) ~ (4, 42) => 0.998395
+(3, 41) ~ (4, 43) => 0.998593
+(3, 42) ~ (4, 44) => 0.998744
+(3, 43) ~ (4, 45) => 0.998774
+(3, 44) ~ (4, 46) => 0.998657
+(3, 45) ~ (4, 47) => 0.99856
+(3, 46) ~ (4, 48) => 0.998716
+(3, 47) ~ (4, 49) => 0.998885
+(3, 48) ~ (4, 50) => 0.998833
+(3, 49) ~ (4, 51) => 0.998673
+(3, 50) ~ (4, 52) => 0.998235
+(3, 51) ~ (4, 53) => 0.998379
+(3, 52) ~ (4, 54) => 0.998923
+(3, 53) ~ (4, 55) => 0.999092
+(3, 54) ~ (4, 56) => 0.999044
+(3, 55) ~ (4, 57) => 0.998946
+(3, 56) ~ (4, 58) => 0.999078
+(3, 57) ~ (4, 59) => 0.999169
+(3, 58) ~ (4, 60) => 0.999287
+(3, 59) ~ (4, 61) => 0.999352
+(3, 60) ~ (4, 62) => 0.999499
+(3, 61) ~ (4, 63) => 0.999638
+(3, 62) ~ (4, 64) => 0.999671
+(3, 63) ~ (4, 65) => 0.999653
+(3, 64) ~ (4, 66) => 0.999679
+(3, 65) ~ (4, 67) => 0.999716
+(3, 66) ~ (4, 68) => 0.999772
+(3, 67) ~ (4, 69) => 0.999893
+(3, 68) ~ (4, 70) => 0.999934
+
+; gap posteriors
+(3, 0) ~ (4, -1) => 0.00271541
+(3, 1) ~ (4, -1) => 0.00700843
+(3, 2) ~ (4, -1) => 0.0111883
+(3, 3) ~ (4, -1) => 0.0167065
+(3, 4) ~ (4, -1) => 0.0288411
+(3, 5) ~ (4, -1) => 0.0355971
+(3, 6) ~ (4, -1) => 0.0673243
+(3, 7) ~ (4, -1) => 0.084801
+(3, 8) ~ (4, -1) => 0.112096
+(3, 9) ~ (4, -1) => 0.148158
+(3, 10) ~ (4, -1) => 0.174656
+(3, 11) ~ (4, -1) => 0.165435
+(3, 12) ~ (4, -1) => 0.12282
+(3, 13) ~ (4, -1) => 0.0650001
+(3, 14) ~ (4, -1) => 0.0508256
+(3, 15) ~ (4, -1) => 0.0490953
+(3, 16) ~ (4, -1) => 0.0560949
+(3, 17) ~ (4, -1) => 0.0454046
+(3, 18) ~ (4, -1) => 0.034706
+(3, 19) ~ (4, -1) => 0.0334462
+(3, 20) ~ (4, -1) => 0.0298373
+(3, 21) ~ (4, -1) => 0.0279173
+(3, 22) ~ (4, -1) => 0.0303174
+(3, 23) ~ (4, -1) => 0.0301821
+(3, 24) ~ (4, -1) => 0.0254968
+(3, 25) ~ (4, -1) => 0.0231351
+(3, 26) ~ (4, -1) => 0.0234612
+(3, 27) ~ (4, -1) => 0.0276558
+(3, 28) ~ (4, -1) => 0.0223477
+(3, 29) ~ (4, -1) => 0.0243657
+(3, 30) ~ (4, -1) => 0.0281865
+(3, 31) ~ (4, -1) => 0.0240664
+(3, 32) ~ (4, -1) => 0.0189616
+(3, 33) ~ (4, -1) => 0.0142764
+(3, 34) ~ (4, -1) => 0.0103343
+(3, 35) ~ (4, -1) => 0.0086115
+(3, 36) ~ (4, -1) => 0.00586039
+(3, 37) ~ (4, -1) => 0.00362867
+(3, 38) ~ (4, -1) => 0.00192404
+(3, 39) ~ (4, -1) => 0.00176054
+(3, 40) ~ (4, -1) => 0.0016048
+(3, 41) ~ (4, -1) => 0.00140727
+(3, 42) ~ (4, -1) => 0.00125629
+(3, 43) ~ (4, -1) => 0.00122613
+(3, 44) ~ (4, -1) => 0.00134307
+(3, 45) ~ (4, -1) => 0.00144017
+(3, 46) ~ (4, -1) => 0.0012843
+(3, 47) ~ (4, -1) => 0.0011152
+(3, 48) ~ (4, -1) => 0.00116652
+(3, 49) ~ (4, -1) => 0.00132734
+(3, 50) ~ (4, -1) => 0.0017646
+(3, 51) ~ (4, -1) => 0.00162137
+(3, 52) ~ (4, -1) => 0.00107741
+(3, 53) ~ (4, -1) => 0.000908136
+(3, 54) ~ (4, -1) => 0.000956237
+(3, 55) ~ (4, -1) => 0.00105375
+(3, 56) ~ (4, -1) => 0.000921726
+(3, 57) ~ (4, -1) => 0.00083077
+(3, 58) ~ (4, -1) => 0.000712752
+(3, 59) ~ (4, -1) => 0.000647902
+(3, 60) ~ (4, -1) => 0.000500739
+(3, 61) ~ (4, -1) => 0.000361562
+(3, 62) ~ (4, -1) => 0.000329196
+(3, 63) ~ (4, -1) => 0.000346661
+(3, 64) ~ (4, -1) => 0.000320613
+(3, 65) ~ (4, -1) => 0.000283718
+(3, 66) ~ (4, -1) => 0.000228167
+(3, 67) ~ (4, -1) => 0.000107467
+(3, 68) ~ (4, -1) => 0.0001
+
+(3, -1) ~ (4, 0) => 0.00271541
+(3, -1) ~ (4, 1) => 0.00700843
+(3, -1) ~ (4, 2) => 0.0111883
+(3, -1) ~ (4, 3) => 0.0167065
+(3, -1) ~ (4, 4) => 0.0150261
+(3, -1) ~ (4, 5) => 0.0190183
+(3, -1) ~ (4, 6) => 0.0232125
+(3, -1) ~ (4, 7) => 0.0264437
+(3, -1) ~ (4, 8) => 0.0268854
+(3, -1) ~ (4, 9) => 0.0279289
+(3, -1) ~ (4, 10) => 0.032088
+(3, -1) ~ (4, 11) => 0.0217061
+(3, -1) ~ (4, 12) => 0.010382
+(3, -1) ~ (4, 13) => 0.0199166
+(3, -1) ~ (4, 14) => 0.0192406
+(3, -1) ~ (4, 15) => 0.0212876
+(3, -1) ~ (4, 16) => 0.0247724
+(3, -1) ~ (4, 17) => 0.0331775
+(3, -1) ~ (4, 18) => 0.0511122
+(3, -1) ~ (4, 19) => 0.0811947
+(3, -1) ~ (4, 20) => 0.096484
+(3, -1) ~ (4, 21) => 0.406505
+(3, -1) ~ (4, 22) => 0.590076
+(3, -1) ~ (4, 23) => 0.500228
+(3, -1) ~ (4, 24) => 0.472993
+(3, -1) ~ (4, 25) => 0.436121
+(3, -1) ~ (4, 26) => 0.262965
+(3, -1) ~ (4, 27) => 0.136439
+(3, -1) ~ (4, 28) => 0.0695145
+(3, -1) ~ (4, 29) => 0.0425707
+(3, -1) ~ (4, 30) => 0.0357003
+(3, -1) ~ (4, 31) => 0.0360287
+(3, -1) ~ (4, 32) => 0.0281865
+(3, -1) ~ (4, 33) => 0.0240664
+(3, -1) ~ (4, 34) => 0.0189616
+(3, -1) ~ (4, 35) => 0.0142764
+(3, -1) ~ (4, 36) => 0.0103343
+(3, -1) ~ (4, 37) => 0.0086115
+(3, -1) ~ (4, 38) => 0.00586039
+(3, -1) ~ (4, 39) => 0.00362867
+(3, -1) ~ (4, 40) => 0.00192404
+(3, -1) ~ (4, 41) => 0.00176054
+(3, -1) ~ (4, 42) => 0.0016048
+(3, -1) ~ (4, 43) => 0.00140727
+(3, -1) ~ (4, 44) => 0.00125629
+(3, -1) ~ (4, 45) => 0.00122613
+(3, -1) ~ (4, 46) => 0.00134307
+(3, -1) ~ (4, 47) => 0.00144017
+(3, -1) ~ (4, 48) => 0.0012843
+(3, -1) ~ (4, 49) => 0.0011152
+(3, -1) ~ (4, 50) => 0.00116652
+(3, -1) ~ (4, 51) => 0.00132734
+(3, -1) ~ (4, 52) => 0.0017646
+(3, -1) ~ (4, 53) => 0.00162137
+(3, -1) ~ (4, 54) => 0.00107741
+(3, -1) ~ (4, 55) => 0.000908136
+(3, -1) ~ (4, 56) => 0.000956237
+(3, -1) ~ (4, 57) => 0.00105375
+(3, -1) ~ (4, 58) => 0.000921726
+(3, -1) ~ (4, 59) => 0.00083077
+(3, -1) ~ (4, 60) => 0.000712752
+(3, -1) ~ (4, 61) => 0.000647902
+(3, -1) ~ (4, 62) => 0.000500739
+(3, -1) ~ (4, 63) => 0.000361562
+(3, -1) ~ (4, 64) => 0.000329196
+(3, -1) ~ (4, 65) => 0.000346661
+(3, -1) ~ (4, 66) => 0.000320613
+(3, -1) ~ (4, 67) => 0.000283718
+(3, -1) ~ (4, 68) => 0.000228167
+(3, -1) ~ (4, 69) => 0.000107467
+(3, -1) ~ (4, 70) => 0.0001
+
diff --git a/examples/tRNA.aln1.mfa b/examples/tRNA.aln1.mfa
new file mode 100644
index 0000000..ce0e381
--- /dev/null
+++ b/examples/tRNA.aln1.mfa
@@ -0,0 +1,11 @@
+>AE004843.1-4972_4900
+GCUCAUGUAGCUCAGUUGGUAGAGCACACCCUUGGUAAGGGUGAGGUCAG-CGGUUCAAAUCCGCUCAUGAGCU
+>Z82044.1-16031_16103
+GCGGUUGUGGCGAAGUGGUUAACGCACCAGAUUGUGGCUCUGGCACUCGU-GGGUUCGAUUCCCAUCAAUCGCC
+>M83762.1-1031_1093
+GCUUUAAAAGCUUUGCUGAA---GCAACGGCCUUGUAAGUCGUAG-AAAAC-------UAUACGUUUUAAAGCU
+>AB042432.1-14140_14072
+GUUUCUGUAGUUGAAUUACA---ACGAUGAUUUUUCAUGUCAUUG-GUCG-CAGUUGAAUGCUGUGUAGAAAUA
+>AC008670.6-83725_83795
+ACUUUUAAAGGAUAACAGCCAUC-CGUUGGUCUUAGGCCCCAAAA-AUUU-UGGUGCAACUCCAAAUAAAAGUA
+
diff --git a/examples/tRNA.aln1.reference.mfa b/examples/tRNA.aln1.reference.mfa
new file mode 100644
index 0000000..0bde3f9
--- /dev/null
+++ b/examples/tRNA.aln1.reference.mfa
@@ -0,0 +1,15 @@
+>AE004843.1-4972_4900
+GCUCAUGUAGCUCAGUUGGU-AGAGCACACCCUUGGUAAGGGUGAGGUCA
+GCGGUUCAAAUCCGCUCAUGAGCU
+>Z82044.1-16031_16103
+GCGGUUGUGGCGAAGU-GGUUAACGCACCAGAUUGUGGCUCUGGCACUCG
+UGGGUUCGAUUCCCAUCAAUCGCC
+>M83762.1-1031_1093
+GCUUUAAAAGCUUUG--CU--GAAGCAACGGCCUUGUAAGUCGUAGA-AA
+AC---UAUAC---GUUUUAAAGCU
+>AB042432.1-14140_14072
+GUUUCUGUAGUUGAA--UU--ACAACGAUGAUUUUUCAUGUCAUUGG-UC
+GCAGUUGAAUGCUGUGUAGAAAUA
+>AC008670.6-83725_83795
+ACUUUUAAAGGAUAAC-AGC-CAUCCGUUGGUCUUAGGCCCCAAAAA-UU
+UUGGUGCAACUCCAAAUAAAAGUA
diff --git a/examples/tRNA.aln1.reference.stock b/examples/tRNA.aln1.reference.stock
new file mode 100644
index 0000000..5c5c87d
--- /dev/null
+++ b/examples/tRNA.aln1.reference.stock
@@ -0,0 +1,13 @@
+# STOCKHOLM 1.0
+AB042432.1-14140_14072 GUUUCUGUAGUUGAA--UU--ACAACGAUGAUUUUUCAUGUCAUUGG-UCGCAGUUGAAUGCUGUGUAGAAAUA
+#=GR AB042432.1-14140_14072 SS <<<<<<<--<<<<--------->>>>-<<<<<------->>>>>-----<<<<<------->>>>>>>>>>>>-
+Z82044.1-16031_16103 GCGGUUGUGGCGAAGU-GGUUAACGCACCAGAUUGUGGCUCUGGCACUCGUGGGUUCGAUUCCCAUCAAUCGCC
+#=GR Z82044.1-16031_16103 SS <<<<<<<--<<<<--------->>>>-<<<<<------->>>>>-----<<<<<------->>>>>>>>>>>>-
+AC008670.6-83725_83795 ACUUUUAAAGGAUAAC-AGC-CAUCCGUUGGUCUUAGGCCCCAAAAA-UUUUGGUGCAACUCCAAAUAAAAGUA
+#=GR AC008670.6-83725_83795 SS <<<<<<<--<<<<--------->>>>-<<<<<------->>>>>-----<<<<<------->>>>>>>>>>>>-
+AE004843.1-4972_4900 GCUCAUGUAGCUCAGUUGGU-AGAGCACACCCUUGGUAAGGGUGAGGUCAGCGGUUCAAAUCCGCUCAUGAGCU
+#=GR AE004843.1-4972_4900 SS <<<<<<<--<<<<--------->>>>-<<<<<------->>>>>-----<<<<<------->>>>>>>>>>>>-
+M83762.1-1031_1093 GCUUUAAAAGCUUUG--CU--GAAGCAACGGCCUUGUAAGUCGUAGA-AAAC---UAUAC---GUUUUAAAGCU
+#=GR M83762.1-1031_1093 SS <<<<<<<--<<<<--------->>>>-<<<<<------->>>>>-----<<<----------->>>>>>>>>>-
+#=GC SS_cons <<<<<<<..<<<<.........>>>>.<<<<<.......>>>>>.....<<<<<.......>>>>>>>>>>>>.
+//
diff --git a/examples/tRNA.aln1.stock b/examples/tRNA.aln1.stock
new file mode 100644
index 0000000..9b18270
--- /dev/null
+++ b/examples/tRNA.aln1.stock
@@ -0,0 +1,9 @@
+# STOCKHOLM 1.0
+#=GF Accuracy 0.702093
+AE004843.1-4972_4900 GCUCAUGUAGCUCAGUUGGUAGAGCACACCCUUGGUAAGGGUGAGGUCAG-CGGUUCAAAUCCGCUCAUGAGCU
+Z82044.1-16031_16103 GCGGUUGUGGCGAAGUGGUUAACGCACCAGAUUGUGGCUCUGGCACUCGU-GGGUUCGAUUCCCAUCAAUCGCC
+M83762.1-1031_1093 GCUUUAAAAGCUUUGCUGAA---GCAACGGCCUUGUAAGUCGUAG-AAAAC-------UAUACGUUUUAAAGCU
+AB042432.1-14140_14072 GUUUCUGUAGUUGAAUUACA---ACGAUGAUUUUUCAUGUCAUUG-GUCG-CAGUUGAAUGCUGUGUAGAAAUA
+AC008670.6-83725_83795 ACUUUUAAAGGAUAACAGCCAUC-CGUUGGUCUUAGGCCCCAAAA-AUUU-UGGUGCAACUCCAAAUAAAAGUA
+#=GC Accuracy 99999999999988888776555455555555544444444444434444066667776667778888999999
+//
diff --git a/html/FAQ.html b/html/FAQ.html
new file mode 100644
index 0000000..8eff1a4
--- /dev/null
+++ b/html/FAQ.html
@@ -0,0 +1,532 @@
+
+<HTML>
+ <HEAD>
+
+ <link rel = "stylesheet" href = "pretty.css" type = "text/css">
+
+ <TITLE>FSA Frequently Asked Questions</TITLE>
+ <META NAME="version" content="0.9" />
+ <META NAME="keywords" CONTENT="FSA, fast statistical alignment, multiple sequence alignment, statistical alignment, bioinformatics, sequence annealing">
+ <META NAME="description" CONTENT="FSA Frequently Asked Questions">
+ <META NAME="ROBOTS" CONTENT="ALL">
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <!-- ImageReady Preload Script (faq.tif) -->
+ </HEAD>
+
+
+ <BODY BGCOLOR=#FFFFFF ONLOAD="preloadImages();">
+
+ <h1><a href="http://fsa.sourceforge.net/index.html">FSA</a> Frequently Asked Questions</h1>
+
+ <h2>Introduction</h2>
+ <ul>
+ <li><a href = "#intro">What is FSA?</a></li>
+ <li><a href = "#acronym">What does FSA stand for?</a></li>
+ <li><a href = "#install"> How do I download and install FSA?</a></li>
+ <li><a href = "#runfsa">How do I run FSA?</a></li>
+ <li><a href = "#server">Is there a webserver for FSA?</a></li>
+ <li><a href = "#help"> How do I get a help message to explain the options?</a></li>
+ </ul>
+
+ <h2>Alignments</h2>
+ <ul>
+ <li><a href = "#manyseqs"> How do I align many sequences?</a></li>
+ <li><a href = "#longseqs"> How do I align long sequences?</a></li>
+ <li><a href = "#genomes"> How do I align genomes?</a></li>
+ <li><a href = "#manygaps">Why are there so many gaps in my alignment?</a></li>
+ <li><a href = "#gapfactor">How do I control the sensitivity/specificity tradeoff of my alignment?</a></li>
+ </ul>
+
+ <h2>Visualization</h2>
+ <ul>
+ <li><a href="#gui">How do I visualize the alignments produced by FSA?</a></li>
+ <li><a href = "#reliable">How do I see what parts of my alignment are the most reliable?</a></li>
+ </ul>
+
+ <h2>Output formats and tools</h2>
+ <ul>
+ <li><a href = "#stockholm"> How do I parse Stockholm alignments?</a></li>
+ <li><a href = "#comparealign"> How do I compare alignments?</a></li>
+ </ul>
+
+ <h2>Troubleshooting</h2>
+ <ul>
+ <li> <a href = "#logging"> My alignment is taking a long time. How do I see what FSA is doing?</a>
+ <li> <a href = "#gui_memory">I'm getting memory errors when using the GUI.</a>
+ <li> <a href = "#malloc">I get out-of-memory (bad alloc) errors when I try to align long sequences.</a>
+ </ul>
+
+ <h2>More information</h2>
+ <ul>
+ <li><a href = "#contact"> How do I contact you?</a></li>
+ <li><a href = "#citation"> How do I cite FSA?</a></li>
+ <li><a href = "#license"> Under what license is FSA distributed?</a></li>
+ <li><a href = "#git"> How do I become an FSA developer?</a></li>
+ <li><a href = "#influences"> What other programs influenced the development of FSA?</a></li>
+ </ul>
+
+
+ <!-- Introduction -->
+ <hr>
+ <h2>Introduction</h2>
+
+ <h4><a name = "intro">What is FSA?</a></h4>
+
+ FSA is a probabilistic multiple sequence alignment algorithm which uses
+ a "distance-based" approach to aligning homologous protein, RNA or DNA
+ sequences. Much as distance-based phylogenetic reconstruction methods
+ like Neighbor-Joining build a phylogeny using only pairwise divergence
+ estimates, FSA builds a multiple alignment using only pairwise
+ estimations of homology. This is made possible by the sequence
+ annealing technique for constructing a multiple alignment from pairwise
+ comparisons, developed by Ariel Schwartz in
+ <a href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2007/EECS-2007-39.html">
+ "Posterior Decoding Methods for Optimization and Control of Multiple
+ Alignments</a>."
+
+ <p>
+ FSA brings the high accuracies previously available only for small-scale analyses of proteins or RNAs
+ to large-scale problems such as aligning thousands of sequences or megabase-long sequences.
+ FSA introduces several novel methods for constructing better alignments:
+ <ul>
+ <li type=square>
+ FSA uses machine-learning techniques to estimate gap and
+ substitution parameters on the fly for each set of input sequences.
+ This "query-specific learning" alignment method makes FSA very robust: it
+ can produce superior alignments of sets of homologous sequences
+ which are subject to very different evolutionary constraints.
+ <li type=square>
+ FSA is capable of aligning hundreds or even thousands of sequences
+ using a randomized inference algorithm to reduce the computational
+ cost of multiple alignment. This randomized inference can be over
+ ten times faster than a direct approach with little loss of
+ accuracy.
+ <li type=square>
+ FSA can quickly align very long sequences using the "anchor
+ annealing" technique for resolving anchors and projecting them with
+ transitive anchoring. It then stitches together the alignment
+ between the anchors using the methods described above.
+ <li type=square>
+ The included GUI, MAD (Multiple Alignment Display), can display
+ the intermediate alignments produced by FSA, where each character
+ is colored according to the probability that it is correctly
+ aligned.
+ </ul>
+
+
+
+ <h4><a name = "acronym">What does FSA stand for?</a></h4>
+ Fast statistical alignment: We use machine-learning techniques to quickly
+ re-estimate parameters for each alignment problem.
+ <p>
+ Fast sequence annealing: We build a multiple alignment from pairwise comparisons
+ with the sequence annealing technique.
+ <p>
+ Functional statistical alignment: We implicitly use functional information when
+ constructing alignments.
+ <p>
+ <a href="http://www.fullspeedahead.com/">Full Speed Ahead</a><p>
+ <p>
+ ...and more...
+
+
+
+ <h4><a name = "install">How do I download and install FSA?</a></h4>
+ FSA is hosted by <a href="http://sourceforge.net">SourceForge</a>.
+ You can download the latest version from the <a href="http://sourceforge.net/projects/fsa/">SourceForge project page</a>.
+ <p>
+
+ FSA is built and installed by running the following commands: <br>
+ <p><kbd>
+ tar xvzf fsa-X.X.X.tar.gz <br>
+ cd fsa-X.X.X <br>
+ ./configure <br>
+ make <br>
+ make install <br>
+ </kbd>
+
+ <p>
+ (Substitute <var>fsa-X.X.X.tar.gz</var> with the name of the file
+ that you downloaded.)
+
+ <p>
+ The FSA executables can then be found in your system's standard
+ binary directory (e.g., /usr/local/bin). Alternatively, you may
+ just run FSA from the src/main subdirectory in which it is built
+ (which does not require running the <kbd>make install</kbd> step).
+ If you wish to install the FSA binaries in a location other than
+ your system's standard directories (which usually requires root
+ permissions), specify the top-level installation directory with
+ the <kbd>--prefix</kbd> option to configure. For example,
+ <p><kbd>./configure --prefix=$HOME</kbd>
+ <p>
+ specifies that binaries should be installed in <var>$HOME/bin</var>, libraries in
+ <var>$HOME/lib</var>, etc. <br>
+ <p>
+ If you wish to align long sequences, then you must download and install <a href="http://mummer.sourceforge.net/">MUMmer</a>,
+ which FSA calls to get candidate anchors between sequences.
+ When running <kbd>./configure</kbd>, either have the MUMmer executable in your path
+ or specify the executable with the <kbd>--with-mummer</kbd> option to <kbd>./configure</kbd>.
+
+ <p>
+ FSA can also call <a href="http://www.ebi.ac.uk/~guy/exonerate/">exonerate</a>
+ to obtain anchors. If you wish to use exonerate, then as with MUMmer,
+ when running <kbd>./configure</kbd>, you must either have the exonerate executable in your path
+ or specify the executable with the <kbd>--with-exonerate</kbd> option to <kbd>./configure</kbd>.
+
+ <p>
+ See the <var>README</var> file and <a href = "#longseqs">How do I align long sequences?</a>
+ for more information.
+ <p>
+ Please contact us if you have any build problems.
+
+
+
+ <h4><a name = "runfsa"> How do I run FSA?</a></h4>
+ FSA accepts FASTA-format input files and outputs multi-FASTA
+ alignments by default. The most basic usage is:
+ <p><kbd>fsa <mysequences.fa> >myalignedsequences.mfa</kbd>
+ <p>
+ or
+ <p><kbd>fsa --stockholm <mysequences.fa> >myalignedsequences.stk</kbd>
+ <p>
+
+
+ <h4><a name = "server"> Is there a webserver for FSA?</a></h4>
+ There is a webserver hosted <a href="http://orangutan.math.berkeley.edu/fsa/">here</a>
+ which you can submit alignment jobs to.
+ You will be emailed when the alignment is completed.
+
+
+
+ <h4><a name = "help"> How do I get a help message to explain the options?</a></h4>
+ Run
+ <p><kbd>fsa --help</kbd>
+
+
+
+ <h4><a name = "example_files"> Are there example sequence files and alignments?</a></h4>
+ Yes. Please see the <var>examples/</var> directory.
+
+
+
+ <!-- Alignments -->
+ <hr>
+ <h2>Alignments</h2>
+
+ <h4><a name = "manyseqs"> How do I align many sequences?</a></h4>
+ FSA can align thousands or tens of thousands of sequences.
+ Try running FSA with the <kbd>--fast</kbd> option. You can get finer-grained control with
+ the <kbd>--alignment-number <int></kbd> option, which controls the total number of pairwise
+ comparisons which FSA uses to build a multiple alignment. If you want to align
+ N sequences, then you can set <kbd>--alignment-number</kbd> to as low as (N - 1) or as
+ high as (N choose 2) == (N * (N - 1) / 2).
+
+
+
+
+ <h4><a name = "longseqs"> How do I align long sequences?</a></h4>
+ FSA can align long sequences (megabases or tens of megabases) with the
+ "anchor annealing" technique. It uses the program MUMmer to find maximal
+ unique matches between pairs of sequences to be aligned, resolves
+ inconsistencies with anchor annealing, and then pieces together the alignment
+ between anchored regions using its standard inference method.
+
+ <p>
+ FSA can also use the program exonerate to detect remote homology.
+
+ <p>
+ Please use the <kbd>--with-mummer</kbd> and <kbd>--with-exonerate</kbd> options to <kbd>./configure</kbd>
+ before compilation as explained in <a href="#runfsa">How do I run FSA?</a>.
+
+ <p>
+ You can read about the MUMmer and exonerate programs in:
+ <p>
+ S. Kurtz, A. Phillippy, A.L. Delcher, M. Smoot, M. Shumway, C. Antonescu, and S.L. Salzberg.
+ <a href="http://genomebiology.com/2004/5/2/R12">Versatile and open software for comparing large genomes</a>. Genome Biology. 2004, 5:R12.
+ <p>
+ G. S. Slater and E. Birney.
+ <a href="http://www.biomedcentral.com/1471-2105/6/31">Automated generation of heuristics for biological sequence comparison</a>. BMC Bioinformatics. 2005, 6:31.
+
+
+
+ <h4><a name = "genomes"> How do I align genomes?</a></h4>
+ If the genomes which you want to align have few rearrangements, then
+ you can run FSA directly on them. If they have rearrangments, then
+ you must first use a program such as Colin Dewey's <a href="http://www.biostat.wisc.edu/~cdewey/mercator/">Mercator</a>
+ to construct a homology map for the genomes and then run FSA on the
+ homologous segments. FSA can directly use the constraint information
+ produced by Mercator to inform its multiple alignment
+ (use the <kbd>--mercator</kbd> option to specify the Mercator constraint file).
+
+ <p>
+ You can read about Mercator in:
+
+ <p>
+ C. Dewey. <a href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-104.html">Whole-genome alignments and polytopes for comparative genomics</a>.
+ Ph.D. thesis, University of California, Berkeley. 2006.
+
+
+ <h4><a name = "logging"> My alignment is taking a long time. How do I see what FSA is doing?</a></h4>
+
+ FSA has an extensive logging system. Try running with the <kbd>--log 7</kbd> option
+ to see progress of the DP algorithm, and <kbd>--log 6</kbd> to see progress of anchoring
+ (when aligning long sequences).
+ Log levels from 0 to 10 are permitted,
+ where lower numbers are more verbose.
+
+
+ <h4><a name = "manygaps">Why are there so many gaps in my alignment?</a></h4>
+
+ Most alignment programs attempt to maximize sensitivity, even at
+ the expense of specificity, leading to over-alignment (alignment of
+ non-homologous sequence). FSA, in contrast, maximizes the expected
+ accuracy of the alignment with a measure which rewards sensitivity
+ but penalizes over-alignment. If FSA cannot reliably detect homology,
+ then it will leave characters unaligned (gapped).
+
+
+ <h4><a name = "gapfactor">How do I control the sensitivity/specificity tradeoff of my alignment?</a></h4>
+
+ By default FSA stops aligning characters when the probability that
+ a character is aligned is equal to the probability that it is gapped.
+ Use the <kbd>--maxsn</kbd> option for maximum sensitivity.
+
+ <p>
+ You can get finer-grained control with the <kbd>--gapfactor <int></kbd> option.
+ By default FSA runs at <kbd>--gapfactor 1</kbd>.
+ Use <kbd>--gapfactor 0</kbd> for highest sensitivity (this is equivalent to <kbd>--maxsn</kbd>)
+ and gap factors > 1 for higher specificity.
+
+
+
+ <!-- Visualization -->
+ <hr>
+ <h2>Visualization</h2>
+
+ <h4><a name = "gui"> How do I visualize the alignments produced by FSA?</a></h4>
+ Run FSA with the command-line option <kbd>--gui</kbd>. If the input alignment file
+ is <var>myseqs.fasta</var>, then FSA will write the files <var>myseqs.fasta.gui</var> and
+ 'myseqs.fasta.probs'. Invoke the MAD (Multiple Alignment Display) GUI
+ as
+ <p><kbd>java -jar display/mad.jar myseqs.fasta</kbd>
+ <p>
+ Please be patient if it takes a while to load.
+ <p>
+ Characters in the multiple alignment are colored according to the
+ probability that they are correctly aligned.
+
+ <p>
+ You can see what a typical FSA alignment looks like by running
+ on one of the provided example alignments, such as
+ <p><kbd>java -jar display/mad.jar examples/tRNA.aln1.fasta</kbd>
+
+ <p>
+ You can also use the GUI to compare a FSA alignment with another alignment,
+ such as one which you have edited by hand. Invoke the GUI as
+ <p><kbd>java -jar display/mad.jar examples/tRNA.aln1.fasta myalignment.fa</kbd>
+ The alternate alignment <kbd>myalignment.mfa</kbd> must be in multi-FASTA format.
+
+
+
+ <h4><a name = "reliable">How do I see what parts of my alignment are the most reliable?</a></h4>
+ The accuracy estimates produced by FSA and the GUI are useful for
+ downstream analyses, for example allowing biologists to restrict
+ their analyses to the most reliable portions of the alignment
+ or edit unreliable parts of the alignment by hand.
+
+ The accuracy measures also allow you to visualize how FSA works.
+ If you switch to the "Specificity" coloring and watch the animation from the beginning,
+ you will see FSA first aligns characters whose homology it is most sure of (red),
+ and only later aligns characters of unclear homology (blue).
+ Similarly, you can visualize the sensitivity/specificity tradeoff: Near the beginning
+ of the alignment the specificity is very high, but the sensitivity is low.
+ The specificity decreases and the sensitivity increases as the alignment progresses.
+
+ The GUI displays five different accuracy measures for each position in the multiple alignment.
+ These are:
+ <ul>
+
+ <li type=square><u>Accuracy</u>: What characters or gaps of the multiple alignment are the most accurate?
+ <blockquote>
+ Accuracy is the per-character estimated Alignment Metric Accuracy,
+ which measures the fidelity of both aligned characters and unaligned characters (gaps).
+ It can be thought of as a single measure encompassing the sensitivity/specificity tradeoff.
+ </blockquote>
+
+ <li type=square><u>Sensitivity</u>: What characters are aligned with the greatest sensitivity?
+ <blockquote>
+ Sensitivity is the estimated number of correctly-aligned character pairs divided by the
+ true number of aligned character pairs.
+ <br>
+ Sensitivity is defined as the expectation of (True positives) / (True positives + False negatives).
+ This definition is equivalent to <a href="http://en.wikipedia.org/wiki/Precision_and_recall">recall</a> as used in classification problems.
+ </blockquote>
+
+ <li type=square><u>Specificity</u>: What characters are aligned with the greatest specificity?
+ <blockquote>
+ Specificity is the estimated fraction of character pairs which are aligned correctly.
+ <br>
+ Specificity is defined as the expectation of (True positives) / (True positives + False positives).
+ This definition is equivalent to <a href="http://en.wikipedia.org/wiki/Precision_and_recall">precision</a> as used in classification problems.
+ It is also frequently called <a href="http://en.wikipedia.org/wiki/Positive_predictive_value">Positive Predictive Value</a> in the literature.
+ </blockquote>
+
+ <li type=square><u>Certainty</u>: Was there a better place to align this character?
+ <blockquote>
+ Certainty measures whether a character or gap is aligned correctly.
+ </blockquote>
+
+ <li type=square><u>Consistency</u>: What parts of the multiple alignment are optimal on a pairwise level?
+ <blockquote>
+ Consistency measures the extent to which the posterior probabilities from pairwise comparisons
+ are optimized by the multiple alignment. If a multiple alignment is perfectly consistent,
+ then each pairwise alignment implied by the multiple alignment corresponds perfectly to the pairwise alignment
+ which you would obtain by aligning only those two sequences.
+ </blockquote>
+
+ </ul>
+
+ <p>
+ Please see the manuscript for precise definitions of these reliability measures.
+
+ <p>
+ Notice that the accuracy scores tend to
+ decrease near gaps, reflecting the difficulty of precisely
+ resolving gap boundaries.
+
+
+
+ <!-- Output formats and tools -->
+ <hr>
+ <h2>Output formats and tools</h2>
+
+ <h4><a name = "stockholm"> How do I parse Stockholm alignments?</a></h4>
+ Use the <kbd>--stockholm</kbd> output option to tell FSA
+ to produce a Stockholm-format alignment. The alignment is marked up with
+ a per-column accuracy annotation which is identical to the values
+ reported by the <a href="#gui">GUI</a>.
+
+ FSA includes tools for working with Stockholm alignments, such as
+ <kbd>prettify.pl</kbd> for making Stockholm-format alignments human-
+ readable, in the <var>perl/</var> directory.
+
+
+ <h4><a name = "comparealign"> How do I compare alignments?</a></h4>
+ The included script <kbd>cmpalign.pl</kbd> will compare two alignments
+ and report accuracies measures including Accuracy (AMA), Sensitivity and Specificity.
+ It can parse Stockholm, multi-FASTA, MSF and CLUSTAL format alignments.
+
+
+
+
+ <!-- Troubleshooting -->
+ <hr>
+ <h2>Troubleshooting</h2>
+
+ <h4><a name = "gui_memory"> I'm getting memory errors when using the GUI.</a></h4>
+ If you're getting errors which say something like
+ <p><kbd>Exception in thread ... java.lang.OutOfMemoryError: Java heap space</kbd>
+ <p>
+ then try increasing the memory allowed with with <kbd>-Xmx</kbd> option, ie
+ <p><kbd>java -Xmx256m jar display/mad.jar examples/tRNA.aln1.fasta</kbd>
+ <p>
+ You can increase it up to the maximum allowed by your machine.
+
+
+ <h4><a name = "malloc"> I get out-of-memory (bad alloc) errors when I try to align long sequences.</a></h4>
+ This occurs when FSA is unable to find good anchors between your sequences
+ to restrict the complexity of inference. This can occur if you use the option
+ <kbd>--noanchored</kbd> to prevent anchoring, if your sequences are very diverged,
+ or if they have many simple repeats. Use the <kbd>--maxram</kbd> option to
+ prevent FSA from attempting to perform exhaustive inference when it can't
+ find good anchors. It will leave sequence for which it can't find
+ sufficiently-good anchors unaligned.
+
+
+
+
+
+
+ <!-- More information -->
+ <hr>
+ <h2>More information</h2>
+
+ <h4><a name = "contact"> How do I contact you?</a></h4>
+ You can reach the FSA team at <a href="mailto:fsa at math.berkeley.edu">fsa at math.berkeley.edu</a> with any questions, feedback, etc.
+
+
+ <h4><a name = "citation"> How do I cite FSA?</a></h4>
+ Bradley RK, Roberts A, Smoot M, Juvekar S, Do J, Dewey C, Holmes I, Pachter L (2009) <a href="http://www.ploscompbiol.org/article/info%3Adoi%2F10.1371%2Fjournal.pcbi.1000392">Fast Statistical Alignment</a>. PLoS Computational Biology. 5:e1000392.
+ <p>The FSA manuscript can also be found in the <var>doc/</var>
+ directory of the FSA source code distribution.
+
+
+ <h4><a name = "license">Under what license is FSA distributed?</a></h4>
+ FSA is licensed under version 3 of the <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public License</a>.
+ Please see the files <var>LICENSE</var> and <var>COPYING</var> for further information.
+
+
+ <h4><a name = "git"> How do I become an FSA developer?</a></h4>
+ FSA is designed to be modular and there are many aspects of the program that can be improved;
+ we welcome your help! The code is under <a href="http://git.or.cz/">Git</a> version control.
+ Please contact us at <a href="mailto:fsa at math.berkeley.edu">fsa at math.berkeley.edu</a> for information.
+ The source code is set up for use with <a href="http://www.doxygen.org/">Doxygen</a>,
+ a system for automated building of documentation.
+
+ <h4><a name = "influences"> What other programs influenced the development of FSA?</a></h4>
+ Source code in <var>seq/</var> and <var>util/</var> is from Ian Holmes's DART library [1],
+ which is used for input and output routines.
+
+ <p>
+ FSA's DP code was generated by HMMoC by Gerton Lunter [2]. The
+ aligner example distributed with HMMoC, which implements a
+ learning procedure for gap parameters, was an inspiration for FSA's
+ learning strategies. FSA's banding code is taken directly from the
+ aligner example.
+
+ <p>
+ The sequence annealing technique for constructing a multiple
+ alignment from pairwise comparisons was developed by Ariel Schwartz.
+ The implementation of sequence annealing in FSA is a modified version
+ of the original implementation in AMAP by Ariel Schwartz and Lior Pachter [3,4].
+
+ <p>
+ The anchor annealing approach used in FSA is modeled after the recursive
+ anchoring strategy used in MAVID by Nicolas Bray and Lior Pachter [5].
+
+ <p>
+ The MAD GUI interface to FSA was written by Adam Roberts based on a preliminary
+ version developed by Michael Smoot.
+
+ <p>
+ Please see:
+
+ <p>[1] I. Holmes and R. Durbin. <a href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=9773345">Dynamic Programming Alignment Accuracy</a>. Journal of Computational Biology. 1998, 5 (3):493-504.
+
+ <p>[2] G.A. Lunter. <a href="http://bioinformatics.oxfordjournals.org/cgi/content/abstract/23/18/2485">HMMoC - a Compiler for Hidden Markov Models</a>. Bioinformatics. 2007, 23 (18):2485-2487.
+
+ <p>[3] A.S. Schwartz. <a href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2007/EECS-2007-39.html">Posterior Decoding Methods for Optimization and Control of Multiple Alignments</a>. Ph.D. Thesis, UC Berkeley. 2007.
+
+ <p>[4] A.S. Schwartz and L. Pachter. <a href="http://bioinformatics.oxfordjournals.org/cgi/content/abstract/23/2/e24?etoc">Multiple Alignment by Sequence Annealing</a>. Bioinformatics. 2007, 23 (2):e24-e29.
+
+ <p>[5] N. Bray and L. Pachter. <a href="http://www.genome.org/cgi/content/abstract/14/4/693">MAVID: Constrained Ancestral Alignment of Multiple Sequences</a>. Genome Research. 2004, 14:693-699.
+
+ <hr>
+ <a href="http://sourceforge.net/projects/fsa"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=234783&type=15" width="150" height="40" border="0" alt="Get FSA at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
+
+ <!-- Piwik -->
+ <script type="text/javascript">
+ var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/fsa/" : "http://apps.sourceforge.net/piwik/fsa/");
+ document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
+ </script><script type="text/javascript">
+ piwik_action_name = '';
+ piwik_idsite = 1;
+ piwik_url = pkBaseURL + "piwik.php";
+ piwik_log(piwik_action_name, piwik_idsite, piwik_url);
+ </script>
+ <object><noscript><p><img src="http://apps.sourceforge.net/piwik/fsa/piwik.php?idsite=1" alt="piwik"/></p></noscript></object>
+ <!-- End Piwik Tag -->
+
+ </BODY>
+</HTML>
diff --git a/html/Makefile.am b/html/Makefile.am
new file mode 100644
index 0000000..7ace2a7
--- /dev/null
+++ b/html/Makefile.am
@@ -0,0 +1,3 @@
+EXTRA_DIST = \
+ FAQ.html \
+ pretty.css
diff --git a/html/Makefile.in b/html/Makefile.in
new file mode 100644
index 0000000..35ebe8a
--- /dev/null
+++ b/html/Makefile.in
@@ -0,0 +1,411 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = html
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ FAQ.html \
+ pretty.css
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign html/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign html/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
+ ctags-am distclean distclean-generic distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/html/pretty.css b/html/pretty.css
new file mode 100644
index 0000000..e9a8eef
--- /dev/null
+++ b/html/pretty.css
@@ -0,0 +1,12 @@
+body{margin:10px 10px 10px 10px;font-family:times;background-color:#FFFFF9;}
+
+a{text-decoration:none;}
+
+a:link{font-weight:bold; color:#000066;}
+
+a:visited{color:#000099; font-weight:bold;}
+
+a:hover{text-decoration:underline;}
+
+a:active{text-decoration:underline;}
+
diff --git a/perl/FSA/Model.pm b/perl/FSA/Model.pm
new file mode 100644
index 0000000..449f768
--- /dev/null
+++ b/perl/FSA/Model.pm
@@ -0,0 +1,493 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+FSA::Model.pm
+
+=head1 SYNOPSIS
+
+Perl module encapsulating FSA's statistical model.
+
+Written by Robert Bradley.
+
+=head1 METHODS
+
+=cut
+
+package FSA::Model;
+
+use strict;
+use Carp;
+
+use FSA::SparseMatrices;
+use Stockholm;
+
+use vars '@ISA';
+
+sub new {
+ my ($class) = @_;
+
+ my $self = {
+ 'sparse_matrices' => "", # SparseMatrices object
+ 'seqname_map' => {}, # map sequence names to their SparseMatrices indices
+ 'acc' => '', # Acc (total accuracy)
+ 'sn' => '', # Sn (total sensivity)
+ 'ppv' => '', # PPV (total positive predictive value)
+ 'cert' => '', # Certainty (total certainty)
+ 'cons' => '', # Consistency (total consistency)
+ 'acc_annot' => "", # Acc per-column annotation
+ 'sn_annot' => "", # Sn per-column annotation
+ 'ppv_annot' => "", # PPV per-column annotation
+ 'cert_annot' => "", # Certainty per-column annotation
+ 'cons_annot' => "", # Consistency per-column annotation
+ 'model_cert' => "", # Model certainty (approximate average slope of probability distributions)
+ 'exp_correct' => 0, # expected number of correctly-aligned characters
+ 'exp_incorrect' => 0, # expected number of correctly-aligned characters
+ 'total_chars' => 0 # total number of characters
+ };
+
+ bless $self, ref ($class) || $class;
+
+ return $self;
+}
+
+# Catch methods.
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ my $sub = our $AUTOLOAD; # $AUTOLOAD contains the fully qualified name of the original subroutine
+ $sub =~ s/.*:://;
+
+ # check for DESTROY
+ return if $sub eq 'DESTROY';
+
+ # check for directives accessor, e.g. $self->directives_debug or $self->directives_('debug')
+ if ($sub =~ /^directives_(\S*)$/i) {
+ my $flag = lc ($1);
+ $flag = shift @args unless (length $flag); # this catches the argument 'debug' in the second example usage given above
+ if (!defined $self->{'directives'}->{$flag}) {
+ $self->{'directives'}->{$flag} = ""; # if no such flag exists, create one with the value ""
+ } # we therefore have to test 'if ($self->directives_debug)' rather than 'if (defined $self->directives_debug)'
+ return $self->{'directives'}->{$flag}; # the second will always be true because AUTOLOAD will create an empty flag for us
+ }
+
+ # check for ordinary accessors
+ # This has the effect of automatically implementing getter and setter methods.
+ # If there's an instance variable $name, then the getter method is $self->name
+ # and the setter method is $self->name('newName')
+ if (exists $self->{$sub}) {
+ if (@args > 1) { croak "Usage: $sub() or $sub(newValue)"; }
+ return
+ @args # if @args > 0
+ ? $self->{$sub} = $args[0] # { $self->{$sub} = $args[0]; return $args[0]; }
+ : $self->{$sub}; # else { return $self->{$sub}; }
+ }
+
+ croak "Unsupported method: $sub\n";
+}
+
+# Initialization routines.
+sub _initialize {
+ my ($class, $seqfile) = @_;
+
+ if (!defined $seqfile) { croak "You must define a sequence file!\n"; }
+
+ my $self = $class->new;
+
+ # create map from sequence names to indices
+ unless (Stockholm->detect_FASTA ($seqfile)) {
+ croak "'$seqfile' isn't a valid FASTA file.\n";
+ }
+ my $fasta = Stockholm->from_file ($seqfile);
+ for (my $seq = 0; $seq < @{$fasta->seqname}; ++$seq) {
+ $self->seqname_map->{@{$fasta->seqname}[$seq]} = $seq;
+ }
+
+ return $self;
+}
+
+# Load model from a FSA .probs file.
+sub from_probsfile {
+ my ($class, $seqfile, $probsfile) = @_;
+
+ my $self = $class->_initialize ($seqfile);
+
+ # initialize sparse matrices
+ $self->sparse_matrices (FSA::SparseMatrices->from_probsfile ($probsfile));
+
+ return $self;
+}
+
+# Initialize 0-1 posterior probabilities using the passed reference alignment.
+sub from_alignment {
+ my ($class, $seqfile, $alignfile) = @_;
+
+ my $self = $class->_initialize ($seqfile);
+ $self->sparse_matrices (FSA::SparseMatrices->new);
+
+ # initialize sparse matrices from the passed alignment
+ my $stock = Stockholm->from_file ($alignfile);
+ # sanity checks
+ $stock->assert_flush();
+ $stock->drop_allgaps_columns();
+ for (my $col = 0; $col < $stock->columns; ++$col) {
+
+ foreach my $seq1 (@{$stock->seqname}) {
+ # convert to index
+ my $i = $self->seqname_map->{$seq1};
+ my $ii = ($stock->is_gap ($seq1, $col)) ? -1 : ($stock->map_align_to_seq_coords ($col, $col, $seq1, 0))[0];
+
+ foreach my $seq2 (@{$stock->seqname}) {
+ my $j = $self->seqname_map->{$seq2};
+ my $jj = ($stock->is_gap ($seq2, $col)) ? -1 : ($stock->map_align_to_seq_coords ($col, $col, $seq2, 0))[0];
+
+ # skip gap-gap entries
+ if (($ii < 0) && ($jj < 0)) { next; }
+
+ # store with unit probability
+ $self->sparse_matrices->store_entry ($i, $j, $ii, $jj, 1.0);
+
+ }
+ }
+
+ }
+
+ return $self;
+}
+
+
+# Calculate alignment accuracy information.
+# Use either a "soft" logarithmic transform
+# or a hard threshold for the certainty calculation.
+sub calc_accuracies {
+ my ($self, $stock, $acc_threshold, $cert_threshold, $use_log) = @_;
+
+ if (!defined $acc_threshold) { $acc_threshold = 0.9; }
+ if (!defined $cert_threshold) { $cert_threshold = 5.0; }
+ if (!defined $use_log) { $use_log = 1; }
+
+ # initialize temporary variables to 0
+ # (these will be used to populate the alignment-specific variables in $self)
+
+ # accuracy (Acc)
+ my $acc_num = 0;
+ my $acc_denom = 0;
+ my $acc_annot = "";
+
+ # positive predictive value (PPV)
+ my $ppv_num = 0;
+ my $ppv_denom = 0;
+ my $ppv_annot = "";
+
+ # sensitivity (Sn)
+ my $sn_num = 0;
+ my $sn_denom = 0;
+ my $sn_annot = "";
+
+ # certainty
+ my $cert_num = 0;
+ my $cert_denom = 0;
+ my $cert_annot = "";
+
+ # consistency
+ my $cons_num = 0;
+ my $cons_denom = 0;
+ my $cons_annot = "";
+
+ # expected numbers of correctly and incorrectly-aligned characters
+ # (meeting our $acc_threshold)
+ my $exp_correct = 0;
+ my $exp_incorrect = 0;
+ my $total_chars = 0;
+
+ # first calculate Acc and PPV
+ # loop over columns
+ for (my $col = 0; $col < $stock->columns; ++$col) {
+
+ # per-column values
+ my $col_acc_num = 0;
+ my $col_acc_denom = 0;
+
+ my $col_ppv_num = 0;
+ my $col_ppv_denom = 0;
+
+ my $col_sn_num = 0;
+ my $col_sn_denom = 0;
+
+ my $col_cert_num = 0;
+ my $col_cert_denom = 0;
+
+ my $col_cons_num = 0;
+ my $col_cons_denom = 0;
+
+ # loop over seqs in column
+ foreach my $seq1 (@{$stock->seqname}) {
+
+ # convert to index
+ my $i = $self->seqname_map->{$seq1};
+
+ # estimate whether it's correctly-aligned
+ my $char_acc_num = 0;
+ my $char_acc_denom = 0;
+
+ # loop over all seqs
+ foreach my $seq2 (@{$stock->seqname}) {
+
+ my $j = $self->seqname_map->{$seq2};
+
+ # skip the diagonal
+ next if ($i == $j);
+
+ # check that matrix is available
+ if (!$self->sparse_matrices->exists_matrix ($i, $j)) { next; }
+
+ # skip gap-gap entries
+ if ($stock->is_gap ($seq1, $col) && $stock->is_gap ($seq2, $col)) { next; }
+
+ # if seq1 is gapped
+ if ($stock->is_gap ($seq1, $col)) {
+
+ # get position in seq j
+ my $jj = ($stock->map_align_to_seq_coords ($col, $col, $seq2, 0))[0]; # final argument to map_align_to_seq_coords
+ # specifies 0-based coordinates
+ my $p = $self->sparse_matrices->get_gap_prob ($j, $i, $jj);
+
+ $col_acc_num += $p;
+ $col_acc_denom += 1;
+
+ }
+
+ # if seq2 is gapped
+ elsif ($stock->is_gap ($seq2, $col)) {
+
+ # get position in seq i
+ my $ii = ($stock->map_align_to_seq_coords ($col, $col, $seq1, 0))[0];
+
+ my $p = $self->sparse_matrices->get_gap_prob ($i, $j, $ii);
+
+ $col_acc_num += $p;
+ $col_acc_denom += 1;
+
+ $char_acc_num += $p;
+ $char_acc_denom += 1;
+
+ # numerator for sn doesn't increase
+ # but denominator does
+ $col_sn_denom += $self->sparse_matrices->get_sum_prob ($i, $j, $ii);
+
+ # both numerator and denominator for consistency increase
+ $col_cons_num += $p;
+ $col_cons_denom += $self->sparse_matrices->get_max_prob ($i, $j, $ii);
+
+ if ($use_log) {
+ $col_cert_num += $p;
+ $col_cert_denom += $self->sparse_matrices->get_altmax_prob ($i, $j, $ii, -1);
+ } else {
+ $col_cert_num += ($p / $self->sparse_matrices->get_altmax_prob ($i, $j, $ii, -1) >= $cert_threshold) ? 1 : 0;
+ $col_cert_denom += 1;
+ }
+
+ }
+
+ # if match
+ else {
+
+ # get position in seqs i and j
+ my $ii = ($stock->map_align_to_seq_coords ($col, $col, $seq1, 0))[0];
+ my $jj = ($stock->map_align_to_seq_coords ($col, $col, $seq2, 0))[0];
+
+ my $p = $self->sparse_matrices->get_match_prob ($i, $j, $ii, $jj);
+
+ $col_acc_num += 2 * $p;
+ $col_acc_denom += 2;
+
+ $char_acc_num += 2 * $p;
+ $char_acc_denom += 2;
+
+ $col_ppv_num += 2 * $p;
+ $col_ppv_denom += 2;
+
+ # both numerator and denominator for sn increase
+ $col_sn_num += $p;
+ $col_sn_denom += $self->sparse_matrices->get_sum_prob ($i, $j, $ii);
+
+ # both numerator and denominator for consistency increase
+ $col_cons_num += $p;
+ $col_cons_denom += $self->sparse_matrices->get_max_prob ($i, $j, $ii);
+
+ if ($use_log) {
+ $col_cert_num += 2 * $p;
+ $col_cert_denom += 2 * $self->sparse_matrices->get_altmax_prob ($i, $j, $ii, $jj);
+ } else {
+ $col_cert_num += 2 * (($p / $self->sparse_matrices->get_altmax_prob ($i, $j, $ii, $jj) >= $cert_threshold) ? 1 : 0);
+ $col_cert_denom += 2 * 1;
+ }
+
+ }
+
+ }
+
+ # is it correctly aligned according to our threshold?
+ if (!$stock->is_gap ($seq1, $col)) {
+ ++$total_chars;
+ if ($char_acc_num / $char_acc_denom > $acc_threshold) { ++$exp_correct; }
+ elsif ($char_acc_num / $char_acc_denom < 1.0 - $acc_threshold) { ++$exp_incorrect; }
+ }
+
+ }
+
+ # increment alignment counters
+ $acc_num += $col_acc_num;
+ $acc_denom += $col_acc_denom;
+
+ $ppv_num += $col_ppv_num;
+ $ppv_denom += $col_ppv_denom;
+
+ $sn_num += $col_sn_num;
+ $sn_denom += $col_sn_denom;
+
+ $cons_num += $col_cons_num;
+ $cons_denom += $col_cons_denom;
+
+ $cert_num += $col_cert_num;
+ $cert_denom += $col_cert_denom;
+
+ # sanity checks
+ if (($col_acc_num / $col_acc_denom < 0) || ($col_acc_num / $col_acc_denom > 1)) {
+ warn "Dangerous-looking Acc for column $col: $col_acc_num / $col_acc_denom.\n";
+ }
+ if (($col_ppv_denom > 0) and
+ ($col_ppv_num / $col_ppv_denom < 0) || ($col_ppv_num / $col_ppv_denom > 1)) {
+ warn "Dangerous-looking PPV for column $col: $col_ppv_num / $col_ppv_denom.\n";
+ }
+
+ # modify per-column annotation as appropriate
+ substr ($acc_annot, $col, 1) = get_markup_char ($col_acc_num / $col_acc_denom);
+ substr ($ppv_annot, $col, 1) = ($col_ppv_denom > 0) ? get_markup_char ($col_ppv_num /$col_ppv_denom) : "-";
+ substr ($sn_annot, $col, 1) = get_markup_char ($col_sn_num / $col_sn_denom);
+ substr ($cons_annot, $col, 1) = get_markup_char ($col_cons_num / $col_cons_denom);
+ if ($use_log) {
+ substr ($cert_annot, $col, 1) = get_markup_char ($self->normalize_certainty ($col_cert_num / $col_cert_denom, $cert_threshold));
+ } else {
+ substr ($cert_annot, $col, 1) = get_markup_char ($col_cert_num / $col_cert_denom);
+ }
+
+ }
+
+ # store total values
+ $self->acc ($acc_num / $acc_denom);
+ $self->sn ($sn_num / $sn_denom);
+ $self->ppv ($ppv_num / $ppv_denom);
+ $self->cons ($cons_num / $cons_denom);
+ if ($use_log) {
+ $self->cert ($self->normalize_certainty ($cert_num / $cert_denom, $cert_threshold));
+ } else {
+ $self->cert ($cert_num / $cert_denom);
+ }
+ $self->model_cert ($self->sparse_matrices->get_model_certainty());
+
+ $self->exp_correct ($exp_correct);
+ $self->exp_incorrect ($exp_incorrect);
+ $self->total_chars ($total_chars);
+
+ # store per-column annotation lines
+ $self->acc_annot ($acc_annot);
+ $self->sn_annot ($sn_annot);
+ $self->ppv_annot ($ppv_annot);
+ $self->cons_annot ($cons_annot);
+ $self->cert_annot ($cert_annot);
+
+}
+
+# Normalize certainty to [0,1] with a logarithmic transform.
+# Use the logarithm transform on values below $cert_threshold.
+sub normalize_certainty {
+ my ($class, $c, $cert_threshold) = @_;
+
+ if (!defined $cert_threshold) { $cert_threshold = 5.0; }
+
+ # if there was a better alternative, then return 0
+ if ($c < 1.0) {
+ return 0;
+ }
+
+ # if it was $cert_threshold times better than the best alternative, then return 1
+ elsif ($c >= $cert_threshold) {
+ return 1;
+ }
+
+ # else perform a logarithmic transform
+ else {
+ return (log ($c) / log ($cert_threshold));
+ }
+
+}
+
+# Show alignment accuracy information.
+sub show_accuracies {
+ my ($self, $precision, $terse) = @_;
+
+ if (!defined $precision) { $precision = 3; }
+ if (!defined $terse) { $terse = 0; }
+
+ # summary of accuracy metrics
+ my $acc_summary = sprintf "%.${precision}f %.${precision}f %.${precision}f %.${precision}f %.${precision}f", $self->acc, $self->sn, $self->ppv, $self->cert, $self->cons;
+ # model certainty
+ my $model_cert = sprintf "%.${precision}f", $self->model_cert;
+ # estimated number of definitely correct and incorrect characters`
+ my $correctness = sprintf "%d %d %d", $self->exp_correct, $self->exp_incorrect, $self->total_chars;
+
+ if (!$terse) {
+ printf "Acc %.${precision}f\n", $self->acc;
+ printf "Sn %.${precision}f\n", $self->sn;
+ printf "PPV %.${precision}f\n", $self->ppv;
+ printf "Certainty %.${precision}f\n", $self->cert;
+ printf "Consistency %.${precision}f\n", $self->cons;
+ printf "Model certainty (slope) %.${precision}f\n", $self->model_cert;
+ printf "Definitely correct characters %d / %d\n", $self->exp_correct, $self->total_chars;
+ printf "Definitely incorrect characters %d / %d\n", $self->exp_incorrect, $self->total_chars;
+ printf "%-10s %s %s %s\n", "Summary:", $acc_summary, $model_cert, $correctness;
+ }
+ else {
+ print "$acc_summary $model_cert $correctness\n";
+ }
+
+
+}
+
+
+# Annotate Stockholm alignment.
+sub annotate_alignment {
+ my ($self, $stock, $precision) = @_;
+
+ # #=GF annotations
+ $stock->add_gf ("Acc", sprintf "%.${precision}f", $self->acc);
+ $stock->add_gf ("Sn", sprintf "%.${precision}f", $self->sn);
+ $stock->add_gf ("PPV", sprintf "%.${precision}f", $self->ppv);
+ $stock->add_gf ("Consistency", sprintf "%.${precision}f", $self->cons);
+
+ # #=GC annotations
+ $stock->gc->{"Acc"} = $self->acc_annot;
+ $stock->gc->{"Sn"} = $self->sn_annot;
+ $stock->gc->{"PPV"} = $self->ppv_annot;
+ $stock->gc->{"Consistency"} = $self->cons_annot;
+
+ if (!$stock->is_flush()) {
+ croak "Alignment not flush.\n";
+ }
+
+}
+
+
+# Convert a number in the interval [0-1] to an integer [0-9].
+sub get_markup_char {
+ my ($norm) = @_;
+
+ my $safe = int (10 * $norm);
+ $safe = ($safe > 9) ? 9 : $safe;
+ my $char = substr ("0123456789", $safe, 1);
+
+ return $char;
+}
+
+
+1
diff --git a/perl/FSA/SparseMatrices.pm b/perl/FSA/SparseMatrices.pm
new file mode 100644
index 0000000..e9216e3
--- /dev/null
+++ b/perl/FSA/SparseMatrices.pm
@@ -0,0 +1,490 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+FSA::SparseMatrices.pm
+
+=head1 SYNOPSIS
+
+Perl module encapsulating sparse alignment posterior probability matrices.
+
+Written by Robert Bradley.
+
+=head1 METHODS
+
+=cut
+
+package FSA::SparseMatrices;
+
+use strict;
+use Carp;
+
+use vars '@ISA';
+
+sub new {
+ my ($class) = @_;
+
+ my $self = {
+ 'seq_keys' => {}, # sequence keys (names)
+ 'seq_len' => {}, # sequence lengths
+ 'match_probs' => {}, # seq1->seq2->pos1->pos2; transpose stored also
+ 'gap_probs' => {}, # seq1->seq2->pos1
+ 'sum_probs' => {}, # seq1->seq2->pos1
+ 'max_probs' => {} # seq1->seq2->pos1 is a 2-element hash (element 0 is max, 1 is altmax)
+ };
+
+ bless $self, ref ($class) || $class;
+
+ return $self;
+}
+
+# catch methods
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ my $sub = our $AUTOLOAD; # $AUTOLOAD contains the fully qualified name of the original subroutine
+ $sub =~ s/.*:://;
+
+ # check for DESTROY
+ return if $sub eq 'DESTROY';
+
+ # check for directives accessor, e.g. $self->directives_debug or $self->directives_('debug')
+ if ($sub =~ /^directives_(\S*)$/i) {
+ my $flag = lc ($1);
+ $flag = shift @args unless (length $flag); # this catches the argument 'debug' in the second example usage given above
+ if (!defined $self->{'directives'}->{$flag}) {
+ $self->{'directives'}->{$flag} = ""; # if no such flag exists, create one with the value ""
+ } # we therefore have to test 'if ($self->directives_debug)' rather than 'if (defined $self->directives_debug)'
+ return $self->{'directives'}->{$flag}; # the second will always be true because AUTOLOAD will create an empty flag for us
+ }
+
+ # check for ordinary accessors
+ # This has the effect of automatically implementing getter and setter methods.
+ # If there's an instance variable $name, then the getter method is $self->name
+ # and the setter method is $self->name('newName')
+ if (exists $self->{$sub}) {
+ if (@args > 1) { croak "Usage: $sub() or $sub(newValue)"; }
+ return
+ @args # if @args > 0
+ ? $self->{$sub} = $args[0] # { $self->{$sub} = $args[0]; return $args[0]; }
+ : $self->{$sub}; # else { return $self->{$sub}; }
+ }
+
+ croak "Unsupported method: $sub\n";
+}
+
+# Load from a FSA .probs file.
+sub from_probsfile {
+ my ($class, $probsfile) = @_;
+
+ my $self = $class->new;
+
+ # parse post probs
+ open PROBS,"<$probsfile" or croak "Couldn't open '$probsfile' for reading.\n";
+
+ warn "Loading posterior alignment probabilities from '$probsfile'.\n";
+
+ while (<PROBS>) {
+
+ chomp;
+ next if $_ eq '';
+
+ # comment
+ if (/^;/) { next; }
+
+ # probability entry
+ # (0, 4022) ~ (1, -1) => 0.773072
+ # handle case of scientific notation
+ elsif (/\((\d+),\s(-?\d+)\)\s~\s\((\d+),\s(-?\d+)\)\s=>\s(\d?\.?\d+)\*?[eE]?(-\d+)?/) {
+
+ my ($seq1, $pos1) = ($1, $2);
+ my ($seq2, $pos2) = ($3, $4);
+ my $prob = $5;
+ my $exponent = $6;
+
+ if (defined $exponent) {
+ $prob *= 10 ** $exponent;
+ }
+
+ # store
+ $self->store_entry ($seq1, $seq2, $pos1, $pos2, $prob);
+
+ }
+
+ else {
+ warn "Skipping input line '$_'.\n";
+ }
+
+ }
+
+ close PROBS;
+
+ return $self;
+}
+
+# Store a match or gap probability.
+# Update all information about the sparse matrices accordingly.
+sub store_entry {
+ my ($self, $seq1, $seq2, $pos1, $pos2, $prob) = @_;
+
+ # sequence keys
+ $self->seq_keys->{$seq1} = 1;
+ $self->seq_keys->{$seq2} = 1;
+
+ # sequence lengths
+ # remember 0-based indexing!
+ if (!defined $self->seq_len->{$seq1}) { $self->seq_len->{$seq1} = $pos1; }
+ else { $self->seq_len->{$seq1} = ($self->seq_len->{$seq1} < $pos1 + 1) ? $pos1 + 1 : $self->seq_len->{$seq1}; }
+ if (!defined $self->seq_len->{$seq2}) { $self->seq_len->{$seq2} = $pos2; }
+ else { $self->seq_len->{$seq2} = ($self->seq_len->{$seq2} < $pos2 + 1) ? $pos2 + 1 : $self->seq_len->{$seq2}; }
+
+ # match probs
+ # store transpose
+ if (($pos1 >= 0) && ($pos2 >= 0)) {
+
+ # match_probs
+ $self->match_probs->{$seq1}->{$seq2}->{$pos1}->{$pos2} = $prob;
+ $self->match_probs->{$seq2}->{$seq1}->{$pos2}->{$pos1} = $prob;
+
+ # max_probs: seq1
+
+ # if max_prob is undefined, then store new value
+ if (!defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0]) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1} = [];
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] = $prob;
+ }
+ # if new max, then store new value and update alternate max
+ elsif ($self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] < $prob) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] = $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0];
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] = $prob;
+ }
+ # if new alternate max because alternate max is undefined
+ elsif (!defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1]) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] = $prob;
+ }
+ # if new alternate max
+ elsif ($self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] < $prob) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] = $prob;
+ }
+
+ # max_probs: seq2
+
+ # if max_prob is undefined, then store new value
+ if (!defined $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0]) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2} = [];
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0] = $prob;
+ }
+ # if new max, then store new value and update alternate max
+ elsif ($self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0] < $prob) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] = $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0];
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0] = $prob;
+ }
+ # if new alternate max because alternate max is undefined
+ elsif (!defined $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1]) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] = $prob;
+ }
+ # if new alternate max
+ elsif ($self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] < $prob) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] = $prob;
+ }
+
+ # sum prob: seq1
+ if (!defined $self->sum_probs->{$seq1}->{$seq2}->{$pos1}) {
+ $self->sum_probs->{$seq1}->{$seq2}->{$pos1} = $prob;
+ } else {
+ $self->sum_probs->{$seq1}->{$seq2}->{$pos1} += $prob;
+ }
+
+ # sum prob: seq2
+ if (!defined $self->sum_probs->{$seq2}->{$seq1}->{$pos2}) {
+ $self->sum_probs->{$seq2}->{$seq1}->{$pos2} = $prob;
+ } else {
+ $self->sum_probs->{$seq2}->{$seq1}->{$pos2} += $prob;
+ }
+
+ }
+
+ # seq1 ~ -
+ elsif (($pos1 >= 0) && ($pos2 == -1)) {
+
+ # gap_probs
+ $self->gap_probs->{$seq1}->{$seq2}->{$pos1} = $prob;
+
+ # max_prob: seq1
+
+ # if max_prob is undefined, then store new value
+ if (!defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0]) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1} = [];
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] = $prob;
+ }
+ # if new max, then store new value and update alternate max
+ elsif ($self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] < $prob) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] = $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0];
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] = $prob;
+ }
+ # if new alternate max because alternate max is undefined
+ elsif (!defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1]) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] = $prob;
+ }
+ # if new alternate max
+ elsif ($self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] < $prob) {
+ $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1] = $prob;
+ }
+
+ }
+
+ # - ~ seq2
+ elsif (($pos1 == -1) && ($pos2 >= 0)) {
+
+ # gap_probs
+ $self->gap_probs->{$seq2}->{$seq1}->{$pos2} = $prob;
+
+ # max_prob: seq2
+
+ # if max_prob is undefined, then store new value
+ if (!defined $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0]) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2} = [];
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0] = $prob;
+ }
+ # if new max, then store new value and update alternate max
+ elsif ($self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0] < $prob) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] = $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0];
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[0] = $prob;
+ }
+ # if new alternate max because alternate max is undefined
+ elsif (!defined $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1]) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] = $prob;
+ }
+ # if new alternate max
+ elsif ($self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] < $prob) {
+ $self->max_probs->{$seq2}->{$seq1}->{$pos2}->[1] = $prob;
+ }
+
+ } else {
+ croak "Unreachable on input line:\n$_";
+ }
+
+}
+
+# Write formatted .probs file to a string.
+# In the format produced by FSA.
+sub to_string {
+ my ($self) = @_;
+
+ my $s;
+ my @seqs = sort { $a <=> $b } keys %{$self->seq_keys};
+ for (my $i = 0; $i < @seqs; ++$i) {
+ my $seq1 = $seqs[$i];
+
+ for (my $j = $i + 1; $j < @seqs; ++$j) {
+ my $seq2 = $seqs[$j];
+
+ if (!$self->exists_matrix ($seq1, $seq2)) { next; }
+
+ $s .= "
+; Sparse posterior probability matrix for sequences $seq1 and $seq2
+; Format is:
+; ($seq1, position_1) ~ ($seq2, position_2) => prob
+; which means that ($seq1, position_1) is aligned to ($seq2, position_2) with probability prob.
+; ($seq1, position_1) ~ ($seq2, -1) => prob
+; means that ($seq1, position_1) is aligned to a gap in $seq2 with probability prob.
+; sequence is 0-based and position is 0-based
+";
+
+ $s .= "; match posteriors\n";
+ foreach my $pos1 (sort { $a <=> $b } keys %{$self->match_probs->{$seq1}->{$seq2}}) {
+ foreach my $pos2 (sort { $a <=> $b } keys %{$self->match_probs->{$seq1}->{$seq2}->{$pos1}}) {
+ $s .= "($seq1, $pos1) ~ ($seq2, $pos2) => " . $self->match_probs->{$seq1}->{$seq2}->{$pos1}->{$pos2} . "\n";
+ }
+ }
+ $s .= "\n";
+
+ $s .= "; gap posteriors\n";
+ foreach my $pos1 (sort { $a <=> $b } keys %{$self->gap_probs->{$seq1}->{$seq2}}) {
+ $s .= "($seq1, $pos1) ~ ($seq2, -1) => " . $self->gap_probs->{$seq1}->{$seq2}->{$pos1} . "\n";
+ }
+ $s .= "\n";
+ foreach my $pos2 (sort { $a <=> $b } keys %{$self->gap_probs->{$seq2}->{$seq1}}) {
+ $s .= "($seq1, -1) ~ ($seq2, $pos2) => " . $self->gap_probs->{$seq2}->{$seq1}->{$pos2} . "\n";
+ }
+ $s .= "\n";
+
+ }
+ }
+
+ return $s;
+}
+
+# Do we have information for a particular sequence pair?
+sub exists_matrix {
+ my ($self, $seq1, $seq2) = @_;
+
+ if (defined $self->match_probs->{$seq1} and
+ defined $self->match_probs->{$seq1}->{$seq2}) {
+ return 1;
+ }
+
+ return 0;
+}
+
+# Get match probability.
+sub get_match_prob {
+ my ($self, $seq1, $seq2, $pos1, $pos2) = @_;
+
+ if (!$self->exists_matrix ($seq1, $seq2)) {
+ croak "No probability matrix for sequences '$seq1' and '$seq2'.";
+ }
+
+ # if no entry, return 0
+ if (!defined $self->match_probs->{$seq1}->{$seq2}->{$pos1} or
+ !defined $self->match_probs->{$seq1}->{$seq2}->{$pos1}->{$pos2}) {
+ return 0;
+ }
+
+ return assert_valid_prob ($self->match_probs->{$seq1}->{$seq2}->{$pos1}->{$pos2});
+}
+
+sub assert_valid_prob {
+ my ($prob) = shift;
+
+ if ($prob > 1.0001) { die "Probability of ", $prob, " exceeds bounds.\n"; }
+
+ return ($prob > 1.0) ? 1.0 : $prob;
+}
+
+# Get gap probability.
+sub get_gap_prob {
+ my ($self, $seq1, $seq2, $pos1) = @_;
+
+ if (!$self->exists_matrix ($seq1, $seq2)) {
+ croak "No matrix for sequences '$seq1' and '$seq2';"
+ }
+
+ # there must exist an entry (FSA always outputs one)
+ if (!defined $self->gap_probs->{$seq1}->{$seq2}->{$pos1}) {
+ croak "No gap probability ($seq1, $pos1) ~ ($seq2, -1); I'm quitting.";
+ }
+
+ return $self->gap_probs->{$seq1}->{$seq2}->{$pos1};
+}
+
+# Get sum_pos2 P((seq1, pos1) ~ (seq2, pos2)).
+# Cover the case of no entry for a match probability > 0.01.
+# This coarse-graining of probabilities is important,
+# since sum_prob is used as a denominator.
+sub get_sum_prob {
+ my ($self, $seq1, $seq2, $pos1) = @_;
+
+ my $p = (defined $self->sum_probs->{$seq1}->{$seq2}->{$pos1}) ? $self->sum_probs->{$seq1}->{$seq2}->{$pos1} : 0.01;
+ return assert_valid_prob ($p);
+}
+
+# Get max_pos2 P((seq1, pos1) ~ (seq2, pos2)),
+# where pos2 can be a gap as well.
+sub get_max_prob {
+ my ($self, $seq1, $seq2, $pos1) = @_;
+
+ # assert that max prob is defined
+ # (because pos2 can be a gap, a max prob is always defined)
+ if (!defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0]) {
+ croak "A max prob is undefined; this should never happen!\n";
+ }
+
+ return assert_valid_prob ($self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0]);
+}
+
+# Get altmax_pos2 P((seq1, pos1) ~ (seq2, pos2)),
+# where pos2 can be a gap as well.
+# Note that we need to know $pos2 here (in contrast to get_max_prob),
+# in order to determine whether the probability corresponding to
+# the alignment ($seq1, $pos1) ~ ($seq2, $pos2)
+# is the max, altmax or otherwise.
+sub get_altmax_prob {
+ my ($self, $seq1, $seq2, $pos1, $pos2) = @_;
+
+ # assert that max prob is defined
+ if (!defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0]) {
+ croak "A max prob is undefined; this should never happen!\n";
+ }
+ # note that an altmax might not be defined,
+ # ie if there is no match probability entry and so the max prob is
+ # the gap prob
+
+ my $p;
+ if ($pos1 >= 0 && $pos2 >= 0) {
+ $p = $self->get_match_prob ($seq1, $seq2, $pos1, $pos2);
+ }
+ elsif ($pos1 >= 0 && $pos2 == -1) {
+ $p = $self->get_gap_prob ($seq1, $seq2, $pos1);
+ }
+ else {
+ croak "No good; tried to get the altmax for a gap!\n";
+ }
+
+ # if $p is the max, then return the second-best alternative
+ if (abs ($p - $self->get_max_prob ($seq1, $seq2, $pos1)) < 0.0001) {
+ if (defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1]) {
+ return $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1];
+ } else {
+ return 0.01;
+ }
+ }
+ # else return the max
+ else {
+ return $self->get_max_prob ($seq1, $seq2, $pos1);
+ }
+
+}
+
+# Compute the average certainty of the model.
+# This corresponds to:
+# for each sequence seq1
+# for each sequence seq2
+# for each position pos1 in seq1
+# += P(pos1 ~ best)
+# += P(pos1 ~ next-best)
+# Note that this calculation is only a measure of the width of the
+# probability distribution in the DP matrix, and as such is alignment-independent.
+sub get_model_certainty {
+ my ($self) = @_;
+
+ my $max = 0;
+ my $altmax = 0;
+
+ foreach my $seq1 (keys %{$self->max_probs}) {
+ for (my $pos1 = 0; $pos1 < $self->seq_len->{$seq1}; ++$pos1) {
+ foreach my $seq2 (keys %{$self->max_probs->{$seq1}}) {
+ # remember that altmax automatically gets initialized to minimum value
+ # when max is initialized
+ $max += $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0];
+ if (defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1]) {
+ $altmax += $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1];
+ } else {
+ $altmax += 0.01;
+ }
+ }
+ }
+ }
+
+ return ($max / $altmax);
+}
+
+# As above, but show the entire distribution of slopes (for all characters).
+sub show_model_certainty_slopes {
+ my ($self, $precision) = @_;
+
+ foreach my $seq1 (keys %{$self->max_probs}) {
+ for (my $pos1 = 0; $pos1 < $self->seq_len->{$seq1}; ++$pos1) {
+ foreach my $seq2 (keys %{$self->max_probs->{$seq1}}) {
+ if (defined $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1]) {
+ printf "%.${precision}f\n", $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] / $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[1];
+ } else {
+ printf "%.${precision}f\n", $self->max_probs->{$seq1}->{$seq2}->{$pos1}->[0] / 0.01;
+ }
+ }
+ }
+ }
+
+}
+
+
+1
diff --git a/perl/GFF.pm b/perl/GFF.pm
new file mode 100644
index 0000000..34bd2cc
--- /dev/null
+++ b/perl/GFF.pm
@@ -0,0 +1,271 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+GFF.pm
+
+=head1 SYNOPSIS
+
+Perl module encapsulating a single GFF entry.
+Note that the GFF format, which specifies that coordinates
+are 1-based and fully-closed, is enforced by this module.
+
+The original GFF module was written by Ian Holmes.
+This version has been extended by Robert Bradley.
+
+=head1 METHODS
+
+=cut
+
+package GFF;
+
+use strict;
+use Carp;
+
+=head2 new
+
+ my $gff = GFF->new()
+
+Creates an empty GFF object.
+
+=cut
+sub new {
+ my $class = shift;
+
+ my $self = {
+ 'seqid' => '.',
+ 'source' => '.',
+ 'type' => '.',
+ 'start' => '.',
+ 'end' => '.',
+ 'score' => '.',
+ 'strand' => '.',
+ 'phase' => '.',
+ 'attributes' => '.',
+ 'attributes_hash' => undef,
+ @_
+ };
+
+ bless $self, ref($class) || $class;
+
+ return $self;
+}
+
+=head2 seqid
+
+ my $seqid = $gff->seqid
+
+Returns the seqid field.
+
+ $gff->seqid ($newseqid)
+
+Sets the seqid field.
+
+Similarly implemented for all GFF fields.
+
+Catches all methods by default.
+
+=cut
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ my $sub = our $AUTOLOAD; # $AUTOLOAD contains the fully qualified name of the original subroutine
+ $sub =~ s/.*:://;
+
+ # check for DESTROY
+ return if $sub eq 'DESTROY';
+
+ # check for ordinary accessors
+ # This has the effect of automatically implementing getter and setter methods.
+ # If there's an instance variable $name, then the getter method is $self->name
+ # and the setter method is $self->name('newName')
+ if (exists $self->{$sub}) {
+ if (@args > 1) { croak "Usage: $sub() or $sub(newValue)"; }
+ return
+ @args # if @args > 0
+ ? $self->{$sub} = $args[0] # { $self->{$sub} = $args[0]; return $args[0]; }
+ : $self->{$sub}; # else { return $self->{$sub}; }
+ }
+
+ croak "Unsupported method: $sub\n";
+}
+
+=head2 from_string
+
+ my $gff = GFF->from_string ($str)
+
+Reads values from a string in GFF format.
+
+=cut
+sub from_string {
+ my $class = shift;
+
+ my $self = $class;
+ if (!ref ($class)) { $self = $class->new(); }
+
+ my $str = shift if (@_);
+ if (!defined $str) { return undef; }
+
+ chomp ($str);
+
+ # check for:
+ # empty lines
+ # comment and sequence header lines
+ # sequence lines
+ if ($str eq ""
+ || $str =~ /^\s*(#|>)/
+ || $str =~ /^\s*\S+\s*$/)
+ { return undef; }
+
+ my @gff = split /\t/, $str;
+ $self->{"seqid"} = $gff[0];
+ $self->{"source"} = $gff[1];
+ $self->{"type"} = $gff[2];
+ $self->set_start ($gff[3]);
+ $self->{"end"} = $gff[4];
+ $self->{"score"} = $gff[5];
+ $self->{"strand"} = $gff[6];
+ $self->{"phase"} = $gff[7];
+ $self->{"attributes"} = $gff[8];
+
+ return $self;
+}
+
+=head2 to_string
+
+ print $gff->to_string()
+
+Output to a string in GFF format.
+
+=cut
+sub to_string {
+ my $self = shift;
+ return join ("\t", $self->seqid, $self->source, $self->type,
+ $self->start, $self->end, $self->score,
+ $self->strand, $self->phase, (defined $self->attributes ? $self->attributes : '') . "\n");
+}
+
+=head2 to_file
+
+ $gff->to_file ($myfile)
+
+Output to a file in GFF format.
+
+ $gff->to_file ($myfile, 1)
+
+Append mode.
+
+=cut
+sub to_file {
+ my ($self, $pFile, $pMode) = @_;
+
+ my $modeOp = ">";
+ if ($pMode) {$modeOp = ">>";}
+ open(FILE, $modeOp . $pFile) or die "Could not open $pFile.\n";
+ print FILE $self->to_string();
+}
+
+=head2 set_start
+
+ $gff->set_start ($start)
+
+Set the start coordinate.
+Enforces start coordinate >= 1.
+
+=cut
+sub set_start {
+ my ($self, $s) = @_;
+ if ($s < 1) { warn "Setting start coordinate '$s' to 1.\n"; $s = 1; }
+ $self->start ($s);
+}
+
+=head2 add_value
+
+ $gff->add_value()
+
+Add single entry (key and value) to attributes field.
+
+=cut
+sub add_value {
+ my ($self, $key, $value) = @_;
+
+ # add value to string for attributes field
+ if (($self->attributes eq ".") || !length ($self->attributes)) {
+ $self->attributes ("$key=$value");
+ } elsif ($self->attributes =~ /;$/) {
+ $self->{attributes} .= "$key=$value";
+ } else {
+ $self->{attributes} .= ";$key=$value";
+ }
+
+ # store in attributes hash if appropriate
+ if ($self->{attributes_hash}) { ${$self->{attributes_hash}}{$key} = $value; }
+}
+
+=head2 get_attributes_hash
+
+ $gff->get_attributes_hash()
+
+Get attributes field as a hash from keys to values.
+Creates it if it doesn't already exist.
+
+=cut
+sub get_attributes_hash {
+ my $self = shift;
+
+ my $hashRef = $self->{attributes_hash};
+ my %hash;
+ if (!$hashRef) {
+ my @pairs = split (/;/, $self->{attributes});
+ foreach my $pair (@pairs) {
+ my @keyVal = split (/=/, $pair);
+ $hash{$keyVal[0]} = $keyVal[1];
+ }
+ $hashRef = \%hash;
+ # set attributes_hash
+ $self->{attributes_hash} = $hashRef;
+ }
+
+ return $hashRef;
+
+}
+
+=head2 get_value
+
+ $gff->get_value ($key)
+
+Get value in attributes field.
+
+=cut
+sub get_value {
+ my ($self, $key) = @_;
+
+ return ${$self->get_attributes_hash()}{$key};
+
+}
+
+=head2 set_value
+
+ $gff->set_value ($key)
+
+Set value in attributes field.
+
+=cut
+sub set_value {
+ my ($self, $key, $value) = @_;
+
+ my $hashref = $self->get_attributes_hash();
+ # add the value if it's new
+ if (!defined $hashref->{$key}) {
+ $self->add_value ($key, $value);
+ }
+ # else parse out and replace the old value
+ # (yes, this is very slow, but I can't be bothered to fix it now)
+ else {
+ my $oldstr = "$key=" . $hashref->{$key};
+ my $newstr = "$key=" . $value;
+ $self->{attributes} =~ s/$oldstr/$newstr/;
+ }
+
+}
+
+1
diff --git a/perl/GFF/Database.pm b/perl/GFF/Database.pm
new file mode 100644
index 0000000..e259877
--- /dev/null
+++ b/perl/GFF/Database.pm
@@ -0,0 +1,201 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+GFF::Database.pm
+
+=head1 SYNOPSIS
+
+Perl module encapsulating a GFF file ("database").
+
+The original GFF::Database module was written by Ian Holmes.
+This version has been extended by Robert Bradley.
+
+=cut
+
+package GFF::Database;
+
+use strict;
+use Carp;
+
+use GFF;
+
+=head2 new
+
+ my $gffdb = GFF::Database->new()
+
+Creates an empty GFF::Database object.
+
+=cut
+sub new {
+ my ($class) = @_;
+
+ my $self = {
+ 'db' => []
+ };
+
+ bless $self, ref ($class) || $class;
+
+ return $self;
+}
+
+=head2 db
+
+ my $records = $gffdb->db
+
+Returns the list of GFF records contained.
+
+Catches all methods by default.
+
+=cut
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ my $sub = our $AUTOLOAD; # $AUTOLOAD contains the fully qualified name of the original subroutine
+ $sub =~ s/.*:://;
+
+ # check for DESTROY
+ return if $sub eq 'DESTROY';
+
+ # check for ordinary accessors
+ # This has the effect of automatically implementing getter and setter methods.
+ # If there's an instance variable $name, then the getter method is $self->name
+ # and the setter method is $self->name('newName')
+ if (exists $self->{$sub}) {
+ if (@args > 1) { croak "Usage: $sub() or $sub(newValue)"; }
+ return
+ @args # if @args > 0
+ ? $self->{$sub} = $args[0] # { $self->{$sub} = $args[0]; return $args[0]; }
+ : $self->{$sub}; # else { return $self->{$sub}; }
+ }
+
+ croak "Unsupported method: $sub\n";
+}
+
+=head2 from_file
+
+ my $gffdb = GFF::Database->from_file ($filename)
+
+Reads GFF file.
+
+=cut
+sub from_file {
+ my ($class, $filename) = @_;
+
+ my $self = $class->new;
+
+ $self->append_from_file ($filename);
+
+ return $self;
+}
+
+=head2 append_from_file
+
+ my $gffdb->append_from_file ($filename)
+
+Appends from GFF file.
+
+=cut
+sub append_from_file {
+ my ($self, $filename) = @_;
+
+ my $gff;
+ local *FILE;
+ local $_;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ while (<FILE>) {
+
+ # skip empty lines
+ chomp;
+ if ($_ eq "") { next; }
+
+ # skip comment and sequence header lines
+ if (/^\s*(#|>)/) { next; }
+
+ # skip sequence lines
+ if (/^\s*\S+\s*$/) { next; }
+
+ $gff = GFF->new unless defined $gff;
+ if ($gff->from_string ($_)) {
+ $self->add ($gff);
+ $gff = undef;
+ }
+
+ }
+ close FILE;
+
+ # catch end case
+ $self->add ($gff) if defined $gff;
+
+}
+
+=head2 add
+
+ $gffdb->add ($gff)
+
+Add a single GFF entry to database.
+
+=cut
+sub add {
+ my ($self, $gff, $verbose) = @_;
+ push @{$self->db}, $gff;
+ warn "...loaded GFF record ", $gff->to_string() if $verbose;
+ return $self;
+}
+
+=head2 to_string
+
+ print $gff->to_string()
+
+Output to a string in GFF format.
+
+=cut
+sub to_string {
+ my ($self) = @_;
+
+ my $str = join ("", map ($_->to_string(), @{$self->db}));
+
+ return $str;
+
+}
+
+=head2 find_by_group
+
+ $gff->find_by_group ($key, $value)
+
+Query for GFF records matching a given key/value in the group field.
+
+=cut
+sub find_by_group {
+ my ($self, $pKey, $pVal) = @_;
+
+ my @gffList;
+ foreach my $gff (@{$self->{db}})
+ {
+ my $group_hash = $gff->get_group_hash();
+ if (${$group_hash}{$pKey} eq $pVal) { push(@gffList, $gff); }
+ }
+
+ return \@gffList;
+}
+
+=head2 find_by_type
+
+ my $list = $gff->find_by_type ("type")
+
+Get all entries with a particular type field.
+
+=cut
+sub find_by_type {
+ my ($self, $type) = @_;
+
+ my @list;
+ foreach my $gff (@{$self->{db}}) {
+ if ($gff->type eq $type) {
+ push @list, $gff;
+ }
+ }
+
+ return \@list;
+}
+
+1
diff --git a/perl/Makefile.am b/perl/Makefile.am
new file mode 100644
index 0000000..0caca20
--- /dev/null
+++ b/perl/Makefile.am
@@ -0,0 +1,14 @@
+EXTRA_DIST = \
+ accuracy.pl\
+ cmpalign.pl \
+ dartlog.pl \
+ fasta2stockholm.pl \
+ FSA/SparseMatrices.pm \
+ FSA/Model.pm \
+ GFF.pm \
+ GFF/Database.pm \
+ prettify.pl \
+ seqdotplot.pl \
+ stockholm2fasta.pl \
+ Stockholm.pm \
+ Stockholm/Database.pm
diff --git a/perl/Makefile.in b/perl/Makefile.in
new file mode 100644
index 0000000..40ec6be
--- /dev/null
+++ b/perl/Makefile.in
@@ -0,0 +1,422 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = perl
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ accuracy.pl\
+ cmpalign.pl \
+ dartlog.pl \
+ fasta2stockholm.pl \
+ FSA/SparseMatrices.pm \
+ FSA/Model.pm \
+ GFF.pm \
+ GFF/Database.pm \
+ prettify.pl \
+ seqdotplot.pl \
+ stockholm2fasta.pl \
+ Stockholm.pm \
+ Stockholm/Database.pm
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign perl/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign perl/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
+ ctags-am distclean distclean-generic distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/perl/Stockholm.pm b/perl/Stockholm.pm
new file mode 100644
index 0000000..784bb6a
--- /dev/null
+++ b/perl/Stockholm.pm
@@ -0,0 +1,1788 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+Stockholm.pm
+
+=head1 SYNOPSIS
+
+Perl module encapsulating a Stockholm multiple alignment.
+Can load Stockholm, multi-FASTA (MFA), CLUSTAL and MSF alignments.
+Can print Stockholm and MFA aligments.
+
+The original Stockholm module was written by Ian Holmes for his DART library.
+This version has been modified and extended by Robert Bradley.
+
+=head1 METHODS
+
+=cut
+
+package Stockholm;
+
+use strict;
+use vars '@ISA';
+
+use Carp qw(carp cluck croak);
+
+# define the gap alphabet
+my $gapChars = '-._';
+
+# define percent id annotation
+my $percentid_annot = 'Percent_id';
+
+# define gap fraction annotation
+my $gapfraction_annot = 'Gap_fraction';
+
+
+=head2 new
+
+ my $stock = Stockholm->new();
+
+Creates an empty Stockholm object.
+
+=cut
+sub new {
+ my ($class) = @_;
+
+ my $self = {
+ 'seqname' => [], # order of sequences
+ 'seqdata' => {}, # sequence data itself
+ 'gf' => {}, # Generic File annotation (freeform)
+ 'gc' => {}, # Generic Consensus annotation (by-column)
+ 'gs' => {}, # Generic Sequence annotation (by-sequence, freeform)
+ 'gr' => {}, # Generic by-Row annotation (by-sequence, by-column)
+ 'gforder' => [] # order of GF lines
+ };
+
+ bless $self, ref ($class) || $class;
+
+ return $self;
+}
+
+=head2 from_file
+
+ my $stock = Stockholm->from_file ($filename);
+ my $stock = Stockholm->from_file ($filename, 1);
+
+Creates a new Stockholm object and reads it from a file.
+Attempts to automatically detect the format of the input file
+and parse accordingly.
+
+If last argument is true, then call strip_leading_chr to remove
+the 'chr' frequently prepended to chromosome names.
+
+=cut
+sub from_file {
+ my ($class, $filename, $remove_chr) = @_;
+
+ my $self;
+
+ # by default don't remove the leading 'chr'
+ if (!defined $remove_chr) { $remove_chr = 0; }
+
+ # FASTA
+ if ($class->detect_FASTA ($filename)) {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ $self = $class->from_filehandle_FASTA (\*FILE, $remove_chr);
+ close FILE;
+ }
+
+ # CLUSTAL
+ elsif ($class->detect_CLUSTAL ($filename)) {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ $self = $class->from_filehandle_CLUSTAL (\*FILE, $remove_chr);
+ close FILE;
+ }
+
+ # MSF
+ elsif ($class->detect_MSF ($filename)) {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ $self = $class->from_filehandle_MSF (\*FILE, $remove_chr);
+ close FILE;
+ }
+
+ # Stockholm
+ else {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ $self = $class->from_filehandle_Stockholm (\*FILE, $remove_chr);
+ close FILE;
+ }
+
+ return $self;
+
+}
+
+=head2 detect_FASTA
+
+ detect_FASTA ($filename);
+
+Detects whether the alignment is FASTA format.
+Looks for lines of the form
+>seqname
+
+=cut
+sub detect_FASTA {
+ my ($class, $filename) = @_;
+
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open '$filename'.\n";
+ while (<FILE>) {
+ if (/^\s*>\s*\S+/) { return 1; }
+ }
+ close FILE;
+
+ return 0;
+}
+
+=head2 from_filehandle_FASTA
+
+ $self->from_filehandle_FASTA ($filehandle);
+
+Creates a new Stockholm object and reads it from a filehandle.
+
+=cut
+sub from_filehandle_FASTA {
+ my ($class, $filehandle, $remove_chr) = @_;
+
+ my $self = $class->new;
+
+ # by default don't remove the leading 'chr'
+ if (!defined $remove_chr) { $remove_chr = 0; }
+
+ my $name = "";
+ my $data = "";
+
+ # perform a first pass through the data to put each alignment row
+ # onto a single line
+ # this *dramatically* speeds up reading in FASTA alignments
+ local $_;
+ my $str = "";
+ while (<$filehandle>) {
+ if (/^\s*>/) { $str .= "\n$_"; next; }
+ chomp;
+ $str .= $_;
+ }
+
+ # now read in this compressed format
+ my $str_handle;
+ open ($str_handle, "<", \$str);
+ while (<$str_handle>) {
+ chomp;
+
+ # if beginning of new sequence
+ if (/^\s*>/) {
+
+ # store previous sequence if available
+ if ($name ne "") {
+ push @{$self->seqname}, $name;
+ $self->seqdata->{$name} = $data;
+ $data = ""; # reset data
+ }
+
+ # store new name
+ unless (/^\s*>\s*(\S+)/) { croak "Couldn't parse out sequence name from line: $_\n"; }
+ $name = $1;
+ if ($remove_chr) { $name = $self->strip_leading_chr ($name); }
+ }
+
+ # else store data
+ else {
+ $data .= $_;
+ $data =~ s/\s//g; # remove whitespace
+ }
+
+ }
+ close $str_handle;
+
+ # catch last sequence
+ push @{$self->seqname}, $name;
+ $self->seqdata->{$name} = $data;
+
+ return $self;
+
+}
+
+=head2 detect_CLUSTAL
+
+ detect_CLUSTAL ($filename);
+
+Detects whether the alignment is CLUSTAL format.
+
+=cut
+sub detect_CLUSTAL {
+ my ($class, $filename) = @_;
+
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open '$filename'.\n";
+ while (<FILE>) {
+ if (/^\s*CLUSTAL/) { return 1; }
+ }
+ close FILE;
+
+ return 0;
+}
+
+=head2 from_filehandle_CLUSTAL
+
+ $self->from_filehandle_CLUSTAL ($filehandle);
+
+Creates a new Stockholm object and reads it from a filehandle.
+
+=cut
+sub from_filehandle_CLUSTAL {
+ my ($class, $filehandle, $remove_chr) = @_;
+
+ my $self = $class->new;
+
+ # by default don't remove the leading 'chr'
+ if (!defined $remove_chr) { $remove_chr = 0; }
+
+ local $_;
+ while (<$filehandle>) {
+ chomp;
+
+ # skip conservation lines with * : .
+ next if (/^(\s*[\*:\.]*\s*)+$/);
+
+ # sequence data
+ my @a = split;
+ next unless @a == 2;
+ my ($seq, $data) = @a;
+ if ($remove_chr) { $seq = $self->strip_leading_chr ($seq); }
+
+ if (defined $self->seqdata->{$seq}) {
+ $self->seqdata->{$seq} .= $data;
+ } else {
+ push @{$self->seqname}, $seq;
+ $self->seqdata->{$seq} = $data;
+ }
+
+ }
+
+ return $self;
+
+}
+
+=head2 detect_MSF
+
+ detect_MSF ($filename);
+
+Detects whether the alignment is MSF format.
+Looks for the special line containing
+"MSF:", "Type:" , and "Check:" and ending with two dots.
+Specification taken from:
+http://biobug.life.nthu.edu.tw/predictprotein/Dexa/optin_msfDes.html
+
+=cut
+sub detect_MSF {
+ my ($class, $filename) = @_;
+
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open '$filename'.\n";
+ while (<FILE>) {
+ # "MSF:", "Type:" , and "Check:" and ending with two dots.
+ if (/(MSF:){1}.*(Type:){1}.*(Check:){1}.*(\.\.){1}/i) { return 1; }
+ }
+ close FILE;
+
+ return 0;
+}
+
+=head2 from_filehandle_MSF
+
+ $self->from_filehandle_MSF ($filehandle);
+
+Creates a new Stockholm object and reads it from a filehandle.
+
+=cut
+sub from_filehandle_MSF {
+ my ($class, $filehandle, $remove_chr) = @_;
+
+ my $self = $class->new;
+
+ # by default don't remove the leading 'chr'
+ if (!defined $remove_chr) { $remove_chr = 0; }
+
+ my $in_body = 0;
+
+ local $_;
+ while (<$filehandle>) {
+ chomp;
+
+ # alignment header
+ if (!$in_body) {
+
+ # if a sequence descriptor in the alignment description,
+ # store the sequence name and initialize the sequence data
+ if (/^\s*Name:\s*(\S+)\s*/) {
+ my $name = $1;
+ if ($remove_chr) { $name = $self->strip_leading_chr ($name); }
+ push @{$self->seqname}, $name;
+ if (defined $self->seqdata->{$name}) {
+ croak "Duplicate sequence name '$name' in MSF alignment descriptor; I'm quitting.\n";
+ }
+ $self->seqdata->{$name} = "";
+ }
+
+ # termination of header list
+ elsif (/^\s*\/\/\s*$/) { $in_body = 1; }
+
+ }
+
+ # alignment body
+ else {
+
+ # if a sequence line
+ if (/^\s*(\S+)\s+(\S+.*)+\s*$/) { # allows empty sequence lines
+ my $name = $1;
+ if ($remove_chr) { $name = $self->strip_leading_chr ($name); }
+ if (!defined $self->seqdata->{$name}) {
+ warn "Skipping line because I don't recognize the sequence '$name':\n$_\n";
+ }
+ $self->seqdata->{$name} .= $2;
+ $self->seqdata->{$name} =~ s/\s//g; # remove whitespace
+ }
+
+ }
+
+ }
+
+ return $self;
+
+}
+
+=head2 detect_Stockholm
+
+ detect_Stockholm ($filename);
+
+Detects whether the alignment is Stockholm format.
+Doesn't allow empty sequence lines.
+
+=cut
+sub detect_Stockholm {
+ my ($class, $filename) = @_;
+
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open '$filename'.\n";
+
+ while (<FILE>) {
+
+ # look for Stockholm header
+ if (/\# STOCKHOLM/) { return 1; }
+
+ # look for Stockholm comment lines
+ elsif (/^\s*\#=[GF|GS|GC|GR]/) { return 1; }
+
+ # skip unrecognized comment lines
+ elsif (/^\s*\#.*$/) { next; }
+
+ # skip alignment separators
+ elsif (/^\s*\/\/\s*$/) { next; }
+
+ # confirm that format of sequence lines is Stockholm-compatible
+ elsif (/^\s*(\S+)\s+(\S+)\s*$/) { next; } # don't allow empty sequence lines
+
+ # else declare it not Stockholm format
+ else { return 0; }
+
+ }
+ close FILE;
+
+ return 1;
+}
+
+
+=head2 from_filehandle_Stockholm
+
+ my $stock = Stockholm->from_filehandle_Stockholm ($filehandle);
+
+Creates a new Stockholm object and reads it from a filehandle.
+
+=cut
+sub from_filehandle_Stockholm {
+ my ($class, $filehandle, $remove_chr) = @_;
+
+ my $self = $class->new;
+
+ # by default don't remove the leading 'chr'
+ if (!defined $remove_chr) { $remove_chr = 0; }
+
+ local $_;
+ while (<$filehandle>) {
+ last if $self->parse_input_line ($_, $remove_chr);
+ }
+ carp "Warning: alignment is not flush" unless $self->is_flush();
+
+ return $self;
+}
+
+=head2 to_file
+
+ $stock->to_file ($filename);
+
+Writes a Stockholm object to a file.
+
+=cut
+sub to_file {
+ my ($self, $filename, $maxcols) = @_;
+
+ local *FILE;
+ open FILE, ">$filename" or croak "Couldn't open '$filename' for writing: $!";
+ print FILE $self->to_string ($maxcols);
+ close FILE or croak "Couldn't close '$filename': $!";;
+
+ return $filename;
+}
+
+=head2 to_string_FASTA
+
+ print $fasta->to_string_FASTA();
+ print $fasta->to_string_FASTA (0);
+
+Returns the object as a multi-FASTA or ungapped FASTA formatted string.
+
+=cut
+sub to_string_FASTA {
+ my ($self, $ungapped) = @_;
+
+ my $fasta;
+
+ # write MFA rather than ungapped FASTA by default
+ if (!defined $ungapped) { $ungapped = 0; }
+
+ foreach my $seq (@{$self->seqname}) {
+ $fasta .= ">$seq\n";
+ my $newseq = $self->seqdata->{$seq};
+ if ($ungapped) { $newseq =~ s/[$gapChars]//g; } # remove gaps if requested
+ $fasta .= $newseq . "\n";
+ }
+
+ return $fasta;
+
+}
+
+=head2 to_string
+
+ print $stock->to_string ($maxcols)
+ print $stock->to_string ($maxcols, ARG1=>VAL1, ARG2=>VAL2 ...)
+ print $stock->to_string (MAXCOLS=>$maxcols, ARG1=>VAL1, ARG2=>VAL2 ...)
+
+Returns the object as a Stockholm-formatted string.
+
+ARGs can include...
+ MAXCOLS -- limit maximum number of columns (can also be specified as a single scalar arg)
+ NOSEQDATA -- don\'t print any sequence data (can be used this to compress output)
+
+=cut
+sub to_string {
+ my ($self, @args) = @_;
+
+ my (%args, $maxcols);
+ if (@args % 2 == 1) {
+ $maxcols = shift @args;
+ %args = @args;
+ } else {
+ %args = @args;
+ $maxcols = $args{'MAXCOLS'};
+ }
+ $maxcols = 80 unless defined $maxcols; # default 80-column output
+
+ # init output array
+ my @out;
+ push @out, "# STOCKHOLM 1.0";
+
+ # determine alignment columns, legend columns & effective columns per line
+ my $acols = $self->columns();
+ my $lcols = $self->lcols();
+ my $colstep = $maxcols < 1 ? $acols : $maxcols - $lcols - 1;
+ $colstep = $maxcols if $colstep < 1; # protect against negative and 0 colstep...
+
+ # GF lines
+ # check for gforder (insane, fragile Stockholm line ordering strikes again)
+ if (@{$self->gforder} == map { (@$_) } values %{$self->gf}) { # gforder same number of lines as #=GF block?
+ my %gfCursor = map (($_ => 0), keys %{$self->gf});
+ foreach my $feature (@{$self->gforder}) {
+ push @out, $self->prettify ($lcols, "#=GF $feature", $self->gf_($feature)->[$gfCursor{$feature}++]);
+ }
+ } else {
+ @{$self->gforder} = (); # gforder is useless, so flush it
+ foreach my $feature (sort { $a cmp $b } keys %{$self->gf}) {
+ push @out, $self->prettify ($lcols, "#=GF $feature", @{$self->gf_($feature)});
+ }
+ }
+
+ # GS lines
+ my @gs_seqname = @{$self->seqname};
+ my %gs_seqname_hash = map (($_=>1), grep (!exists $self->seqdata->{$_}, map (keys(%{$self->gs_($_)}), keys %{$self->gs})));
+ push @gs_seqname, keys %gs_seqname_hash;
+ foreach my $feature (sort { $a cmp $b } keys %{$self->gs}) {
+ my $hash = $self->gs_($feature);
+ foreach my $seqname (grep (exists($hash->{$_}), @gs_seqname)) {
+ push @out, $self->prettify ($lcols, "#=GS $seqname $feature", @{$hash->{$seqname}});
+ }
+ }
+
+ my @gcfeat = sort { $a cmp $b } keys %{$self->gc};
+ my @gr_seqname = @{$self->seqname};
+ my %gr_seqname_hash = map (($_=>1), grep (!exists $self->seqdata->{$_}, map (keys(%{$self->gr_($_)}), keys %{$self->gr})));
+ push @gr_seqname, keys %gr_seqname_hash;
+
+ # Loop over columns
+ for (my $col = 0; $col < $acols; $col += $colstep) {
+
+ # GC lines
+ foreach my $feature (@gcfeat) {
+ push @out, $self->prettify ($lcols, "#=GC $feature",
+ substr ($self->gc_($feature), $col, $colstep));
+ }
+ for (my $i = 0; $i < @gr_seqname; ++$i) {
+ my $seqname = $gr_seqname[$i];
+ # Sequences
+ # warn "Writing cols $col+$colstep for $seqname";
+ push @out, $self->prettify ($lcols, $seqname,
+ substr ($self->seqdata->{$seqname}, $col, $colstep))
+ if exists $self->seqdata->{$seqname}
+ && !$args{'NOSEQDATA'};
+ # GR lines
+ foreach my $feature (grep (exists ($self->gr->{$_}->{$seqname}), keys %{$self->gr})) {
+ # warn "Writing cols $col+$colstep for $seqname $feature";
+ push @out, $self->prettify ($lcols, "#=GR $seqname $feature",
+ substr ($self->gr_($feature)->{$seqname}, $col, $colstep));
+ }
+ }
+ push @out, "";
+ }
+
+ # alignment separator
+ push @out, "//";
+
+ # convert output array to string & return
+ return join ("", map ("$_\n", @out));
+}
+
+=head2 copy
+
+ my $newStock = $stock->copy();
+
+Does a deep-copy, duplicating all information.
+
+=cut
+sub copy {
+ my ($self) = @_;
+
+ my $stock = Stockholm->new;
+
+ # Sequence names & data
+ @{$stock->seqname} = @{$self->seqname};
+ %{$stock->seqdata} = %{$self->seqdata};
+
+ #=GF
+ while (my ($feature, $arrayRef) = each %{$self->gf}) {
+ $stock->gf->{$feature} = [@$arrayRef];
+ }
+ @{$stock->gforder} = @{$self->gforder};
+
+ #=GC
+ while (my ($feature, $string) = each %{$self->gc}) {
+ $stock->gc->{$feature} = $string;
+ }
+
+ #=GR
+ while (my ($feature, $seqHash) = each %{$self->gr}) {
+ $stock->gr->{$feature} = {%$seqHash};
+ }
+
+ #=GS
+ while (my ($feature, $seqHash) = each %{$self->gs}) {
+ $stock->gs->{$feature} = {%$seqHash};
+ }
+
+ # Return
+ return $stock;
+}
+
+=head2 columns
+
+ my $cols = $stock->columns()
+
+Returns the number of columns in this alignment.
+The value is recalculated each time because the
+sequence or annotation data may have changed since
+the method was last called.
+
+=cut
+sub columns {
+ my ($self) = @_;
+
+ return max (map (length ($_),
+ values (%{$self->seqdata}),
+ values (%{$self->gc}),
+ map (values (%$_), values (%{$self->gr}))));
+
+}
+
+=head2 sequences
+
+ my $cols = $stock->sequences()
+
+Returns the number of sequences (rows) in this alignment.
+
+=cut
+sub sequences {
+ my ($self) = @_;
+ return @{$self->seqname} + 0;
+}
+
+=head2 seqname
+
+ my $rowName = $stock->seqname->[$rowIndex];
+
+Returns a reference to an array of sequence names.
+
+=head2 seqdata
+
+ my $row = $stock->seqdata->{$rowName};
+
+Returns a reference to a hash of alignment rows, keyed by sequence name.
+
+=head2 gf
+
+ my @gf = @{$stock->gf->{FEATURE}};
+ my @gf = @{$stock->gf_FEATURE};
+
+Returns a reference to an array of all the lines beginning '#=GF FEATURE ...'
+
+=head2 gc
+
+ my $gc = $stock->gc->{FEATURE};
+ my $gc = $stock->gc_FEATURE;
+
+Returns the line beginning '#=GC FEATURE ...'
+
+=head2 gs
+
+ my @gs = @{$stock->gs->{FEATURE}->{SEQNAME}};
+ my @gs = @{$stock->gs_FEATURE->{SEQNAME}};
+
+Returns a reference to an array of all the lines beginning '#=GS SEQNAME FEATURE ...'
+
+=head2 gr
+
+ my $gr = $stock->gr->{FEATURE}->{SEQNAME};
+ my $gr = $stock->gr_FEATURE->{SEQNAME};
+
+Returns the line beginning '#=GR SEQNAME FEATURE ...'
+
+Catches all methods by default.
+
+=cut
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ my $sub = our $AUTOLOAD;
+ $sub =~ s/.*:://;
+
+ # check for DESTROY
+ return if $sub eq "DESTROY";
+
+ # check for GF, GC, GS, GR tag_feature accessors
+ # e.g. $self->GF_ID
+ # can also use $self->GF_('ID')
+ if ($sub =~ /^(gf|gc|gs|gr)_(\S*)$/i) {
+ my ($tag, $feature) = ($1, $2);
+ $tag = lc $tag;
+ $feature = shift(@args) unless length $feature;
+ my $hash = $self->{$tag};
+ if (@args) {
+ $hash->{$feature} = shift(@args); # TODO: check ref-type of arg
+ }
+ cluck "Warning: ignoring extra arguments to ${tag}_$feature"
+ if @args > 0;
+ if (!defined $hash->{$feature}) {
+ $hash->{$feature} =
+ $tag eq "gf" ? [] :
+ $tag eq "gc" ? "" :
+ $tag eq "gs" ? {} :
+ $tag eq "gr" ? {} :
+ croak "Unreachable";
+ }
+ return $hash->{$feature};
+ }
+
+ # check for ordinary accessors
+ if (exists $self->{$sub}) {
+ croak "Usage: $sub() or $sub(newValue)" if @args > 1;
+ return
+ @args
+ ? $self->{$sub} = $args[0]
+ : $self->{$sub};
+ }
+
+ # croak
+ croak "Unsupported method: $sub";
+}
+
+
+=head2 prettify
+
+ prettify ($lcols, $legend, @data);
+
+Format a line.
+
+=cut
+sub prettify {
+ my ($self, $lcols, $legend, @data) = @_;
+
+ # This horribly inefficient/redundant series of transformations comes out with something I like (IH, 7/24/07)
+ # Trim it down? pah! Like I have nothing better to do
+ $legend = sprintf ("% ${lcols}s", $legend);
+ $legend =~ s/^(\s+)(\#=\S\S)(\s+\S+)$/$2$1$3/;
+ $legend =~ s/^(\s+)(\#=\S\S\s+\S+)(\s+\S+)$/$2$1$3/;
+ $legend =~ s/^(\s\s\s\s\s)(\s+)([^\#]\S+)/$1$3$2/;
+
+ return map ("$legend $_", @data);
+}
+
+=head2 lcols
+
+ lcols();
+
+Get legend width.
+Subtract this from maxcols - 1 to get the number of columns
+available for sequence display.
+
+=cut
+sub lcols {
+ my ($self) = @_;
+ my $lcols = max ($self->maxNameLen,
+ map(length("#=GF $_"), keys(%{$self->gf})),
+ map(length("#=GC $_"), keys(%{$self->gc})));
+ while (my ($gr_key, $gr_hash) = each %{$self->gr}) {
+ $lcols = max ($lcols, map(length("#=GR $gr_key $_"), keys(%$gr_hash)));
+ }
+ while (my ($gs_key, $gs_hash) = each %{$self->gs}) {
+ $lcols = max ($lcols, map(length("#=GS $gs_key $_"), keys(%$gs_hash)));
+ }
+ return $lcols;
+}
+
+=head2 add_gf
+
+ $stock->add_gf (FEATURE, $line)
+ $stock->add_gf (FEATURE, $line1, $line2, ...)
+ $stock->add_gf (FEATURE, @lines)
+ $stock->add_gf (FEATURE, "$line1\n$line2\n$...")
+
+Add '#=GF FEATURE' annotation, preserving the order of the '#=GF' lines.
+
+Each list entry gets printed on its own line.
+
+=cut
+sub add_gf {
+ my ($self, $feature, @data) = @_;
+ unless (@data > 0) {
+ carp "Missing parameters to 'add_gf'; nothing will be done";
+ return;
+ }
+
+ foreach my $line (map {$_ eq '' ? '' : split ("\n", $_, -1)} @data) {
+ push @{$self->gf_($feature)}, $line;
+ push @{$self->gforder}, $feature;
+ }
+}
+
+=head2 set_gf
+
+ $stock->set_gf (FEATURE, $line)
+ $stock->set_gf (FEATURE, $line1, $line2, ...)
+ $stock->set_gf (FEATURE, @lines)
+ $stock->set_gf (FEATURE, "$line1\n$line2\n$...")
+
+Set a '#=GF FEATURE ...' annotation.
+The difference between this and 'add_gf' is that here, if this sequence and
+feature have an annotation already, it will be overwritten instead of appended to.
+
+As with add_gf, each list entry gets printed on its own line.
+
+=cut
+sub set_gf {
+ my ($self, $feature, @data) = @_;
+
+ unless (defined $self->{gf}->{$feature}) {
+ carp "No #=GF feature '$feature' to set, creating new";
+ $self->add_gf ($feature, @data);
+ return;
+ }
+ @data = map {$_ eq '' ? '' : split ("\n", $_, -1)} @data;
+
+ ### go to insane lengths to preserve original line ordering
+
+ my %gfCursor = map {$_ => 0} keys %{$self->{gf}};
+ my (%new_gfFeature, @new_gforder);
+
+ foreach my $curFeat (@{$self->{gforder}}) {
+ $new_gfFeature{$curFeat} = [] unless defined $new_gfFeature{$curFeat};
+
+ if ($curFeat eq $feature) {
+ if (@data) {
+ push (@{$new_gfFeature{$curFeat}}, shift @data);
+ push (@new_gforder, $curFeat);
+ }
+ } else {
+ push (@{$new_gfFeature{$curFeat}},
+ $self->{gf}->{$curFeat}->[$gfCursor{$curFeat}++]);
+ push (@new_gforder, $curFeat);
+ }
+ }
+
+ # still have lines left, insert them after last occurence of feature tag
+ if (@data) {
+ my $insertAt = $#new_gforder;
+ $insertAt-- while $new_gforder[$insertAt] ne $feature;
+ splice (@new_gforder, ++$insertAt, 0, map {$feature} @data);
+ push (@{$new_gfFeature{$feature}}, @data);
+ }
+
+ $self->{gf} = {%new_gfFeature};
+ $self->{gforder} = [@new_gforder];
+}
+
+=head2 get_gf
+
+ my $gf = $stock->get_gf (FEATURE)
+
+Get a #=GF annotation.
+Concatenates and returns all lines beginning '#=GF FEATURE ...'
+
+=cut
+sub get_gf {
+ my ($self, $feature) = @_;
+ if (defined $self->{gf}->{$feature}) {
+ return join ("\n", @{$self->{gf}->{$feature}});
+ } else {
+ #carp "No #=GF feature '$feature' in Stockholm object, returning undef";
+ return undef;
+ }
+}
+
+=head2 add_gs
+
+ $stock->add_gs (SEQNAME, FEATURE, $line)
+ $stock->add_gs (SEQNAME, FEATURE, $line1, $line2, ...)
+ $stock->add_gs (SEQNAME, FEATURE, @lines)
+ $stock->add_gs (SEQNAME, FEATURE, "$line1\n$line2\n$...")
+
+Add a GS annotation: '#=GS SEQNAME FEATURE ...'
+
+If such a line already exists for this sequence and feature, append to it.
+
+Each list entry gets printed on its own line.
+
+=cut
+sub add_gs {
+ my ($self, $seq, $feature, @text) = @_;
+ unless (@text > 0) {
+ carp "Missing parameters to 'add_gs' method; nothing will be done";
+ return;
+ }
+ @text = map {$_ eq '' ? '' : split ("\n", $_, -1)} @text;
+ push (@{$self->{gs}->{$feature}->{$seq}}, @text);
+}
+
+=head2 set_gs
+
+ $stock->set_gs (SEQNAME, FEATURE, $line)
+ $stock->set_gs (SEQNAME, FEATURE, $line1, $line2, ...)
+ $stock->set_gs (SEQNAME, FEATURE, @lines)
+ $stock->set_gs (SEQNAME, FEATURE, "$line1\n$line2\n$...")
+
+Set a GS annotation: '#=GS SEQNAME FEATURE ...'
+
+The difference between this and 'add_gs' is that here, if this sequence and
+feature have an annotation already, it will be overwritten instead of appended to.
+
+Each list entry gets printed on its own line.
+
+=cut
+sub set_gs {
+ my ($self, $seq, $feature, @text) = @_;
+ unless (@text > 0) {
+ carp "Missing parameters to 'set_gs' method; nothing will be done";
+ return;
+ }
+ @text = map {$_ eq '' ? '' : split ("\n", $_, -1)} @text;
+ $self->{gs}->{$feature}->{$seq} = [@text];
+}
+
+=head2 get_gs
+
+ my $gs = $stock->get_gs (SEQNAME, FEATURE)
+
+Get a #=GS annotation.
+Concatenates and returns all lines beginning '#=GS SEQNAME FEATURE ...'
+
+=cut
+sub get_gs {
+ my ($self, $seq, $feature) = @_;
+ unless (defined $feature) {
+ carp "Missing parameters to 'get_gs' method; nothing will be done";
+ return undef;
+ }
+ if (defined $self->{gs}->{$feature}->{$seq}) {
+ return join ("\n", @{$self->{gs}->{$feature}->{$seq}});
+ }
+ else {
+ #carp "Annotation for sequence $seq, feature $feature not found; returning empty string";
+ return undef;
+ }
+}
+
+=head2 drop_columns
+
+ my $success = $stock->drop_columns (@columns)
+
+Drops a set of columns from the alignment and the GC and GR annotations. Note
+that this may break annotations where the column annotations are not
+independent (e.g. you might drop one base in an RNA base pair, but not the
+other). The caller is responsible for making sure the set of columns passed
+in does not mess up the annoation.
+
+Arguments: a list of scalar, zero-based column indices to drop.
+
+Returns success of operation (1 for success, 0 for failure)
+
+=cut
+sub drop_columns {
+ my ($self, @columns) = @_;
+
+ unless ($self->is_flush()) {
+ carp "File is not flush; cannot (should not) drop columns";
+ return 0;
+ }
+
+ # drop from sequences and per-column annotations
+ foreach my $seq_or_annot ($self->{seqdata}, $self->{gc})
+ {
+ # for each sequence or annotation string
+ foreach my $key (keys %$seq_or_annot)
+ {
+ # convert string to array form
+ my @data = split (//, $seq_or_annot->{$key});
+ foreach my $col (@columns)
+ {
+ if ( ($col < 0) or ($col >= @data) ) {
+ carp "Column $col is out of range [1, ", scalar(@data),
+ "] in $key; can't drop, skipping";
+ }
+ else {
+ # blank out the column that should get dropped
+ $data[$col] = '';
+ }
+ }
+ # re-assemble back to string
+ $seq_or_annot->{$key} = join ('', @data);
+ }
+ }
+
+ # drop from per-column/per-sequence annotations
+ foreach my $feat_key (keys %{$self->{gr}})
+ {
+ foreach my $seq_key (keys %{$self->{gr}->{$feat_key}})
+ {
+ my @data = split (//, $self->{gr}->{$feat_key}->{$seq_key});
+ foreach my $col (@columns)
+ {
+ if ( ($col < 0) or ($col >= @data) ) {
+ carp "Column $col is out of range [1, ", scalar(@data),
+ "] in $feat_key, $seq_key; can't drop, skipping";
+ }
+ else {
+ # blank out the column that should get dropped
+ $data[$col] = '';
+ }
+ }
+ # re-assemble back to string
+ $self->{gr}->{$feat_key}->{$seq_key} = join ('', @data);
+ }
+ }
+
+ return 1;
+}
+
+# parse line of Stockholm format file
+# returns true if it finds a separator
+sub parse_input_line {
+ my ($self, $line, $remove_chr) = @_;
+
+ # by default don't remove the leading 'chr'
+ if (!defined $remove_chr) { $remove_chr = 0; }
+
+ $line = $_ unless defined $line;
+
+ # "#=GF [feature] [data]" line
+ if ($line =~ /^\s*\#=GF\s+(\S+)\s+(\S.*)\s*$/) {
+ my ($feature, $data) = ($1, $2);
+ $self->add_gf ($feature, $data); # preserve order of #=GF lines, for crazy context-sensitive Stockholm semantics
+ }
+
+ # "#=GC [feature] [data]" line
+ elsif ($line =~ /^\s*\#=GC\s+(\S+)\s+(\S+)\s*$/) {
+ my ($feature, $data) = ($1, $2, $3);
+ $self->gc->{$feature} .= $data;
+ }
+
+ # "#=GS [seqname] [feature] [data]" line
+ elsif ($line =~ /^\s*\#=GS\s+(\S+)\s+(\S+)\s+(\S.*)\s*$/) {
+ my ($seqname, $feature, $data) = ($1, $2, $3);
+ if ($remove_chr) { $seqname = $self->strip_leading_chr ($seqname); }
+ my $gs = $self->gs_($feature);
+ $gs->{$seqname} = [] unless exists $gs->{$seqname};
+ push @{$gs->{$seqname}}, $data;
+ }
+
+ # "#=GR [seqname] [feature] [data]" line
+ elsif ($line =~ /^\s*\#=GR\s+(\S+)\s+(\S+)\s+(\S+)\s*$/) {
+ my ($seqname, $feature, $data) = ($1, $2, $3);
+ if ($remove_chr) { $seqname = $self->strip_leading_chr ($seqname); }
+ my $gr = $self->gr_($feature);
+ $gr->{$seqname} = "" unless exists $gr->{$seqname};
+ $gr->{$seqname} .= $data;
+ }
+
+ # Unrecognised "#" line
+ elsif ($line =~ /^\s*\#.*$/) {
+ # warn "Comment line $line";
+ }
+
+ # Alignment separator: return true to indicate loop exit
+ elsif ($line =~ /^\s*\/\/\s*$/) {
+ return 1;
+ }
+
+ # Sequence line
+ elsif ($line =~ /^\s*(\S+)\s*(\S*)\s*$/) { # allows empty sequence lines
+ my ($seqname, $data) = ($1, $2);
+ if ($remove_chr) { $seqname = $self->strip_leading_chr ($seqname); }
+ unless (defined $self->seqdata->{$seqname}) {
+ $self->seqdata->{$seqname} = "";
+ push @{$self->seqname}, $seqname; # preserve sequence order, for tidiness
+ }
+ $self->seqdata->{$seqname} .= $data;
+ } elsif ($line =~ /\S/) {
+ carp "Ignoring line: $_";
+ }
+
+ # This line wasn't a alignment separator: return false
+ return 0;
+}
+
+=head2 empty
+
+ my $isEmpty = $stock->empty
+
+Returns true if the alignment is empty (i.e. there are no sequences).
+
+=cut
+sub empty {
+ my ($self) = @_;
+ return @{$self->seqname} == 0;
+}
+
+=head2 ungapped_length
+
+ my $seqlength = $stock->ungapped_length (SEQNAME)
+
+Calculates the length of the ungapped sequence.
+
+=cut
+sub ungapped_length {
+ my ($self, $name) = @_;
+
+ if (!defined $self->seqdata->{$name}) { croak "No sequence exists for '$name':\n", $self->to_string; }
+
+ my $numgaps = $self->seqdata->{$name} =~ tr/-._//;
+ return (length ($self->seqdata->{$name}) - $numgaps);
+
+}
+
+=head2 subseq
+
+ my $subseq = $stock->subseq (SEQNAME, $startPos)
+ my $subseq = $stock->subseq (SEQNAME, $startPos, $length)
+
+Returns a subsequence of the named alignment row.
+
+Note that the coordinates are with respect to the alignment columns (starting at zero), NOT sequence positions.
+That is, gaps are counted.
+
+If $length is omitted, this call returns the subsequence from $startPos to the end of the row.
+
+=cut
+sub subseq {
+ my ($self, $name, $start, $len) = @_;
+
+ if (!defined $self->seqdata->{$name}) { croak "No sequence exists for '$name'."; }
+
+ if (!defined $len) { carp "Setting undefined length to 0."; $len = 0; }
+
+ my $seqlength = length $self->seqdata->{$name};
+
+ # check start position sane
+ if (!defined $start) { croak "Start position undefined."; }
+ elsif (($start > $seqlength) or ($start < 0)) {
+ carp
+ "Subsequence start position $start is outside of sequence bounds ",
+ "[0, " . $seqlength-1 . "]; returning empty string for subsequence of $name\n";
+ return '';
+ }
+
+ return substr ($self->seqdata->{$name}, $start, $len);
+}
+
+=head2 get_column
+
+ my $column = $stock->get_column ($colNum)
+
+Extracts the specified column and returns it as a string.
+
+The column number $colNum uses zero-based indexing.
+
+=cut
+sub get_column {
+ my ($self, $col_num) = @_;
+ my $col_as_string;
+
+ unless ($self->is_flush()) {
+ carp "File is not flush; cannot (should not) get column";
+ return 0;
+ }
+
+ my $align_length = $self->columns();
+
+ if ( ($col_num >= $align_length) or ($col_num < 0) ) {
+ carp
+ "Column index $col_num is outside of alignment bounds ",
+ "[1, $align_length]; returning empty string for column $col_num\n";
+ return '';
+ }
+ else {
+ foreach my $seq (@{$self->{seqname}}) {
+ $col_as_string .= substr ($self->{seqdata}->{$seq}, $col_num, 1);
+ }
+ return $col_as_string;
+ }
+}
+
+=head2 map_align_to_seq_coords
+
+ my ($start, $end) = $stock->map_align_to_seq_coords ($colStart, $colEnd, $seqName);
+ croak "Failed" unless defined ($start);
+
+ my ($start, $end) = $stock->map_align_to_seq_coords ($colStart, $colEnd, $seqName, $seqStart);
+ croak "Failed" unless defined ($start);
+
+Given a range of column indices ($colStart, $colEnd), returns the coordinates
+of sequence $seqName contained within that range, accounting for gaps.
+
+Returns start and end coordinates as a 2-ple list, or returns the empty list
+if there is no sequence in the given range (i.e. range contains all gaps in
+$seqName).
+
+You can provide $seqStart, which is the coordinate of the first non-gap
+character in $seqName. If you don\'t, the default is that the sequence starts
+at 0 (0-based indexing).
+
+=cut
+sub map_align_to_seq_coords {
+ my ($self, $colStart, $colEnd, $seqName, $seqStart) = @_;
+ $seqStart = 0 unless defined $seqStart;
+
+ my $seq = $self->subseq ($seqName, $colStart, ($colEnd - $colStart + 1));
+
+ if (my @seq = $seq =~ /[^$gapChars]/g)
+ {
+ my $rangeStart;
+
+ if ($colStart == 0) {
+ # special case: range starts in the first column
+ $rangeStart = $seqStart;
+ }
+ else {
+ my $prefix = $self->subseq ($seqName, 0, $colStart);
+ $rangeStart = $seqStart + length (join ('', ($prefix =~ /[^$gapChars]/g)));
+ }
+
+ return ($rangeStart, ($rangeStart + @seq - 1));
+ }
+ else {
+ # no sequence in desired range (i.e. all gaps)
+ return ();
+ }
+}
+
+=head2 map_seq_to_align_coords
+
+ my ($start, $end) = $stock->map_seq_to_align_coords ($seq, $start, $end);
+
+Given a range of sequence position indices ($start, $end),
+returns the alignment coordinates corresponding to that range.
+Returns undef if can't map coordinates.
+
+Returns start and end coordinates as a duple.
+
+=cut
+sub map_seq_to_align_coords {
+ my ($self, $seq, $start, $end) = @_;
+
+ # sanity check
+ if (!defined $self->seqdata->{$seq}) { croak "Can't find sequence '$seq'.\n"; }
+ if ($end < $start) { croak "Invalid coordinates.\n"; }
+
+ # do the mapping with a linear search
+ my ($s, $e); # alignment coordinates
+ my $seqpos = 0; # position within the sequence
+
+ # NB: This operation can be quite slow,
+ # although the time hit is worth it if the desired
+ # coordinates are deep into the alignment
+ # (substr to pull out each character becomes expensive)
+ # unpack seems to be slightly faster than split
+ my @data = unpack 'a' x length $self->seqdata->{$seq}, $self->seqdata->{$seq};
+
+ my $cols = $self->columns();
+ for (my $alignpos = 0; $alignpos < $cols; ++$alignpos) {
+
+ # keep going if it's a gap
+ if ($data[$alignpos] =~ /[$gapChars]/) { next; }
+
+ # else see if we've reached a boundary
+ if ($seqpos == $start) { $s = $alignpos; }
+ if ($seqpos == $end) { $e = $alignpos; last; }
+
+ # increment coords
+ ++$seqpos;
+
+ }
+
+ return ($s, $e);
+}
+
+=head2 build_seq_to_align_coords_map
+
+ my $map = $stock->build_seq_to_align_coords_map ($seq);
+
+Returns a map from sequence to alignment coordinates
+for a particular sequence as an array reference.
+
+=cut
+sub build_seq_to_align_coords_map {
+ my ($self, $seq, $verbose) = @_;
+
+ if ($verbose) {
+ print STDERR "Building coordinate index for '$seq'...";
+ }
+
+ # sanity check
+ if (!defined $self->seqdata->{$seq}) { croak "Can't find sequence '$seq'.\n"; }
+
+ my @map;
+
+ # do the mapping with a linear search
+ my ($s, $e); # alignment coordinates
+ my $seqpos = 0; # position within the sequence
+
+ # assemble sequence data as character arrays for fast access
+ # (avoid having to use substr, which is slow)
+ # unpack seems to be slightly faster than split
+ my @data = unpack 'a' x length $self->seqdata->{$seq}, $self->seqdata->{$seq};
+
+ my $cols = $self->columns();
+ for (my $alignpos = 0; $alignpos < $cols; ++$alignpos) {
+
+ # keep going if it's a gap
+ if ($data[$alignpos] =~ /[$gapChars]/) { next; }
+
+ # else store the record
+ $map[$seqpos++] = $alignpos;
+
+ }
+
+ if ($verbose) {
+ print STDERR "done.\n";
+ }
+
+ return \@map;
+
+}
+
+
+=head2 is_gap
+
+ $stock->is_gap (SEQNAME, $colNum)
+
+Return true if a given (SEQNAME,column) coordinate is a gap.
+
+=cut
+sub is_gap {
+ my ($self, $row_name, $col) = @_;
+ my $c = substr ($self->seqdata->{$row_name}, $col, 1);
+ return $c =~ /[$gapChars]/;
+}
+
+=head2 is_allgaps_col
+
+ $stock->is_allgaps_col ($col)
+
+Returns true if a given column is all gaps.
+
+=cut
+sub is_allgaps_col {
+ my ($self, $c) = @_;
+ my $is = 1;
+ foreach my $seqname (@{$self->seqname}) {
+ if (!$self->is_gap ($seqname, $c)) {
+ $is = 0;
+ }
+ }
+ return $is;
+}
+
+=head2 drop_allgaps_columns
+
+ $stock->drop_allgaps_columns()
+
+Drops columns which are all gaps from an alignment.
+
+=cut
+sub drop_allgaps_columns {
+ my ($self) = @_;
+
+ my $cols = $self->columns();
+ my @drop; # columns to drop
+ for (my $c = 0; $c < $cols; ++$c) {
+ if ($self->is_allgaps_col ($c)) {
+ push @drop, $c;
+ }
+ }
+
+ $self->drop_columns (@drop);
+
+}
+
+=head2 subalign
+
+ my $substock = $stock->subalign ($start, $len)
+ my $substock = $stock->subalign ($start, $len, $strand)
+
+Subalignment accessor.
+Returns a Stockholm object representing a sub-alignment of the current alignment,
+starting at column $start (zero-based) and containing $len columns.
+
+If $strand is supplied and is equal to '-', then the sub-alignment will be reverse-complemented.
+
+=cut
+sub subalign {
+ my ($self, $start, $len, $strand) = @_;
+
+ # check strand sane
+ if (!defined $strand) {
+ $strand = '+';
+ } elsif (($strand ne '-') && ($strand ne '+')) {
+ warn "Unrecognized strand '$strand'; using positive strand.\n";
+ $strand = '+';
+ }
+
+ # init subalign
+ my $subalign = Stockholm->new;
+
+ # sequence data
+ foreach my $seqname (@{$self->seqname}) {
+ $subalign->seqdata->{$seqname} = substr ($self->seqdata->{$seqname}, $start, $len);
+ if ($strand eq '-') {
+ $subalign->seqdata->{$seqname} = revcomp ($subalign->seqdata->{$seqname});
+ }
+ }
+ @{$subalign->seqname} = @{$self->seqname};
+
+ # GF lines
+ while (my ($feature, $arrayRef) = each %{$self->gf}) {
+ $subalign->gf->{$feature} = [@$arrayRef];
+ }
+ @{$subalign->gforder} = @{$self->gforder};
+
+ # GC lines
+ foreach my $tag (keys %{$self->gc}) {
+ $subalign->gc->{$tag} = substr ($self->gc->{$tag}, $start, $len);
+ if ($strand eq '-') {
+ $subalign->gc->{$tag} = reverse $subalign->gc->{$tag};
+ }
+ }
+
+ # GR lines
+ foreach my $tag (keys %{$self->gr}) {
+ foreach my $seqname (keys %{$self->gr->{$tag}}) {
+ $subalign->gr->{$tag}->{$seqname} = substr ($self->gr->{$tag}->{$seqname}, $start, $len);
+ if ($strand eq '-') {
+ $subalign->gr->{$tag}->{$seqname} = reverse ($subalign->gr->{$tag}->{$seqname});
+ }
+ }
+ }
+
+
+ #=GS
+ while (my ($feature, $seqHash) = each %{$self->gs}) {
+ $subalign->gs->{$feature} = {%$seqHash};
+ }
+
+ return $subalign;
+}
+
+=head2 concatenate
+
+ $stock->concatenate ($stock2)
+
+Concatenates another alignment onto the end of this one.
+
+=cut
+sub concatenate {
+ my ($self, $stock) = @_;
+
+ # get widths
+ my $cols = $self->columns;
+ my $catcols = $stock->columns;
+
+ # Sequence data
+ foreach my $seqname (@{$stock->seqname}) {
+ if (exists $self->seqdata->{$seqname}) {
+ $self->seqdata->{$seqname} .= $stock->seqdata->{$seqname};
+ } else {
+ push @{$self->seqname}, $seqname;
+ $self->seqdata->{$seqname} = "." x $cols . $stock->seqdata->{$seqname};
+ }
+ }
+ foreach my $seqname (@{$self->seqname}) {
+ unless (exists $stock->seqdata->{$seqname}) {
+ $self->seqdata->{$seqname} .= "." x $catcols;
+ }
+ }
+
+ # GC lines
+ foreach my $tag (keys %{$stock->gc}) {
+ if (exists $self->gc->{$tag}) {
+ $self->gc->{$tag} .= $stock->gc->{$tag};
+ } else {
+ $self->gc->{$tag} = "." x $cols . $stock->gc->{$tag};
+ }
+ }
+ foreach my $tag (keys %{$self->gc}) {
+ unless (exists $stock->gc->{$tag}) {
+ $self->gc->{$tag} .= "." x $catcols;
+ }
+ }
+
+ # GR lines
+ foreach my $tag (keys %{$stock->gr}) {
+ if (exists $self->gr->{$tag}) {
+ foreach my $seqname (keys %{$stock->gr->{$tag}}) {
+ if (exists $self->gr->{$tag}->{$seqname}) {
+ $self->gr->{$tag}->{$seqname} .= $stock->gr->{$tag}->{$seqname};
+ } else {
+ $self->gr->{$tag}->{$seqname} = "." x $cols . $stock->gr->{$tag}->{$seqname};
+ }
+ }
+ } else {
+ $self->gr->{$tag} = {};
+ foreach my $seqname (keys %{$stock->gr->{$tag}}) {
+ $self->gr->{$tag}->{$seqname} = "." x $cols . $stock->gr->{$tag}->{$seqname};
+ }
+ }
+ }
+ foreach my $tag (keys %{$self->gr}) {
+ foreach my $seqname (keys %{$self->gr->{$tag}}) {
+ unless (exists $stock->gr->{$tag} && exists $stock->gr->{$tag}->{$seqname}) {
+ $self->gr->{$tag}->{$seqname} .= "." x $catcols;
+ }
+ }
+ }
+
+ # GF and GS lines
+ foreach my $tag (keys %{$stock->gf}) {
+ $self->gf->{$tag} = [] unless exists $self->gf->{$tag};
+ push @{$self->gf->{$tag}}, @{$stock->gf->{$tag}};
+ }
+
+ foreach my $tag (keys %{$stock->gs}) {
+ $self->gs->{$tag} = {} unless exists $self->gs->{$tag};
+ foreach my $seqname (keys %{$stock->gs->{$tag}}) {
+ $self->gs->{$tag}->{$seqname} = [] unless exists $self->gs->{$tag}->{$seqname};
+ push @{$self->gs->{$tag}->{$seqname}}, @{$stock->gs->{$tag}->{$seqname}};
+ }
+ }
+}
+
+# add_row method
+sub add_row {
+ my ($self, $seqname, $rowdata) = @_;
+ die "Attempt to add duplicate row" if exists $self->seqdata->{$seqname};
+ push @{$self->seqname}, $seqname;
+ $self->seqdata->{$seqname} = $rowdata;
+ return @{$self->seqname} - 1; # new row index
+}
+
+
+# Reverse complement a sequence
+sub revcomp {
+ my ($arg0, $arg1) = @_;
+ my $seq;
+
+ if (defined ($arg1)) { # must have been called externally (as method or package sub)
+ $seq = $arg1;
+ } else {
+ $seq = $arg0;
+ }
+
+ $seq =~ tr/acgtuACGTU/tgcaaTGCAA/;
+ $seq = reverse $seq;
+ return $seq;
+}
+
+# Determine maximum sequence name length
+sub maxNameLen {
+ my ($self) = @_;
+ return max (map ( length ($_), @{$self->seqname}));
+}
+
+=head2 is_flush
+
+ my $flush = $stock->is_flush()
+
+Returns true if the alignment is "flush", i.e. all sequence and annotation lines have the same length.
+
+=cut
+sub is_flush {
+ my ($self) = @_;
+ my $columns = $self->columns();
+
+ # do stuff that has one key
+
+ map {
+ if (length ($self->{seqdata}->{$_}) != $columns) {
+ carp "Sequence $_ is not flush!";
+ return 0;
+ }
+ } keys %{$self->{seqdata}};
+
+ map {
+ if (length($self->{gc}->{$_}) != $columns) {
+ carp "#=GC annotation for feature $_ is not flush!";
+ return 0;
+ }
+ } keys %{$self->{gc}};
+
+ # do stuff that has two keys
+
+ map {
+ if (length($_) != $columns) {
+ carp "#=GR annotation is not flush! ($_)";
+ return 0;
+ }
+ } map { values %{$self->{gr}->{$_}} } keys %{$self->{gr}};
+
+ return 1; # if we got this far, everything must be flush
+}
+
+=head2 assert_flush
+
+ $stock->assert_flush()
+
+Dies if the alignment isn't "flush."
+
+=cut
+sub assert_flush {
+ my ($self) = @_;
+
+ unless ($self->is_flush()) {
+ die "Alignment not flush (rows are not the same length).\n";
+ }
+}
+
+
+# Determine the list maximum value.
+sub max {
+ my ($x, @y) = @_;
+ foreach my $y (@y)
+ {
+ $x = $y if !defined($x) || (defined($y) && $y > $x)
+ }
+ return $x;
+}
+
+=head2 NH
+
+ $self->NH();
+ $self->NH ($newtree);
+
+Get/set the New Hampshire tree.
+
+=cut
+sub NH {
+ my ($self, $newval) = @_;
+ if (defined $newval) {
+ @{$self->gf_NH} = ($newval);
+ }
+ return join ("", @{$self->gf_NH});
+}
+
+=head2 gapfraction
+
+ $self->gapfraction()
+
+Calculate fraction of gaps (# gaps / total # of characters)
+in the alignment.
+
+=cut
+sub gapfraction {
+ my ($self) = @_;
+
+ my ($num, $denom) = (0, 0);
+ map { $num += $self->ungapped_length ($_); $denom += length ($self->seqdata->{$_}); } keys %{$self->seqdata};
+
+ return ($num / $denom);
+}
+
+=head2 percentid_annot
+
+ $self->percentid_annot()
+
+Annotation for #=GF Percent_id line.
+
+=cut
+sub percentid_annot {
+ my $self = shift;
+ return $percentid_annot;
+}
+
+=head2 gapfraction_annot
+
+ $self->gapfraction_annot()
+
+Annotation for #=GF Gap_fraction line.
+
+=cut
+sub gapfraction_annot {
+ my $self = shift;
+ return $gapfraction_annot;
+}
+
+=head2 percentid
+
+ $self->percentid();
+ $self->percentid ($seqs);
+
+Calculate percent id for two or more sequences of the alignment.
+Calculates per-column percent id as:
+(# of times most common non-gap character in column appears) / (# non-gap characters in column)
+Reports the average per-column percent id.
+
+Considers gaps during calculation if requested.
+
+=cut
+sub percentid {
+ my ($self, $seqs, $countgaps) = @_;
+
+ # must be at least 2 seqs
+ # ($seqs = ref to array of sequence names)
+ if (!defined $seqs) { $seqs = $self->seqname; }
+ unless (@$seqs >= 2) { croak "Must be at least 2 sequences.\n"; }
+
+ # don't count gaps by default
+ if (!defined $countgaps) { $countgaps = 0; }
+
+ # assemble sequence data as character arrays for fast access
+ my $data;
+ foreach my $seq (@$seqs) {
+ croak "Sequence '$seq' not defined.\n" unless exists $self->seqdata->{$seq};
+ @{$data->{$seq}} = unpack 'a' x length $self->seqdata->{$seq}, $self->seqdata->{$seq};
+ }
+
+ # assert flush
+ croak "Alignment is not flush.\n" unless $self->is_flush();
+
+ my $sum = 0;
+ my $n = 0;
+
+ for (my $c = 0; $c < $self->columns; ++$c) {
+ my %f;
+ my $count = 0; # ungapped
+ my $countall = 0; # gaps as well
+ for (my $i = 0; $i < @$seqs; ++$i) {
+ my $char = lc $data->{$seqs->[$i]}->[$c];
+ if ($char ne '-' && $char ne '.') {
+ ++$f{$char};
+ ++$count;
+ }
+ ++$countall;
+ }
+ # unless $countgaps, only count columns with > 1 non-gap character
+ if (!$countgaps && ($count > 1)) {
+ my @sym = sort { $f{$b} <=> $f{$a} } keys %f;
+
+ my $id;
+ # if no character appears more than once, then % id = 0
+ if ($f{$sym[0]} == 1) {
+ $id = 0;
+ }
+ # else calculate % id as (# most common character) / (# non-gap characters in column)
+ else {
+ $id = $f{$sym[0]} / $count;
+ }
+ $sum += $id;
+ ++$n;
+ }
+ # if $countsgaps, count columns with >= 1 non-gap character
+ elsif ($countgaps && ($count >= 1)) {
+ my @sym = sort { $f{$b} <=> $f{$a} } keys %f;
+
+ my $id;
+ # if no character appears more than once, then % id = 0
+ if ($f{$sym[0]} == 1) {
+ $id = 0;
+ }
+ # else calculate % id as (# most common character) / (# total characters in column)
+ else {
+ $id = $f{$sym[0]} / $countall;
+ }
+ $sum += $id;
+ ++$n;
+ }
+
+ }
+
+ if ($n == 0) {
+ return 0;
+ }
+
+ return $sum / $n;
+}
+
+=head2 strip_leading_chr
+
+ strip_leading_chr ("chr2R");
+
+Removed the leading 'chr' frequently prepended to chromosome names.
+
+=cut
+sub strip_leading_chr {
+
+ my ($class, $str) = @_;
+
+ $str =~ s/^chr//;
+
+ return $str;
+
+}
+
+1
diff --git a/perl/Stockholm/Database.pm b/perl/Stockholm/Database.pm
new file mode 100644
index 0000000..c76a13c
--- /dev/null
+++ b/perl/Stockholm/Database.pm
@@ -0,0 +1,284 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+Stockholm::Database.pm
+
+=head1 SYNOPSIS
+
+Perl module encapsulating a flatfile database of Stockholm multiple alignments.
+
+The original Stockholm::Database module was written by Ian Holmes for his DART library.
+
+=head1 GENERAL USAGE
+
+A Stockholm::Database object is a blessed array reference.
+(This is in contrast to most Perl objects, which are blessed hash references.)
+
+The referenced array contains the constituent Stockholm objects.
+So, if $db is a Stockholm::Database, then @$db is simply an array of Stockholm objects.
+
+=head1 METHODS
+
+=cut
+
+package Stockholm::Database;
+
+use strict;
+use vars '@ISA';
+
+use Stockholm;
+use Carp;
+
+=head2 new
+
+ my $db = Stockholm::Database->new();
+
+Creates an empty Stockholm::Database object.
+
+=cut
+
+# constructor
+sub new {
+ my ($class) = @_;
+ my $self = [];
+ bless $self, $class;
+ return $self;
+}
+
+=head2 align_callback
+
+ Stockholm::Database->align_callback (sub
+ {
+ my $stock = shift; # Stockholm object
+ # ...do something with the alignment...
+ })
+
+Streams through alignments in a file, calling a callback function on each alignment as it is parsed.
+
+This method can be used as an efficient alternative to reading the entire database into memory with the from_file method, for some applications.
+
+=cut
+
+# align_callback method
+# streams through alignments in a file, calling a callback function as it parses each one
+# can use in place of from_file method for some applications
+sub align_callback {
+ my ($class, $filename, $callback) = @_;
+
+ my $self = $class->new;
+ my $stock;
+
+ local *FILE;
+ local $_;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ while (<FILE>) {
+ next unless /\S+/; # skip blank lines
+ $stock = Stockholm->new unless defined $stock;
+ if ($stock->parse_input_line ($_)) {
+ &$callback ($stock);
+ $stock = undef;
+ }
+ }
+ close FILE;
+ &$callback ($stock) if defined $stock;
+
+ return $self;
+}
+
+=head2 from_file
+
+ my $db = Stockholm::Database->from_file ($filename)
+ my $db = Stockholm::Database->from_file ($filename, 0)
+
+Creates a Stockholm::Database object and populates it from a named Stockholm flatfile.
+
+Reading a large database (e.g. PFAM) can take a while.
+By default, a message is printed when each alignment is loaded.
+The second form of the method suppresses these verbose messages.
+
+=cut
+
+# from_file method
+sub from_file {
+ my ($class, $filename, $verbose) = @_;
+ $verbose = 1 unless defined $verbose; # default
+
+ my $self;
+
+ # FASTA
+ if (Stockholm->detect_FASTA ($filename)) {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ my $stock = Stockholm->from_filehandle_FASTA (\*FILE);
+ close FILE;
+ $self = $class->new;
+ $self->add_alignment ($stock, $verbose);
+ }
+
+ # CLUSTAL
+ elsif (Stockholm->detect_CLUSTAL ($filename)) {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ my $stock = Stockholm->from_filehandle_CLUSTAL (\*FILE);
+ close FILE;
+ $self = $class->new;
+ $self->add_alignment ($stock, $verbose);
+ }
+
+ # MSF
+ elsif (Stockholm->detect_MSF ($filename)) {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ my $stock = Stockholm->from_filehandle_MSF (\*FILE);
+ close FILE;
+ $self = $class->new;
+ $self->add_alignment ($stock, $verbose);
+ }
+
+ # Stockholm
+ else {
+ local *FILE;
+ open FILE, "<$filename" or croak "Couldn't open $filename: $!";
+ $self = $class->from_filehandle (\*FILE, $verbose);
+ close FILE;
+ }
+
+ return $self;
+
+}
+
+=head2 from_filehandle
+
+ my $db = Stockholm::Database->from_filehandle ($filehandle)
+ my $db = Stockholm::Database->from_filehandle ($filehandle, 0)
+
+Creates a Stockholm::Database object and populates it from a Stockholm flatfile, pointed to by a given filehandle.
+
+Reading a large database (e.g. PFAM) can take a while.
+By default, a message is printed when each alignment is loaded.
+The second form of the method suppresses these verbose messages.
+
+=cut
+
+# from_filehandle method
+sub from_filehandle {
+ my ($class, $filehandle, $verbose) = @_;
+ $verbose = 1 unless defined $verbose; # default
+
+ my $self = $class->new;
+ my $stock;
+ local $_;
+ while (<$filehandle>) {
+ next unless /\S+/; # skip blank lines
+ $stock = Stockholm->new unless defined $stock;
+ if ($stock->parse_input_line ($_)) {
+ $self->add_alignment ($stock, $verbose);
+ $stock = undef;
+ }
+ }
+ $self->add_alignment ($stock, $verbose) if defined $stock;
+
+ return $self;
+}
+
+
+=head2 from_string
+
+ $db->from_string ($string)
+ $db->from_string ($string, 0)
+
+Creates a Stockholm::Database object and populates it from a Stockholm-format string.
+
+Reading a large database (e.g. PFAM) can take a while.
+By default, a message is printed when each alignment is loaded.
+The second form of the method suppresses these verbose messages.
+
+=cut
+
+# from_string
+sub from_string {
+ my ($class, $text, $verbose) = @_;
+ my @text = map (split(/\n/), $text);
+
+ my $self = $class->new;
+ my $stock;
+
+ foreach my $line (@text) {
+ next unless $line =~ /\S+/; # skip blank lines
+ $stock = Stockholm->new unless defined $stock;
+ if ($stock->parse_input_line ($line)) {
+ $self->add_alignment ($stock, $verbose);
+ $stock = undef;
+ }
+ }
+ $self->add_alignment ($stock, $verbose) if defined $stock;
+
+ return $self;
+}
+
+=head2 to_file
+
+ $db->to_file ($filename)
+ $db->to_file ($filename, $maxcols)
+
+Saves a Stockholm::Database to a named file.
+
+The second form of the method sets the maximum column width for the Stockholm::to_string method.
+
+=cut
+
+# to_file method
+sub to_file {
+ my ($self, $filename, $maxcols) = @_;
+
+ local *FILE;
+ open FILE, ">$filename" or croak "Couldn't open '$filename' for writing: $!";
+ print FILE $self->to_string ($maxcols);
+ close FILE or croak "Couldn't close '$filename': $!";;
+
+ return $filename;
+}
+
+=head2 to_string
+
+ $db->to_string()
+ $db->to_string ($maxcols)
+
+Renders a Stockholm::Database as a (Stockholm-format) string.
+
+The second form of the method sets the maximum column width for the Stockholm::to_string method.
+
+=cut
+
+# to_string
+sub to_string {
+ my ($self, $maxcols) = @_;
+ return join ("", map ($_->to_string ($maxcols), @$self));
+}
+
+
+=head2 add_alignment
+
+ $db->add_alignment ($stock)
+ $db->add_alignment ($stock, 0)
+
+Adds a Stockholm alignment to a Stockholm::Database.
+
+By default, a message is printed when the alignment is added.
+The second form of the method suppresses these verbose messages.
+
+=cut
+
+# add_alignment method
+sub add_alignment {
+ my ($self, $stock, $verbose) = @_;
+ push @$self, $stock;
+ my $id = $stock->get_gf ('ID');
+ warn "...loaded Stockholm alignment", defined $id ? " '$id'" : '', " (", $stock->sequences, " sequences)\n" if $verbose;
+ return $self;
+}
+
+# end of package
+
+1
diff --git a/perl/accuracy.pl b/perl/accuracy.pl
new file mode 100755
index 0000000..5526104
--- /dev/null
+++ b/perl/accuracy.pl
@@ -0,0 +1,97 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+accuracy.pl
+
+=head1 SYNOPSIS
+
+Compute expected accuracy of an alignment under FSA's statistical model.
+
+Written by Robert Bradley.
+
+=cut
+
+use strict;
+
+use Stockholm;
+use FSA::Model;
+
+my $acc_threshold = 0.9;
+my $cert_threshold = 5.0;
+my $usage = "\nUsage: $0 -f <sequence file> [-p <.probs file>] [<MFA file(s)> <Stockholm file(s)>]
+
+Calculates Acc, Sn, PPV, Certainty and Consistency for input alignments.
+
+ [--annotate] annotates the input alignment and prints it as a Stockholm-format alignment
+ [--accuracy-threshold <double>] threshold for calling a character correctly aligned (default is $acc_threshold)
+ [--certainty-threshold <double>] threshold for calling a character certain (default is $cert_threshold)
+ [--hard] use a hard cutoff for certainty calculation instead of a \"soft\" logarithmic transform
+ [--model-certainty-dist] show distribution of \"slopes\" for model certainty; suppress all other output
+ [--precision <double>] precision of output
+ [--terse] terse output format
+
+";
+
+my @alignments;
+my ($seqfile, $probsfile);
+my $annotate = 0;
+my $use_log = 1;
+my $certainty_slopes = 0;
+my $precision = 3;
+my $terse = 0;
+
+while (@ARGV) {
+ my $arg = shift;
+ if ($arg =~ /^-/) {
+ if (($arg eq "-h") || ($arg eq "--help")) { print $usage; exit; }
+ elsif (($arg eq "-f")) { $seqfile = shift; }
+ elsif (($arg eq "-p")) { $probsfile = shift; }
+ elsif (($arg eq "--annotate")) { $annotate = 1; }
+ elsif (($arg eq "--accuracy-threshold")) { $acc_threshold = shift; }
+ elsif (($arg eq "--certainty-threshold")) { $cert_threshold = shift; }
+ elsif (($arg eq "--hard")) { $use_log = 0; }
+ elsif (($arg eq "--model-certainty-dist")) { $certainty_slopes = 1; }
+ elsif (($arg eq "--precision")) { $precision = shift; }
+ elsif (($arg eq "--terse")) { $terse = 1; }
+ else { die $arg, "\n", $usage; }
+ }
+ else { push @alignments, $arg; }
+}
+
+# test files ok
+unless (defined $seqfile && -r $seqfile) { die "You must provide a readable FSA input sequence file (don't forget the -f switch!).\n"; }
+if (!defined $probsfile) { $probsfile = $seqfile . ".probs"; }
+if (! -r $probsfile) { die ".probs file '$probsfile' not readable."; }
+
+# initialize FSA::Model object
+my $model = FSA::Model->from_probsfile ($seqfile, $probsfile);
+
+# loop over alignments
+foreach my $align (@alignments) {
+
+ my $stock = Stockholm->from_file ($align);
+ $stock->assert_flush();
+ $stock->drop_allgaps_columns();
+ if (!$terse) {
+ print "Looking at alignment '$align'...\n";
+ }
+
+ # if requested, just show the distribution of certainty slopes
+ if ($certainty_slopes) {
+ $model->sparse_matrices->show_model_certainty_slopes ($precision);
+ exit 0;
+ }
+
+ # calculate accuracies
+ $model->calc_accuracies ($stock, $acc_threshold, $cert_threshold, $use_log);
+
+ # print the annotated alignment if requested
+ if ($annotate) {
+ $model->annotate_alignment ($stock, $precision);
+ print $stock->to_string();
+ }
+ # else just show results
+ $model->show_accuracies ($precision, $terse);
+
+}
diff --git a/perl/cmpalign.pl b/perl/cmpalign.pl
new file mode 100755
index 0000000..a90be9c
--- /dev/null
+++ b/perl/cmpalign.pl
@@ -0,0 +1,277 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+cmpalign.pl
+
+=head1 SYNOPSIS
+
+Compare two alignments.
+
+Written by Robert Bradley.
+
+=cut
+
+use strict;
+use Stockholm;
+use Stockholm::Database;
+
+my $usage = "\nUsage: $0 <reference alignment> <comparison alignment>
+
+Compares two alignments.
+Aligments can be in Stockholm, multi-FASTA, ClustalW or MSF formats.
+
+ [--precision <double>] precision of output
+ [--terse] terse output format
+ [--log] log progress
+ [--lazy] allow sequence data in two alignments to differ
+ [--rna] allow U and T to be interchangeable
+ [--pairwise-reference] reference alignment is a Stockholm database of pairwise alignments
+ (for e.g. SABmark, which provides pairwise reference alignments)
+
+\n";
+
+my $lazy = 0;
+my $rna = 0;
+my $log = 0;
+my ($reffile, $cmpfile);
+my $precision = 3;
+my $terse = 0;
+my $pairwiseref = 0;
+
+my @argv;
+while (@ARGV) {
+ my $arg = shift;
+ if ($arg =~ /^-/) {
+ if (($arg eq "-h") || ($arg eq "--help")) { print $usage; exit; }
+ elsif ($arg eq "--precision") { $precision = shift; }
+ elsif ($arg eq "--terse") { $terse = 1; }
+ elsif ($arg eq "--log") { $log = 1; }
+ elsif ($arg eq "--lazy") { $lazy = 1; }
+ elsif ($arg eq "--rna") { $rna = 1; }
+ elsif ($arg eq "--pairwise-reference") { $pairwiseref = 1; }
+ else { die $usage; }
+ } else {
+ push @argv, $arg;
+ }
+}
+if (@argv == 2) {
+ ($reffile, $cmpfile) = @argv;
+}
+else {
+ die $usage;
+}
+
+my $gapChars = '-._';
+
+my $refdb; # fake a Stockholm::Database
+if ($pairwiseref) { $refdb = Stockholm::Database->from_file ($reffile); }
+else { push @{$refdb}, Stockholm->from_file ($reffile); }
+my $cmp = Stockholm->from_file ($cmpfile);
+$cmp->assert_flush();
+$cmp->drop_allgaps_columns();
+
+# make sure that the 2 alignments contain the same sequence names and data
+# convert seqs to uppercase as side effect
+my %seqname;
+foreach my $ref (@{$refdb}) {
+ foreach my $seq (@{$ref->seqname}) {
+ $seqname{$seq} = 1;
+
+ $ref->assert_flush();
+ $ref->drop_allgaps_columns();
+
+ unless (defined $cmp->seqdata->{$seq}) { die "Sequence data for '$seq' not in comparison alignment; I'm bailing.\n"; }
+ # make sure that they're the same sequence
+ if (ungapped ($ref->seqdata->{$seq}, $rna) ne ungapped ($cmp->seqdata->{$seq}, $rna)) {
+ if ($lazy) { warn "Sequence data for '$seq' doesn't match:\n",ungapped ($ref->seqdata->{$seq}, $rna),"\n",ungapped ($cmp->seqdata->{$seq}, $rna),"\n (but I'm doing the comparison regardless)\n"; }
+ else { die "Sequence data for '$seq' doesn't match:\n",ungapped ($ref->seqdata->{$seq}, $rna),"\n",ungapped ($cmp->seqdata->{$seq}, $rna),"\n"; }
+ }
+
+ # convert everything to uppercase for safety
+ $ref->seqdata->{$seq} = uc ($ref->seqdata->{$seq});
+ $cmp->seqdata->{$seq} = uc ($cmp->seqdata->{$seq});
+
+ }
+}
+
+# keep seqnames sorted (otherwise nasty things happen!)
+my @seqname_sorted = sort keys %{seqname};
+
+# total number of characters (sum-of-pairs)
+my $total_char = 0;
+# total number of residue pairs (sum-of-pairs) in each alignment
+my ($sn1, $sn2) = (0, 0); # (ref, cmp)
+
+# (num_aligned_pairs, num_unaligned_1, num_unaligned_2)
+my @overlap = (0,0,0);
+
+# (num_aligned_pairs, num_unaligned_1, num_unaligned_2)
+my @stats_ref = (0,0,0);
+my @stats_cmp = (0,0,0);
+
+# for each pair of sequences
+
+# for logging
+my $num_seqs = scalar @seqname_sorted;
+my $num_seq_pairs = $num_seqs * ($num_seqs - 1) / 2;
+my $cnt = 0;
+for (my $s1 = 0; $s1 < @seqname_sorted; $s1++) {
+ for (my $s2 = $s1+1; $s2 < @seqname_sorted; $s2++) {
+ my ($seqname1, $seqname2) = ($seqname_sorted[$s1], $seqname_sorted[$s2]);
+
+ # get the reference alignment containing the sequences
+ # (necessary for the case where the reference alignment is a Stockholm::Database
+ # of pairwise comparisons)
+ my $ref = get_alignment_with ($refdb, $seqname1, $seqname2);
+
+ # increment total number of characters
+ $total_char += length (ungapped ($ref->seqdata->{$seqname1}, $rna)) + length (ungapped ($ref->seqdata->{$seqname2}, $rna));
+
+ # for the reference alignment
+ # $align_cmp->{$i} = $j means that the positions ($i,$j) are aligned
+ my ($row0, $row1) = ($ref->seqdata->{$seqname1}, $ref->seqdata->{$seqname2});
+ my $align_ref = aligned_pairwise ($row0, $row1);
+ my @indel_ref = @{indel_single ($row0,$row1)};
+ $stats_ref[0] += scalar keys %$align_ref;
+ $stats_ref[1] += scalar keys %{$indel_ref[0]};
+ $stats_ref[2] += scalar keys %{$indel_ref[1]};
+
+ # for the other alignment
+ ($row0, $row1) = ($cmp->seqdata->{$seqname1}, $cmp->seqdata->{$seqname2});
+ my $align_cmp = aligned_pairwise ($row0, $row1);
+ my @indel_cmp = @{indel_single ($row0,$row1)};
+ $stats_cmp[0] += scalar keys %$align_cmp;
+ $stats_cmp[1] += scalar keys %{$indel_cmp[0]};
+ $stats_cmp[2] += scalar keys %{$indel_cmp[1]};
+
+ # compare aligned characters
+ foreach my $i (sort { $a <=> $b } keys %{$align_ref}) {
+ if (defined (my $j = $align_ref->{$i})) {
+ $sn1++; # reference alignment
+ if (defined $align_cmp->{$i} && $j == $align_cmp->{$i}) { # b/c $i isn't necessarily aligned in cmp
+ ++$overlap[0];
+ }
+ }
+ }
+
+ # compare unaligned (gapped) characters
+ foreach my $i (sort { $a <=> $b } keys %{$indel_ref[0]}) {
+ if (defined $indel_cmp[0]->{$i}) { ++$overlap[1]; }
+ }
+ foreach my $i (sort { $a <=> $b } keys %{$indel_ref[1]}) {
+ if (defined $indel_cmp[1]->{$i}) { ++$overlap[2]; }
+ }
+
+ # now get counts for comparison alignment (for e.g. specificity measure)
+ foreach my $i (sort { $a <=> $b } keys %{$align_cmp}) {
+ if (defined (my $j = $align_cmp->{$i})) {
+ $sn2++;
+ }
+ }
+
+ # log progress if desired
+ if (($cnt++ % 100 == 0) && $log) {
+ my $percent_done = int (100 * $cnt / $num_seq_pairs + 0.5);
+ warn "Processed sequence pair '$seqname1' and '$seqname2'; ", $percent_done, "% (", $cnt, "/", $num_seq_pairs, ") complete.\n";
+ }
+
+ }
+}
+
+# calculate and print the results
+my $acc = (2*$overlap[0] + $overlap[1]+ $overlap[2]) / $total_char;
+my $sn = ($sn1 > 0) ? $overlap[0] / $sn1 : 0;
+my $ppv = ($sn2 > 0) ? $overlap[0] / $sn2 : 0;
+
+my $summary = $stats_ref[0] . " " . $stats_ref[1] . " " . $stats_ref[2]
+ . " " . $stats_cmp[0] . " " . $stats_cmp[1] . " " . $stats_cmp[2]
+ . " " . $overlap[0] . " " . $overlap[1] . " " . $overlap[2];
+
+# terse results only if requested
+if ($terse) {
+ print "$summary\n";
+}
+
+# else pretty results
+else {
+ print "Alignment '$reffile' has ", $stats_ref[0], " aligned character pairs, ", $stats_ref[1], " insertions, ", $stats_ref[2], " deletions.\n";
+ print "Alignment '$cmpfile' has ", $stats_cmp[0], " aligned character pairs, ", $stats_cmp[1], " insertions, ", $stats_cmp[2], " deletions.\n";
+ print "Overlap is ", $overlap[0], " aligned character pairs, ", $overlap[1], " insertions, ", $overlap[2], " deletions.\n";
+ printf "Acc %.${precision}f\n", $acc;
+ printf "Sn %.${precision}f\n", $sn;
+ printf "PPV %.${precision}f\n", $ppv;
+ print "Summary: $summary\n";
+}
+
+# Remove gaps from a string.
+# Convert to uppercase for safety.
+# Converts T to U if requested.
+sub ungapped {
+ my ($row, $rna) = @_;
+ if (!defined $rna) { $rna = 0; }
+
+ my $new = uc ($row);
+ if ($rna) { $new =~ tr/T/U/; }
+ $new =~ s/[$gapChars]//g;
+
+ return $new;
+}
+
+# Takes 2 strings (alignments rows) as input.
+# Returns a hash reference where $align_cmp->{$i} = $j means that the positions ($i,$j) are aligned.
+sub aligned_pairwise {
+ my ($row0, $row1) = @_;
+
+ my $align_cmp = {};
+ my $cols = length ($row0);
+ my ($i, $j) = (0, 0); # keep track of positions in seq0, seq1
+ for (my $col = 0; $col < $cols; $col++) {
+ my $c0 = substr ($row0, $col, 1);
+ my $c1 = substr ($row1, $col, 1);
+ if (!($c0 =~ /[$gapChars]/)) {
+ if (!($c1 =~ /[$gapChars]/)) {
+ $align_cmp->{$i} = $j;
+ }
+ $i++;
+ }
+ if (!($c1 =~ /[$gapChars]/)) {
+ $j++;
+ }
+ }
+
+ return $align_cmp;
+}
+
+# Takes 2 strings (alignment rows) as input.
+# Returns a hash reference where $indel->[0]->{$i} = 1 means that position $i (alignment coords) is gapped in sequence 0.
+sub indel_single {
+ my ($row0, $row1) = @_;
+
+ my $indel = [];
+ my $cols = length ($row0);
+ my ($i, $j) = (0, 0); # keep track of positions in seq0, seq1
+ for (my $col = 0; $col < $cols; $col++) {
+ my $c0 = substr ($row0, $col, 1);
+ my $c1 = substr ($row1, $col, 1);
+ if (!($c0 =~ /[$gapChars]/) && ($c1 =~ /[$gapChars]/)) { $indel->[0]->{$i} = 1; ++$i; } # ungapped in 0 (i)
+ elsif (($c0 =~ /[$gapChars]/) && !($c1 =~ /[$gapChars]/)) { $indel->[1]->{$j} = 1; ++$j; } # ungapped in 1 (j)
+ elsif (!($c0 =~ /[$gapChars]/) && !($c1 =~ /[$gapChars]/)) { ++$i; ++$j; }
+ }
+
+ return $indel;
+}
+
+# Find the alignment containing the passed sequences.
+sub get_alignment_with {
+ my ($db, $seq1, $seq2) = @_;
+
+ foreach my $stk (@$db) {
+ if (exists $stk->seqdata->{$seq1} && exists $stk->seqdata->{$seq2}) {
+ return $stk;
+ }
+ }
+
+ die "Couldn't find a reference alignment containing '$seq1' and '$seq2'.";
+
+}
diff --git a/perl/dartlog.pl b/perl/dartlog.pl
new file mode 100755
index 0000000..12de248
--- /dev/null
+++ b/perl/dartlog.pl
@@ -0,0 +1,168 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+dartlog.pl
+
+=head1 SYNOPSIS
+
+Follow logfiles.
+
+Written by Ian Holmes (from the DART library).
+
+=cut
+
+# set up pagers
+my $less = "less -rF";
+my $tail = "tail -f";
+my $cat = "cat";
+
+# get program name
+my $progname = $0;
+$progname =~ s/^.*\///;
+
+# initialise help string & args
+my $usage = "\n";
+$usage .= "Usage:\n";
+$usage .= " $progname [options] <logfile(s)>\n";
+$usage .= " or\n";
+$usage .= " cat <logfile> | $progname [options]\n";
+$usage .= "\n";
+$usage .= "Options:\n";
+$usage .= "\t [-h] this help message\n";
+$usage .= "\t [-fl] print file & line info\n";
+$usage .= "\t [-dt] print date & time info\n";
+$usage .= "\t [-lev] print log level\n";
+$usage .= "\t [-tag] print tags\n";
+$usage .= "\t [-f,-fancy] synonym for \"-fl -dt -lev -tag\"\n";
+$usage .= "\t [-cat] pipe file through '$cat' instead of '$less'\n";
+$usage .= "\t [-tail] pipe file from '$tail' and through '$cat' instead of '$less'\n";
+$usage .= "\t[-min <level>] only display log messages above this log level\n";
+$usage .= "\t [-skip <tag>] skip log messages with this tag\n";
+$usage .= "\t [-show <tag>] show log messages with this tag (overrides -min and -skip)\n";
+
+my $print_file_and_line = 0;
+my $print_date_and_time = 0;
+my $print_level = 0;
+my $print_tags = 0;
+my $pipe_from_tail = 0;
+my $pipe_to_cat = 0;
+my $tab = "";
+my $minlev;
+my %show;
+my %skip;
+
+# parse cmd-line opts
+my @argv;
+while (@ARGV) {
+ my $arg = shift;
+ if ($arg eq "-h") {
+ die $usage;
+ } elsif ($arg eq "-lev") {
+ $print_level = 1;
+ } elsif ($arg eq "-fl") {
+ $print_file_and_line = 1;
+ } elsif ($arg eq "-dt") {
+ $print_date_and_time = 1;
+ } elsif ($arg eq "-tag") {
+ $print_tags = 1;
+ } elsif ($arg eq "-f" || $arg eq "-fancy") {
+ unshift @ARGV, qw(-fl -dt -lev -tag);
+ } elsif ($arg eq "-cat") {
+ $pipe_to_cat = 1;
+ } elsif ($arg eq "-tail") {
+ $pipe_from_tail = $pipe_to_cat = 1;
+ } elsif ($arg eq "-min") {
+ defined ($minlev = shift) or die $usage;
+ } elsif ($arg eq "-skip") {
+ my $tag = shift;
+ defined ($tag) or die $usage;
+ $skip{$tag} = 1;
+ } elsif ($arg eq "-show") {
+ my $tag = shift;
+ defined ($tag) or die $usage;
+ $show{$tag} = 1;
+ } else {
+ push @argv, $arg;
+ }
+}
+ at argv = qw(-) unless @argv;
+
+# open less pager
+my $pager = $pipe_to_cat ? $cat : $less;
+local *LESS;
+open (LESS, "|$pager") or open (LESS, ">-");
+
+# autoflush
+select LESS;
+$| = 1;
+select STDOUT;
+
+# set up ANSI color codes
+my @col = (map (e(7).e(23).e($_), reverse (31..35), 37), # inverse, not-italics, (magenta..red,white)
+ map (e(27).e(23).e($_), 31..37), # not-inverse, not-italics, (red..white)
+ e(7).e(23).e(36)); # inverse, not-italics, cyan
+
+
+my $w = e(27).e(23).e(37); # not-inverse, not-italics, white
+my $invw = e(7).e(23).e(37); # inverse, not-italics, white
+my $invr = e(7).e(23).e(31); # inverse, not-italics, red
+my $invg = e(7).e(23).e(32); # inverse, not-italics, green
+my $invy = e(7).e(23).e(33); # inverse, not-italics, yellow
+my $invb = e(7).e(23).e(34); # inverse, not-italics, blue
+my $invm = e(7).e(23).e(35); # inverse, not-italics, magenta
+my $invc = e(7).e(23).e(36); # inverse, not-italics, cyan
+
+# parse logfile
+my ($date, $time, $file, $line, $tags) = map ("", 1..5);
+my ($last_date, $last_time, $last_file, $last_line, $last_tags) = map ("", 1..5);
+my ($lev, $last_lev) = (9, 9);
+my @tag;
+my $c = "";
+foreach my $infile (@argv) {
+ local *INFILE;
+ if ($pipe_from_tail) {
+ open INFILE, "$tail $infile|" or die "Couldn't run '$tail $infile'";
+ } else {
+ open INFILE, "<$infile" or die "Couldn't open $infile";
+ }
+ while (<INFILE>) {
+ my $text = $_;
+ if ($text =~ /<log.*>/) {
+ if (/date="(\S+)"/) { $date = $1 }
+ if (/time="(\S+)"/) { $time = $1 }
+ if (/file="(\S+)"/) { $file = $1 }
+ if (/line=(\d+)/) { $line = $1 }
+ if (/level=(\-?\d+)/) { $lev = $1 }
+
+ $c = $col [$lev<-5 ? 0 : ($lev+5>=@col ? @col-1 : $lev+5)];
+ if (/tags=\"([^\"]+)\"/) {
+ $tags = $1;
+ @tag = split /\s+/, $tags;
+ } else {
+ $tags = "";
+ @tag = ();
+ }
+ } else {
+ my $show = grep (exists($show{$_}), @tag);
+ next if !$show && defined($minlev) && $lev < $minlev;
+ next if !$show && %skip && grep (exists($skip{$_}), @tag);
+ my $info = 0;
+ if ($print_level) { print LESS $invc, ($lev == $last_lev ? (" ") : (($lev<0||$lev>9?():(' ')), $lev)), $invc, $w, ' ' }
+ if ($print_file_and_line && ($file ne $last_file || $line ne $last_line)) { print LESS $invr, $file, '#', $line, $invr, $w; $last_file = $file; $last_line = $line; $info = 1 }
+ if ($print_date_and_time && $time ne $last_time) { print LESS $invg, $time, $invg, $w; $last_time = $time; $info = 1 }
+ if ($print_date_and_time && $date ne $last_date) { print LESS $invm, $date, $invm, $w; $last_date = $date; $info = 1 }
+ if ($print_tags && $tags ne $last_tags) { print LESS $invy, $tags, $invy, $w; $last_tags = $tags; $info = 1 }
+ print LESS "\t" if $info;
+ chomp $text;
+ print LESS $w, $c, $text, $c, $w, "\n"; # sandwiching with $w$c allows paging back with 'less'
+ }
+ }
+ close INFILE;
+}
+
+# escape code subroutine
+sub e {
+ my $code = shift;
+ return chr(27)."[$code"."m";
+}
diff --git a/perl/fasta2stockholm.pl b/perl/fasta2stockholm.pl
new file mode 100755
index 0000000..228ce20
--- /dev/null
+++ b/perl/fasta2stockholm.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/perl -w
+
+my $usage = "Usage: $0 <gapped FASTA alignment file(s)>\n";
+
+my @argv;
+while (@ARGV) {
+ my $arg = shift;
+ if ($arg =~ /^-/) {
+ if ($arg eq "-h") { print $usage; exit }
+ else { die $usage }
+ } else {
+ push @argv, $arg;
+ }
+}
+push @argv, "-" unless @argv;
+
+# loop through FASTA files
+foreach my $fasta (@argv) {
+# read FASTA file
+ my %seq;
+ my @name;
+ my $name;
+ open FASTA, "<$fasta" or die "Couldn't open '$fasta': $!";
+ while (<FASTA>) {
+ if (/^\s*>\s*(\S+)/) {
+ $name = $1;
+ push @name, $name;
+ } else {
+ if (/\S/ && !defined $name) {
+ warn "Ignoring: $_";
+ } else {
+ s/\s//g;
+ $seq{$name} .= $_;
+ }
+ }
+ }
+ close FASTA;
+
+# check all seqs are same length
+ my $length;
+ my $lname;
+ foreach my $name (@name) {
+ my $l = length $seq{$name};
+ if (defined $length) {
+ die "Sequences not all same length ($lname is $length, $name is $l)" unless $length == $l;
+ } else {
+ $length = length $seq{$name};
+ $lname = $name;
+ }
+ }
+
+# print Stockholm output
+ print "# STOCKHOLM 1.0\n";
+ foreach my $name (@name) {
+ print $name, " ", $seq{$name}, "\n";
+ }
+ print "//\n";
+}
+
diff --git a/perl/prettify.pl b/perl/prettify.pl
new file mode 100755
index 0000000..f342ce7
--- /dev/null
+++ b/perl/prettify.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+prettify.pl
+
+=head1 SYNOPSIS
+
+Prettify (make human-readable) an alignment.
+
+Written by Robert Bradley.
+
+=cut
+
+use Stockholm;
+
+my $usage = "\nUsage: $0 <alignment file>
+
+Prints a human-readable alignment in Stockholm format.
+
+\n";
+
+# make everything look nice
+# drop all-gap columns
+
+my $file = shift;
+if (!defined $file) { die $usage; }
+
+my $stk = Stockholm->from_file ($file);
+$stk->assert_flush();
+
+# drop all-gap columns
+$stk->drop_allgaps_columns();
+
+# display
+print $stk->to_string();
diff --git a/perl/seqdotplot.pl b/perl/seqdotplot.pl
new file mode 100755
index 0000000..18a69c1
--- /dev/null
+++ b/perl/seqdotplot.pl
@@ -0,0 +1,173 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+seqdotplot.pl
+
+=head1 SYNOPSIS
+
+Plot alignment posterior probabilities.
+
+Written by Ian Holmes (from the DART library).
+
+=cut
+
+use GD;
+
+# usage string
+my $usage = "Usage: $0 [-diag] [-noscale] [-notext] <file>\n";
+
+# default opts
+my $diag = 0;
+my $printScale = 1;
+my $noText = 0;
+
+# parse args
+my @argv;
+while (@ARGV) {
+ my $arg = shift;
+ if ($arg eq "-diag") { $diag = 1 }
+ elsif ($arg eq "-noscale") { $printScale = 0 }
+ elsif ($arg eq "-notext") { $noText = 1 }
+ elsif ($arg =~ /^-/) { die $usage }
+ else { push @argv, $arg }
+}
+ at ARGV = @argv;
+
+my $file = $argv[0];
+
+# read data
+my $xAxis = <>;
+chomp $xAxis;
+my ($dummy, @xAxis) = split /\s+/, $xAxis;
+
+my @data;
+my @yAxis;
+while (my $data = <>) {
+ chomp $data;
+ my ($yCoord, @row) = split /\s+/, $data;
+ push @yAxis, $yCoord;
+ push @data, \@row;
+}
+
+# if -diag specified, check dimensions match
+if ($diag && @xAxis != @yAxis) { die "-diag option specified, but x & y sequences don't match" }
+
+# get font
+my $font = gdTinyFont;
+my $charWidth = $font->width;
+my $charHeight = $font->height;
+
+# make it square
+my ($cellWidth, $cellHeight) = ($charWidth, $charHeight);
+if ($noText) { $cellWidth = $cellHeight = 2 }
+else { if ($cellWidth > $cellHeight) { $cellHeight = $cellWidth } else { $cellWidth = $cellHeight } }
+
+# create a new image
+my $imWidth = $cellWidth * (@xAxis + 2);
+my $imHeight = $cellHeight * (@yAxis + ($printScale ? 3 : 2));
+my $im = new GD::Image ($imWidth, $imHeight);
+
+# allocate some colors
+my $black = $im->colorAllocate(0,0,0);
+my $green = $im->colorAllocate(0,255,0);
+my $blue = $im->colorAllocate(0,0,255);
+my $yellow = $im->colorAllocate(180,180,0);
+my $purple = $im->colorAllocate(180,0,180);
+my $grey = $im->colorAllocate(16,16,16);
+my @col = ($black);
+my $shades = 250;
+for (my $i = 1; $i <= $shades; ++$i) {
+ my $r = 32 + 224 * (3 * $i) / $shades;
+ my $g = 256 * (3 * $i - $shades) / $shades;
+ my $b = 256 * (3 * $i - 2*$shades) / $shades;
+ if ($r > 255) { $r = 255 } elsif ($r < 0) { $r = 0 }
+ if ($g > 255) { $g = 255 } elsif ($g < 0) { $g = 0 }
+ if ($b > 255) { $b = 255 } elsif ($b < 0) { $b = 0 }
+ push @col, $im->colorAllocate ($r, $g, $b);
+}
+my $white = $col[@col-1];
+my %charCol = ('a' => $purple, 't' => $blue, 'u' => $blue,
+ 'c' => $green, 'g' => $yellow, '*' => $white);
+
+# plot color scale
+if ($printScale) {
+ my $ltext = "Probability: 0 ";
+ my $rtext = " 1";
+ my $lchars = length ($ltext);
+ my $rchars = length ($rtext);
+ my $barWidth = ($imWidth - $charWidth * ($lchars + $rchars)) / @col;
+ for (my $c = 0; $c < @col; ++$c) {
+ $im->filledRectangle ($charWidth * $lchars + $c * $barWidth, $imHeight - $charHeight,
+ $charWidth * $lchars + ($c + 1) * $barWidth - 1, $imHeight,
+ $col[$c]);
+ }
+ $im->string ($font, 0, $imHeight - $charHeight, $ltext, $white);
+ $im->string ($font, $imWidth - $charWidth * $rchars, $imHeight - $charHeight, $rtext, $white);
+}
+
+
+# plot data
+for (my $y = 0; $y < @yAxis; ++$y) {
+ for (my $x = $diag ? $y+1 : 0; $x < @xAxis; ++$x) {
+ my $datum = $data[$y]->[$x];
+ if ($datum eq ".") { $datum = 0 }
+ my $colIndex = int ($datum * @col);
+ if ($colIndex >= @col) { $colIndex = @col - 1}
+ elsif ($colIndex < 0) { $colIndex = 0 }
+ $im->filledRectangle (($x + 1) * $cellWidth, ($y + 1) * $cellHeight,
+ ($x + 2) * $cellWidth - 1, ($y + 2) * $cellHeight - 1,
+ $col[$colIndex]);
+ }
+}
+
+# plot sequence axes
+if ($diag) {
+ my $len = @xAxis;
+# my $triangle = new GD::Polygon;
+# $triangle->addPt (0, 0);
+# $triangle->addPt (0, ($len+1)*$cellHeight);
+# $triangle->addPt (($len+1)*$cellWidth, ($len+1)*$cellHeight);
+# $im->filledPolygon ($triangle, $white);
+
+ renderAxis ($im, \@xAxis, $cellWidth, 0, $cellWidth, 0);
+ renderAxis ($im, \@xAxis, $cellWidth, $cellHeight, $cellWidth, $cellHeight);
+ renderAxis ($im, \@xAxis, $imWidth - $cellWidth, $cellHeight, 0, $cellHeight);
+} else {
+ renderAxis ($im, \@xAxis, $cellWidth, 0, $cellWidth, 0);
+ renderAxis ($im, \@xAxis, $cellWidth, $imHeight - ($printScale ? 2 : 1) * $cellHeight, $cellWidth, 0);
+ renderAxis ($im, \@yAxis, 0, $cellHeight, 0, $cellHeight);
+ renderAxis ($im, \@yAxis, $imWidth - $cellWidth, $cellHeight, 0, $cellHeight);
+}
+
+# make sure we are writing to a binary stream
+binmode STDOUT;
+
+# Convert the image to PNG and print it on standard output
+open OUTPUT, ">$file.png";
+print OUTPUT $im->png;
+
+print "Created '$file.png'.\n";
+
+# subroutine to render an axis
+sub renderAxis {
+ my ($im, $axisRef, $x, $y, $xStep, $yStep) = @_;
+ warn "Drawing sequence from ($x,$y) to (", $x+$xStep*@$axisRef, ",", $y+$yStep*@$axisRef, ")\n";
+ my $xOffset = ($cellWidth - $charWidth) / 2;
+ my $yOffset = ($cellHeight - $charHeight) / 2;
+ for (my $i = 0; $i < @$axisRef; ++$i) {
+ my $c = $axisRef->[$i];
+ fillCell ($im, $x, $y, $charCol{lc$c});
+ if ($cellWidth >= $charWidth && $cellHeight >= $charHeight) {
+ $im->char ($font, $x + $xOffset, $y + $yOffset, $c, $black);
+ }
+ $x += $xStep;
+ $y += $yStep;
+ }
+}
+
+# low-level drawing subroutine to fill a cell
+sub fillCell {
+ my ($im, $x, $y, $col) = @_;
+ $im->filledRectangle ($x, $y, $x + $cellWidth - 1, $y + $cellHeight - 1, $col);
+}
diff --git a/perl/stockholm2fasta.pl b/perl/stockholm2fasta.pl
new file mode 100755
index 0000000..c2e1e70
--- /dev/null
+++ b/perl/stockholm2fasta.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl -w
+
+my $columns = 50;
+my $gapped = 0;
+
+my $progname = $0;
+$progname =~ s/^.*?([^\/]+)$/$1/;
+
+my $usage = "Usage: $progname [<Stockholm file(s)>]\n";
+$usage .= " [-h] print this help message\n";
+$usage .= " [-g] write gapped FASTA output\n";
+$usage .= " [-s] sort sequences by name\n";
+$usage .= " [-c <cols>] number of columns for FASTA output (default is $columns)\n";
+# parse cmd-line opts
+my @argv;
+while (@ARGV) {
+ my $arg = shift;
+ if ($arg eq "-h") {
+ die $usage;
+ } elsif ($arg eq "-g") {
+ $gapped = 1;
+ } elsif ($arg eq "-s"){
+ $sorted = 1;
+ } elsif ($arg eq "-c") {
+ defined ($columns = shift) or die $usage;
+ } else {
+ push @argv, $arg;
+ }
+}
+ at ARGV = @argv;
+
+my %seq;
+while (<>) {
+ next unless /\S/;
+ next if /^\s*\#/;
+ if (/^\s*\/\//) { printseq() }
+ else {
+ chomp;
+ my ($name, $seq) = split;
+ $seq =~ s/[\.\-]//g unless $gapped;
+ $seq{$name} .= $seq;
+ }
+}
+printseq();
+
+sub printseq {
+ if($sorted){
+ foreach $key (sort keys %seq){
+ print ">$key\n";
+ for (my $i = 0; $i < length $seq{$key}; $i += $columns){
+ print substr($seq{$key}, $i, $columns), "\n";
+ }
+ }
+ } else{
+ while (my ($name, $seq) = each %seq) {
+ print ">$name\n";
+ for (my $i = 0; $i < length $seq; $i += $columns) {
+ print substr ($seq, $i, $columns), "\n";
+ }
+ }
+ }
+ %seq = ();
+}
diff --git a/src/annealing/Makefile.am b/src/annealing/Makefile.am
new file mode 100644
index 0000000..08411e3
--- /dev/null
+++ b/src/annealing/Makefile.am
@@ -0,0 +1,35 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+LDADD = \
+ libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a
+
+if HAVE_CONDOR
+AM_CPPFLAGS += -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+
+AM_LDFLAGS = -static -L$(top_builddir)/MW/lib
+LDADD += \
+ -lMW \
+ -lMWRMComm \
+ -lMWutil \
+ -lNWS \
+ -lMWsocketmaster \
+ -lpthread
+endif
+
+noinst_LIBRARIES = libannealing.a
+libannealing_a_SOURCES = \
+ alignment_DAG.cc \
+ dotplot.cc \
+ tree_weights.cc
+
+noinst_HEADERS = \
+ SparseMatrix.h \
+ alignment_DAG.h \
+ dotplot.h \
+ tree_weights.h
diff --git a/src/annealing/Makefile.in b/src/annealing/Makefile.in
new file mode 100644
index 0000000..14df81f
--- /dev/null
+++ b/src/annealing/Makefile.in
@@ -0,0 +1,569 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ at HAVE_CONDOR_TRUE@am__append_1 = -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+ at HAVE_CONDOR_TRUE@am__append_2 = \
+ at HAVE_CONDOR_TRUE@ -lMW \
+ at HAVE_CONDOR_TRUE@ -lMWRMComm \
+ at HAVE_CONDOR_TRUE@ -lMWutil \
+ at HAVE_CONDOR_TRUE@ -lNWS \
+ at HAVE_CONDOR_TRUE@ -lMWsocketmaster \
+ at HAVE_CONDOR_TRUE@ -lpthread
+
+subdir = src/annealing
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_ at AM_V@)
+am__v_AR_ = $(am__v_AR_ at AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libannealing_a_AR = $(AR) $(ARFLAGS)
+libannealing_a_LIBADD =
+am_libannealing_a_OBJECTS = alignment_DAG.$(OBJEXT) dotplot.$(OBJEXT) \
+ tree_weights.$(OBJEXT)
+libannealing_a_OBJECTS = $(am_libannealing_a_OBJECTS)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(libannealing_a_SOURCES)
+DIST_SOURCES = $(libannealing_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src $(am__append_1)
+LDADD = libannealing.a $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a $(am__append_2)
+ at HAVE_CONDOR_TRUE@AM_LDFLAGS = -static -L$(top_builddir)/MW/lib
+noinst_LIBRARIES = libannealing.a
+libannealing_a_SOURCES = \
+ alignment_DAG.cc \
+ dotplot.cc \
+ tree_weights.cc
+
+noinst_HEADERS = \
+ SparseMatrix.h \
+ alignment_DAG.h \
+ dotplot.h \
+ tree_weights.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/annealing/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/annealing/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libannealing.a: $(libannealing_a_OBJECTS) $(libannealing_a_DEPENDENCIES) $(EXTRA_libannealing_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libannealing.a
+ $(AM_V_AR)$(libannealing_a_AR) libannealing.a $(libannealing_a_OBJECTS) $(libannealing_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libannealing.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/alignment_DAG.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dotplot.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tree_weights.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/annealing/SparseMatrix.h b/src/annealing/SparseMatrix.h
new file mode 100644
index 0000000..cc12a09
--- /dev/null
+++ b/src/annealing/SparseMatrix.h
@@ -0,0 +1,530 @@
+
+/**
+ * \file SparseMatrix.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Chuong Do.
+ * Robert Bradley wrote the Post_probs struct, corresponding
+ * SparseMatrix constructor and write_gui_output.
+ * Jaeyoung Do wrote a SparseMatrix constructor,
+ * add_probability and finishing_adding_probability
+ * to construct a SparseMatrix with probabilities transfered
+ * from Database or MW workers on-the-fly.
+ */
+
+#ifndef SPARSEMATRIX_INCLUDED
+#define SPARSEMATRIX_INCLUDED
+
+// Note that the SparseMatrix class uses 1-based indexing for positions in sequences.
+// This is IN CONTRAST to the rest of FSA, which uses 0-based indexing.
+
+#define DOUBLE_TINY 0.001
+#define DOUBLE_VERY_TINY 0.000001
+#define PRECISION_DEFAULT 5
+
+#include <iostream>
+#include <iomanip>
+
+#include "util/logfile.h"
+#include "manager/db_misc.h"
+
+namespace fsa {
+
+ /**
+ * \brief Sparse matrix entry type
+ *
+ * (column, value)
+ */
+ typedef std::pair<unsigned, float> Matrix_entry;
+
+ /**
+ * \brief Representation of a single posterior probability.
+ *
+ * Assumes 0-based coordinates.
+ */
+ struct Post_prob {
+
+ unsigned x; ///< coordinate in first sequence
+ unsigned y; ///< coordinate in second sequence
+ float prob; ///< posterior probability entry
+
+ /**
+ * \brief Constructor.
+ */
+ Post_prob (unsigned x, unsigned y, float prob)
+ : x (x), y (y), prob (prob)
+ { }
+
+ /**
+ * \brief Lexical order on the coordinates x and y.
+ */
+ bool operator< (const Post_prob& r) const {
+ if (x == r.x)
+ return y < r.y;
+ else
+ return x < r.x;
+ }
+
+ /**
+ * \brief Output operator.
+ *
+ * Output in 0-based coordinates (which Post_probs uses).
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Post_prob& post_prob) {
+ o << "[" << post_prob.x << ", " << post_prob.x << "] ~ [" << post_prob.y << ", " << post_prob.y << "]" << " => "
+ << std::setprecision (PRECISION_DEFAULT) << post_prob.prob;
+ return o;
+ }
+
+ };
+
+ /**
+ * \brief Sparse representation of a set of posterior probabilities.
+ */
+ typedef std::vector<Post_prob> Post_probs;
+
+
+ /**
+ * \brief Sparse matrix.
+ *
+ * Uses 1-based coordinates internally.
+ */
+ class SparseMatrix {
+
+ size_t xidx; ///< numerical index of the first sequence
+ size_t yidx; ///< numerical index of the second sequence
+ size_t seq1Length, seq2Length; ///< dimensions of matrix
+ std::vector<size_t> rowSize; ///< rowSize[i] = # of cells in row i
+ std::vector<Matrix_entry> data; ///< data values
+ std::vector<std::vector<Matrix_entry>::iterator> rowPtrs; ///< pointers to the beginning of each row
+
+ std::vector<float> gapPosteriors; ///< gap posteriors (sum of pairs) for first and second sequences
+
+ /**
+ * \brief Default constructor.
+ */
+ SparseMatrix()
+ { }
+
+ public:
+
+#ifdef HAVE_POSTGRES
+ /**
+ * \brief Constructor.
+ *
+ * Builds a sparse matrix with posterior probabilities from Database.
+ */
+ SparseMatrix (const size_t xidx, const size_t yidx,
+ const size_t xlen, const size_t ylen,
+ const size_t num_cells)
+ : xidx (xidx), yidx (yidx),
+ seq1Length (xlen), seq2Length (ylen) {
+
+ // ensure sane
+ assert (xlen >= 0);
+ assert (ylen >= 0);
+
+ // allocate memory
+ data.resize (num_cells);
+ rowSize.assign (xlen + 1, 0); rowSize[0] = 0; // catch case of no entry!
+ rowPtrs.resize (xlen + 1); rowPtrs[0] = data.end();
+ gapPosteriors.resize (xlen + ylen + 2, 1.0); // initialize the gap posteriors
+
+ }
+
+ void add_probability (const int pos1, const int pos2, const float prob, const int offset) {
+
+ std::vector<Matrix_entry>::iterator dataPtr = data.begin();
+ dataPtr+=offset;
+
+ if (pos1 == 0)
+ gapPosteriors[seq1Length + pos2 + 1] = prob;
+ else if (pos2 == 0)
+ gapPosteriors[pos1] = prob;
+ else {
+ if (rowSize[pos1] == 0)
+ rowPtrs[pos1] = dataPtr;
+
+ rowSize[pos1]++;
+
+ dataPtr->first = pos2;
+ dataPtr->second = prob;
+ }
+ }
+#endif
+
+#ifdef HAVE_CONDOR
+
+ /**
+ * \brief Constructor.
+ *
+ * Builds a sparse matrix with posterior probabilities from workers.
+ */
+ SparseMatrix (const size_t xidx, const size_t yidx,
+ const size_t xlen, const size_t ylen,
+ int pre_len, int len, Sparse_Matrix_Buffer *sm_buffer)
+ : xidx (xidx), yidx (yidx),
+ seq1Length (xlen), seq2Length (ylen) {
+
+ // ensure sane
+ assert (xlen >= 0);
+ assert (ylen >= 0);
+
+ // allocate memory
+ data.resize (len - xlen - ylen);
+ rowSize.assign (xlen + 1, 0); rowSize[0] = 0; // catch case of no entry!
+ rowPtrs.resize (xlen + 1); rowPtrs[0] = data.end();
+ gapPosteriors.resize (xlen + ylen + 2, 1.0); // initialize the gap posteriors
+
+ std::vector<Matrix_entry>::iterator dataPtr = data.begin();
+
+ int row=0;
+
+ for (int cnt = pre_len; cnt < (pre_len + len); cnt++) {
+ if (sm_buffer[cnt].pos1 == 0)
+ gapPosteriors[seq1Length + sm_buffer[cnt].pos2 + 1] = sm_buffer[cnt].prob;
+ else if (sm_buffer[cnt].pos2 == 0)
+ gapPosteriors[sm_buffer[cnt].pos1] = sm_buffer[cnt].prob;
+ else {
+
+ if (row != sm_buffer[cnt].pos1) {
+ rowSize[row] = dataPtr - rowPtrs[row];
+ rowPtrs[sm_buffer[cnt].pos1] = dataPtr;
+ row = sm_buffer[cnt].pos1;
+ }
+ dataPtr->first = sm_buffer[cnt].pos2;
+ dataPtr->second = sm_buffer[cnt].prob;
+ dataPtr++;
+ }
+ } //end for cnt
+ rowSize[row] = dataPtr - rowPtrs[row]; //for the last tuple
+ }
+#endif
+
+ /**
+ * \brief Constructor.
+ *
+ * Builds a sparse matrix from a Post_probs representation
+ * of a posterior matrix. The coordinates stored in the Post_prob entries
+ * are assumed to be 0-based; note that this is in contrast to the 1-based coordinates
+ * used internally by the SparseMatrix class.
+ * The entries Post_prob must be in lexical order, ie
+ * sorted by first coordinate (x), then second (y).
+ * DOES NOT enforce a cutoff on posterior probabilities;
+ * because the input is sparse, assumes that all entries should be kept.
+ */
+ SparseMatrix (const size_t xidx, const size_t yidx,
+ const size_t xlen, const size_t ylen,
+ const Post_probs& post_probs)
+ : xidx (xidx), yidx (yidx),
+ seq1Length (xlen), seq2Length (ylen) {
+
+ // ensure sane
+ assert (xlen >= 0);
+ assert (ylen >= 0);
+
+ // calculate memory required; count the number of cells in the posterior matrix
+ const size_t num_cells = post_probs.size();
+
+ // allocate memory
+ data.resize (num_cells);
+ rowSize.assign (xlen + 1, 0); rowSize[0] = 0; // catch case of no entry!
+ rowPtrs.resize (xlen + 1); rowPtrs[0] = data.end();
+ gapPosteriors.resize (xlen + ylen + 2, 1.0); // initialize the gap posteriors
+
+ if (CTAGGING(-1, SPARSEMATRIX)) {
+ CTAG(-1, SPARSEMATRIX) << "Initializing SparseMatrix:" << endl;
+ }
+
+ // read the data
+ int xprev = -1; // the previous x-coordinate
+ int xcurr = -1; // the current x-coordinate
+ int yprev = -1; // the previous y-coordinate
+ std::vector<Matrix_entry>::iterator dataPtr = data.begin(); // iterator through SparseMatrix::data
+ // Note: When initializing the SparseMatrix like this, it's crucial that we iterate through the x-coordinate
+ // in increasing order => Post_probs must be sorted properly. If we don't do it in order
+ // then the pointers will get messed up. Which is Very Bad.
+ for (Post_probs::const_iterator iter = post_probs.begin(); iter != post_probs.end(); ++iter) {
+
+ if (CTAGGING(-1, SPARSEMATRIX)) {
+ CL << " " << *iter << endl;
+ }
+
+ // pull out coordinates and convert to 1-based coordinates
+ const int x = iter->x + 1;
+ const int y = iter->y + 1;
+ float prob = iter->prob;
+
+ // check sane (now we're in 1-based coordinates)
+ assert ((x >= 1) && (static_cast<size_t> (x) <= xlen));
+ assert ((y >= 1) && (static_cast<size_t> (y) <= ylen));
+
+ // don't allow prob to overflow (results in negative gap posteriors => negative weights => very bad)
+ prob = (prob > 1.) ? 1. : prob;
+
+ // if we just changed x coordinate
+ if (x != xprev) {
+
+ // store the row size for the previous x coordinate
+ if (xprev != -1) // catch case of first row
+ rowSize[xprev] = dataPtr - rowPtrs[xprev];
+
+ // then continue on to the new x coordinate
+ xcurr = x;
+ rowPtrs[x] = dataPtr;
+ yprev = -1; // reset
+
+ }
+
+ // ensure that entries are ordered properly (we require lexical ordering)
+ assert (xprev <= xcurr);
+ // ensure no duplicate entries
+ assert (yprev < y);
+
+ // store this entry
+ dataPtr->first = y;
+ dataPtr->second = prob;
+ ++dataPtr;
+
+ // decrement gap posteriors accordingly
+ gapPosteriors[x] -= prob;
+ gapPosteriors[xlen + y + 1] -= prob;
+
+ // sanity checks: gap posteriors can't be negative beyond roundoff error
+ // (ensure that we're actually storing a probability distribution)
+ if (gapPosteriors[x] < -DOUBLE_TINY) {
+ (*this).Print (CL, true);
+ THROWEXPR ("ERROR: Negative gap posterior: gapPosteriors[x = " << x << "] = " << gapPosteriors[x]);
+ }
+ if (gapPosteriors[xlen + y + 1] < -DOUBLE_TINY) {
+ (*this).Print (CL, true);
+ THROWEXPR ("ERROR: Negative gap posterior: gapPosteriors[y = " << y << "] = " << gapPosteriors[xlen + y + 1]);
+ }
+ // if acceptable roundoff error, then round up to zero
+ if (gapPosteriors[x] < 0.)
+ gapPosteriors[x] = 0.;
+ if (gapPosteriors[xlen + y + 1] < 0.)
+ gapPosteriors[xlen + y + 1] = 0.;
+
+ // prevent overflow
+ if (gapPosteriors[x] < 1e-4)
+ gapPosteriors[x] = 1e-4;
+ if (gapPosteriors[xlen + y + 1] < 1e-4)
+ gapPosteriors[xlen + y + 1] = 1e-4;
+
+ // increment our indices
+ xprev = xcurr;
+ yprev = y;
+ }
+
+ // catch edge case of the last row
+ if (xcurr != -1)
+ rowSize[xcurr] = dataPtr - rowPtrs[xcurr];
+
+ }
+
+ /**
+ * \brief Get row pointer.
+ *
+ * \return pointer to a particular row in the sparse matrix
+ */
+ std::vector<Matrix_entry>::iterator GetRowPtr (const unsigned row) const {
+ assert (row >= 1 && row <= seq1Length);
+ return rowPtrs[row];
+ }
+
+ /**
+ * \brief Get match probability in matrix.
+ *
+ * \param row (0-based) row position
+ * \param col (0-based) column position
+ * \return value at a particular row, column
+ */
+ float get_match_prob (const unsigned row, const unsigned col) const {
+ assert (row >= 1 && row <= seq1Length);
+ assert (col >= 1 && col <= seq2Length);
+ for (size_t i = 0; i < rowSize[row]; i++){
+ if (rowPtrs[row][i].first == col)
+ return rowPtrs[row][i].second;
+ }
+ return 0;
+ }
+
+ /**
+ * \brief Get row size.
+ *
+ * \return number of entries in a particular row.
+ */
+ size_t GetRowSize (const unsigned row) const {
+ assert (row >= 1 && row <= seq1Length);
+ return rowSize[row];
+ }
+
+ /**
+ * \brief Get length of X (sequence 1).
+ *
+ * \return first dimension of the matrix
+ */
+ size_t GetSeq1Length() const {
+ return seq1Length;
+ }
+
+ /**
+ * \brief Get length of Y (sequence 2).
+ *
+ * \return second dimension of the matrix
+ */
+ size_t GetSeq2Length() const {
+ return seq2Length;
+ }
+
+ /// Get number of entries in matrix.
+ /*
+ * \return number of entries
+ */
+ size_t size() const {
+ return data.size();
+ }
+
+ /**
+ * \brief Write contents of object.
+ *
+ * Position indices are 0-based in output.
+ * The SparseMatrix class uses 1-based sequence indexing internally;
+ * this is converted to 0-based indexing when formatting output.
+ */
+ void Print (std::ostream &outfile, bool show_gaps = false) const {
+ outfile << "Sparse match posteriors (0-based coords):" << endl;
+ for (unsigned i = 1; i <= seq1Length; i++) {
+ // skip zero entries
+ if (rowSize[i] == 0)
+ continue;
+ outfile << " " << i - 1 << ":"; // convert to 0-based indexing
+ for (unsigned j = 0; j < rowSize[i]; j++) {
+ outfile << " (" << rowPtrs[i][j].first - 1 << "," << rowPtrs[i][j].second << ")"; // convert to 0-based indexing
+ }
+ outfile << endl;
+ }
+ if (show_gaps) {
+ outfile << "Gap posteriors 0 (0-based coords): ";
+ for (unsigned i = 1; i <= seq1Length; i++){
+ outfile << " (" << i - 1 << "," << gapPosteriors[i] << ")"; // convert to 0-based indexing
+ }
+ outfile << endl << "Gap posteriors 1 (0-based coords): ";
+ for (unsigned i = 1; i <= seq2Length; i++){
+ outfile << " (" << i - 1 << "," << gapPosteriors[i + seq1Length + 1] << ")"; // convert to 0-based indexing
+ }
+ outfile << endl;
+ }
+ }
+
+ /**
+ * \brief Write output formatted for GUI.
+ *
+ * Sequence and position indices are both 0-based in output.
+ * The SparseMatrix class uses 1-based sequence indexing internally;
+ * this is converted to 0-based indexing when formatting output.
+ */
+ void write_gui_output (std::ostream& o) const {
+
+ o << "; Sparse posterior probability matrix for sequences " << xidx << " and " << yidx << endl
+ << "; Format is:" << endl
+ << "; (" << xidx << ", position_1) ~ (" << yidx << ", position_2) => prob" << endl
+ << "; which means that (" << xidx << ", position_1) is aligned to (" << yidx << ", position_2) with probability prob." << endl
+ << "; (" << xidx << ", position_1) ~ (" << yidx << ", -1) => prob" << endl
+ << "; means that (" << xidx << ", position_1) is aligned to a gap in " << yidx << " with probability prob." << endl
+ << "; sequence is 0-based and position is 0-based" << endl
+ << endl;
+
+ o << "; match posteriors" << endl;
+ for (unsigned i = 1; i <= seq1Length; i++) {
+ // skip zero entries
+ if (rowSize[i] == 0)
+ continue;
+ for (unsigned j = 0; j < rowSize[i]; j++) {
+ o << "(" << xidx << ", " << i - 1 << ") ~ (" << yidx << ", " << rowPtrs[i][j].first - 1 << ") => " << rowPtrs[i][j].second << endl; // convert to 0-based indexing
+ }
+ }
+ o << endl;
+
+ o << "; gap posteriors" << endl;
+ for (unsigned i = 1; i <= seq1Length; i++)
+ o << "(" << xidx << ", " << i - 1 << ") ~ (" << yidx << ", " << "-1" << ") => " << gapPosteriors[i] << endl; // convert to 0-based indexing
+ o << endl;
+ for (unsigned j = 1; j <= seq2Length; j++)
+ o << "(" << xidx << ", " << "-1" << ") ~ (" << yidx << ", " << j - 1 << ") => " << gapPosteriors[seq1Length + j + 1] << endl; // convert to 0-based indexing
+
+ o << endl;
+ }
+
+ /**
+ * \brief Compute transpose of matrix.
+ *
+ * \return SparseMatrix which is the tranpose of the current matrix
+ */
+ SparseMatrix* ComputeTranspose() const {
+
+ // create a new sparse matrix
+ SparseMatrix* transpose = new SparseMatrix();
+ const size_t numCells = data.size();
+
+ transpose->xidx = yidx;
+ transpose->yidx = xidx;
+ transpose->seq1Length = seq2Length;
+ transpose->seq2Length = seq1Length;
+
+ // allocate memory
+ transpose->data.resize (numCells);
+ transpose->rowSize.resize (seq2Length + 1); transpose->rowSize[0] = 0;
+ transpose->rowPtrs.resize (seq2Length + 1); transpose->rowPtrs[0] = transpose->data.end();
+ transpose->gapPosteriors.resize(seq1Length + seq2Length + 2);
+
+ // compute row sizes
+ for (unsigned i = 1; i <= seq2Length; i++)
+ transpose->rowSize[i] = 0;
+ for (unsigned i = 0; i < numCells; i++)
+ transpose->rowSize[data[i].first]++;
+
+ // compute row ptrs
+ for (unsigned i = 1; i <= seq2Length; i++)
+ transpose->rowPtrs[i] = (i == 1) ? transpose->data.begin() : transpose->rowPtrs[i-1] + transpose->rowSize[i-1];
+
+ // now fill in data
+ std::vector<std::vector<Matrix_entry>::iterator> currPtrs = transpose->rowPtrs;
+
+ for (unsigned i = 1; i <= seq1Length; i++){
+ std::vector<Matrix_entry>::iterator row = rowPtrs[i];
+ for (unsigned j = 0; j < rowSize[i]; j++){
+ currPtrs[row[j].first]->first = i;
+ currPtrs[row[j].first]->second = row[j].second;
+ currPtrs[row[j].first]++;
+ }
+ }
+
+ for (unsigned i = 0; i <= seq1Length; i++)
+ transpose->gapPosteriors[i + seq2Length + 1] = gapPosteriors[i];
+ for (unsigned i = 0; i <= seq2Length; i++)
+ transpose->gapPosteriors[i] = gapPosteriors[i + seq1Length + 1];
+
+ return transpose;
+ }
+
+ /**
+ * \brief Get gap probability in matrix.
+ *
+ * \param which 0 for sequence 0, 1 for sequence 1
+ * \param pos (1-based) position in sequence
+ * \return gap probability for pos
+ */
+ float get_gap_prob (const unsigned which, const unsigned pos) const {
+
+ // check no overflow of sequence lengths
+ assert ((which == 0 && pos <= seq1Length) || (which == 1 && pos <= seq2Length));
+
+ return gapPosteriors[pos + which * (seq1Length + 1)];
+ }
+
+ };
+
+}
+
+#endif /* SPARSEMATRIX_INCLUDED */
diff --git a/src/annealing/alignment_DAG.cc b/src/annealing/alignment_DAG.cc
new file mode 100644
index 0000000..dde285d
--- /dev/null
+++ b/src/annealing/alignment_DAG.cc
@@ -0,0 +1,1666 @@
+
+/**
+ * \file alignment_DAG.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Ariel Schwartz and Robert Bradley.
+ * Sudeep Juvekar wrote the iterative refinement code do_lateral_refinement.
+ * Jaeyoung Do wrote the parallelization and database code.
+ */
+
+#include <limits>
+
+#include "annealing/alignment_DAG.h"
+#include "manager/manager.h"
+
+using namespace fsa;
+
+
+// use a hash map if available; otherwise use a standard map
+#ifdef HAVE_TR1_UNORDERED_MAP
+typedef std::tr1::unordered_map<std::pair<Column*, Column*>, Edge*, column_pair_hash> Edge_table;
+#else
+typedef std::map<std::pair<Column*, Column*>, Edge*> Edge_table;
+#endif
+
+Manager* Edge::manager = NULL;
+Manager* Column::manager = NULL;
+
+std::pair<float, float> Column::get_accuracy_normalized (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, const size_t num_seqs) const {
+
+ float p_match = 0.;
+ float p_gap = 0.;
+ float denom = 0.; // denominator of expected accuracy calculation: number of (sum-of-pairs) characters
+ for (Seq_pos_map::const_iterator seq_pos = seq_pos_map.begin(); seq_pos != seq_pos_map.end(); seq_pos++) {
+ const size_t i = seq_pos->first;
+ const unsigned ii = seq_pos->second;
+
+ for (size_t j = 0; j < num_seqs; j++) {
+
+ if (i == j)
+ continue;
+
+ // do we have the (i,j) posterior probability matrix available?
+ // if not, go to the next matrix
+ if (sparse_matrices[i][j] == 0 && !manager->get_sparse_matrix (sparse_matrices, i, j))
+ continue;
+ const SparseMatrix* ijMatrix = sparse_matrices[i][j];
+
+ // does this column contains sequence j?
+ const Seq_pos_map::const_iterator jj = seq_pos_map.find (j);
+
+ // if seq j isn't present in this column, then increment p_gap accordingly
+ if (jj == seq_pos_map.end()) {
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (0, ii + 1);
+ denom += tree_weights (i, j);
+ }
+
+ // if it is, then increment p_match
+ else if (i < j) {
+ p_match += tree_weights (i, j) * ijMatrix->get_match_prob (ii + 1, jj->second + 1);
+ denom += tree_weights (i, j) * 2;
+ }
+
+ }
+ }
+
+ return std::make_pair (2 * p_match + p_gap, denom);
+}
+
+float Column::expected_score (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor, size_t num_seqs) const {
+
+ float p_match = 0.;
+ float p_gap = 0.;
+ for (Seq_pos_map::const_iterator seq_pos = seq_pos_map.begin(); seq_pos != seq_pos_map.end(); seq_pos++) {
+ const size_t i = seq_pos->first;
+ const unsigned ii = seq_pos->second;
+
+ for (size_t j = 0; j < num_seqs; j++) {
+
+ if (i == j)
+ continue;
+
+ // do we have the (i,j) posterior probability matrix available?
+ // if not, go to the next matrix
+
+ if (sparse_matrices[i][j] == 0 && !manager->get_sparse_matrix (sparse_matrices, i, j))
+ continue;
+ const SparseMatrix* ijMatrix = sparse_matrices[i][j];
+
+ // does this column contains sequence j?
+ const Seq_pos_map::const_iterator jj = seq_pos_map.find (j);
+
+ // if seq j isn't present in this column, then increment p_gap accordingly
+ if (jj == seq_pos_map.end())
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (0, ii + 1);
+
+ // if it is, then increment p_match
+ else if (i < j) {
+ p_match += tree_weights (i, j) * ijMatrix->get_match_prob (ii + 1, jj->second + 1);
+ }
+ }
+ }
+
+ return (2 * p_match + gap_factor * p_gap);
+}
+
+float Column::change_in_expected_score (const Seq_pos& seq_pos, std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor, size_t num_seqs, bool skip_seq_pos /* = false */) const {
+
+ // sequence and position of the character to be aligned
+ const size_t i = seq_pos.first;
+ const unsigned ii = seq_pos.second;
+
+ // if so requested, make sure that sequence i doesn't already have a character in this column
+ if (!skip_seq_pos && contains_seq (i))
+ return INVALID_EDGE;
+
+ // if not, then calculate the change in expected accuracy associated with aligning it to this column
+ float p_match = 0.;
+ float p_gap = 0.;
+ for (size_t j = 0; j < num_seqs; j++) {
+
+ if (i == j)
+ continue;
+
+ // do we have the (i,j) posterior probability matrix available?
+ // if not, go to the next matrix
+ if (sparse_matrices[i][j] == 0 && !manager->get_sparse_matrix (sparse_matrices, i, j))
+ continue;
+ const SparseMatrix* ijMatrix = sparse_matrices[i][j];
+
+ // does this column contains sequence j?
+ const Seq_pos_map::const_iterator jj = seq_pos_map.find (j);
+
+ // 2 cases for sequence j:
+ // if gapped, then increment p_gap
+ if (jj == seq_pos_map.end())
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (0, ii + 1);
+
+ // if aligned, then increment p_match and decrement p_gap
+ else {
+ p_match += tree_weights (i, j) * ijMatrix->get_match_prob (ii + 1, jj->second + 1);
+ p_gap -= tree_weights (i, j) * ijMatrix->get_gap_prob (1, jj->second + 1);
+ }
+
+ }
+
+ return (2 * p_match + gap_factor * p_gap);
+}
+
+bool Edge::update_weight_tgf (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, bool update_weight /* = true */) {
+
+ // NB: It's crucial that at this point the Edge be between
+ // the current (after merges) source and dest columns;
+ // this must be assured by the calling function.
+
+ float p_match = 0.;
+ float p_gap = 0.;
+
+ // for all pairs of positions (i, ii) ~ (j, jj) in each column which will be aligned after the merge
+ const Seq_pos_map& source_seq_pos_map = source->get_seq_pos_map();
+ const Seq_pos_map& dest_seq_pos_map = dest->get_seq_pos_map();
+
+ // loop over seqs i,j and associated seq positions ii,jj in columns joined by edge
+ for (Seq_pos_map::const_iterator source_seq_pos = source_seq_pos_map.begin(); source_seq_pos != source_seq_pos_map.end(); ++source_seq_pos) {
+ const size_t i = source_seq_pos->first; // sequence i
+ const unsigned ii = source_seq_pos->second; // position ii
+
+ for (Seq_pos_map::const_iterator dest_seq_pos = dest_seq_pos_map.begin(); dest_seq_pos != dest_seq_pos_map.end(); ++dest_seq_pos) {
+ const size_t j = dest_seq_pos->first; // sequence j
+ const unsigned jj = dest_seq_pos->second; // position jj
+
+ // simplest consistency check
+ if (i == j)
+ return true;
+
+ // do we have the (i,j) posterior probability matrix available?
+ // if not, go to the next matrix
+ if (sparse_matrices[i][j] == 0 && !manager->get_sparse_matrix (sparse_matrices, i, j))
+ continue;
+ const SparseMatrix* ijMatrix = sparse_matrices[i][j];
+
+ p_match += tree_weights (i, j) * ijMatrix->get_match_prob (ii + 1, jj + 1);
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (0, ii + 1); // so p_gap gets incremented as:
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (1, jj + 1); // for each (seq,position) pair (i,ii) and (j,jj),
+ // add P(position ii in seq i is gapped) and P(position jj in seq j is gapped)
+
+ // Here's a long-winded explanation of p_match and p_gap:
+ // Consider merging column 1 with n non-gap characters and column 2 with m non-gap characters.
+ // P_match should have (n + m choose 2) terms,
+ // one for each pair of aligned characters in the newly-created column.
+ // P_gap should have 2 * (n + m choose 2) terms,
+ // two for each pair of aligned characters in the newly-created column.
+ // Because P_gap is actually incremented at each merging operation rather than being calculated anew,
+ // the incremental increase in P_gap after a merge operation has (n * m + m * n) = (2 * n * m terms).
+
+ }
+ }
+
+ // update weight if requested
+ if (update_weight) {
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << " updated weight: " << weight << " (p_match = " << p_match << "; p_gap = " << p_gap << ") -> " << 2 * p_match / p_gap << endl;
+ }
+
+ // update weight of edge:
+ // calculated like eq (4) in the AMAP paper,
+ // but gap factor scaled s.t. value of 1 (instead of 1/2) gives accuracy
+ weight = 2 * p_match / p_gap;
+
+ }
+
+ // keep track of the size of the nodes
+ // (for tracking whether the re-weighting needs to be redone
+ // after edge re-insertion onto heap)
+ weight_size = source->size() + dest->size();
+
+ return false;
+}
+
+bool Edge::update_weight_maxstep (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor, bool update_weight /* = true */) {
+
+ // NB: It's crucial that at this point the Edge be between
+ // the current (after merges) source and dest columns;
+ // this must be assured by the calling function.
+
+ float p_match = 0.;
+ float p_gap = 0.;
+
+ // for all pairs of positions (i, ii) ~ (j, jj) in each column which will be aligned after the merge
+ const Seq_pos_map& source_seq_pos_map = source->get_seq_pos_map();
+ const Seq_pos_map& dest_seq_pos_map = dest->get_seq_pos_map();
+
+ // for all pairs of positions (i, ii) ~ (j, jj) in each column which will be aligned after the merge
+ for (Seq_pos_map::const_iterator source_seq_pos = source_seq_pos_map.begin(); source_seq_pos != source_seq_pos_map.end(); ++source_seq_pos) {
+ const size_t i = source_seq_pos->first;
+ const unsigned ii = source_seq_pos->second;
+
+ for (Seq_pos_map::const_iterator dest_seq_pos = dest_seq_pos_map.begin(); dest_seq_pos != dest_seq_pos_map.end(); ++dest_seq_pos) {
+ const size_t j = dest_seq_pos->first;
+ const unsigned jj = dest_seq_pos->second;
+
+ // simplest consistency check
+ if (i == j)
+ return true;
+
+ // do we have the (i,j) posterior probability matrix available?
+ // if not, go to the next matrix
+ if (sparse_matrices[i][j] == 0 && !manager->get_sparse_matrix (sparse_matrices, i, j))
+ continue;
+ const SparseMatrix* ijMatrix = sparse_matrices[i][j];
+
+ p_match += tree_weights (i, j) * ijMatrix->get_match_prob (ii + 1, jj + 1);
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (0, ii + 1);
+ p_gap += tree_weights (i, j) * ijMatrix->get_gap_prob (1, jj + 1);
+
+ }
+ }
+
+ // update weight if requested
+ if (update_weight) {
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << " updated weight: " << weight << " (p_match = " << p_match << "; p_gap = " << p_gap << ") -> " << (2 * p_match - gap_factor * p_gap) << endl;
+ }
+
+ // update weight of edge
+ weight = (2 * p_match - gap_factor * p_gap) / (source_seq_pos_map.size() * dest_seq_pos_map.size());
+
+ }
+
+ // keep track of the size of the nodes
+ // (for tracking whether the re-weighting needs to be redone
+ // after edge re-insertion onto heap)
+ weight_size = source->size() + dest->size();
+
+ return false;
+
+}
+
+Alignment_DAG::Alignment_DAG (const Sequence_database& seq_db)
+ : seq_db (seq_db),
+ num_seqs (seq_db.size()), num_columns (0) {
+
+ // get maximum sequence length
+ size_t maxlen = 0;
+ for (size_t seq = 0; seq < seq_db.size(); ++seq) {
+ const Sequence& sequence = seq_db.get_seq (seq);
+ maxlen = std::max (maxlen, sequence.length());
+ }
+
+ // initialize seq_pos_col_maps for sequences
+ // use 0-based indexing
+ seq_pos_col_maps.resize (num_seqs);
+ for (size_t r = 0; r < num_seqs; ++r)
+ seq_pos_col_maps[r].resize (seq_db.get_seq (r).length(), NULL);
+
+ // store sequence data
+ num_columns = 0;
+ for (unsigned pos = 0; pos < maxlen; ++pos) { // position within the sequences
+ for (size_t seq = 0; seq < num_seqs; ++seq) {
+
+ // are we done with this sequence?
+ const Sequence& sequence = seq_db.get_seq (seq);
+ if (pos >= sequence.length())
+ continue;
+
+ // store character
+ columns.push_back (new Column (num_columns++)); // 0-based indexing for Column::index
+ const Seq_pos seq_pos (seq, pos);
+ (*(--columns.end()))->add_seq_pos (seq_pos);
+ set_seq_pos_col (seq_pos, *(--columns.end()));
+ }
+ }
+
+}
+
+Alignment_DAG::Alignment_DAG (const Sequence_database& seq_db, const Stockholm& stock)
+ : seq_db (seq_db),
+ num_seqs (seq_db.size()), num_columns (stock.columns()) {
+
+ // initialize seq_pos_col_maps for sequences
+ // use 0-based indexing
+ seq_pos_col_maps.resize (num_seqs);
+ for (size_t seq = 0; seq < num_seqs; ++seq)
+ seq_pos_col_maps[seq].resize (seq_db.get_seq (seq).length(), NULL);
+
+ // create columns
+ for (size_t c = 0; c < num_columns; ++c)
+ columns.push_back (new Column (c)); // 0-based indexing for Column::index
+
+ // store sequence data
+ for (size_t seq = 0; seq < num_seqs; ++seq) {
+
+ // reset position within current sequence
+ unsigned pos = 0;
+
+ // iterate over columns, storing (seq, pos) information as we go
+ for (std::vector<Column*>::iterator col = columns.begin(); col != columns.end(); ++col) {
+
+ // if seq has a character in column col
+ if (!stock.is_gapped (seq, (*col)->get_index())) {
+ const Seq_pos seq_pos (seq, pos++);
+ (*col)->add_seq_pos (seq_pos);
+ set_seq_pos_col (seq_pos, *col);
+ }
+
+ // else seq must be gapped in column col, so store nothing
+
+ }
+
+ }
+
+ // drop all-gaps columns (if they were present in the input Stockholm alignment)
+ drop_all_gaps_columns();
+
+}
+
+Alignment_DAG::~Alignment_DAG() {
+
+ // columns
+ for (std::vector<Column*>::iterator col = columns.begin(); col != columns.end(); ++col)
+ (*col)->set_merged_into (NULL);
+ for (std::vector<Column*>::iterator col = columns.begin(); col != columns.end(); ++col) {
+ Column* colPtr = *col;
+ *col = NULL;
+ delete colPtr;
+ }
+ columns.clear();
+
+ Edge::manager = NULL;
+ Column::manager = NULL;
+
+}
+
+void Alignment_DAG::drop_all_gaps_columns() {
+
+ // drop all-gaps columns
+ std::vector<Column*> sans_allgaps;
+ size_t idx = 0;
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+ if ((*col)->size()) {
+ (*col)->set_index (idx++);
+ sans_allgaps.push_back (*col);
+ }
+ }
+
+ columns.assign (sans_allgaps.begin(), sans_allgaps.end());
+ num_columns = columns.size();
+
+}
+
+void Alignment_DAG::dfs_topological_sort() {
+
+ CTAG(7,ANNEALING ANNEALING_VERBOSE DAG) << "Finding the most-parsimonious indel structure." << endl;
+
+ // unmark all nodes
+ unmark (columns);
+
+ // initialize stack of nodes by pushing on columns holding the first characters of all sequences
+ std::stack<Column*> nodes;
+ std::vector<bool> on_stack (columns.size(), false);
+ std::vector<int> finishing_times (columns.size(), -1);
+ std::vector<Column*> starting_cols;
+ for (size_t s = 0; s < num_seqs; ++s) {
+ if (seq_db.get_seq (s).length() == 0) // handle case of 0-length sequences
+ continue;
+ Column* node = get_seq_pos_col (Seq_pos (s, 0)); // remember 0-based indexing
+ assert (!node->is_dead());
+ if (!on_stack[node->get_index()]) {
+ starting_cols.push_back (node);
+ on_stack[node->get_index()] = true;
+ }
+ }
+ // now sort these starting columns (MUST preserve the partial order!)
+ std::sort (starting_cols.begin(), starting_cols.end(), smaller_index());
+ for (std::vector<Column*>::iterator col = starting_cols.begin(); col != starting_cols.end(); ++col)
+ nodes.push (*col);
+
+ // perform a postorder traversal to get finishing times for columns
+ unsigned time = 0;
+ while (!nodes.empty()) {
+
+ // get next node on stack
+ Column* node = nodes.top();
+ nodes.pop();
+ assert (!node->is_dead());
+
+ // if the node which we've just popped is marked, then we're finished with it
+ if (node->is_marked()) {
+ finishing_times[node->get_index()] = time++;
+ continue;
+ }
+
+ // else mark the node and push it on the stack
+ node->mark();
+ nodes.push (node);
+
+ // continue DFS: explore node's neighbors
+ std::vector<Column*> neighbors;
+ const Seq_pos_map& seq_pos_map = node->get_seq_pos_map();
+ for (Seq_pos_map::const_iterator seq_pos_iter = seq_pos_map.begin(); seq_pos_iter != seq_pos_map.end(); ++seq_pos_iter) {
+
+ // get the next position in this sequence
+ const Seq_pos next_seq_pos = Seq_pos (seq_pos_iter->first, seq_pos_iter->second + 1);
+
+ // have we reached the end of this sequence?
+ if (next_seq_pos.second >= seq_db.get_seq (next_seq_pos.first).length())
+ continue;
+
+ // if not, then continue DFS on neighbors
+ Column* w = get_seq_pos_col (next_seq_pos);
+
+ // store the neighbors (if they're not already on the stack)
+ if (!on_stack[w->get_index()]) {
+ neighbors.push_back (w);
+ on_stack[w->get_index()] = true;
+ }
+
+ }
+
+ // now a *critical* step: use the current total order
+ // to impose the correct partial order on the neighboring nodes
+ // (otherwise we won't be doing a postorder traversal => things will break mysteriously)
+ std::sort (neighbors.begin(), neighbors.end(), smaller_index()); // not doing this will MESS EVERYTHING UP!!
+
+ // then store
+ for (std::vector<Column*>::iterator column = neighbors.begin(); column != neighbors.end(); ++column)
+ nodes.push (*column);
+
+ } // end DFS loop
+
+ // construct list of live columns for sorting
+ std::vector<Column*> columns_tmp;
+ for (std::vector<Column*>::iterator column = columns.begin(); column != columns.end(); ++column) {
+ if (!(*column)->is_dead()) {
+ columns_tmp.push_back (*column);
+ assert (finishing_times[(*column)->get_index()] >= 0); // assert node finished in postorder traversal
+ (*column)->set_index (finishing_times[(*column)->get_index()]); // store finishing times as indices
+ }
+ }
+ assert (num_columns == columns_tmp.size());
+
+ // now (reverse) sort according to finishing times
+ std::sort (columns_tmp.begin(), columns_tmp.end(), greater_index());
+
+ // store and make column indices sane as we go
+ columns.clear();
+ for (size_t idx = 0; idx < columns_tmp.size(); ++idx) {
+ columns.push_back (columns_tmp[idx]);
+ columns[idx]->set_index (idx);
+ }
+
+}
+
+Stockholm Alignment_DAG::get_stockholm() const {
+
+ // store alignment as matrix of booleans,
+ // with each row representing the alignment for a particular sequence
+ // (see Alignment_row::Row_path)
+ std::vector<Alignment_row::Row_path*> align_matrix (num_seqs, NULL);
+ for (std::vector<Alignment_row::Row_path*>::iterator row_path = align_matrix.begin(); row_path != align_matrix.end(); ++row_path)
+ *row_path = new Alignment_row::Row_path (num_columns, false);
+
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+
+ // skip dead columns
+ if ((*col)->is_dead())
+ continue;
+
+ for (size_t seq = 0; seq < num_seqs; seq++) {
+ if ((*col)->contains_seq (seq))
+ (*align_matrix[seq])[(*col)->get_index()] = true;
+ }
+
+ }
+
+ // now add the sequence data
+ Stockholm stock (const_cast<Sequence_database&> (seq_db)); // hacky cast away const
+ for (size_t r = 0; r < num_seqs; ++r)
+ stock.set_row (seq_db.get_seq (r).name, align_matrix[r]);
+
+ stock.assert_flush();
+
+ return stock;
+}
+
+Stockholm Alignment_DAG::get_stockholm (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights) const {
+
+ // get the base alignment
+ Stockholm stock = get_stockholm();
+
+ // clear out the unnormalized accuracy annotations and
+ // store the properly normalized ones
+ stock.clear_annot();
+ std::pair<float, std::string> accuracy_pair = get_accuracy_annotation_normalized (sparse_matrices, tree_weights);
+ std::string acc = Util::to_string (accuracy_pair.first);
+ stock.add_gf_annot (ACCURACY_ANNOT, acc);
+ stock.set_gc_annot (ACCURACY_ANNOT, accuracy_pair.second);
+
+ stock.assert_flush();
+
+ return stock;
+}
+
+void Alignment_DAG::anneal (std::vector<std::vector<SparseMatrix*> >& sparse_matrices,
+ Manager& manager,
+ const bool use_tgf,
+ const float gap_factor, const bool enable_dynamic_weights, const float edge_weight_threshold,
+ const size_t num_refinement_steps,
+ const bool output_for_gui, const std::string gui_prefix) {
+
+ // initialize dummy Tree_weights (returns all weights as 1.0)
+ Tree_weights tree_weights;
+ anneal (sparse_matrices, tree_weights,
+ manager,
+ use_tgf,
+ gap_factor, enable_dynamic_weights, edge_weight_threshold,
+ num_refinement_steps,
+ output_for_gui, gui_prefix);
+
+}
+
+void Alignment_DAG::anneal (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights,
+ Manager& manager,
+ const bool use_tgf,
+ const float gap_factor, const bool enable_dynamic_weights, const float edge_weight_threshold,
+ const size_t num_refinement_steps,
+ const bool output_for_gui, const std::string gui_prefix) {
+
+ // set db manager to Column class and Edge class
+ Edge::manager = &manager;
+ Column::manager = &manager;
+
+ // log
+ CTAG(6,ANNEALING DAG ANNEALING_VERBOSE) << "Creating candidate edge list." << endl;
+
+ // pre-count the number of sequence pairs which we have SparseMatrix entries for
+ // as well as the maximum possible number of edges
+ size_t seq_pairs = 0;
+ size_t num_max_edges = 0;
+ for (size_t i = 0; i < num_seqs; ++i)
+ for (size_t j = i + 1; j < num_seqs; ++j) {
+ if ((sparse_matrices[i][j] != 0) || (sparse_matrices[j][i] != 0 || manager.is_sparse_matrix_available (i, j))) {
+ ++seq_pairs;
+ num_max_edges += std::min (seq_db.get_seq (i).length(), seq_db.get_seq (j).length());
+ }
+ }
+
+ // gui output
+ const std::string gui_filename = gui_prefix + GUI_FILENAME_DAG_SUFFIX;
+ std::ofstream gui_file;
+ // show initial DAG
+ if (output_for_gui) {
+ gui_file.open (gui_filename.c_str());
+ if (!gui_file.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << gui_filename << "'.");
+ write_gui_output (gui_file);
+ gui_file << "; Merges (added edges)" << endl
+ << "; Format is:" << endl
+ << "; source_column -> dest_column => accuracy_change" << endl
+ << "; (new accuracy is source_column_accuracy + dest_column_accuracy + accuracy_change)" << endl
+ << "; (note that all accuracies are unnormalized)" << endl
+ << endl;
+ }
+
+ // gui output: post prob matrices
+ if (output_for_gui) {
+ const std::string prob_filename = gui_prefix + GUI_FILENAME_PROB_SUFFIX;
+ std::ofstream prob_file;
+ prob_file.open (prob_filename.c_str());
+ if (!prob_file.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << prob_filename << "'.");
+ for (size_t i = 0; i < num_seqs; ++i)
+ for (size_t j = i + 1; j < num_seqs; ++j) {
+ if (sparse_matrices[i][j] != 0)
+ sparse_matrices[i][j]->write_gui_output (prob_file);
+ else if (sparse_matrices[j][i] != 0)
+ sparse_matrices[j][i]->write_gui_output (prob_file);
+ else if (manager.get_sparse_matrix (sparse_matrices, i, j))
+ sparse_matrices[i][j]->write_gui_output (prob_file);
+
+ }
+ prob_file.close();
+ CTAG(9,ANNEALING ANNEALING_VERBOSE) << "Created GUI output file '" << prob_filename << "'." << endl;
+ }
+
+ // create priority queue of candidate edges
+ std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> edges;
+
+ // if relevant, get edges from database
+ if (manager.is_edges_available()) {
+
+#if defined(HAVE_CONDOR) || defined(HAVE_POSTGRES)
+
+ // log
+ CTAG(8,ANNEALING DAG ANNEALING_VERBOSE) << "Getting candidate edges from database." << endl;
+ manager.get_edges (edges, seq_pos_col_maps);
+ // log
+ CTAG(8,ANNEALING DAG ANNEALING_VERBOSE) << "Got all candidate edges." << endl;
+
+#endif
+
+ }
+
+ else {
+ // loop through upper-triangle of sequences:
+ // calculate weights (maxstep or tgf) for each potential edge;
+ // store edges whose weights meet edge_weight_threshold and
+ // have a weight >= the gap_factor (if using tgf)
+ CTAG(9,ANNEALING DAG ANNEALING_VERBOSEs) << "Assembling list of candidate edges." << endl;
+ size_t seq_pairs_processed = 0;
+
+ for (size_t i = 0; i < num_seqs; ++i) {
+ const size_t xlen = seq_db.get_seq (i).length();
+
+ for (size_t j = i + 1; j < num_seqs; ++j) {
+
+ const SparseMatrix* ijMatrix = sparse_matrices[i][j];
+ // do we have the (i,j) posterior probability matrix available?
+ // if not, go to the next matrix
+ if (ijMatrix == 0)
+ continue;
+
+ // for all entries in the SparseMatrix, calculate the corresponding weight
+ // and store the edge
+ for (unsigned ii = 0; ii < xlen; ii++) { // note 0-based indexing for sequences
+ const float p_gap_ii = ijMatrix->get_gap_prob (0, ii + 1);
+
+ for (std::vector<Matrix_entry>::iterator rowPtr = ijMatrix->GetRowPtr (ii + 1),
+ rowEnd = rowPtr + ijMatrix->GetRowSize (ii + 1); rowPtr != rowEnd; rowPtr++) {
+ const unsigned jj = rowPtr->first - 1; // convert from SparseMatrix's 1-based coords to the 0-based coords which we use here
+
+ const float p_match = tree_weights (i, j) * rowPtr->second;
+ if (!p_match)
+ continue;
+ const float p_gap = tree_weights (i, j) * (p_gap_ii + ijMatrix->get_gap_prob (1, jj + 1));
+ const float weight = use_tgf ? (2 * p_match / p_gap) : (2 * p_match - gap_factor * p_gap);
+
+ // if the edge already scores too low to ever be accepted, then skip it
+ if ((weight < edge_weight_threshold) || (use_tgf && weight < gap_factor))
+ continue;
+
+ // else create and store it
+ // magic number 2 = 1 + 1 = size of columns
+
+ Edge* edge = new Edge (get_seq_pos_col (Seq_pos (i, ii)), get_seq_pos_col (Seq_pos (j, jj)),
+ weight, 2);
+ edges.push (edge);
+
+ if (CTAGGING(-1,ANNEALING_VERBOSE)) {
+ CL << "Stored candidate edge: " << *edge << "." << endl;
+ CL << " p_match = " << p_match << "; p_gap = " << p_gap << endl;
+ }
+ }
+ }
+
+ // log progress
+ ++seq_pairs_processed;
+ const unsigned percent_done = static_cast<unsigned> (std::floor ((100.0 * seq_pairs_processed / seq_pairs) + 0.5));
+ if (CTAGGING(7,ANNEALING DAG ANNEALING_VERBOSE) && (seq_pairs_processed % 100 == 0)) {
+ CTAG(7,ANNEALING DAG ANNEALING_VERBOSE) << "Stored candidate edges from " << seq_pairs_processed << "/" << seq_pairs << " sequence pairs (" << percent_done << "% done)." << endl;
+ }
+
+ }
+ }
+
+ }
+
+ // assert a greedy algorithm
+ //#ifndef NDEBUG
+ // float prev_weight = std::numeric_limits<float>::max();
+ //#endif
+ // see comment near endif directive
+
+ // keep track of candidate edges:
+ // - edges which were previously re-inserted in the heap
+ // (in order to prevent unnecessary re-weighting of duplicate edges)
+ // - edges which were found to be inconsistent
+ // (for these, store a NULL value)
+ Edge_table edge_table;
+
+ // anneal:
+ // loop through the priority queue of edges,
+ // greedily adding edges based on their (updated) weights
+ CTAG(9,ANNEALING DAG ANNEALING_VERBOSE) << "Annealing by adding edges to the DAG." << endl;
+
+ size_t edges_annealed = 0; // for logging progress
+ const size_t num_orig_edges = manager.get_edges_size (edges);
+ size_t sequential_skips = 0; // number of sequential edges skipped because they created a cycle
+ while (!edges.empty()) {
+
+ // get candidate edge
+ Edge *edge = manager.get_next_top_edge (edges, seq_pos_col_maps);
+
+ // log
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Popped edge: " << *edge << endl;
+ }
+
+ // lookup current columns for edge:
+ // note that this can be linear in the number of merges,
+ // although this shouldn't be too bad for common alignments
+ while (edge->source != edge->source->get_merged_into())
+ edge->source = edge->source->get_merged_into();
+ while (edge->dest != edge->dest->get_merged_into())
+ edge->dest = edge->dest->get_merged_into();
+
+ // fast check for redundant edges
+ // (edges specifying columns which have already been constructed)
+ // (wrapped in braces to prevent compiler complaints about
+ // 'jump to label skipping initialization of variables' blah blah blah...)
+ {
+ if (edge->source == edge->dest) {
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Inconsistent (redundant) edge: " << *edge << endl;
+ }
+ goto DELETE_EDGE;
+ }
+ }
+
+ // now DFS for full-blown consistency-checking
+ // this is also where the actual Pearce-Kelly takes place
+ // (assuming the edge is consistent)
+ {
+
+ // check whether this is a duplicate edge:
+ // do we already have an edge corresponding to merging these columns
+ // in our table of candidate edges edge_table?
+ Edge_table::iterator edge_in_table_iter = edge_table.find (std::make_pair (edge->source, edge->dest));
+
+ // use symmetry: edge can be in either direction
+ if (edge_in_table_iter == edge_table.end())
+ edge_in_table_iter = edge_table.find (std::make_pair (edge->dest, edge->source));
+
+ // have we seen the current edge previously?
+ bool in_table = false;
+ Edge* edge_in_table = NULL;
+ if (edge_in_table_iter != edge_table.end()) {
+ in_table = true;
+ edge_in_table = edge_in_table_iter->second;
+ }
+
+ // is this a previously-seen inconsistent edge?
+ if (in_table && (edge_in_table == 0)) { // test for NULL
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Inconsistent (previously-seen) edge: " << *edge << endl;
+ }
+ goto DELETE_EDGE;
+ }
+
+ // is this a duplicate edge?
+ // if we already have a different edge corresponding to this merge
+ // (with an updated, "current" weight),
+ // then this is a duplicate edge, so get rid of it
+ // (it conveys no new information)
+ if (in_table && (edge_in_table != edge)) {
+ assert (edge_in_table_iter != edge_table.end());
+ assert (edge_in_table != 0);
+
+ // if the weight is current, meaning that the columns
+ // joined by the edges have not been affected by other merges
+ // since the weight was last calculated, then the weight
+ // for edge_in_table is correct and we can just delete
+ // the current edge
+ if (!edge_in_table->weight_outdated()) {
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Ignoring edge: " << *edge << " (" << edge << " != " << edge_in_table << ")" << endl;
+ }
+ goto DELETE_EDGE;
+ }
+
+ // if the weight isn't current, meaning that the columns
+ // joined by the edges have been affected by other merges
+ // since the weight was last calculated, then we need to re-weight it
+ // in order to ensure that we maintain greediness
+ // (otherwise it won't be a steepest ascent algorithm)
+ // use a quasi-hack to accomplish this:
+ // replace the stored edge with the current one;
+ else {
+ edge_table.erase (edge_in_table_iter);
+ edge_in_table_iter = (edge_table.insert (std::make_pair (std::make_pair (edge->source, edge->dest), edge))).first; // get new iterator
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Erased and re-inserted edge to force re-weighting." << endl;
+ }
+ }
+
+ }
+
+ // recalculate edge weight if using dynamic edge weights
+ // as a byproduct, calculate the change in expected accuracy from adding the edge
+ if (edge->weight_outdated() && enable_dynamic_weights) {
+
+ // the second argument enable_dynamic_weights is now obsolete;
+ // originally the update_weight_{tgf,maxstep} functions were used
+ // to calculate changes to the expected accuracy after each merge,
+ // but this functionality is retired for speed when
+ // dynamic weighting is disabled
+ bool conflict = false;
+ if (use_tgf) {
+ conflict = (edge->update_weight_tgf) (sparse_matrices, tree_weights, enable_dynamic_weights);
+ }
+ else {
+ conflict = (edge->update_weight_maxstep) (sparse_matrices, tree_weights, gap_factor, enable_dynamic_weights);
+ }
+
+ // if an inconsistency detected, record it and delete edge
+ if (conflict) {
+
+ // log
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Inconsistent edge: " << *edge << endl;
+ }
+
+ // if present, mark record as inconsistent
+ if (in_table)
+ edge_in_table_iter->second = (Edge*) NULL;
+ // else record it as inconsistent
+ else
+ edge_table.insert (std::make_pair (std::make_pair (edge->source, edge->dest), (Edge*) NULL));
+
+ goto DELETE_EDGE;
+ }
+
+ // if priority queue sorting is wrong, then push and go to the next
+ if (edge->weight < edges.top()->weight) {
+
+ // if this is the first time we've seen this edge, record it
+ if (!in_table) {
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Recorded new edge: " << *edge << endl;
+ }
+ edge_table.insert (std::make_pair (std::make_pair (edge->source, edge->dest), edge));
+ }
+
+ // log
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Re-inserted edge: " << *edge << endl;
+ }
+
+ // push back on heap
+ manager.push_edge (edges, edge);
+
+ continue;
+ }
+
+ } // if (edge->weight_outdated() && enable_dynamic_weights)
+
+ // if best edge has weight < edge_weight_threshold or has
+ // a weight < gap_factor (if using tgf), then we're done with sequence annealing
+ // only relevant for dynamic weights;
+ // edges whose initial weights don't satisfy these criteria are never
+ // stored on the heap as candidate edges
+ if (enable_dynamic_weights
+ && ((edge->weight < edge_weight_threshold) || (use_tgf && (edge->weight < gap_factor)))) {
+ while (!edges.empty()) {
+ edge = edges.top();
+ edges.pop();
+ delete edge;
+ }
+ break;
+ }
+
+ // now actually perform the consistency check and Pearce-Kelly
+
+ // NB: Do NOT NOT NOT forget to unmark nodes after visiting!
+ // Crucial and easy to forget.
+ std::vector<Column*> R_forward;
+
+ // get the lower and upper bounds of the depth-first searches
+ // (we have already imposed a total order on columns)
+ Column *l_bound, *u_bound;
+ if (*(edge->source) < *(edge->dest)) {
+ l_bound = edge->source;
+ u_bound = edge->dest;
+ } else {
+ l_bound = edge->dest;
+ u_bound = edge->source;
+ }
+
+ // if edge is inconsistent (induces cycle)
+ if (induces_cycle (edge, l_bound, u_bound, R_forward)) {
+
+ // log
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Inconsistent edge: " << *edge << endl;
+ }
+
+ // erase record if present
+ if (in_table)
+ edge_in_table_iter->second = (Edge*) NULL;
+ // else record it as inconsistent
+ else
+ edge_table.insert (std::make_pair (std::make_pair (edge->source, edge->dest), (Edge*) NULL));
+
+ goto DELETE_EDGE;
+ }
+
+ // if edge is consistent (doesn't induce cycle)
+ else {
+
+ // add edge with the Pearce-Kelly algorithm
+ add_edge (edge, l_bound, u_bound, R_forward);
+
+ // log
+ if (CTAGGING(4,ANNEALING DAG ANNEALING_VERBOSE)) {
+ CL << "Added edge: " << *edge << endl;
+ }
+
+ // we've added the edge, so remove the record
+ if (in_table) {
+ edge_table.erase (edge_in_table_iter);
+ if (CTAGGING(3,ANNEALING_VERBOSE)) {
+ CL << "Erased added edge: " << *edge_in_table << endl;
+ }
+ }
+
+#ifndef NDEBUG
+ // if (use_tgf)
+ // assert (edge->weight - prev_weight < DOUBLE_TINY);
+ // prev_weight = edge->weight;
+ // comment in to check that sequence annealing is truly steepest ascent
+ // note that this check can fail due to floating-point error if the weights are large (ie the max 10000)
+ // -- RKB 10/21/08
+#endif
+
+ ++edges_annealed; // increment counter
+ sequential_skips = 0; // reset counter
+
+ //log
+ if (CTAGGING(-1,DAG)) {
+ CL << "DAG after annealing " << edges_annealed << "/" << num_orig_edges << " candidate edges." << endl;
+ this->show (CL, true);
+ }
+
+ // write gui output if requested
+ if (output_for_gui) {
+ edge->write_gui_output (gui_file);
+ }
+
+ } // end if edge doesn't induce cycle
+
+ } // end block for DFS
+
+
+
+ // clean up: delete edge and log progress
+ // goto is ugly but appropriate here...
+ DELETE_EDGE:
+
+ delete edge;
+
+ // check whether we've skipped more than 10 * (maximum possible number of remaining edges to anneal) edges;
+ // if so, then stop annealing
+ if (sequential_skips >= 10 * (num_max_edges - edges_annealed)) {
+ CTAG(7,ANNEALING ANNEALING_VERBOSE) << "Skipped more than 10 * (maximum possible number of remaining edges to anneal) sequential edges; breaking." << endl;
+ while (!edges.empty()) {
+ edge = edges.top();
+ edges.pop();
+ delete edge;
+ }
+ break;
+ }
+
+ const size_t edges_size = manager.get_edges_size (edges);
+
+ // log progress
+ if (CTAGGING(7,ANNEALING ANNEALING_VERBOSE) && (((edges_annealed % 10000) == 0) || (((num_orig_edges - edges_size) % 10000) == 0))) {
+ const unsigned percent_done = static_cast<unsigned> (std::floor ((100.0 * edges_annealed / num_orig_edges) + 0.5));
+ const unsigned percent_remaining = static_cast<unsigned> (std::floor ((100.0 * edges_size / num_orig_edges) + 0.5));
+ CTAG(7,ANNEALING ANNEALING_VERBOSE) << "Annealed " << edges_annealed << "/" << num_orig_edges << " (" << percent_done << "%) candidate edges;"
+ << " " << edges_size << "/" << num_orig_edges << " (" << percent_remaining << "%) remaining candidate edges to process." << endl;
+ }
+
+ } // while (!edges.empty())
+
+ // we're done with annealing!
+ CTAG(8,ANNEALING DAG ANNEALING_VERBOSE) << "Finished adding edges to the DAG." << endl;
+
+ // perform iterative refinement if requested
+ // use "lateral shift"
+ if (num_refinement_steps > 0) {
+
+ CTAG(9,ANNEALING REFINEMENT) << "Beginning iterative refinement." << endl;
+
+ // do hill-climbing refinement
+ float curr_score = expected_score (sparse_matrices, tree_weights, gap_factor);
+ size_t step = 0;
+ for (step = 0; step < num_refinement_steps; ++step) {
+
+ // refine
+ do_lateral_refinement (sparse_matrices, tree_weights, gap_factor);
+
+ // log
+ if (CTAGGING(8,ANNEALING REFINEMENT) && ((step % 5) == 0)) {
+ CTAG(8,ANNEALING REFINEMENT) << "Completed " << step + 1 << " iterative refinement steps." << endl;
+ }
+
+ // did we improve?
+ // if not, then stop iterative refinement
+ const float score = expected_score (sparse_matrices, tree_weights, gap_factor);
+ if (score > curr_score)
+ curr_score = score;
+ else {
+ if (score + DOUBLE_TINY < curr_score) // warn if score has decreased (shouldn't be able to!)
+ CTAG(8,ANNEALING REFINEMENT) << "WARNING: Expected score dropped from " << curr_score << " to " << score << " during iterative refinement!" << endl;
+ break;
+ }
+
+ }
+
+ // log (if didn't just do so)
+ if (CTAGGING(8,ANNEALING REFINEMENT) && ((step % 5) != 0)) {
+ CTAG(8,ANNEALING REFINEMENT) << "Finished iterative refinement (" << step + 1 << " steps)." << endl;
+ }
+
+ }
+
+ // close gui file
+ if (output_for_gui) {
+ gui_file.close();
+ CTAG(9,ANNEALING) << "Created GUI output file '" << gui_filename << "'." << endl;
+ }
+
+}
+
+void Alignment_DAG::show (std::ostream& o, const bool aligned_only /* = false */) const {
+
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+
+ if ((*col)->is_dead())
+ continue;
+ if (aligned_only && ((*col)->get_seq_pos_map().size() < 2))
+ continue;
+
+ // show the column and its forward and back edges
+ o << **col << endl;
+
+ // incoming cols
+ const Seq_pos_map& seq_pos_map = (*col)->get_seq_pos_map();
+ for (Seq_pos_map::const_iterator seq_pos_iter = seq_pos_map.begin(); seq_pos_iter != seq_pos_map.end(); ++seq_pos_iter) {
+
+ // have we reached the beginning of this sequence?
+ // (remember that sequence coordinates are 0-based)
+ if (seq_pos_iter->second == 0)
+ continue;
+
+ // get the previous position in this sequence
+ const Seq_pos prev_seq_pos = Seq_pos (seq_pos_iter->first, seq_pos_iter->second - 1);
+
+ // show this column
+ const Column* w = get_seq_pos_col (prev_seq_pos);
+ o << " <- " << *w << endl;
+
+ }
+
+ // check outgoing cols
+ for (Seq_pos_map::const_iterator seq_pos_iter = seq_pos_map.begin(); seq_pos_iter != seq_pos_map.end(); ++seq_pos_iter) {
+
+ // get the next position in this sequence
+ const Seq_pos next_seq_pos = Seq_pos (seq_pos_iter->first, seq_pos_iter->second + 1);
+
+ // have we reached the end of this sequence?
+ if (next_seq_pos.second >= seq_db.get_seq (next_seq_pos.first).length())
+ continue;
+
+ // show this column
+ const Column* w = get_seq_pos_col (next_seq_pos);
+ o << " -> " << *w << endl;
+
+ }
+
+ }
+
+}
+
+void Alignment_DAG::write_gui_output (std::ostream& o, bool show_edges /* = false */) const {
+
+ o << "; Initial DAG" << endl
+ << "; Format is:" << endl
+ << "; column: (sequence, position) => initial_accuracy" << endl
+ << "; sequence is 0-based and position is 0-based" << endl
+ << endl;
+
+ // first show column indices and the corresponding sequence positions, as well as initial accuracies
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+
+ assert (!(*col)->is_dead());
+
+ // show the column and its forward and back edges
+ const Seq_pos_map& seq_pos_map = (*col)->get_seq_pos_map();
+ assert (seq_pos_map.size() == 1);
+
+ o << (*col)->get_orig_index() << ": (" << seq_pos_map.begin()->first << ", " << seq_pos_map.begin()->second << ")" << endl;
+ }
+
+ o << endl;
+
+ // show edges if requested
+ if (show_edges) {
+
+ o << "; Initial edges" << endl;
+ o << "; Format is:" << endl;
+ o << "; source_column -> dest_column" << endl;
+ o << endl;
+
+ // now show forward edges
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+
+ const Seq_pos_map& seq_pos_map = (*col)->get_seq_pos_map();
+
+ // get the next position in this sequence
+ const Seq_pos next_seq_pos = Seq_pos (seq_pos_map.begin()->first, seq_pos_map.begin()->second + 1);
+
+ // have we reached the end of this sequence?
+ if (next_seq_pos.second >= seq_db.get_seq (next_seq_pos.first).length())
+ continue;
+
+ // else show this edge
+ const Column* w = get_seq_pos_col (next_seq_pos);
+ o << (*col)->get_orig_index() << " -> " << w->get_orig_index() << endl;
+
+ }
+
+ o << endl;
+ }
+
+}
+
+bool Alignment_DAG::dfs_f (Column* l_bound, Column* u_bound, std::vector<Column*>& R_forward) {
+
+ // init stack of nodes with the start node l_bound
+ std::stack<Column*> nodes;
+ const size_t offset = l_bound->get_index();
+ std::vector<bool> on_stack ((u_bound->get_index() - offset + 1), false);
+
+ nodes.push (l_bound);
+ on_stack[l_bound->get_index() - offset] = true;
+
+ while (!nodes.empty()) {
+
+ // get next node on stack
+ Column* node = nodes.top();
+ nodes.pop();
+
+ // if we've already seen node, then continue with the next
+ if (node->is_marked())
+ continue;
+
+ // else mark as visited and store it
+ node->mark();
+ R_forward.push_back (node);
+
+ // continue DFS: explore node's neighbors
+ const Seq_pos_map& seq_pos_map = node->get_seq_pos_map();
+ for (Seq_pos_map::const_iterator seq_pos_iter = seq_pos_map.begin(); seq_pos_iter != seq_pos_map.end(); ++seq_pos_iter) {
+
+ // get the next position in this sequence
+ const Seq_pos next_seq_pos = Seq_pos (seq_pos_iter->first, seq_pos_iter->second + 1);
+
+ // have we reached the end of this sequence?
+ if (next_seq_pos.second >= seq_db.get_seq (next_seq_pos.first).length())
+ continue;
+
+ // if not, then continue DFS on neighbors
+ Column* w = get_seq_pos_col (next_seq_pos);
+
+ // have we found a cycle?
+ if (*w == *u_bound)
+ return true;
+
+ // if not, then continue DFS
+ // it's critical that the conditional is ordered like this to prevent overflowing on_stack
+ // if *w > *u_bound!
+ else if (!(w->is_marked()) && (*w < *u_bound) && !on_stack[w->get_index() - offset]) {
+ nodes.push (w);
+ on_stack[w->get_index() - offset] = true;
+ }
+
+ }
+
+ }
+
+ // DFS terminated successfully, so no cycles found!
+ return false;
+}
+
+void Alignment_DAG::dfs_b (Column* u_bound, Column* l_bound, std::vector<Column*>& R_backward) {
+
+ // init stack of nodes with the start node u_bound
+ std::stack<Column*> nodes;
+ const size_t offset = l_bound->get_index();
+ std::vector<bool> on_stack ((u_bound->get_index() - offset + 1), false);
+
+ nodes.push (u_bound);
+ on_stack[l_bound->get_index() - offset] = true;
+
+ while (!nodes.empty()) {
+
+ // get next node on stack
+ Column* node = nodes.top();
+ nodes.pop();
+
+ // if we've already seen node, then continue with the next
+ if (node->is_marked())
+ continue;
+
+ // else mark as visited and store it
+ node->mark();
+ R_backward.push_back (node);
+
+ // continue DFS: explore node's neighbors
+ const Seq_pos_map& seq_pos_map = node->get_seq_pos_map();
+ for (Seq_pos_map::const_iterator seq_pos_iter = seq_pos_map.begin(); seq_pos_iter != seq_pos_map.end(); ++seq_pos_iter) {
+
+ // have we reached the beginning of this sequence?
+ // (remember that sequence coordinates are 0-based)
+ if (seq_pos_iter->second == 0)
+ continue;
+
+ // get the previous position in this sequence (remember that we're searching backwards)
+ Seq_pos prev_seq_pos = Seq_pos (seq_pos_iter->first, seq_pos_iter->second - 1);
+
+ // if not, then continue DFS on neighbors
+ Column* w = get_seq_pos_col (prev_seq_pos);
+
+ // note that there's no need to check for cycles here,
+ // since we've already done so in the dfs_f() call
+
+ // continue DFS
+ if (!(w->is_marked()) && (*l_bound < *w) && !on_stack[w->get_index() - offset]) {
+ nodes.push (w);
+ on_stack[w->get_index() - offset] = true;
+ }
+ }
+
+ }
+
+}
+
+void Alignment_DAG::reorder (std::vector<Column*>& R_forward, std::vector<Column*>& R_backward) {
+
+ // sort nodes in deltaB and deltaF
+ std::sort (R_backward.begin(), R_backward.end(), smaller_index());
+ std::sort (R_forward.begin(), R_forward.end(), smaller_index());
+
+ // assemble list of indices from nodes in deltaB and deltaF
+ // R_indices is R, the pool of available indices, in the Pearce and Kelly paper
+ std::vector<size_t> R_indices;
+ std::vector<Column*> L_columns;
+ // deltaB
+ for (std::vector<Column*>::const_iterator column = R_backward.begin(); column != R_backward.end(); ++column) {
+ L_columns.push_back (*column);
+ R_indices.push_back ((*column)->get_index());
+ }
+ // deltaF
+ for (std::vector<Column*>::const_iterator column = R_forward.begin(); column != R_forward.end(); ++column) {
+ L_columns.push_back (*column);
+ R_indices.push_back ((*column)->get_index());
+ }
+ // sort indices
+ std::sort (R_indices.begin(), R_indices.end());
+
+ // allocate indices to nodes in deltaB and deltaF
+ for (size_t i = 0; i < R_indices.size(); ++i) {
+ Column* col = L_columns[i];
+ const size_t index = R_indices[i];
+ assert (index < this->columns.size()); // remember 0-based indexing for Column::index
+ col->set_index (index);
+ this->columns[index] = col;
+ }
+
+}
+
+void Alignment_DAG::unmark (std::vector<Column*>& cols) {
+ for (std::vector<Column*>::iterator column = cols.begin(); column != cols.end(); ++column)
+ (*column)->unmark();
+}
+
+void Alignment_DAG::merge (Edge* edge) {
+ Column* source = edge->source;
+ Column* dest = edge->dest;
+
+ // add dest sequence positions to source
+ const Seq_pos_map& dest_seq_pos_map = dest->get_seq_pos_map();
+ for (Seq_pos_map::const_iterator seq_pos = dest_seq_pos_map.begin(); seq_pos != dest_seq_pos_map.end(); ++seq_pos) {
+ source->add_seq_pos (*seq_pos);
+ set_seq_pos_col (*seq_pos, source);
+ }
+
+ // merge dest into source
+ dest->set_merged_into (source);
+
+}
+
+bool Alignment_DAG::induces_cycle (Edge* edge, Column* l_bound, Column* u_bound, std::vector<Column*>& R_forward) {
+
+ // does this edge induce a cycle in the graph?
+ if (dfs_f (l_bound, u_bound, R_forward)) {
+
+ // sanity check: must be at least one node (l_bound)
+ assert (R_forward.size());
+
+ // unmark marked nodes
+ unmark (R_forward);
+
+ return true;
+ }
+
+ // sanity check: must be at least one node (l_bound)
+ assert (R_forward.size());
+
+ return false;
+
+}
+
+void Alignment_DAG::add_edge (Edge* edge, Column* l_bound, Column* u_bound, std::vector<Column*>& R_forward) {
+
+ Column* source = edge->source;
+ Column* dest = edge->dest;
+
+ // NB: It's crucial that at this point the Edge be between
+ // the current (after merges) source and dest columns;
+ // this must be assured by the calling function.
+
+ // we assume that induces_cycle has been called,
+ // thereby ensuring that the edge doesn't induce a cycle
+ // and populating R_forward; now we just need to perform
+ // the backward depth-first search, storing nodes as the search proceeds
+ std::vector<Column*> R_backward;
+ dfs_b (u_bound, l_bound, R_backward);
+
+ // sanity check: must be at least one node (l_bound and u_bound respectively)
+ assert (R_forward.size());
+ assert (R_backward.size());
+
+ // unmark visited nodes
+ unmark (R_forward);
+ unmark (R_backward);
+
+ // impose a new total order via the Pearce-Kelly Reorder() procedure
+ if (R_forward.size() == 1) { // catch edge cases
+ source = u_bound;
+ dest = l_bound;
+ } else if (R_backward.size() == 1) {
+ source = l_bound;
+ dest = u_bound;
+ } else {
+ reorder (R_forward, R_backward);
+ }
+
+ // modify the DAG: merge the (current) source and dest columns
+ edge->source = source;
+ edge->dest = dest;
+ merge (edge);
+
+ // mark the dest column as dead
+ // (note that this is /much/ faster than erasing it!)
+ dest->set_dead();
+
+ // decrement the number of columns in the alignment accordingly
+ --num_columns;
+
+}
+
+// (sequence position to shift, (original column, new column))
+typedef std::pair<Seq_pos, std::pair<size_t, size_t> > Shift;
+
+
+void Alignment_DAG::do_lateral_refinement (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor) {
+
+ // create priority queue of sequence positions to shift
+ std::priority_queue<std::pair<float, Shift> > shifts;
+
+ // create vector of (non-dead) columns
+ std::vector<Column*> tmp_columns;
+ for (std::vector<Column*>::iterator col = columns.begin(); col != columns.end(); ++col) {
+ if (!(*col)->is_dead())
+ tmp_columns.push_back (*col);
+ }
+
+ // for each column
+ // for each (seq, pos) in the column, consider shifting it
+ // left or right
+ for (size_t i = 0; i < tmp_columns.size(); i++) {
+
+ Column* curr_col = tmp_columns[i];
+
+ // consider shifting each character
+ const Seq_pos_map& seq_pos_map = curr_col->get_seq_pos_map();
+ for (Seq_pos_map::const_iterator seq_pos = seq_pos_map.begin(); seq_pos != seq_pos_map.end(); ++seq_pos) {
+
+ // column with the greatest change in expected accuracy from adding *seq_pos
+ // initialize to the original column holding this Seq_pos
+ size_t best_j = i;
+ // best change in expected accuracy from adding *seq_pos to another column
+ float best_score_change;
+
+ // initialize best_score_change to change in score corresponding to current column
+ // (corresponding to removing *seq_pos from curr_col, calculating expected change and then re-adding)
+ best_score_change = curr_col->change_in_expected_score (*seq_pos, sparse_matrices, tree_weights, gap_factor, num_seqs, true); // skip_seq_pos = true
+
+ // now search over other columns: search right
+ for (size_t j = i + 1; j < tmp_columns.size(); ++j) {
+
+ // get the column
+ Column* col = tmp_columns[j];
+ assert (!col->is_dead());
+ while (col != col->get_merged_into())
+ col = col->get_merged_into();
+
+ // if col contains a character from the sequence in *seq_pos, then break
+ // (can't slide it over)
+ const float change = col->change_in_expected_score (*seq_pos, sparse_matrices, tree_weights, gap_factor, num_seqs);
+ if (change == INVALID_EDGE)
+ break;
+
+ // if an improvement, then record it
+ if (change > best_score_change) {
+ best_score_change = change;
+ best_j = j;
+ }
+
+ }
+
+ // search left
+ for (int j = i - 1; j >= 0; --j) {
+
+ // get the column
+ Column* col = tmp_columns[j];
+ assert (!col->is_dead());
+ while (col != col->get_merged_into())
+ col = col->get_merged_into();
+
+ // if col contains a character from the sequence in *seq_pos, then break
+ // (can't slide it over)
+ const float change = col->change_in_expected_score (*seq_pos, sparse_matrices, tree_weights, gap_factor, num_seqs);
+ if (change == INVALID_EDGE)
+ break;
+
+ if (change > best_score_change) {
+ best_score_change = change;
+ best_j = j;
+ }
+
+ }
+
+ // if we've found a better position, then record it
+ if (best_j != i) {
+ const Shift shift (*seq_pos, std::pair<size_t, size_t> (i, best_j));
+ shifts.push (std::pair<float, Shift> (best_score_change, shift));
+ }
+
+ }
+ }
+
+ // now shift the (seq, pos) according to the corresponding
+ // change in expected score
+ // for each candidate shift, check that it's still a valid shift;
+ // also check whether there's a new, better shift
+ std::pair<float, Shift> score_shift;
+ while (!shifts.empty()) {
+
+ // get the top candidate shift
+ score_shift = shifts.top();
+ shifts.pop();
+ const Shift& shift = score_shift.second;
+ const Seq_pos& seq_pos = shift.first;
+
+ // get the original column holding seq_pos
+ const size_t orig_j = (shift.second).first;
+
+ // initialize best column to original column
+ size_t best_j = orig_j;
+ // best change in expected accuracy from adding *seq_pos to another column
+ float best_score_change;
+
+ // initialize best_score_change to change in score corresponding to original column
+ // (corresponding to removing *seq_pos from curr_col, calculating expected change and then re-adding)
+ // Note that this is different from Sudeep's original method,
+ // which initialized the scores to 0 rather than the score associated with
+ // the current column (and so, I believe, was biased towards shifting)
+ best_score_change = tmp_columns[orig_j]->change_in_expected_score (seq_pos, sparse_matrices, tree_weights, gap_factor, num_seqs, true); // skip_seq_pos = true
+
+ // search right
+ for (size_t j = orig_j + 1; j < tmp_columns.size(); ++j) {
+
+ // get the column
+ Column* col = tmp_columns[j];
+ assert (!col->is_dead());
+ while (col != col->get_merged_into())
+ col = col->get_merged_into();
+
+ // if col contains a character from the sequence in *seq_pos, then break
+ // (can't slide it over)
+ const float change = col->change_in_expected_score (seq_pos, sparse_matrices, tree_weights, gap_factor, num_seqs);
+ if (change == INVALID_EDGE)
+ break;
+
+ // if an improvement, then record it
+ if (change > best_score_change) {
+ best_score_change = change;
+ best_j = j;
+ }
+
+ }
+
+ // search left
+ for (int j = orig_j - 1; j >= 0; --j) {
+
+ // get the column
+ Column* col = tmp_columns[j];
+ assert (!col->is_dead());
+ while (col != col->get_merged_into())
+ col = col->get_merged_into();
+
+ // if col contains a character from the sequence in *seq_pos, then break
+ // (can't slide it over)
+ const float change = col->change_in_expected_score (seq_pos, sparse_matrices, tree_weights, gap_factor, num_seqs);
+ if (change == INVALID_EDGE)
+ break;
+
+ // if an improvement, then record it
+ if (change > best_score_change) {
+ best_score_change = change;
+ best_j = j;
+ }
+
+ }
+
+ // if wrong order on priority queue (if lower expected change in score than next shift on queue)
+ if (best_score_change < (shifts.top()).first) {
+ shifts.push (std::pair<float, Shift> (best_score_change, shift));
+ continue;
+ }
+
+ // if we've found an improvement, then make the change and move seq_pos!
+ if (best_j != orig_j) {
+ if (CTAGGING(-1,REFINEMENT)) {
+ CL << "Converting " << endl
+ << " " << *tmp_columns[orig_j] << endl
+ << " " << *tmp_columns[best_j] << endl;
+ }
+ tmp_columns[orig_j]->erase_seq_pos (seq_pos.first);
+ tmp_columns[best_j]->add_seq_pos (seq_pos);
+ set_seq_pos_col (seq_pos, tmp_columns[best_j]);
+ if (CTAGGING(-1,REFINEMENT)) {
+ CL << "to " << endl
+ << " " << *tmp_columns[orig_j] << endl
+ << " " << *tmp_columns[best_j] << endl;
+ }
+ }
+
+ }
+
+ // we're done, so create new columns object
+ columns.clear();
+ size_t idx = 0;
+ for (size_t i = 0; i < tmp_columns.size(); ++i) {
+ Column* col = tmp_columns[i];
+ // if empty, then skip
+ if (col->get_seq_pos_map().empty())
+ continue;
+ columns.push_back (col); // store
+ col->set_index (idx++); // update index
+ }
+ num_columns = columns.size();
+
+}
+
+std::pair<float, std::string> Alignment_DAG::get_accuracy_annotation_normalized (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights) const {
+
+ float overall_acc = 0.;
+ float overall_denom = 0.;
+ std::string annot;
+ for (std::vector<Column*>::const_iterator column = columns.begin(); column != columns.end(); ++column) {
+
+ // skip dead columns
+ if ((*column)->is_dead())
+ continue;
+
+ // If normalizing, then convert to per-pair accuracy as:
+ // Divide by 2 * (n choose 2 = 1/2*n*(n-1)) + ((num_seqs - n) * n),
+ // where the first part is the (sum-of-pairs) number of matched characters
+ // and the second part the number of characters aligned to gaps.
+ // The factor of 10.0 here is because accuracy as calculated during annealing is <= 1,
+ // and we want to map it to the interval [0-10].
+ const std::pair<float, float> accuracy_pair = (*column)->get_accuracy_normalized (sparse_matrices, tree_weights, num_seqs);
+
+ // cover case of no information for the column (can occur when a sequence is empty in pairwise inference)
+ if (accuracy_pair.second == 0.) {
+ annot += '0';
+ continue;
+ }
+
+ // else perform calculation as usual
+ const float acc_norm = accuracy_pair.first / accuracy_pair.second;
+ assert ((acc_norm >= 0.) && (acc_norm <= 1.00001)); // prevent rounding error for the case of 1.0 (yes, it happens!)
+ annot += static_cast<char> ((acc_norm > 0) ? "0123456789"[ std::min (static_cast<int> (std::floor (acc_norm * 10.0)), 9) ] : '0'); // normalize to 0-9 (0 if expected accuracy < 0)
+
+ // increment for overall calculation
+ overall_acc += accuracy_pair.first;
+ overall_denom += accuracy_pair.second;
+
+ }
+
+ // cover case of no information for the alignment
+ if (overall_denom == 0.)
+ return std::make_pair (0., annot);
+
+ // normalize by number of (non-dead) columns
+ overall_acc /= overall_denom;
+ assert ((overall_acc >= 0.) && (overall_acc <= 1.00001));
+
+ return std::make_pair (overall_acc, annot);
+
+}
+
+float Alignment_DAG::expected_score (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, const float gap_factor) const {
+
+ float score = 0;
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+ if ((*col)->is_dead())
+ continue;
+ score += (*col)->expected_score (sparse_matrices, tree_weights, gap_factor, num_seqs);
+ }
+
+ return score;
+}
diff --git a/src/annealing/alignment_DAG.h b/src/annealing/alignment_DAG.h
new file mode 100644
index 0000000..d479467
--- /dev/null
+++ b/src/annealing/alignment_DAG.h
@@ -0,0 +1,742 @@
+
+/**
+ * \file alignment_DAG.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Ariel Schwartz and Robert Bradley.
+ * Sudeep Juvekar wrote the iterative refinement code do_lateral_refinement.
+ * Jaeyoung Do wrote the parallelization and database code.
+ */
+
+
+
+// to do:
+
+// - try converting dfs_f and dfs_b to a true postorder dfs
+// in order to return R_{forward,backward} in topological order
+// => avoid two sorts in reorder() ?
+
+
+
+/* Notes */
+
+// I have empirically observed that using the sort algorithm on a vector<Column*>
+// is *much* faster than using list<Column*>::sort. I have no idea why,
+// but it means that R_forward and R_backward had better be vectors!
+
+// If I decide that I want to keep track of ppv as well as ama (expected accuracy),
+// then add a member to Column and have update_weight_{tgf,maxstep} return a pair<p_match,p_gap>
+// so that I can update those on the fly.
+
+
+#ifndef ALIGNMENT_DAG_INCLUDED
+#define ALIGNMENT_DAG_INCLUDED
+
+#define ACCURACY_ANNOT "Accuracy"
+#define GUI_FILENAME_DAG_SUFFIX ".gui"
+#define GUI_FILENAME_PROB_SUFFIX ".probs"
+#define INVALID_EDGE -1e10 // to do: this could be fragile; replace with negative return value and test for that?
+
+#include <stack>
+#include <list>
+#include <map>
+#include <queue>
+#include <iostream>
+#include <algorithm>
+
+#include "config.h"
+#ifdef HAVE_TR1_UNORDERED_MAP
+#include <tr1/unordered_map>
+#endif
+
+#ifdef HAVE_TR1_UNORDERED_SET
+#include <tr1/unordered_set>
+#endif
+
+#include "util/hash_fcn.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+#include "annealing/SparseMatrix.h"
+#include "annealing/tree_weights.h"
+
+#include "manager/manager.h"
+
+namespace fsa {
+
+ // Note:
+ // All indexing of sequence data is 0-based here,
+ // but SparseMatrix uses 1-based indexing.
+
+ /**
+ * \brief (sequence, position) duple
+ */
+ typedef std::pair<size_t, unsigned> Seq_pos;
+
+ /**
+ * \brief Map of sequences to positions.
+ *
+ * I have experimented with using a hash_map instead,
+ * but observed better performance in practice with a standard map.
+ */
+ typedef std::map<size_t, unsigned> Seq_pos_map;
+
+
+ /**
+ * \brief Column of the alignment.
+ *
+ * These are the nodes of the DAG.
+ */
+ class Column {
+
+ private:
+
+ size_t index; ///< the position of the column in the alignment (0-based)
+ size_t orig_index; ///< the original index (when DAG first initialized)
+ Seq_pos_map seq_pos_map; ///< map of (seq_id,pos) pairs in the column
+ Column* merged_into; ///< the Column which this column has merged into
+ bool marked; ///< indicates if the column has been visited by the dfs
+ bool dead; ///< mark a column as dead (dropped from the DAG)
+
+ public:
+
+ static Manager* manager; ///< manager for database and MW
+
+ /**
+ * \brief Constructor.
+ *
+ * \param index the initial index of the column
+ */
+ Column (size_t index)
+ : index (index), orig_index (index),
+ merged_into (this), marked (false), dead (false)
+ { }
+
+ /**
+ * \brief Compares two columns based on their current indices.
+ *
+ */
+ bool operator< (Column const &r) const {
+ return (index < r.index);
+ }
+
+ /**
+ * \brief Compares two columns based on their current indices.
+ *
+ */
+ bool operator== (Column const &r) const {
+ return (index == r.index);
+ }
+
+ /**
+ * \brief Number of sequences in column.
+ *
+ */
+ inline size_t size() const {
+ return seq_pos_map.size();
+ }
+
+ /**
+ * \brief Has the column has been marked as visited?
+ *
+ */
+ inline bool is_marked() const {
+ return marked;
+ }
+
+ /**
+ * \brief Mark the column as visited.
+ *
+ */
+ inline void mark() {
+ marked = true;
+ }
+
+ /**
+ * \brief Unmark the column as visited.
+ *
+ */
+ inline void unmark() {
+ marked = false;
+ }
+
+ /**
+ * \brief Is the column dead?
+ *
+ */
+ inline bool is_dead() const {
+ return dead;
+ }
+
+ /**
+ * \brief Mark the column as dead.
+ *
+ * Columns are marked as dead when they have been merged into another column
+ * (ie, the node which they represent is no longer present in the DAG).
+ */
+ inline void set_dead() {
+ dead = true;
+ }
+
+ /**
+ * \brief Returns the current index of the column.
+ *
+ * The index of the column is its position in the total order specified by the alignment.
+ * 0-based.
+ */
+ inline size_t get_index() const {
+ return index;
+ }
+
+ /**
+ * \brief Set the index.
+ *
+ */
+ inline void set_index (const size_t idx) {
+ index = idx;
+ }
+
+ /**
+ * \brief Returns the original index of the column.
+ *
+ */
+ inline const size_t get_orig_index() const {
+ return orig_index;
+ }
+
+ /**
+ * \brief Get the Column* which this column has been merged into.
+ *
+ */
+ inline Column* get_merged_into() const {
+ return merged_into;
+ }
+
+ /**
+ * \brief Set the Column* which this column has been merged into.
+ *
+ */
+ inline void set_merged_into (Column* col) {
+ merged_into = col;
+ }
+
+ /**
+ * \brief Get the sequence positions represented by this column.
+ *
+ */
+ inline const Seq_pos_map& get_seq_pos_map() const {
+ return seq_pos_map;
+ }
+
+ /**
+ * \brief Does this column contain a particular sequence?
+ */
+ inline bool contains_seq (const size_t i) const {
+ return seq_pos_map.find (i) != seq_pos_map.end();
+ }
+
+ /**
+ * \brief Add a sequence position.
+ *
+ */
+ inline void add_seq_pos (const Seq_pos& seq_pos) {
+ seq_pos_map.insert (seq_pos);
+ }
+
+ /**
+ * \brief Remove the entry for a particular sequence.
+ */
+ inline void erase_seq_pos (const size_t seq) {
+ if (seq_pos_map.erase (seq) != 1)
+ THROWEXPR ("Invalid attempt to erase a (sequence, position) pair.");
+ }
+
+ /**
+ * \brief Get the expected accuracy of the column.
+ *
+ * Normalization is by the sum-of-pairs number of characters in the column
+ * (but only if we have posterior information available for a pair).
+ * Note that the denominator has to be a float due to the weights.
+ * \param tree_weights weights for sequence pairs during annealing
+ * \return (numerator, denominator)
+ */
+ std::pair<float, float> get_accuracy_normalized (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, const size_t num_seqs) const;
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Column& col) {
+
+ o << "column " << col.index << ": ";
+
+ const Seq_pos_map seqs = col.seq_pos_map;
+ // catch case of empty (all gaps) column
+ if (seqs.begin() == seqs.end()) {
+ return o;
+ }
+ // else display aligned characters
+ Seq_pos_map::const_iterator iter = seqs.begin();
+ o << "(" << iter->first << ", " << iter->second << ")";
+ for (++iter; iter != seqs.end(); ++iter)
+ o << " ~ (" << iter->first << ", " << iter->second << ")";
+
+ return o;
+ }
+
+ /**
+ * \brief Get the expected sum-of-pairs score of this column.
+ *
+ * Calculates the value of the objective function
+ * (accuracy modified by the gap factor) for this column.
+ * \param tree_weights weights for sequence pairs during annealing
+ * \param gap_factor gap factor
+ * @see change_in_expected_score
+ */
+ float expected_score (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor, size_t num_seqs) const;
+
+ /**
+ * \brief Get the change in expected sum-of-pairs score from aligning a character here.
+ *
+ * Given a character (sequence and position seq_pos) which is not aligned in this column,
+ * returns the /change/ in expected value of the objective function (accuracy modified by gap factor)
+ * associated with aligning the character as part of this column.
+ * Note that we can use this function to calculate the expected change resulting from
+ * removing seq_pos from this column, calculating the expected change, and re-adding,
+ * even when seq_pos already is aligned in this column, by setting skip_seq_pos = true.
+ * \param seq_pos a character (sequence, position) which isn't aligned in this column
+ * \param tree_weights weights for sequence pairs during annealing
+ * \param gap_factor gap factor
+ * \param skip_seq_pos if false, then return INVALID_EDGE if the character is already present in the column; else ignore
+ * \return INVALID_EDGE if there already is a character from the sequence in seq_pos aligned here
+ */
+ float change_in_expected_score (const Seq_pos& seq_pos, std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor, size_t num_seqs, bool skip_seq_pos = false) const;
+
+ };
+
+ /**
+ * \brief Edge between two columns.
+ *
+ * Store information about a candidate edge (between columns, i.e., nodes of the DAG).
+ * Calculates edge weights.
+ */
+ class Edge {
+
+ public:
+
+ Column* source; ///< source column (outgoing edge)
+ Column* dest; ///< destination column (incoming edge)
+ float weight; ///< column weight
+
+ unsigned short weight_size; ///< size of source and dest when the weight was last calculated
+
+ static Manager* manager; ///< manager for database and MW
+
+ /**
+ * \brief Constructor.
+ *
+ * \param source source column
+ * \param dest dest column
+ * \param weight weight of the edge
+ */
+ Edge (Column* source, Column* dest,
+ float weight, unsigned short weight_size)
+ : source (source), dest (dest),
+ weight (weight), weight_size (weight_size)
+ { }
+
+ /**
+ * \brief If requested, updates weight based on tgf.
+ *
+ * Updates change in expected sum-of-pairs score (accuracy modified by gap factor)
+ * from adding the edge.
+ * Note that while annealing with tgf weights is a true steepest ascent algorithm,
+ * the updated weights can increase iff the edge is inconsistent
+ * (in this case the steepest ascent condition doesn't apply, since it's only
+ * a guarantee for accepted edges).
+ * \param tree_weights weights for sequence pairs during annealing
+ * \param update_weight update weight of the edge
+ * \return true if inconsistent edge
+ */
+ bool update_weight_tgf (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, bool update_weight = true);
+
+ /**
+ * \brief If requested, updates weight based on maxstep.
+ *
+ * Updates change in expected sum-of-pairs score (accuracy modified by gap factor)
+ * from adding the edge.
+ * \param tree_weights weights for sequence pairs during annealing
+ * \param update_weight update weight of the edge
+ * \return true if inconsistent edge
+ */
+ bool update_weight_maxstep (std::vector<std::vector<SparseMatrix *> >& sparse_matrices, const Tree_weights& tree_weights, float gap_factor, bool update_weight = true);
+
+ /**
+ * \brief Compare two edges based on their weights.
+ */
+ bool operator< (Edge const e2) const {
+ return weight < e2.weight;
+ }
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<<(std::ostream& o,const Edge& edge) {
+ o << *edge.source << " -> " << *edge.dest << "; weight = " << edge.weight;
+ return o;
+ }
+
+ /**
+ * \brief Does the weight need to be updated?
+ * \return true if the source or dest column has changed size since the weight was last calculated
+ */
+ inline bool weight_outdated() const {
+ return (weight_size != (source->size() + dest->size()));
+ }
+
+ /**
+ * \brief Output for GUI.
+ *
+ * Only for use after calling add_edge();
+ * assumes that source and dest of this edge have been reset with get_merged_into().
+ */
+ inline void write_gui_output (std::ostream& o) {
+ assert (source->get_merged_into() == source);
+ assert (dest->get_merged_into() == source);
+ o << source->get_orig_index() << " -> " << dest->get_orig_index() << endl;
+ }
+
+ };
+
+
+ /**
+ * \brief Function object for defining a binary comparison operator for column pointers.
+ *
+ * Comparison is based on the corresponding columns' indices.
+ * @see Column::operator<().
+ */
+ class greater_index : std::binary_function<Column*, Column*, bool> {
+ public:
+ bool operator() (Column* x, Column* y) const { return (*y < *x); }
+ };
+
+ /**
+ * \brief Function object for defining a binary comparison operator for column pointers.
+ *
+ * Comparison is based on the corresponding columns' indices.
+ * @see Column::operator<().
+ */
+ class smaller_index : std::binary_function<Column*, Column*, bool> {
+ public:
+ bool operator() (Column* x, Column* y) const { return (*x < *y); }
+ };
+
+ /**
+ * \brief Function object for defining a binary comparison operator for column pointers.
+ *
+ * Comparison is based on the corresponding edges' weights.
+ */
+ class smaller_weight : std::binary_function<Edge*, Edge*, bool> {
+ public:
+ bool operator() (Edge* x, Edge* y) const { return (x->weight < y->weight); }
+ };
+
+ /**
+ * \brief Function object for hashing pairs of columns.
+ *
+ * Cast to 64-bit representation (even though may actually be a 32-bit representation
+ * on many systems) for safety.
+ */
+ class column_pair_hash : std::unary_function<std::pair<Column*, Column*>, bit64_t> {
+ public:
+ bit64_t operator() (std::pair<Column*, Column*> col_pair) const {
+ return Hash_functions::bit64_t_pair_hash (reinterpret_cast<bit64_t> (col_pair.first), reinterpret_cast<bit64_t> (col_pair.second));
+ }
+ };
+
+ /**
+ * \brief Map a position in a sequence to the containing Column*.
+ */
+ typedef std::vector<Column*> Seq_pos_col_map;
+
+ /**
+ * \brief Map a sequence position to the containing Column*.
+ *
+ * Indexed by [sequence][position].
+ */
+ typedef std::vector<Seq_pos_col_map > Seq_pos_col_maps;
+
+ /**
+ * \brief Store a multiple alignment as a DAG and perform sequence annealing.
+ *
+ * Imposes a total order on the DAG at all times with
+ * an explicit vector representation of the columns.
+ */
+ class Alignment_DAG {
+
+ private:
+
+ std::vector<Column*> columns; ///< the current columns of the alignment
+ Seq_pos_col_maps seq_pos_col_maps; ///< mapping from sequence positions pair<seq, pos> to the containing Column*
+
+ const Sequence_database& seq_db; ///< sequence data
+ size_t num_seqs; ///< number of sequences in the alignment
+ size_t num_columns; ///< number of columns in the alignment
+
+ public:
+
+ /**
+ * \brief Constructor.
+ *
+ * Initialize alignment DAG to the null alignment.
+ * Initializes to the "maximal chain decomposition" null alignment,
+ * which imposes the total order corresponding to a chain decomposition
+ * where the number of chains is maximized.
+ * This also corresponds to maximizing the possible number of gap-opens.
+ */
+ Alignment_DAG (const Sequence_database& seq_db);
+
+ /**
+ * \brief Constructor.
+ *
+ * Initialize alignment DAG to the passed Stockholm alignment.
+ */
+ Alignment_DAG (const Sequence_database& seq_db, const Stockholm& stock);
+
+ /**
+ * \brief Destructor.
+ */
+ ~Alignment_DAG();
+
+ /**
+ * \brief Get the columns of the alignment.
+ */
+ const std::vector<Column*>& get_columns() const {
+ return (*this).columns;
+ }
+
+ /**
+ * \brief Drop all-gaps columns of the alignment.
+ */
+ void drop_all_gaps_columns();
+
+ /**
+ * \brief Depth-first search for toplogical sorting a la Tarjan.
+ *
+ * Computes the Dilworth chain decomposition for the graph.
+ * Uses a non-recursive (external stack-based) implementation of a postorder traversal of the graph.
+ * Pretty tricky.
+ */
+ void dfs_topological_sort();
+
+ /**
+ * \brief Perform sequence annealing with an equidistant star phylogeny.
+ *
+ * All sequence pairs are weighted equally.
+ * \param sparse_matrices pairwise posterior probabilities
+ * \param manager database manager
+ * \param use_tgf use tgf instead of maxstep weighting
+ * \param gap_factor gap factor
+ * \param enable_dynamic_weights re-weight edges after merges
+ * \param edge_weight_threshold the threshold for accepting edges
+ * \param output_for_gui write GUI-formatted output to disk
+ * \param gui_prefix prefix for GUI filename
+ */
+ void anneal (std::vector<std::vector<SparseMatrix*> >& sparse_matrices,
+ Manager& manager,
+ const bool use_tgf,
+ const float gap_factor, const bool enable_dynamic_weights, const float edge_weight_threshold,
+ const size_t num_refinement_steps,
+ const bool output_for_gui, const std::string gui_prefix);
+
+
+ /**
+ * \brief Perform sequence annealing using sequence pair weights.
+ *
+ * \param sparse_matrices pairwise posterior probabilities
+ * \param tree_weights weights for sequence pairs during annealing
+ * \param manager database manager
+ * \param use_tgf use tgf instead of maxstep weighting
+ * \param gap_factor gap factor
+ * \param enable_dynamic_weights re-weight edges after merges
+ * \param edge_weight_threshold the threshold for accepting edges
+ * \param output_for_gui write GUI-formatted output to disk
+ * \param gui_prefix prefix for GUI filename
+ */
+ void anneal (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights,
+ Manager& manager,
+ const bool use_tgf,
+ const float gap_factor, const bool enable_dynamic_weights, const float edge_weight_threshold,
+ const size_t num_refinement_steps,
+ const bool output_for_gui, const std::string gui_prefix);
+
+ /**
+ * \brief Display the DAG in human-readable format.
+ *
+ * Show the current total order.
+ * If aligned_only, then only show columns with aligned characters.
+ */
+ void show (std::ostream& o, bool aligned_only = false) const;
+
+ /**
+ * \brief Get the Stockholm object corresponding to the current alignment.
+ *
+ * Mark up with unnormalized column accuracy scores.
+ * \param dilworth_resort impose a total order corresponding to a minimal chain decompostion of the DAG
+ */
+ Stockholm get_stockholm() const;
+
+ /**
+ * \brief Get the Stockholm object corresponding to the current alignment.
+ *
+ * Mark up with normalized column accuracy scores.
+ * \param tree_weights weights for sequence pairs during annealing
+ */
+ Stockholm get_stockholm (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights) const;
+
+
+ private:
+
+ /**
+ * \brief Get the Column* specified by seq_pos.
+ */
+ inline Column* get_seq_pos_col (const Seq_pos& seq_pos) const {
+ assert ((seq_pos.first >= 0) && (seq_pos.first < seq_pos_col_maps.size()));
+ assert ((seq_pos.second >= 0) && (seq_pos.second < seq_pos_col_maps[seq_pos.first].size()));
+ assert (seq_pos_col_maps[seq_pos.first][seq_pos.second] != 0);
+
+ return seq_pos_col_maps[seq_pos.first][seq_pos.second];
+ }
+
+ /**
+ * \brief Set the Column* specified by seq_pos.
+ */
+ inline void set_seq_pos_col (const Seq_pos& seq_pos, Column* col) {
+ assert ((seq_pos.first >= 0) && (seq_pos.first < seq_pos_col_maps.size()));
+ assert ((seq_pos.second >= 0) && (seq_pos.second < seq_pos_col_maps[seq_pos.first].size()));
+
+ seq_pos_col_maps[seq_pos.first][seq_pos.second] = col;
+ }
+
+ /**
+ * \brief Output for GUI.
+ *
+ * Should only be called before annealing begins.
+ * \param show_edges show edges of the DAG
+ */
+ void write_gui_output (std::ostream& o, const bool show_edges = false) const;
+
+ /**
+ * \brief Forward depth-first search of the Pearce-Kelly algorithm.
+ *
+ * Search forwards, ie in the direction from l_bound to upper bound.
+ * Look for cycles in the graph, ie a path l_bound ~> u_bound.
+ * Store visited nodes (columns) in R_forward.
+ * Non-recursive (external stack-based) implementation of DFS.
+ * Note that the traversal is neither preorder nor postorder, but rather something arbitrary
+ * (because the columns reached by the iteration over sequence positions
+ * won't be sorted w.r.t. the total order of the DAG).
+ * \param l_bound lower bound of the DFS
+ * \param u_bound upper bound of the DFS
+ * \param R_forward visited nodes
+ */
+ bool dfs_f (Column* l_bound, Column* u_bound, std::vector<Column*>& R_forward);
+
+ /**
+ * \brief Backward depth-first search of the Pearce-Kelly algorithm.
+ *
+ * Searches backwards, ie in the direction from u_bound to u_bound.
+ * Store visited nodes (columns) in R_backward.
+ * Non-recursive (external stack-based) implementation of DFS.
+ * Note that the traversal is neither preorder nor postorder, but rather something arbitrary
+ * (because the columns reached by the iteration over sequence positions
+ * won't be sorted w.r.t. the total order of the DAG).
+ * \param l_bound lower bound of the (backward) DFS
+ * \param u_bound upper bound of the (backward) DFS
+ * \param R_backward visited nodes
+ */
+ void dfs_b (Column* u_bound, Column* l_bound, std::vector<Column*>& R_backward);
+
+ /**
+ * \brief Reorder procedure of the Pearce-Kelly algorithm.
+ *
+ * \param R_forward nodes reached by a forward DFS
+ * \param R_backward nodes reached by a backward DFS
+ */
+ void reorder (std::vector<Column*>& R_forward, std::vector<Column*>& R_backward);
+
+ /**
+ * \brief Unmark all columns in the vector.
+ *
+ * \param cols columns to unmark
+ */
+ void unmark (std::vector<Column*>& cols);
+
+ /**
+ * \brief Check whether a candidate edge induces a cycle.
+ *
+ * Performs cycle-checking with a forward DFS from the destination node.
+ * Stores nodes reached by the forward DFS in R_forward for
+ * later use by add_edge.
+ * \param edge edge to add
+ * \param l_bound lower bound on DFS
+ * \param u_bound upper bound on DFS
+ * \param R_forward nodes reached by forward DFS
+ * \see dfs_f
+ */
+ bool induces_cycle (Edge* edge, Column* l_bound, Column* u_bound, std::vector<Column*>& R_forward);
+
+ /**
+ * \brief Merge the source and dest columns of the edge into the source column.
+ *
+ * \param edge edge to merge
+ */
+ void merge (Edge* edge);
+
+ /**
+ * \brief Add a new edge to the alignment DAG.
+ *
+ * \param edge edge to add
+ * \param l_bound lower bound on DFS
+ * \param u_bound upper bound on DFS
+ * \param R_forward nodes reached by forward DFS
+ */
+ void add_edge (Edge* edge, Column* l_bound, Column* u_bound, std::vector<Column*>& R_forward);
+
+ /**
+ * \brief Perform one iteration of lateral refinement.
+ *
+ * Iterate through all columns of the alignment, re-aligning characters
+ * according to the per-column change in expected accuracy.
+ * \param tree_weights weights for sequence pairs during annealing
+ */
+ void do_lateral_refinement (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, const float gap_factor);
+
+ /**
+ * \brief Get the overall and per-column normalized expected accuracy (formatted as a string for #=GC annotation).
+ *
+ * The sparse matrices are necessary for calculating the denominator for normalization.
+ * \param tree_weights weights for sequence pairs during annealing
+ */
+ std::pair<float, std::string> get_accuracy_annotation_normalized (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights) const;
+
+ /**
+ * \brief Get the expected sum-of-pairs score of the alignment.
+ *
+ * Calculates the value of the objective function (accuracy modified by the gap factor)
+ * over all columns.
+ * \param tree_weights weights for sequence pairs during annealing
+ */
+ float expected_score (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const Tree_weights& tree_weights, const float gap_factor) const;
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o,const Alignment_DAG& dag) {
+ for (std::vector<Column*>::const_iterator iter = dag.columns.begin(); iter != dag.columns.end(); ++iter)
+ o << **iter << endl;
+ return o;
+ }
+
+ };
+
+}
+
+#endif /* ALIGNMENT_DAG_INCLUDED */
diff --git a/src/annealing/dotplot.cc b/src/annealing/dotplot.cc
new file mode 100644
index 0000000..d9fcb9f
--- /dev/null
+++ b/src/annealing/dotplot.cc
@@ -0,0 +1,53 @@
+
+/**
+ * \file dotplot.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Ian Holmes, Lars Barquist and Robert Bradley.
+ */
+
+#include "dotplot.h"
+
+using namespace fsa;
+
+Dotplot::Dotplot (const Sequence& x, const Sequence& y)
+ : array2d<double> (x.length(), y.length(), 0.), xseq (x.name), yseq (y.name)
+{ }
+
+void Dotplot::write_dotplot (const std::string& filename, const double cutoff /* = PROB_DISPLAY_CUTOFF */) const
+{
+ std::ofstream file (filename.c_str());
+ if (!file)
+ THROWEXPR ("ERROR: Couldn't create dotplot file with name '" << filename << "'.");
+ // print horizontal sequence axis labels
+ file << ".";
+ for (unsigned x = 0; x < xseq.size(); ++x)
+ file << ' ' << xseq[x];
+ file << '\n';
+ // print rows
+ for (unsigned y = 0; y < yseq.size(); ++y) {
+ file << yseq[y];
+ for (unsigned x = 0; x < xseq.size(); ++x) {
+ const double& p = (*this) (x, y);
+ file << ' ' << (p < cutoff ? '0' : p);
+ }
+ file << '\n';
+ }
+
+ file.close();
+}
+
+
+void Dotplot::write_dotplot (const std::string& prefix, const std::string& seqname, const double cutoff /* = PROB_DISPLAY_CUTOFF */) const
+{
+ std::string filename;
+ filename += prefix + '-' + seqname;
+ write_dotplot (filename, cutoff);
+}
+
+void Dotplot::write_dotplot (const std::string& prefix, const std::string& xseqname, const std::string& yseqname, const double cutoff /* = PROB_DISPLAY_CUTOFF */) const
+{
+ std::string filename;
+ filename += prefix + '-' + xseqname + '-' + yseqname;
+ write_dotplot (filename, cutoff);
+}
+
diff --git a/src/annealing/dotplot.h b/src/annealing/dotplot.h
new file mode 100644
index 0000000..2a9c430
--- /dev/null
+++ b/src/annealing/dotplot.h
@@ -0,0 +1,62 @@
+
+/**
+ * \file dotplot.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Ian Holmes, Lars Barquist and Robert Bradley.
+ */
+
+#ifndef DOTPLOT_INCLUDED
+#define DOTPLOT_INCLUDED
+
+#define PROB_DISPLAY_CUTOFF 0.01
+
+#include "util/misc.h"
+#include "util/array2d.h"
+#include "seq/sequence.h"
+
+namespace fsa {
+
+ /**
+ * \brief Base class for probability matrices.
+ *
+ * Both alignment and fold (for e.g. Pair SCFGs) dotplots inherit from this class.
+ */
+ struct Dotplot : array2d<double> {
+
+ std::string xseq; ///< x axis label
+ std::string yseq; ///< y axis label
+
+ Dotplot (size_t x, size_t y)
+ : array2d<double> (x, y, 0.) { }
+
+ /**
+ * \brief Constructor.
+ */
+ Dotplot (const Sequence& x, const Sequence& y);
+
+ /**
+ * \brief Output method.
+ *
+ * For e.g. alignment dotplots, output is formatted as:
+ * <cruft>
+ * . x1 x2 x3
+ * y1 .2 .2 .2
+ * y2 .2 .2 .2
+ */
+ void write_dotplot (const std::string& filename, const double cutoff = PROB_DISPLAY_CUTOFF) const;
+
+ /**
+ * \brief Output method for fold dotplots.
+ */
+ void write_dotplot (const std::string& prefix, const std::string& seqname, const double cutoff = PROB_DISPLAY_CUTOFF) const;
+
+ /**
+ * \brief Output method for alignment dotplots.
+ */
+ void write_dotplot (const std::string& prefix, const std::string& xseqname, const std::string& yseqname, const double cutoff = PROB_DISPLAY_CUTOFF) const;
+
+ };
+
+}
+
+#endif /*DOTPLOT_INCLUDED*/
diff --git a/src/annealing/tree_weights.cc b/src/annealing/tree_weights.cc
new file mode 100644
index 0000000..6da396c
--- /dev/null
+++ b/src/annealing/tree_weights.cc
@@ -0,0 +1,100 @@
+
+/**
+ * \file tree_weights.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include "util/logfile.h"
+#include "annealing/tree_weights.h"
+
+using namespace fsa;
+
+const double Tree_weights::min_sequence_weight = 0.000001;
+
+void Tree_weights::from_file (const Sequence_database& seq_db, const std::string& filename) {
+
+ // mark populated
+ __populated = true;
+
+ // initialize all weights to 0.0
+ __weights.assign (seq_db.size(), std::vector<float> (seq_db.size(), 0.0));
+
+ // read in weights from file
+ std::ifstream filestream (filename.c_str(), std::ifstream::in);
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't open file '" << filename << "'.");
+
+ std::string line;
+ while (!filestream.eof()) {
+ getline (filestream, line);
+ Util::chomp (line);
+ if (!line.length())
+ continue;
+
+ // log
+ if (CTAGGING(-1,TREE_WEIGHTS))
+ CL << line;
+ std::string buffer;
+ // skip comments and sequence names
+ std::stringstream ss (line);
+ std::vector<std::string> tokens; // vector to hold whitespace-separated tokens (words)
+ while (ss >> buffer)
+ tokens.push_back (buffer);
+
+ // skip lines which we don't understand
+ if (tokens.size() != 3) {
+ CTAG(8,ANNEALING) << "WARNING: I'm skipping unparseable line '" << line << "'" << endl;
+ continue;
+ }
+ else if (tokens[0] == tokens[1])
+ THROWEXPR ("ERROR: A sequence can't have a weight with itself!" << endl << line << endl);
+
+ // format is:
+ // seqX seqY weight
+ // symmetrize as we go
+ if (!seq_db.exists_seq (tokens[0]) || !seq_db.exists_seq (tokens[1]))
+ THROWEXPR ("ERROR: No sequence pair '" << tokens[0] << "' and '" << tokens[1] << "' in sequence file.");
+ const size_t i = seq_db.get_seq_index (tokens[0]);
+ const size_t j = seq_db.get_seq_index (tokens[1]);
+ __weights[i][j] = __weights[j][i] = static_cast<float> (atof (tokens[2].c_str()));
+
+ }
+
+ // normalize weights
+ normalize();
+
+ CTAG(9,ANNEALING) << "Read sequence pair weights from file '" << filename << "'." << endl;
+
+}
+
+void Tree_weights::normalize() {
+
+ const size_t num_seqs = __weights.size();
+ const size_t num_seq_pairs = num_seqs * (num_seqs - 1) / 2;
+
+ std::vector<double> seqtotal (num_seqs, 0.0); // total for single sequences
+ double total = 0.0; // total for all sequence pairs
+ for (size_t i = 0; i < num_seqs; ++i) {
+ for (size_t j = i + 1; j < num_seqs; ++j) {
+ seqtotal[i] += __weights[i][j];
+ seqtotal[j] += __weights[i][j];
+ total += __weights[i][j];
+ }
+ }
+ for (size_t i = 0; i < num_seqs; ++i) {
+ if (seqtotal[i] < Tree_weights::min_sequence_weight)
+ THROWEXPR ("ERROR: Weights for sequence " << i << " are too small; the sequence will be left unaligned.");
+ }
+
+ if (total < num_seqs * Tree_weights::min_sequence_weight)
+ THROWEXPR ("ERROR: Sequence pair weights are too small for reliable use.");
+
+ const double scaling = num_seq_pairs / total;
+ for (size_t i = 0; i < num_seqs; ++i) {
+ for (size_t j = i + 1; j < num_seqs; ++j)
+ __weights[i][j] *= scaling;
+ }
+
+}
+
diff --git a/src/annealing/tree_weights.h b/src/annealing/tree_weights.h
new file mode 100644
index 0000000..8ade11c
--- /dev/null
+++ b/src/annealing/tree_weights.h
@@ -0,0 +1,96 @@
+
+/**
+ * \file tree_weights.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+// to do:
+// -
+
+#ifndef ANNEALING_TREE_WEIGHTS_INCLUDED
+#define ANNEALING_TREE_WEIGHTS_INCLUDED
+
+#include <iostream>
+#include <map>
+
+#include "util/hash_fcn.h"
+#include "seq/sequence.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a set of (symmetric) weights for sequence pairs.
+ *
+ * Generally these weights will be derived using a tree relating
+ * the sequences.
+ * If used as an "empty class," without calling the method from_file
+ * to populate the data structures, then the weights will all be set to 1.
+ * This allows the method get_weight to be used transparently both when
+ * weights are given and when they are not.
+ */
+ struct Tree_weights {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ *
+ * Returns all weights as 1 until populated with from_file.
+ */
+ Tree_weights()
+ : __populated (false)
+ { }
+
+ /**
+ * \brief Read weights from a file.
+ *
+ * Unless particular weights are present in the file,
+ * sets them to 0. Assumes that weights are symmetric,
+ * i.e., that weight (i, j) == weight (j, i).
+ */
+ void from_file (const Sequence_database& seq_db, const std::string& filename);
+
+ /**
+ * \brief Normalize the weights such that they sum to (N choose 2).
+ *
+ * (N choose 2) is the number of iterations in a sum-of-pairs
+ * operation over N sequences.
+ */
+ void normalize();
+
+ /**
+ * \brief Get the weight for a particular sequence pair.
+ *
+ * This function can be called on an empty instance of this class,
+ * i.e., one for which the data structures have not been populated.
+ * If they have not been, then all weights returned will be 1.
+ * \param i index of first sequence
+ * \param j index of second sequence
+ * \return weight of pair, or 0 if undefined (or always 1 if used as an empty class)
+ */
+ inline float operator() (const size_t i, const size_t j) const;
+
+ static const double min_sequence_weight; ///< minimum weight for a sequence (summed over pairs)
+
+
+ private:
+
+ bool __populated; ///< have we read input data? (all weights = 1 unless true)
+ std::vector<std::vector<float> > __weights; ///< weights for each sequence pair
+
+ };
+
+ inline float Tree_weights::operator() (const size_t i, const size_t j) const {
+ // return 1 if we haven't populated the weights
+ if (!__populated)
+ return 1.0;
+ // else look up the appropriate weighta
+ assert (i < __weights.size());
+ assert (j < __weights[i].size());
+ return __weights[i][j];
+ }
+
+}
+
+#endif /* ANNEALING_TREE_WEIGHTS_INCLUDED */
diff --git a/src/fsa/Makefile.am b/src/fsa/Makefile.am
new file mode 100644
index 0000000..91ae267
--- /dev/null
+++ b/src/fsa/Makefile.am
@@ -0,0 +1,37 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src -Wno-deprecated
+
+# AM_CXXFLAGS = -finline-limit=10000 --param inline-unit-growth=70
+# Commented out b/c was causing bugs on some older compilers.
+# --RKB & CD 4/14/09
+
+if HAVE_CONDOR
+AM_CPPFLAGS += -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+endif
+
+noinst_LIBRARIES = libfsa.a
+
+libfsa_a_SOURCES = \
+ algebras.cc \
+ aminoacid_indel2dp.cc \
+ aminoaciddp.cc \
+ anchors.cc \
+ constraints.cc \
+ fsa.cc \
+ model.cc \
+ nucleotide_indel2dp.cc \
+ nucleotidedp.cc \
+ sequence_pair_selector.cc
+
+noinst_HEADERS = \
+ algebras.h \
+ aminoacid_indel2dp.h \
+ aminoaciddp.h \
+ anchors.h \
+ constraints.h \
+ dptables.h \
+ fsa.h \
+ model.h \
+ mybanding.h \
+ nucleotide_indel2dp.h \
+ nucleotidedp.h \
+ sequence_pair_selector.h
diff --git a/src/fsa/Makefile.in b/src/fsa/Makefile.in
new file mode 100644
index 0000000..fc1c872
--- /dev/null
+++ b/src/fsa/Makefile.in
@@ -0,0 +1,583 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+
+# AM_CXXFLAGS = -finline-limit=10000 --param inline-unit-growth=70
+# Commented out b/c was causing bugs on some older compilers.
+# --RKB & CD 4/14/09
+ at HAVE_CONDOR_TRUE@am__append_1 = -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+subdir = src/fsa
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_ at AM_V@)
+am__v_AR_ = $(am__v_AR_ at AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libfsa_a_AR = $(AR) $(ARFLAGS)
+libfsa_a_LIBADD =
+am_libfsa_a_OBJECTS = algebras.$(OBJEXT) aminoacid_indel2dp.$(OBJEXT) \
+ aminoaciddp.$(OBJEXT) anchors.$(OBJEXT) constraints.$(OBJEXT) \
+ fsa.$(OBJEXT) model.$(OBJEXT) nucleotide_indel2dp.$(OBJEXT) \
+ nucleotidedp.$(OBJEXT) sequence_pair_selector.$(OBJEXT)
+libfsa_a_OBJECTS = $(am_libfsa_a_OBJECTS)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(libfsa_a_SOURCES)
+DIST_SOURCES = $(libfsa_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src -Wno-deprecated $(am__append_1)
+noinst_LIBRARIES = libfsa.a
+libfsa_a_SOURCES = \
+ algebras.cc \
+ aminoacid_indel2dp.cc \
+ aminoaciddp.cc \
+ anchors.cc \
+ constraints.cc \
+ fsa.cc \
+ model.cc \
+ nucleotide_indel2dp.cc \
+ nucleotidedp.cc \
+ sequence_pair_selector.cc
+
+noinst_HEADERS = \
+ algebras.h \
+ aminoacid_indel2dp.h \
+ aminoaciddp.h \
+ anchors.h \
+ constraints.h \
+ dptables.h \
+ fsa.h \
+ model.h \
+ mybanding.h \
+ nucleotide_indel2dp.h \
+ nucleotidedp.h \
+ sequence_pair_selector.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/fsa/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/fsa/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libfsa.a: $(libfsa_a_OBJECTS) $(libfsa_a_DEPENDENCIES) $(EXTRA_libfsa_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libfsa.a
+ $(AM_V_AR)$(libfsa_a_AR) libfsa.a $(libfsa_a_OBJECTS) $(libfsa_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libfsa.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/algebras.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aminoacid_indel2dp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aminoaciddp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/anchors.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/constraints.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/fsa.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/model.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nucleotide_indel2dp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nucleotidedp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sequence_pair_selector.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/fsa/algebras.cc b/src/fsa/algebras.cc
new file mode 100644
index 0000000..202b2e8
--- /dev/null
+++ b/src/fsa/algebras.cc
@@ -0,0 +1,52 @@
+/*
+ * This file is part of HMMoC 1.3, a hidden Markov model compiler.
+ * Copyright (C) 2007 by Gerton Lunter, Oxford University.
+ *
+ * HMMoC 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * HMMOC 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 HMMoC; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+\*/
+//
+// algebras.cc - extended real types
+//
+// Gerton Lunter, 27/8/04
+//
+//
+
+
+#include "algebras.h"
+
+
+BFMantissa *BFloat::aConversionLookup; // Actual location of the static members of BFloat class
+double *BFloat::aDoubleConversionLookup;
+
+
+_BFloatInitialize _dummyInitializer; // This initializes aConversionLookup and aDoubleConversionLookup
+
+
+_BFloatInitialize::_BFloatInitialize() {
+
+ BFloat::aConversionLookup = new BFMantissa[cBFloatConvTableSize];
+ BFloat::aDoubleConversionLookup = new double[cBFloatDoubleConvTableSize];
+
+ BFMantissa iBFM = 1.0;
+ for (int i = 0; i < cBFloatConvTableSize; i++) {
+ BFloat::aConversionLookup[ i ] = iBFM;
+ iBFM *= cBFloatRangeInv;
+ }
+
+ for (int i = 0; i < cBFloatDoubleConvTableSize; i++) {
+ BFloat::aDoubleConversionLookup[ i ] = exp( (i-cBFloatDoubleConvTableSize/2) * logcBFloatRange );
+ }
+
+}
diff --git a/src/fsa/algebras.h b/src/fsa/algebras.h
new file mode 100644
index 0000000..9fe5723
--- /dev/null
+++ b/src/fsa/algebras.h
@@ -0,0 +1,554 @@
+/*
+ * This file is part of HMMoC 1.3, a hidden Markov model compiler.
+ * Copyright (C) 2007 by Gerton Lunter, Oxford University.
+ *
+ * HMMoC 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * HMMOC 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 HMMoC; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+\*/
+//
+// algebras.h - extended real types
+//
+// Gerton Lunter, 27/8/04
+//
+
+#ifndef _algebras_h_
+#define _algebras_h_
+
+#include <ctype.h>
+#include <cstdlib>
+#include <cmath>
+#include <iostream>
+#include <limits>
+#include <string>
+#include <vector>
+
+// below changed to avoid polluting the global namespace
+// -- RKB 12/20/08
+//using namespace std;
+using std::cerr;
+using std::cout;
+using std::endl;
+using std::string;
+using std::vector;
+
+// typedefs
+typedef float BFMantissa;
+const BFMantissa cBFloatRange = 20282409603651670423947251286016.0; // 2.03e+31; 2^104
+const BFMantissa cBFloatRangeInv = 1.0/cBFloatRange;
+// Aaron E. Darling 6/7/7: need to typecast to avoid compiler warnings about imprecise FP representations
+const BFMantissa cBFloatRangeSqrt = (BFMantissa)1.0e+18; // Value between square root of the exponent, and the exponent
+const BFMantissa cBFloatRangeInvSqrt = (BFMantissa)1.0e-18; // Square of this should still be representable, with full mantissa!
+const BFMantissa logcBFloatRange = log(cBFloatRange);
+const int cBFloatDigits = 7; // Number of significant digits for printing (7 for floats, 16 for doubles?)
+const int cBFloatInfinity = 1000000000; // Tiniest number representable is cBFloatRangeInv ^ BFloatInfinity
+const int cBFloatConvTableSize = 100; // This includes many zero entries, it makes additions a bit faster
+const int cBFloatDoubleConvTableSize = 50; // Table size for bfloat -> double conversion; cBFloatRange^(-size/2) is double 0
+//#define BFLOAT_CHECK_UOFLOW // Don't bother with under- and overflow checking.
+
+
+//
+// BFloats: more buoyant floats.
+//
+// struct{ float + int } is 8 bytes; nice size makes noticable speed difference
+//
+class BFloat {
+ public:
+ static BFMantissa* aConversionLookup; // used by addition
+ static double* aDoubleConversionLookup; // used by Value()
+ BFMantissa f;
+ int e;
+ public:
+ BFloat(BFMantissa iF, int iE) : f(iF), e(iE) {};
+ BFloat() {};
+ ~BFloat() {};
+ inline double Value() const {
+ if (abs(e) < cBFloatDoubleConvTableSize/2) {
+ return (double)f * aDoubleConversionLookup[ e + cBFloatDoubleConvTableSize/2 ];
+ } else if (e < cBFloatDoubleConvTableSize/2) {
+ return 0.0;
+ } else {
+ return (double)f * exp((double)e * logcBFloatRange);
+ }
+ }
+ void clear() { f=0; e=-cBFloatInfinity; }
+};
+
+
+//
+// dummy class to initialise BFloat lookup table
+//
+class _BFloatInitialize {
+public:
+ _BFloatInitialize();
+};
+
+
+//
+// implementations of BFloat calculations
+//
+
+
+// Normalization of BFloat result of a single operation
+#ifdef BFLOAT_CHECK_UOFLOW
+static inline void BFloatNormalise(BFloat& a)
+ //#define BFloatNormalise(a)
+{\
+ if (a.f > cBFloatRangeSqrt) {\
+ a.f *= cBFloatRangeInv;\
+ a.e++;\
+ } else if (a.f < cBFloatRangeInvSqrt) {\
+ if (a.f == 0.0) {\
+ a.e = -cBFloatInfinity;\
+ } else {\
+ a.f *= cBFloatRange;\
+ a.e--;\
+ }\
+ }\
+ if (a.e > cBFloatInfinity) {\
+ cerr << "BFloat: Overflow" << endl;\
+ a.e = cBFloatInfinity;\
+ } else if (a.e < -cBFloatInfinity) {\
+ cerr << "BFloat: Underflow" << endl;\
+ a.e = -cBFloatInfinity;\
+ a.f = 0.0;\
+ }\
+};
+#else
+static inline void BFloatNormDown(BFloat& a) {
+ a.f *= cBFloatRangeInv;
+ a.e++;
+}
+static inline void BFloatNormUp(BFloat& a) {
+ if (a.f == 0.0) {
+ a.e = -cBFloatInfinity;
+ } else {
+ a.f *= cBFloatRange;
+ a.e--;
+ }
+}
+static inline void BFloatNormalise(BFloat& a)
+ //#define BFloatNormalise(a)
+{
+ if (a.f > cBFloatRangeSqrt) {
+ BFloatNormDown(a);
+ } else if (a.f < cBFloatRangeInvSqrt) {
+ BFloatNormUp(a);
+ }
+};
+#endif
+
+static inline void DoubleNormalise(double& f, int& e)
+{
+ // comparing to 0.0 here fails, because the comparison is done
+ // using higher-precision doubles, but the subsequent while-loop
+ // uses true doubles, resulting in an infinite loop. (G.L. 3/9/07)
+ if (f < std::numeric_limits<double>::min()) {
+ if (f < 0.0) cerr << "BFloat: Negative number: " << f << endl;
+ f = 0.0;
+ e=-cBFloatInfinity;
+ } else {
+ while (f > (double)cBFloatRangeSqrt) {
+ f *= (double)cBFloatRangeInv;
+ e++;
+ }
+ while (f < (double)cBFloatRangeInvSqrt) {
+ f *= (double)cBFloatRange;
+ e--;
+ }
+ }
+};
+
+// Logarithm of a BFloat
+static inline double bfloat_doublelog( const BFloat& a ) { return a.e*logcBFloatRange+log(a.f); }
+
+// BFloat exp of a double
+static inline BFloat bfloat_doubleexp( double iA )
+{
+ int iE = (int)std::floor( iA / log(cBFloatRange) );
+ iA -= iE * log(cBFloatRange);
+ BFloat iX( exp(iA), iE );
+ BFloatNormalise( iX );
+ return iX;
+}
+
+// Returns a double value - or underflow/overflow if it does not fit.
+static inline double bfloat2double( const BFloat bfloat) { return bfloat.Value(); }
+
+// Simplistic double-to-BFloat conversion - can be slow if 'standard' numbers get very large/small
+static inline BFloat double2bfloat( double prob) {
+ if (prob < std::numeric_limits<double>::min()) {
+ if (prob < 0.0)
+ cerr << "BFloat: Negative number: " << prob << endl;
+ return BFloat (0.0, -cBFloatInfinity );
+ } else {
+ register BFloat a( 0.0, 0 );
+ while (prob > cBFloatRangeSqrt) {
+ prob *= cBFloatRangeInv;
+ a.e++;
+ }
+ while ((prob < cBFloatRangeInvSqrt)) {
+ prob *= cBFloatRange;
+ a.e--;
+ }
+ a.f = prob;
+ return a;
+ }
+}
+
+static inline BFloat bfloat_pr_product (const BFloat& a, const BFloat& b)
+{
+ register BFloat sf(a.f*b.f,a.e+b.e);
+ BFloatNormalise(sf);
+ return sf;
+}
+
+static inline BFloat bfloat_pr_double_product (const BFloat& a, double b)
+{
+ register double mantisse = a.f*b;
+ int exponent = a.e;
+ DoubleNormalise(mantisse, exponent);
+ return BFloat(mantisse, exponent);
+}
+
+static inline void bfloat_pr_product_accum( BFloat& a, const BFloat& b) {
+ a.f *= b.f; a.e += b.e;
+ BFloatNormalise( a );
+}
+
+static inline void bfloat_pr_double_product_accum (BFloat& a, double b)
+{
+ register double mantisse = a.f*b;
+ DoubleNormalise(mantisse, a.e);
+ a.f = mantisse;
+}
+
+static inline BFloat bfloat_pr_quotient( const BFloat& a, const BFloat& b)
+{
+ register BFloat sf(a.f/b.f, a.e-b.e);
+ BFloatNormalise(sf);
+ return sf;
+}
+
+static inline void bfloat_pr_quotient_accum( BFloat& a, const BFloat& b)
+{
+ a.f /= b.f;
+ a.e -= b.e;
+ BFloatNormalise( a );
+}
+
+static inline BFloat bfloat_pr_sum(const BFloat& a, const BFloat& b)
+{
+ if (a.e > b.e) {
+ if (a.e >= b.e + cBFloatConvTableSize)
+ return a;
+ else
+ return BFloat( a.f + b.f * BFloat::aConversionLookup[ a.e - b.e ], a.e );
+ } else {
+ if (a.e <= b.e - cBFloatConvTableSize)
+ return b;
+ else
+ return BFloat( b.f + a.f * BFloat::aConversionLookup[ b.e - a.e ], b.e );
+ }
+}
+
+static inline void bfloat_pr_sum_accum( BFloat& a, const BFloat& b)
+{
+ if (a.e >= b.e) {
+ if (a.e < b.e + cBFloatConvTableSize)
+ a.f += b.f * BFloat::aConversionLookup[ a.e - b.e ];
+ } else {
+ if (a.e > b.e - cBFloatConvTableSize) {
+ a.f = b.f + a.f * BFloat::aConversionLookup[ b.e - a.e ];
+ a.e = b.e;
+ } else {
+ a = b;
+ }
+ }
+}
+
+static inline bool bfloat_less( const BFloat& a, const BFloat& b)
+{
+ if (a.e > b.e) {
+ if (a.e >= b.e + cBFloatConvTableSize)
+ return false;
+ else
+ return a.f < b.f * BFloat::aConversionLookup[ a.e - b.e ];
+ }
+ if (a.e <= b.e - cBFloatConvTableSize)
+ return true;
+ else
+ return a.f * BFloat::aConversionLookup[ b.e - a.e ] < b.f;
+};
+
+static inline bool bfloat_equal( const BFloat& a, const BFloat& b)
+{
+ if (a.e > b.e) {
+ if (a.e >= b.e + cBFloatConvTableSize)
+ return false;
+ else
+ return a.f == b.f * BFloat::aConversionLookup[ a.e - b.e ];
+ }
+ if (a.e <= b.e - cBFloatConvTableSize)
+ return false;
+ else
+ return a.f * BFloat::aConversionLookup[ b.e - a.e ] == b.f;
+};
+
+static inline bool bfloat_lessequal( const BFloat& a, const BFloat& b)
+{
+ if (a.e > b.e) {
+ if (a.e >= b.e + cBFloatConvTableSize)
+ return false;
+ else
+ return a.f <= b.f * BFloat::aConversionLookup[ a.e - b.e ];
+ }
+ if (a.e <= b.e - cBFloatConvTableSize)
+ return true;
+ else
+ return a.f * BFloat::aConversionLookup[ b.e - a.e ] <= b.f;
+};
+
+static inline std::ostream& bfloat_print( std::ostream& out, const BFloat& x )
+{
+ static const double log10 = log(10.0);
+ static const double maxmantisse = 10.0 * (1.0 - 0.55 * exp(-cBFloatDigits * log10));
+ //out.setf(ios::fixed,ios::floatfield);
+ out.precision( cBFloatDigits );
+ if (x.e == cBFloatInfinity) {
+ out << 1.0 << "e+Inf";
+ }
+ if (x.e == -cBFloatInfinity) {
+ out << 1.0 << "e-Inf";
+ } else {
+ double iM = (log(x.f) + log(cBFloatRange)*(double)x.e) / log10;
+ long iExp = long(std::floor(iM));
+ iM = exp((iM - iExp) * log10);
+ if (iM > maxmantisse) {
+ iExp += 1;
+ iM = 1.0;
+ }
+ out << iM << ( iExp<0 ? "e" : "e+" ) << iExp;
+ }
+ //out.setf(ios::fixed,ios::floatfield); // default
+ out.precision( 6 ); // default
+ return out;
+}
+
+
+//
+// Wrapper to allow BFloats to be used by Algebra template
+//
+struct BFloatMethods
+{
+ typedef BFloat Value;
+ static inline double to_prob (BFloat iX) { return bfloat2double(iX); }
+ static inline BFloat from_prob (double iP) { return double2bfloat(iP); }
+ static inline BFloat pmul( BFloat iX, BFloat iY) { return bfloat_pr_product(iX,iY); }
+ static inline BFloat pmuldouble( BFloat iX, double iY) { return bfloat_pr_double_product(iX,iY); }
+ static inline BFloat pdiv( BFloat iX, BFloat iY) { return bfloat_pr_quotient(iX,iY); }
+ static inline BFloat psum( BFloat iX, BFloat iY) { return bfloat_pr_sum(iX,iY); }
+ static inline BFloat pdiff( BFloat iX, BFloat iY) { cerr << "Bfloat pdiff: Not implemented." << endl; return BFloat(0,0); }
+ static inline BFloat doubleexp( double iX) { return bfloat_doubleexp(iX); }
+ static inline double doublelog( BFloat iX) { return bfloat_doublelog(iX); }
+ static inline void pmulacc( BFloat& iX, BFloat iY) { bfloat_pr_product_accum(iX,iY); }
+ static inline void pmulaccdouble( BFloat& iX, double iY) { bfloat_pr_double_product_accum(iX,iY); }
+ static inline void pdivacc( BFloat& iX, BFloat iY) { bfloat_pr_quotient_accum(iX,iY); }
+ static inline void psumacc( BFloat& iX, BFloat iY) { bfloat_pr_sum_accum(iX,iY); }
+ static inline void pdiffacc( BFloat& iX, BFloat iY) { cerr << "Bfloat pdiffacc: Not implemented." << endl; }
+ static inline bool less( BFloat iX, BFloat iY) { return bfloat_less(iX,iY); }
+ static inline bool equal( BFloat iX, BFloat iY) { return bfloat_equal(iX,iY); }
+ static inline bool lessequal( BFloat iX, BFloat iY) { return bfloat_lessequal(iX,iY); }
+ static inline std::ostream& print( std::ostream& iOut, BFloat iX ) { return bfloat_print( iOut, iX ); }
+};
+
+
+//
+// Simple log-space numbers - don't use, except possibly for Viterbi
+//
+class Logspace {
+ double x;
+ public:
+ Logspace( double x ) : x(x) {}
+ Logspace() {}
+ operator double&(){ return x; }
+ void clear() {x=-1.0e+300;}
+};
+
+inline Logspace logspace_addsmall( Logspace iX, Logspace iY ) {
+ if (iX - iY > 36.7) return iX;
+ return iX + log(1.0+exp(iY-iX));
+}
+
+inline Logspace logspace_add( Logspace iX, Logspace iY ) {
+ if (iX>iY) return logspace_addsmall(iX,iY); else return logspace_addsmall(iY,iX);
+}
+
+struct LogspaceMethods
+{
+ typedef Logspace Value;
+ static inline double to_prob (Value iX) { return exp(iX); }
+ static inline Value from_prob (double iP) { return Value(log(iP)); }
+ static inline Value pmul( Value iX, Value iY) { return iX+iY; }
+ static inline Value pmuldouble( Value iX, double iY) { return iX+log(iY); }
+ static inline Value pdiv( Value iX, Value iY) { return iX-iY; }
+ static inline Value psum( Value iX, Value iY) { return logspace_add(iX,iY); }
+ static inline Value pdiff( Value iX, Value iY) { cerr << "Logspace pdiff: Not implemented." << endl; return 0.0; }
+ static inline Value doubleexp( double iX) { return iX; }
+ static inline double doublelog( Value iX) { return iX; }
+ static inline void pmulacc( Value& iX, Value iY) { iX+=iY; }
+ static inline void pmulaccdouble( Value& iX, double iY) { iX+=log(iY); }
+ static inline void pdivacc( Value& iX, Value iY) { iX -= iY; }
+ static inline void psumacc( Value& iX, Value iY) { iX = logspace_add(iX,iY); }
+ static inline void pdiffacc( Value& iX, Value iY) { cerr << "Logspace pdiffacc: Not implemented." << endl; }
+ static inline bool less( Value iX, Value iY) { return iX<iY; }
+ static inline bool equal( Value iX, Value iY) { return iX==iY; }
+ static inline bool lessequal( Value iX, Value iY) { return iX<=iY; }
+ static inline std::ostream& print( std::ostream& iOut, Value iX ) { return bfloat_print( iOut, bfloat_doubleexp(iX) ); }
+};
+
+
+//
+// Algebra class - Wrapper for overloading all arithmetic operators to use a different algebra.
+//
+// Gerton Lunter, 19/3/03
+// Based on logprob.h by by Ian Holmes.
+//
+
+template <class AlgebraMethods>
+class Algebra {
+public:
+ // typedef
+ typedef typename AlgebraMethods::Value Value;
+
+ // value
+ Value val;
+
+public:
+ // constructors
+ Algebra() { } // no initialisation, for speed
+ Algebra (double px) : val(from_prob(px)) { }
+ Algebra (const Algebra& lx) : val(lx.val) { }
+ Algebra (const BFloat v) : val(v) { }
+
+ // fast initialization
+ void clear() { val.clear(); }
+
+ // assignment operators
+ inline Algebra& operator= (const Algebra& lx) { val = lx.val; return *this; }
+ inline Algebra& operator= (double px) { val = from_prob(px); return *this; }
+
+ // arithmetic operators; all combinations of Algebra and double are covered
+ inline friend Algebra operator+ (const Algebra& lx, const Algebra& ly) { return from_log (psum (lx.val, ly.val)); }
+ inline friend Algebra operator+ (const Algebra& lx, double py) { return from_log (psum (lx.val, from_prob(py))); }
+ inline friend Algebra operator+ (double px, const Algebra& ly) { return from_log (psum (from_prob(px), ly.val)); }
+ inline Algebra& operator+= (const Algebra& lx) { psumacc (val, lx.val); return *this; }
+ inline Algebra& operator+= (double px) { psumacc (val, from_prob(px)); return *this; }
+
+ inline friend Algebra operator- (const Algebra& lx, const Algebra& ly) { return from_log (pdiff (lx.val, ly.val)); }
+ inline friend Algebra operator- (const Algebra& lx, double py) { return from_log (pdiff (lx.val, from_prob(py))); }
+ inline friend Algebra operator- (double px, const Algebra& ly) { return from_log (pdiff (from_prob(px), ly.val)); }
+ inline Algebra& operator-= (const Algebra& lx) { pdiffacc (val, lx.val); return *this; }
+ inline Algebra& operator-= (double px) { pdiffacc (val, from_prob(px)); return *this; }
+
+ inline friend Algebra operator* (const Algebra& lx, const Algebra& ly) { return from_log (pmul (lx.val, ly.val)); }
+ inline friend Algebra operator* (const Algebra& lx, double py) { return from_log (pmuldouble (lx.val, py)); }
+ inline friend Algebra operator* (double px, const Algebra& ly) { return from_log (pmuldouble (ly.val, px)); }
+ inline Algebra& operator*= (const Algebra& lx) { pmulacc (val, lx.val); return *this; }
+ inline Algebra& operator*= (double px) { pmulaccdouble (val, px); return *this; }
+
+ inline friend Algebra operator/ (const Algebra& lx, const Algebra& ly) { return from_log (pdiv (lx.val, ly.val)); }
+ inline friend Algebra operator/ (const Algebra& lx, double py) { return from_log (pdiv (lx.val, from_prob(py))); }
+ inline friend Algebra operator/ (double px, const Algebra& ly) { return from_log (pdiv (from_prob(px), ly.val)); }
+ inline Algebra& operator/= (const Algebra& lx) { pdivacc (val, lx.val); return *this; }
+ inline Algebra& operator/= (double px) { pdivacc (val, from_prob(px)); return *this; }
+
+ // miscellaneous operators
+ inline friend double log( const Algebra& lx ) { return doublelog( lx.val ); }
+ inline friend Algebra exp( const Algebra& px ) { return doubleexp( to_prob(px) ); }
+
+ // increment & decremement
+ Algebra& operator++() { *this += 1.; return *this; }
+ Algebra operator++(int) { Algebra tmp (*this); ++(*this); return tmp; }
+
+ Algebra& operator--() { *this -= 1.; return *this; }
+ Algebra operator--(int) { Algebra tmp (*this); --(*this); return tmp; }
+
+ // relational operators
+ inline friend int operator== (const Algebra& lx, const Algebra& ly) { return equal(lx.val, ly.val); }
+ inline friend int operator== (const Algebra& lx, const double py) { return equal(lx.val, from_prob(py)); }
+ inline friend int operator== (const double px, const Algebra& ly) { return equal(from_prob(px), ly.val); }
+
+ inline friend int operator!= (const Algebra& lx, const Algebra& ly) { return !equal(lx.val, ly.val); }
+ inline friend int operator!= (const Algebra& lx, const double py) { return !equal(lx.val, from_prob(py)); }
+ inline friend int operator!= (const double px, const Algebra& ly) { return !equal(from_prob(px), ly.val); }
+
+ inline friend int operator< (const Algebra& lx, const Algebra& ly) { return less(lx.val, ly.val); }
+ inline friend int operator< (const Algebra& lx, const double py) { return less(lx.val, from_prob(py)); }
+ inline friend int operator< (const double px, const Algebra& ly) { return less(from_prob(px), ly.val); }
+
+ inline friend int operator> (const Algebra& lx, const Algebra& ly) { return less(ly.val, lx.val); }
+ inline friend int operator> (const Algebra& lx, const double py) { return less(from_prob(py), lx.val); }
+ inline friend int operator> (const double px, const Algebra& ly) { return less(ly.val, from_prob(px)); }
+
+ inline friend int operator<= (const Algebra& lx, const Algebra& ly) { return lessequal(lx.val, ly.val); }
+ inline friend int operator<= (const Algebra& lx, const double py) { return lessequal( lx.val, from_prob(py) ); }
+ inline friend int operator<= (const double px, const Algebra& ly) { return lessequal( from_prob(px), ly.val); }
+
+ inline friend int operator>= (const Algebra& lx, const Algebra& ly) { return lessequal( ly.val, lx.val); }
+ inline friend int operator>= (const Algebra& lx, const double py) { return lessequal( from_prob(py), lx.val ); }
+ inline friend int operator>= (const double px, const Algebra& ly) { return lessequal( ly.val, from_prob(px) ); }
+
+ // stream operators
+ inline friend std::ostream& operator<< (std::ostream& out, const Algebra& lx) { return AlgebraMethods::print(out, lx.val); }
+ inline friend std::istream& operator>> (std::istream& in, const Algebra& lx) { double px; in >> px; lx.val = px; return in; }
+
+ // cast operators
+ inline double prob() const { return to_prob (val); }
+ inline operator double() const { return to_prob (val); }
+
+private:
+ // private AlgebraMethods method wrappers
+ static inline double to_prob (Value X) { return AlgebraMethods::to_prob (X); }
+ static inline Value from_prob (double P) { return AlgebraMethods::from_prob (P); }
+ static inline Value pmul (Value X, Value Y) { return AlgebraMethods::pmul (X, Y); }
+ static inline Value pmuldouble (Value X, double Y) { return AlgebraMethods::pmuldouble (X, Y); }
+ static inline Value pdiv (Value X, Value Y) { return AlgebraMethods::pdiv( X, Y); }
+ static inline Value psum (Value X, Value Y) { return AlgebraMethods::psum (X, Y); }
+ static inline Value pdiff (Value X, Value Y) { return AlgebraMethods::pdiff (X, Y); }
+ static inline Value doubleexp (double X) { return AlgebraMethods::doubleexp( X ); }
+ static inline double doublelog (Value X) { return AlgebraMethods::doublelog( X ); }
+ static inline void pmulacc (Value& X, Value Y) { AlgebraMethods::pmulacc (X, Y); }
+ static inline void pmulaccdouble (Value& X, double Y) { AlgebraMethods::pmulaccdouble (X, Y); }
+ static inline void pdivacc( Value& X, Value Y) { AlgebraMethods::pdivacc( X, Y); }
+ static inline void psumacc (Value& X, Value Y) { AlgebraMethods::psumacc (X, Y); }
+ static inline void pdiffacc (Value& X, Value Y) { AlgebraMethods::pdiffacc (X, Y); }
+ static inline bool less (Value X, Value Y ) { return AlgebraMethods::less( X, Y ); }
+ static inline bool equal (Value X, Value Y ) { return AlgebraMethods::equal( X, Y ); }
+ static inline bool lessequal( Value X, Value Y ) { return AlgebraMethods::lessequal( X, Y ); }
+
+public:
+ // static constructor from logspace value
+ static inline Algebra from_log (Value X) { Algebra lx; lx.val = X; return lx; }
+};
+
+
+//
+// and these are the the things that we'll use:
+//
+
+#define bfloat Algebra<BFloatMethods>
+
+#define logspace Algebra<LogspaceMethods>
+
+#endif
diff --git a/src/fsa/aminoacid_indel2dp.cc b/src/fsa/aminoacid_indel2dp.cc
new file mode 100644
index 0000000..a817f93
--- /dev/null
+++ b/src/fsa/aminoacid_indel2dp.cc
@@ -0,0 +1,2445 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file aminoacid_indel2.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:18 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "aminoacid_indel2dp.h"
+
+#include "mybanding.h"
+
+const extern string _AminoAcidIndel2AlignstateId[];
+const extern string _AminoAcidIndel2AlignemissionId[];
+const extern string _AminoAcidIndel2AligntransitionId[];
+const extern string _AminoAcidIndel2AligntransF[];
+const extern string _AminoAcidIndel2AligntransT[];
+const extern string _AminoAcidIndel2AligntransP[];
+const extern string _AminoAcidIndel2AligntransE[];
+const extern string _AminoAcidIndel2AlignoutputId[];
+const extern string _AminoAcidIndel2Alignempty;
+const extern int _AminoAcidIndel2AlignstateNum;
+const extern int _AminoAcidIndel2AlignemitNum;
+const extern int _AminoAcidIndel2AligntransNum;
+const extern int _AminoAcidIndel2AlignoutputNum;
+
+AminoAcidIndel2AlignDPTable::AminoAcidIndel2AlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignstateId), emissionId(_AminoAcidIndel2AlignemissionId), transitionId(_AminoAcidIndel2AligntransitionId), transitionFrom(_AminoAcidIndel2AligntransF), transitionTo(_AminoAcidIndel2AligntransT), transitionProb(_AminoAcidIndel2AligntransP), transitionEmit(_AminoAcidIndel2AligntransE), outputId(_AminoAcidIndel2AlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaIndel2Block2.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaIndel2Block1.allocate();
+ StateMemoryaaIndel2Block3.allocate();
+}
+
+
+AminoAcidIndel2AlignDPTable::~AminoAcidIndel2AlignDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaIndel2Block2.absolve();
+ StateMemoryaaIndel2Block1.absolve();
+ StateMemoryaaIndel2Block3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidIndel2AlignDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AligntransNum ? _AminoAcidIndel2AligntransitionId[id] : _AminoAcidIndel2Alignempty; }
+const string& AminoAcidIndel2AlignDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignemitNum ? _AminoAcidIndel2AlignemissionId[id] : _AminoAcidIndel2Alignempty; }
+const string& AminoAcidIndel2AlignDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignstateNum ? _AminoAcidIndel2AlignstateId[id] : _AminoAcidIndel2Alignempty; }
+const string& AminoAcidIndel2AlignDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignoutputNum ? _AminoAcidIndel2AlignoutputId[id] : _AminoAcidIndel2Alignempty; }
+int AminoAcidIndel2AlignDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidIndel2AlignstateNum;i++) {
+ (*pmId)[_AminoAcidIndel2AlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignemitNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AligntransNum; i++) {
+ (*pmId)[_AminoAcidIndel2AligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignoutputNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidIndel2AlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidIndel2AlignDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidIndel2AlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaIndel2Block1Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block2Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
+ return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2Secondary = this->StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaIndel2Block2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
+ return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _AminoAcidIndel2AlignstateId[];
+const extern string _AminoAcidIndel2AlignemissionId[];
+const extern string _AminoAcidIndel2AligntransitionId[];
+const extern string _AminoAcidIndel2AligntransF[];
+const extern string _AminoAcidIndel2AligntransT[];
+const extern string _AminoAcidIndel2AligntransP[];
+const extern string _AminoAcidIndel2AligntransE[];
+const extern string _AminoAcidIndel2AlignoutputId[];
+const extern string _AminoAcidIndel2Alignempty;
+const extern int _AminoAcidIndel2AlignstateNum;
+const extern int _AminoAcidIndel2AlignemitNum;
+const extern int _AminoAcidIndel2AligntransNum;
+const extern int _AminoAcidIndel2AlignoutputNum;
+
+AminoAcidIndel2AlignFoldedDPTable::AminoAcidIndel2AlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignstateId), emissionId(_AminoAcidIndel2AlignemissionId), transitionId(_AminoAcidIndel2AligntransitionId), transitionFrom(_AminoAcidIndel2AligntransF), transitionTo(_AminoAcidIndel2AligntransT), transitionProb(_AminoAcidIndel2AligntransP), transitionEmit(_AminoAcidIndel2AligntransE), outputId(_AminoAcidIndel2AlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaIndel2Block2.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaIndel2Block3.allocate();
+ StateMemoryaaIndel2Block1.allocate();
+}
+
+
+AminoAcidIndel2AlignFoldedDPTable::~AminoAcidIndel2AlignFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaIndel2Block2.absolve();
+ StateMemoryaaIndel2Block3.absolve();
+ StateMemoryaaIndel2Block1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidIndel2AlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AligntransNum ? _AminoAcidIndel2AligntransitionId[id] : _AminoAcidIndel2Alignempty; }
+const string& AminoAcidIndel2AlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignemitNum ? _AminoAcidIndel2AlignemissionId[id] : _AminoAcidIndel2Alignempty; }
+const string& AminoAcidIndel2AlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignstateNum ? _AminoAcidIndel2AlignstateId[id] : _AminoAcidIndel2Alignempty; }
+const string& AminoAcidIndel2AlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignoutputNum ? _AminoAcidIndel2AlignoutputId[id] : _AminoAcidIndel2Alignempty; }
+int AminoAcidIndel2AlignFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidIndel2AlignstateNum;i++) {
+ (*pmId)[_AminoAcidIndel2AlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignemitNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AligntransNum; i++) {
+ (*pmId)[_AminoAcidIndel2AligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignoutputNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidIndel2AlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidIndel2AlignFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidIndel2AlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaIndel2Block1Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block2Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
+ return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2Secondary = this->StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaIndel2Block2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
+ return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int AminoAcidIndel2AlignBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidIndel2AlignBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int AminoAcidIndel2AlignBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidIndel2AlignBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void AminoAcidIndel2AlignBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
+ for (int i=0; i<23; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AligntransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int AminoAcidIndel2AlignBaumWelch::transitionIdentifier00[];
+int AminoAcidIndel2AlignBaumWelch::emissionIdentifier00[];
+int AminoAcidIndel2AlignBaumWelch::emissionIdentifier01[];
+int AminoAcidIndel2AlignBaumWelch::emissionIdentifier10[];
+int AminoAcidIndel2AlignBaumWelch::emissionIdentifier11[];
+
+void AminoAcidIndel2AlignBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> AminoAcidIndel2AlignBaumWelch::mId;
+int AminoAcidIndel2AlignBaumWelch::atransitionIdx[];
+int AminoAcidIndel2AlignBaumWelch::aemissionIdx[];
+
+const extern string _AminoAcidIndel2AlignWithBandingstateId[];
+const extern string _AminoAcidIndel2AlignWithBandingemissionId[];
+const extern string _AminoAcidIndel2AlignWithBandingtransitionId[];
+const extern string _AminoAcidIndel2AlignWithBandingtransF[];
+const extern string _AminoAcidIndel2AlignWithBandingtransT[];
+const extern string _AminoAcidIndel2AlignWithBandingtransP[];
+const extern string _AminoAcidIndel2AlignWithBandingtransE[];
+const extern string _AminoAcidIndel2AlignWithBandingoutputId[];
+const extern string _AminoAcidIndel2AlignWithBandingempty;
+const extern int _AminoAcidIndel2AlignWithBandingstateNum;
+const extern int _AminoAcidIndel2AlignWithBandingemitNum;
+const extern int _AminoAcidIndel2AlignWithBandingtransNum;
+const extern int _AminoAcidIndel2AlignWithBandingoutputNum;
+
+AminoAcidIndel2AlignWithBandingDPTable::AminoAcidIndel2AlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignWithBandingstateId), emissionId(_AminoAcidIndel2AlignWithBandingemissionId), transitionId(_AminoAcidIndel2AlignWithBandingtransitionId), transitionFrom(_AminoAcidIndel2AlignWithBandingtransF), transitionTo(_AminoAcidIndel2AlignWithBandingtransT), transitionProb(_AminoAcidIndel2AlignWithBandingtransP), transitionEmit(_AminoAcidIndel2AlignWith [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaIndel2Block2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaIndel2Block1.allocate();
+ StateMemoryaaIndel2Block3.allocate();
+}
+
+
+AminoAcidIndel2AlignWithBandingDPTable::~AminoAcidIndel2AlignWithBandingDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaIndel2Block2withbanding.absolve();
+ StateMemoryaaIndel2Block1.absolve();
+ StateMemoryaaIndel2Block3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidIndel2AlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingtransNum ? _AminoAcidIndel2AlignWithBandingtransitionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+const string& AminoAcidIndel2AlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingemitNum ? _AminoAcidIndel2AlignWithBandingemissionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+const string& AminoAcidIndel2AlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingstateNum ? _AminoAcidIndel2AlignWithBandingstateId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+const string& AminoAcidIndel2AlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingoutputNum ? _AminoAcidIndel2AlignWithBandingoutputId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+int AminoAcidIndel2AlignWithBandingDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidIndel2AlignWithBandingstateNum;i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignWithBandingemitNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignWithBandingtransNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignWithBandingoutputNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidIndel2AlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidIndel2AlignWithBandingDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidIndel2AlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaIndel2Block1Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block2withbandingSecondary;
+ const bfloat *CurStateMemoryaaIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
+ return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingSecondary = this->StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaIndel2Block2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
+ return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _AminoAcidIndel2AlignWithBandingstateId[];
+const extern string _AminoAcidIndel2AlignWithBandingemissionId[];
+const extern string _AminoAcidIndel2AlignWithBandingtransitionId[];
+const extern string _AminoAcidIndel2AlignWithBandingtransF[];
+const extern string _AminoAcidIndel2AlignWithBandingtransT[];
+const extern string _AminoAcidIndel2AlignWithBandingtransP[];
+const extern string _AminoAcidIndel2AlignWithBandingtransE[];
+const extern string _AminoAcidIndel2AlignWithBandingoutputId[];
+const extern string _AminoAcidIndel2AlignWithBandingempty;
+const extern int _AminoAcidIndel2AlignWithBandingstateNum;
+const extern int _AminoAcidIndel2AlignWithBandingemitNum;
+const extern int _AminoAcidIndel2AlignWithBandingtransNum;
+const extern int _AminoAcidIndel2AlignWithBandingoutputNum;
+
+AminoAcidIndel2AlignWithBandingFoldedDPTable::AminoAcidIndel2AlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignWithBandingstateId), emissionId(_AminoAcidIndel2AlignWithBandingemissionId), transitionId(_AminoAcidIndel2AlignWithBandingtransitionId), transitionFrom(_AminoAcidIndel2AlignWithBandingtransF), transitionTo(_AminoAcidIndel2AlignWithBandingtransT), transitionProb(_AminoAcidIndel2AlignWithBandingtransP), transitionEmit(_AminoAcidInd [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaIndel2Block2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaIndel2Block3.allocate();
+ StateMemoryaaIndel2Block1.allocate();
+}
+
+
+AminoAcidIndel2AlignWithBandingFoldedDPTable::~AminoAcidIndel2AlignWithBandingFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaIndel2Block2withbanding.absolve();
+ StateMemoryaaIndel2Block3.absolve();
+ StateMemoryaaIndel2Block1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingtransNum ? _AminoAcidIndel2AlignWithBandingtransitionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingemitNum ? _AminoAcidIndel2AlignWithBandingemissionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingstateNum ? _AminoAcidIndel2AlignWithBandingstateId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingoutputNum ? _AminoAcidIndel2AlignWithBandingoutputId[id] : _AminoAcidIndel2AlignWithBandingempty; }
+int AminoAcidIndel2AlignWithBandingFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidIndel2AlignWithBandingstateNum;i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignWithBandingemitNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignWithBandingtransNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidIndel2AlignWithBandingoutputNum; i++) {
+ (*pmId)[_AminoAcidIndel2AlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidIndel2AlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidIndel2AlignWithBandingFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidIndel2AlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaIndel2Block1Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block2withbandingSecondary;
+ const bfloat *CurStateMemoryaaIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
+ return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingSecondary = this->StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaIndel2Block2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
+ return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int AminoAcidIndel2AlignWithBandingBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidIndel2AlignWithBandingBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidIndel2AlignWithBandingBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void AminoAcidIndel2AlignWithBandingBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
+ for (int i=0; i<23; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignWithBandingtransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int AminoAcidIndel2AlignWithBandingBaumWelch::transitionIdentifier00[];
+int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier00[];
+int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier01[];
+int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier10[];
+int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier11[];
+
+void AminoAcidIndel2AlignWithBandingBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> AminoAcidIndel2AlignWithBandingBaumWelch::mId;
+int AminoAcidIndel2AlignWithBandingBaumWelch::atransitionIdx[];
+int AminoAcidIndel2AlignWithBandingBaumWelch::aemissionIdx[];
+
+const string _AminoAcidIndel2AlignstateId[] = {"start","delete2","delete1","insert1","match","insert2","end"};
+const string _AminoAcidIndel2AlignemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _AminoAcidIndel2AligntransitionId[] = {"trSM","trSI1","trSD1","trSI2","trSD2","trMM","trMI1","trMD1","trMI2","trMD2","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E","trI2M","trI2I2","trI2E","trD2M","trD2D2","trD2E"};
+const string _AminoAcidIndel2AligntransF[] = {"start","start","start","start","start","match","match","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1","insert2","insert2","insert2","delete2","delete2","delete2"};
+const string _AminoAcidIndel2AligntransT[] = {"match","insert1","delete1","insert2","delete2","match","insert1","delete1","insert2","delete2","end","match","insert1","end","match","delete1","end","match","insert2","end","match","delete2","end"};
+const string _AminoAcidIndel2AligntransP[] = {"probSM","probSI1","probSD1","probSI2","probSD2","probMM","probMI1","probMD1","probMI2","probMD2","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E","probI2M","probI2I2","probI2E","probD2M","probD2D2","probD2E"};
+const string _AminoAcidIndel2AligntransE[] = {"emit12","emit1","emit2","emit1","emit2","emit12","emit1","emit2","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _AminoAcidIndel2AlignoutputId[] = {"sequence1","sequence2"};
+const string _AminoAcidIndel2Alignempty = "";
+const int _AminoAcidIndel2AlignstateNum = 7;
+const int _AminoAcidIndel2AlignemitNum = 4;
+const int _AminoAcidIndel2AligntransNum = 23;
+const int _AminoAcidIndel2AlignoutputNum = 2;
+
+
+
+
+bfloat Forward(AminoAcidIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemoryaaIndel2Block2To;
+ const bfloat *CurStateMemoryaaIndel2Block1From;
+ const bfloat *CurStateMemoryaaIndel2Block2From;
+ bfloat *CurStateMemoryaaIndel2Block3To;
+ const bfloat *CurStateMemoryaaIndel2Block3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidIndel2AlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemoryaaIndel2Block1.write()[0] = 1.0;
+ dp.StateMemoryaaIndel2Block1.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=0; iPos1<iLen2+1; ++iPos1) {
+ for (int iPos0=0; iPos0<iLen1+1; ++iPos0) {
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ }
+ if (1) {
+ if ((iPos1+-1>=0)) {
+ iSymbol[0] = iSequence2[iPos1+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+-1>=0)) {
+ iSymbol[1] = iSequence1[iPos0+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block2To = dp.StateMemoryaaIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+0<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ CurStateMemoryaaIndel2Block2To[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ CurStateMemoryaaIndel2Block2To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ }
+ if ((iPos1+-1>=0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
+ CurStateMemoryaaIndel2Block2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[1] += ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ CurStateMemoryaaIndel2Block2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[0] += ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ CurStateMemoryaaIndel2Block2To[2] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ CurStateMemoryaaIndel2Block2To[4] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ }
+ if ((iPos0+-1>=0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block2To[2] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ CurStateMemoryaaIndel2Block2To[4] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[4] += ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ CurStateMemoryaaIndel2Block2To[3] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ }
+ if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ }
+ dp.StateMemoryaaIndel2Block2.written();
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3To = dp.StateMemoryaaIndel2Block3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block3To[0] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ }
+ dp.StateMemoryaaIndel2Block3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
+ iTempProb[0] = CurStateMemoryaaIndel2Block3From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidIndel2AlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelch(AminoAcidIndel2AlignBaumWelch& bw,AminoAcidIndel2AlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ const bfloat *CurStateMemoryaaIndel2Block3Secondary;
+ bfloat iTransition[23];
+ bfloat *CurStateMemoryaaIndel2Block2To;
+ const bfloat *CurStateMemoryaaIndel2Block2Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block2From;
+ unsigned char alphaSymbolaminoacid[20] = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'};
+ unsigned char alphaIndexaminoacid[256];
+ const bfloat *CurStateMemoryaaIndel2Block3From;
+ bfloat *CurStateMemoryaaIndel2Block1To;
+ const bfloat *CurStateMemoryaaIndel2Block1Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ AminoAcidIndel2AlignFoldedDPTable dp(iLen1,2);
+ AminoAcidIndel2AlignDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexaminoacid[i]=0;
+ }
+
+// for (int i=0; i<20; i++) {
+// alphaIndexaminoacid[alphaSymbolaminoacid[i]]=i;
+// }
+ for (int i=0; i<20; i++) {
+ alphaIndexaminoacid[tolower (alphaSymbolaminoacid[i])] = i;
+ alphaIndexaminoacid[toupper (alphaSymbolaminoacid[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
+ dp.StateMemoryaaIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block3Secondary = dp2.StateMemoryaaIndel2Block3.read();
+ iTempProb[2] = CurStateMemoryaaIndel2Block3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != iPos1) {
+ dp.StateMemoryaaIndel2Block2.clear(iPos1);
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block2To = dp.StateMemoryaaIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block2Secondary = dp2.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block2To[3] = iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[1] = iTempProb[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[1];
+ bw.transitionBaumWelchCount00[15] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[0] = iTempProb[1] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[0];
+ bw.transitionBaumWelchCount00[21] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block2To[2] = iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[4] = iTempProb[1] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[4];
+ bw.transitionBaumWelchCount00[18] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block2To[2] += iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[1] += iTempProb[1] = ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[1];
+ bw.transitionBaumWelchCount00[14] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[4] += iTempProb[1] = ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[4];
+ bw.transitionBaumWelchCount00[17] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[0] += iTempProb[1] = ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[0];
+ bw.transitionBaumWelchCount00[20] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
+ CurStateMemoryaaIndel2Block2To[2] += iTempProb[1] = ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[2];
+ bw.transitionBaumWelchCount00[13] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[1] += iTempProb[1] = ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[1];
+ bw.transitionBaumWelchCount00[16] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[4] += iTempProb[1] = ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[4];
+ bw.transitionBaumWelchCount00[19] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[0] += iTempProb[1] = ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[0];
+ bw.transitionBaumWelchCount00[22] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemoryaaIndel2Block2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
+ CurStateMemoryaaIndel2Block1Secondary = dp2.StateMemoryaaIndel2Block1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemoryaaIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat Backward(AminoAcidIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemoryaaIndel2Block2To;
+ const bfloat *CurStateMemoryaaIndel2Block2From;
+ const bfloat *CurStateMemoryaaIndel2Block3From;
+ bfloat *CurStateMemoryaaIndel2Block1To;
+ const bfloat *CurStateMemoryaaIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidIndel2AlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
+ dp.StateMemoryaaIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block2To = dp.StateMemoryaaIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block2To[0] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ CurStateMemoryaaIndel2Block2To[3] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ CurStateMemoryaaIndel2Block2To[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block2To[2] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ CurStateMemoryaaIndel2Block2To[4] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[0] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[4] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ CurStateMemoryaaIndel2Block2To[1] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
+ CurStateMemoryaaIndel2Block2To[2] += ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2To[3] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2To[4] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2To[1] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ }
+ dp.StateMemoryaaIndel2Block2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
+ }
+ dp.StateMemoryaaIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidIndel2AlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+const string _AminoAcidIndel2AlignWithBandingstateId[] = {"start","delete2","delete1","insert1","match","insert2","end"};
+const string _AminoAcidIndel2AlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _AminoAcidIndel2AlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trSI2","trSD2","trMM","trMI1","trMD1","trMI2","trMD2","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E","trI2M","trI2I2","trI2E","trD2M","trD2D2","trD2E"};
+const string _AminoAcidIndel2AlignWithBandingtransF[] = {"start","start","start","start","start","match","match","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1","insert2","insert2","insert2","delete2","delete2","delete2"};
+const string _AminoAcidIndel2AlignWithBandingtransT[] = {"match","insert1","delete1","insert2","delete2","match","insert1","delete1","insert2","delete2","end","match","insert1","end","match","delete1","end","match","insert2","end","match","delete2","end"};
+const string _AminoAcidIndel2AlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probSI2","probSD2","probMM","probMI1","probMD1","probMI2","probMD2","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E","probI2M","probI2I2","probI2E","probD2M","probD2D2","probD2E"};
+const string _AminoAcidIndel2AlignWithBandingtransE[] = {"emit12","emit1","emit2","emit1","emit2","emit12","emit1","emit2","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _AminoAcidIndel2AlignWithBandingoutputId[] = {"sequence1","sequence2"};
+const string _AminoAcidIndel2AlignWithBandingempty = "";
+const int _AminoAcidIndel2AlignWithBandingstateNum = 7;
+const int _AminoAcidIndel2AlignWithBandingemitNum = 4;
+const int _AminoAcidIndel2AlignWithBandingtransNum = 23;
+const int _AminoAcidIndel2AlignWithBandingoutputNum = 2;
+
+
+
+
+bfloat ForwardBanding(AminoAcidIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemoryaaIndel2Block2withbandingTo;
+ const bfloat *CurStateMemoryaaIndel2Block1From;
+ const bfloat *CurStateMemoryaaIndel2Block2withbandingFrom;
+ bfloat *CurStateMemoryaaIndel2Block3To;
+ const bfloat *CurStateMemoryaaIndel2Block3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidIndel2AlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemoryaaIndel2Block1.write()[0] = 1.0;
+ dp.StateMemoryaaIndel2Block1.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.forwardIterator();
+ bool bLastSlowCoordInited = false;
+ int iLastSlowCoord = -1;
+ do {
+ if (bLastSlowCoordInited) {
+ if (iLastSlowCoord > position[1]) {
+ cout << "WARNING: Banding (forward): Slowest coordinate should be nondecreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ } else {
+ bLastSlowCoordInited = true;
+ }
+ iLastSlowCoord = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+-1>=0)) {
+ iSymbol[0] = iSequence2[position[1]+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+-1>=0)) {
+ iSymbol[1] = iSequence1[position[0]+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block2withbandingTo = dp.StateMemoryaaIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+0<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ CurStateMemoryaaIndel2Block2withbandingTo[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ }
+ if ((position[1]+-1>=0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ CurStateMemoryaaIndel2Block2withbandingTo[2] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ }
+ if ((position[0]+-1>=0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ CurStateMemoryaaIndel2Block2withbandingTo[3] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
+ }
+ if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ }
+ dp.StateMemoryaaIndel2Block2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextForward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ CurStateMemoryaaIndel2Block3To = dp.StateMemoryaaIndel2Block3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block3To[0] = ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ CurStateMemoryaaIndel2Block3To[0] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ }
+ dp.StateMemoryaaIndel2Block3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
+ iTempProb[0] = CurStateMemoryaaIndel2Block3From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidIndel2AlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelchBanding(AminoAcidIndel2AlignWithBandingBaumWelch& bw,AminoAcidIndel2AlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ const bfloat *CurStateMemoryaaIndel2Block3Secondary;
+ bfloat iTransition[23];
+ bfloat *CurStateMemoryaaIndel2Block2withbandingTo;
+ const bfloat *CurStateMemoryaaIndel2Block2withbandingSecondary;
+ const bfloat *CurStateMemoryaaIndel2Block2withbandingFrom;
+ unsigned char alphaSymbolaminoacid[20] = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'};
+ unsigned char alphaIndexaminoacid[256];
+ const bfloat *CurStateMemoryaaIndel2Block3From;
+ bfloat *CurStateMemoryaaIndel2Block1To;
+ const bfloat *CurStateMemoryaaIndel2Block1Secondary;
+ const bfloat *CurStateMemoryaaIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ AminoAcidIndel2AlignWithBandingFoldedDPTable dp(iLen1,2);
+ AminoAcidIndel2AlignWithBandingDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexaminoacid[i]=0;
+ }
+
+// for (int i=0; i<20; i++) {
+// alphaIndexaminoacid[alphaSymbolaminoacid[i]]=i;
+// }
+ for (int i=0; i<20; i++) {
+ alphaIndexaminoacid[tolower (alphaSymbolaminoacid[i])] = i;
+ alphaIndexaminoacid[toupper (alphaSymbolaminoacid[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
+ dp.StateMemoryaaIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block3Secondary = dp2.StateMemoryaaIndel2Block3.read();
+ iTempProb[2] = CurStateMemoryaaIndel2Block3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != position[1]) {
+ dp.StateMemoryaaIndel2Block2withbanding.clear(position[1]);
+ }
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block2withbandingTo = dp.StateMemoryaaIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaIndel2Block2withbandingSecondary = dp2.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[0] = iTempProb[1] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[21] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] = iTempProb[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[15] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] = iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[4] = iTempProb[1] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[4];
+ bw.transitionBaumWelchCount00[18] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] = iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[0] += iTempProb[1] = ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[20] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] += iTempProb[1] = ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[14] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] += iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] += iTempProb[1] = ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[4];
+ bw.transitionBaumWelchCount00[17] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[0] += iTempProb[1] = ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[22] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] += iTempProb[1] = ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[16] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] += iTempProb[1] = ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[13] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] += iTempProb[1] = ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[4];
+ bw.transitionBaumWelchCount00[19] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemoryaaIndel2Block2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
+ CurStateMemoryaaIndel2Block1Secondary = dp2.StateMemoryaaIndel2Block1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemoryaaIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBanding(AminoAcidIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemoryaaIndel2Block2withbandingTo;
+ const bfloat *CurStateMemoryaaIndel2Block2withbandingFrom;
+ const bfloat *CurStateMemoryaaIndel2Block3From;
+ bfloat *CurStateMemoryaaIndel2Block1To;
+ const bfloat *CurStateMemoryaaIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidIndel2AlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
+ dp.StateMemoryaaIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block2withbandingTo = dp.StateMemoryaaIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[3] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ CurStateMemoryaaIndel2Block2withbandingTo[0] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
+ CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
+ }
+ dp.StateMemoryaaIndel2Block2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaIndel2Block1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
+ }
+ dp.StateMemoryaaIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
+ iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidIndel2AlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/aminoacid_indel2dp.h b/src/fsa/aminoacid_indel2dp.h
new file mode 100644
index 0000000..84bae41
--- /dev/null
+++ b/src/fsa/aminoacid_indel2dp.h
@@ -0,0 +1,315 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file aminoacid_indel2.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:18 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _aminoacid_indel2dp_h_
+#define _aminoacid_indel2dp_h_
+
+
+#include "dptables.h"
+#include "algebras.h"
+#include <string>
+
+#include <map>
+
+using std::map;
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesaaIndel2Block2;
+typedef States<bfloat,1> StatesaaIndel2Block1;
+typedef States<bfloat,1> StatesaaIndel2Block3;
+
+class AminoAcidIndel2AlignDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesaaIndel2Block2,2> StateMemoryaaIndel2Block2;
+ DPTable<StatesaaIndel2Block1,0> StateMemoryaaIndel2Block1;
+ DPTable<StatesaaIndel2Block3,0> StateMemoryaaIndel2Block3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidIndel2AlignDPTable(int iLen1,int iLen2);
+ ~AminoAcidIndel2AlignDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat AminoAcidIndel2AlignReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double AminoAcidIndel2AlignShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesaaIndel2Block2;
+typedef States<bfloat,1> StatesaaIndel2Block3;
+typedef States<bfloat,1> StatesaaIndel2Block1;
+
+class AminoAcidIndel2AlignFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesaaIndel2Block2,2> StateMemoryaaIndel2Block2;
+ DPTable<StatesaaIndel2Block3,0> StateMemoryaaIndel2Block3;
+ DPTable<StatesaaIndel2Block1,0> StateMemoryaaIndel2Block1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidIndel2AlignFoldedDPTable(int iLen1,int iLen2);
+ ~AminoAcidIndel2AlignFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class AminoAcidIndel2AlignBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ AminoAcidIndel2AlignBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[23];
+ static int transitionIdentifier00[23];
+ static const int transitionDimension00 = 23;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[20][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[20][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[20][20][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[23];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesaaIndel2Block2withbanding;
+typedef States<bfloat,1> StatesaaIndel2Block1;
+typedef States<bfloat,1> StatesaaIndel2Block3;
+
+class AminoAcidIndel2AlignWithBandingDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesaaIndel2Block2withbanding,2> StateMemoryaaIndel2Block2withbanding;
+ DPTable<StatesaaIndel2Block1,0> StateMemoryaaIndel2Block1;
+ DPTable<StatesaaIndel2Block3,0> StateMemoryaaIndel2Block3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidIndel2AlignWithBandingDPTable(int iLen1,int iLen2);
+ ~AminoAcidIndel2AlignWithBandingDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat AminoAcidIndel2AlignWithBandingReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double AminoAcidIndel2AlignWithBandingShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesaaIndel2Block2withbanding;
+typedef States<bfloat,1> StatesaaIndel2Block3;
+typedef States<bfloat,1> StatesaaIndel2Block1;
+
+class AminoAcidIndel2AlignWithBandingFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesaaIndel2Block2withbanding,2> StateMemoryaaIndel2Block2withbanding;
+ DPTable<StatesaaIndel2Block3,0> StateMemoryaaIndel2Block3;
+ DPTable<StatesaaIndel2Block1,0> StateMemoryaaIndel2Block1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidIndel2AlignWithBandingFoldedDPTable(int iLen1,int iLen2);
+ ~AminoAcidIndel2AlignWithBandingFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class AminoAcidIndel2AlignWithBandingBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ AminoAcidIndel2AlignWithBandingBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[23];
+ static int transitionIdentifier00[23];
+ static const int transitionDimension00 = 23;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[20][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[20][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[20][20][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[23];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+bfloat Forward(AminoAcidIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat BackwardBaumWelch(AminoAcidIndel2AlignBaumWelch& bw,AminoAcidIndel2AlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat Backward(AminoAcidIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat ForwardBanding(AminoAcidIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBaumWelchBanding(AminoAcidIndel2AlignWithBandingBaumWelch& bw,AminoAcidIndel2AlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBanding(AminoAcidIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+#endif // _aminoacid_indel2dp_h_
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/aminoaciddp.cc b/src/fsa/aminoaciddp.cc
new file mode 100644
index 0000000..ff4863a
--- /dev/null
+++ b/src/fsa/aminoaciddp.cc
@@ -0,0 +1,2205 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file aminoacid.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:18 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "aminoaciddp.h"
+
+#include "mybanding.h"
+
+const extern string _AminoAcidAlignstateId[];
+const extern string _AminoAcidAlignemissionId[];
+const extern string _AminoAcidAligntransitionId[];
+const extern string _AminoAcidAligntransF[];
+const extern string _AminoAcidAligntransT[];
+const extern string _AminoAcidAligntransP[];
+const extern string _AminoAcidAligntransE[];
+const extern string _AminoAcidAlignoutputId[];
+const extern string _AminoAcidAlignempty;
+const extern int _AminoAcidAlignstateNum;
+const extern int _AminoAcidAlignemitNum;
+const extern int _AminoAcidAligntransNum;
+const extern int _AminoAcidAlignoutputNum;
+
+AminoAcidAlignDPTable::AminoAcidAlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignstateId), emissionId(_AminoAcidAlignemissionId), transitionId(_AminoAcidAligntransitionId), transitionFrom(_AminoAcidAligntransF), transitionTo(_AminoAcidAligntransT), transitionProb(_AminoAcidAligntransP), transitionEmit(_AminoAcidAligntransE), outputId(_AminoAcidAlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaBlock2.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaBlock1.allocate();
+ StateMemoryaaBlock3.allocate();
+}
+
+
+AminoAcidAlignDPTable::~AminoAcidAlignDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaBlock2.absolve();
+ StateMemoryaaBlock1.absolve();
+ StateMemoryaaBlock3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidAlignDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAligntransNum ? _AminoAcidAligntransitionId[id] : _AminoAcidAlignempty; }
+const string& AminoAcidAlignDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignemitNum ? _AminoAcidAlignemissionId[id] : _AminoAcidAlignempty; }
+const string& AminoAcidAlignDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignstateNum ? _AminoAcidAlignstateId[id] : _AminoAcidAlignempty; }
+const string& AminoAcidAlignDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignoutputNum ? _AminoAcidAlignoutputId[id] : _AminoAcidAlignempty; }
+int AminoAcidAlignDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidAlignstateNum;i++) {
+ (*pmId)[_AminoAcidAlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignemitNum; i++) {
+ (*pmId)[_AminoAcidAlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidAligntransNum; i++) {
+ (*pmId)[_AminoAcidAligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignoutputNum; i++) {
+ (*pmId)[_AminoAcidAlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidAlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidAlignDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidAlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaBlock1Secondary;
+ const bfloat *CurStateMemoryaaBlock2Secondary;
+ const bfloat *CurStateMemoryaaBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
+ return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock2Secondary = this->StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaBlock2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
+ return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _AminoAcidAlignstateId[];
+const extern string _AminoAcidAlignemissionId[];
+const extern string _AminoAcidAligntransitionId[];
+const extern string _AminoAcidAligntransF[];
+const extern string _AminoAcidAligntransT[];
+const extern string _AminoAcidAligntransP[];
+const extern string _AminoAcidAligntransE[];
+const extern string _AminoAcidAlignoutputId[];
+const extern string _AminoAcidAlignempty;
+const extern int _AminoAcidAlignstateNum;
+const extern int _AminoAcidAlignemitNum;
+const extern int _AminoAcidAligntransNum;
+const extern int _AminoAcidAlignoutputNum;
+
+AminoAcidAlignFoldedDPTable::AminoAcidAlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignstateId), emissionId(_AminoAcidAlignemissionId), transitionId(_AminoAcidAligntransitionId), transitionFrom(_AminoAcidAligntransF), transitionTo(_AminoAcidAligntransT), transitionProb(_AminoAcidAligntransP), transitionEmit(_AminoAcidAligntransE), outputId(_AminoAcidAlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaBlock2.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaBlock3.allocate();
+ StateMemoryaaBlock1.allocate();
+}
+
+
+AminoAcidAlignFoldedDPTable::~AminoAcidAlignFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaBlock2.absolve();
+ StateMemoryaaBlock3.absolve();
+ StateMemoryaaBlock1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidAlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAligntransNum ? _AminoAcidAligntransitionId[id] : _AminoAcidAlignempty; }
+const string& AminoAcidAlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignemitNum ? _AminoAcidAlignemissionId[id] : _AminoAcidAlignempty; }
+const string& AminoAcidAlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignstateNum ? _AminoAcidAlignstateId[id] : _AminoAcidAlignempty; }
+const string& AminoAcidAlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignoutputNum ? _AminoAcidAlignoutputId[id] : _AminoAcidAlignempty; }
+int AminoAcidAlignFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidAlignstateNum;i++) {
+ (*pmId)[_AminoAcidAlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignemitNum; i++) {
+ (*pmId)[_AminoAcidAlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidAligntransNum; i++) {
+ (*pmId)[_AminoAcidAligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignoutputNum; i++) {
+ (*pmId)[_AminoAcidAlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidAlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidAlignFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidAlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaBlock1Secondary;
+ const bfloat *CurStateMemoryaaBlock2Secondary;
+ const bfloat *CurStateMemoryaaBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
+ return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock2Secondary = this->StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaBlock2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
+ return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int AminoAcidAlignBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidAlignBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int AminoAcidAlignBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidAlignBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void AminoAcidAlignBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ for (int i=0; i<13; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAligntransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int AminoAcidAlignBaumWelch::transitionIdentifier00[];
+int AminoAcidAlignBaumWelch::emissionIdentifier00[];
+int AminoAcidAlignBaumWelch::emissionIdentifier01[];
+int AminoAcidAlignBaumWelch::emissionIdentifier10[];
+int AminoAcidAlignBaumWelch::emissionIdentifier11[];
+
+void AminoAcidAlignBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> AminoAcidAlignBaumWelch::mId;
+int AminoAcidAlignBaumWelch::atransitionIdx[];
+int AminoAcidAlignBaumWelch::aemissionIdx[];
+
+const extern string _AminoAcidAlignWithBandingstateId[];
+const extern string _AminoAcidAlignWithBandingemissionId[];
+const extern string _AminoAcidAlignWithBandingtransitionId[];
+const extern string _AminoAcidAlignWithBandingtransF[];
+const extern string _AminoAcidAlignWithBandingtransT[];
+const extern string _AminoAcidAlignWithBandingtransP[];
+const extern string _AminoAcidAlignWithBandingtransE[];
+const extern string _AminoAcidAlignWithBandingoutputId[];
+const extern string _AminoAcidAlignWithBandingempty;
+const extern int _AminoAcidAlignWithBandingstateNum;
+const extern int _AminoAcidAlignWithBandingemitNum;
+const extern int _AminoAcidAlignWithBandingtransNum;
+const extern int _AminoAcidAlignWithBandingoutputNum;
+
+AminoAcidAlignWithBandingDPTable::AminoAcidAlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignWithBandingstateId), emissionId(_AminoAcidAlignWithBandingemissionId), transitionId(_AminoAcidAlignWithBandingtransitionId), transitionFrom(_AminoAcidAlignWithBandingtransF), transitionTo(_AminoAcidAlignWithBandingtransT), transitionProb(_AminoAcidAlignWithBandingtransP), transitionEmit(_AminoAcidAlignWithBandingtransE), outputId(_AminoAcidAlignWithBandingout [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaBlock2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaBlock1.allocate();
+ StateMemoryaaBlock3.allocate();
+}
+
+
+AminoAcidAlignWithBandingDPTable::~AminoAcidAlignWithBandingDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaBlock2withbanding.absolve();
+ StateMemoryaaBlock1.absolve();
+ StateMemoryaaBlock3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidAlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingtransNum ? _AminoAcidAlignWithBandingtransitionId[id] : _AminoAcidAlignWithBandingempty; }
+const string& AminoAcidAlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingemitNum ? _AminoAcidAlignWithBandingemissionId[id] : _AminoAcidAlignWithBandingempty; }
+const string& AminoAcidAlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingstateNum ? _AminoAcidAlignWithBandingstateId[id] : _AminoAcidAlignWithBandingempty; }
+const string& AminoAcidAlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingoutputNum ? _AminoAcidAlignWithBandingoutputId[id] : _AminoAcidAlignWithBandingempty; }
+int AminoAcidAlignWithBandingDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidAlignWithBandingstateNum;i++) {
+ (*pmId)[_AminoAcidAlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignWithBandingemitNum; i++) {
+ (*pmId)[_AminoAcidAlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignWithBandingtransNum; i++) {
+ (*pmId)[_AminoAcidAlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignWithBandingoutputNum; i++) {
+ (*pmId)[_AminoAcidAlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidAlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidAlignWithBandingDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidAlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaBlock1Secondary;
+ const bfloat *CurStateMemoryaaBlock2withbandingSecondary;
+ const bfloat *CurStateMemoryaaBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
+ return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingSecondary = this->StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaBlock2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
+ return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _AminoAcidAlignWithBandingstateId[];
+const extern string _AminoAcidAlignWithBandingemissionId[];
+const extern string _AminoAcidAlignWithBandingtransitionId[];
+const extern string _AminoAcidAlignWithBandingtransF[];
+const extern string _AminoAcidAlignWithBandingtransT[];
+const extern string _AminoAcidAlignWithBandingtransP[];
+const extern string _AminoAcidAlignWithBandingtransE[];
+const extern string _AminoAcidAlignWithBandingoutputId[];
+const extern string _AminoAcidAlignWithBandingempty;
+const extern int _AminoAcidAlignWithBandingstateNum;
+const extern int _AminoAcidAlignWithBandingemitNum;
+const extern int _AminoAcidAlignWithBandingtransNum;
+const extern int _AminoAcidAlignWithBandingoutputNum;
+
+AminoAcidAlignWithBandingFoldedDPTable::AminoAcidAlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignWithBandingstateId), emissionId(_AminoAcidAlignWithBandingemissionId), transitionId(_AminoAcidAlignWithBandingtransitionId), transitionFrom(_AminoAcidAlignWithBandingtransF), transitionTo(_AminoAcidAlignWithBandingtransT), transitionProb(_AminoAcidAlignWithBandingtransP), transitionEmit(_AminoAcidAlignWithBandingtransE), outputId(_AminoAcidAlignWi [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemoryaaBlock2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemoryaaBlock3.allocate();
+ StateMemoryaaBlock1.allocate();
+}
+
+
+AminoAcidAlignWithBandingFoldedDPTable::~AminoAcidAlignWithBandingFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemoryaaBlock2withbanding.absolve();
+ StateMemoryaaBlock3.absolve();
+ StateMemoryaaBlock1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& AminoAcidAlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingtransNum ? _AminoAcidAlignWithBandingtransitionId[id] : _AminoAcidAlignWithBandingempty; }
+const string& AminoAcidAlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingemitNum ? _AminoAcidAlignWithBandingemissionId[id] : _AminoAcidAlignWithBandingempty; }
+const string& AminoAcidAlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingstateNum ? _AminoAcidAlignWithBandingstateId[id] : _AminoAcidAlignWithBandingempty; }
+const string& AminoAcidAlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingoutputNum ? _AminoAcidAlignWithBandingoutputId[id] : _AminoAcidAlignWithBandingempty; }
+int AminoAcidAlignWithBandingFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_AminoAcidAlignWithBandingstateNum;i++) {
+ (*pmId)[_AminoAcidAlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignWithBandingemitNum; i++) {
+ (*pmId)[_AminoAcidAlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignWithBandingtransNum; i++) {
+ (*pmId)[_AminoAcidAlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_AminoAcidAlignWithBandingoutputNum; i++) {
+ (*pmId)[_AminoAcidAlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "AminoAcidAlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat AminoAcidAlignWithBandingFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat AminoAcidAlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemoryaaBlock1Secondary;
+ const bfloat *CurStateMemoryaaBlock2withbandingSecondary;
+ const bfloat *CurStateMemoryaaBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
+ return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingSecondary = this->StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemoryaaBlock2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
+ return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int AminoAcidAlignWithBandingBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidAlignWithBandingBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int AminoAcidAlignWithBandingBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "AminoAcidAlignWithBandingBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void AminoAcidAlignWithBandingBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ for (int i=0; i<13; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignWithBandingtransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_AminoAcidAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int AminoAcidAlignWithBandingBaumWelch::transitionIdentifier00[];
+int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier00[];
+int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier01[];
+int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier10[];
+int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier11[];
+
+void AminoAcidAlignWithBandingBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> AminoAcidAlignWithBandingBaumWelch::mId;
+int AminoAcidAlignWithBandingBaumWelch::atransitionIdx[];
+int AminoAcidAlignWithBandingBaumWelch::aemissionIdx[];
+
+const string _AminoAcidAlignstateId[] = {"start","insert1","match","delete1","end"};
+const string _AminoAcidAlignemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _AminoAcidAligntransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
+const string _AminoAcidAligntransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
+const string _AminoAcidAligntransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
+const string _AminoAcidAligntransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
+const string _AminoAcidAligntransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _AminoAcidAlignoutputId[] = {"sequence1","sequence2"};
+const string _AminoAcidAlignempty = "";
+const int _AminoAcidAlignstateNum = 5;
+const int _AminoAcidAlignemitNum = 4;
+const int _AminoAcidAligntransNum = 13;
+const int _AminoAcidAlignoutputNum = 2;
+
+
+
+
+bfloat Forward(AminoAcidAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemoryaaBlock2To;
+ const bfloat *CurStateMemoryaaBlock1From;
+ const bfloat *CurStateMemoryaaBlock2From;
+ bfloat *CurStateMemoryaaBlock3To;
+ const bfloat *CurStateMemoryaaBlock3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidAlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemoryaaBlock1.write()[0] = 1.0;
+ dp.StateMemoryaaBlock1.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=0; iPos1<iLen2+1; ++iPos1) {
+ for (int iPos0=0; iPos0<iLen1+1; ++iPos0) {
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ }
+ if (1) {
+ if ((iPos1+-1>=0)) {
+ iSymbol[0] = iSequence2[iPos1+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+-1>=0)) {
+ iSymbol[1] = iSequence1[iPos0+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock2To = dp.StateMemoryaaBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+0<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ CurStateMemoryaaBlock2To[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
+ }
+ if ((iPos1+-1>=0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
+ CurStateMemoryaaBlock2To[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ CurStateMemoryaaBlock2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ CurStateMemoryaaBlock2To[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
+ }
+ if ((iPos0+-1>=0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock2To[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ CurStateMemoryaaBlock2To[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ CurStateMemoryaaBlock2To[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
+ }
+ if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
+ CurStateMemoryaaBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ CurStateMemoryaaBlock2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ CurStateMemoryaaBlock2To[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ }
+ dp.StateMemoryaaBlock2.written();
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemoryaaBlock3To = dp.StateMemoryaaBlock3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock3To[0] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ CurStateMemoryaaBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ CurStateMemoryaaBlock3To[0] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ }
+ dp.StateMemoryaaBlock3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
+ iTempProb[0] = CurStateMemoryaaBlock3From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidAlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelch(AminoAcidAlignBaumWelch& bw,AminoAcidAlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ const bfloat *CurStateMemoryaaBlock3Secondary;
+ bfloat iTransition[13];
+ bfloat *CurStateMemoryaaBlock2To;
+ const bfloat *CurStateMemoryaaBlock2Secondary;
+ const bfloat *CurStateMemoryaaBlock2From;
+ unsigned char alphaSymbolaminoacid[20] = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'};
+ unsigned char alphaIndexaminoacid[256];
+ const bfloat *CurStateMemoryaaBlock3From;
+ bfloat *CurStateMemoryaaBlock1To;
+ const bfloat *CurStateMemoryaaBlock1Secondary;
+ const bfloat *CurStateMemoryaaBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ AminoAcidAlignFoldedDPTable dp(iLen1,2);
+ AminoAcidAlignDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexaminoacid[i]=0;
+ }
+
+// for (int i=0; i<20; i++) {
+// alphaIndexaminoacid[alphaSymbolaminoacid[i]]=i;
+// }
+ for (int i=0; i<20; i++) {
+ alphaIndexaminoacid[tolower (alphaSymbolaminoacid[i])] = i;
+ alphaIndexaminoacid[toupper (alphaSymbolaminoacid[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemoryaaBlock3.write()[0] = 1.0;
+ dp.StateMemoryaaBlock3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock3Secondary = dp2.StateMemoryaaBlock3.read();
+ iTempProb[2] = CurStateMemoryaaBlock3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != iPos1) {
+ dp.StateMemoryaaBlock2.clear(iPos1);
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock2To = dp.StateMemoryaaBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock2Secondary = dp2.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock2To[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2To[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock2To[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[0];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2To[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock2To[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[2];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2To[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[0];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2To[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
+ CurStateMemoryaaBlock2To[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaBlock2To[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[0];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaBlock2To[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemoryaaBlock2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
+ CurStateMemoryaaBlock1Secondary = dp2.StateMemoryaaBlock1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemoryaaBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ iTempProb[0] = CurStateMemoryaaBlock1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat Backward(AminoAcidAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemoryaaBlock2To;
+ const bfloat *CurStateMemoryaaBlock2From;
+ const bfloat *CurStateMemoryaaBlock3From;
+ bfloat *CurStateMemoryaaBlock1To;
+ const bfloat *CurStateMemoryaaBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidAlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemoryaaBlock3.write()[0] = 1.0;
+ dp.StateMemoryaaBlock3.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock2To = dp.StateMemoryaaBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock2To[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ CurStateMemoryaaBlock2To[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock2To[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ CurStateMemoryaaBlock2To[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock2To[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ CurStateMemoryaaBlock2To[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ CurStateMemoryaaBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
+ CurStateMemoryaaBlock2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ CurStateMemoryaaBlock2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ CurStateMemoryaaBlock2To[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ }
+ dp.StateMemoryaaBlock2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
+ }
+ dp.StateMemoryaaBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ iTempProb[0] = CurStateMemoryaaBlock1From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidAlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+const string _AminoAcidAlignWithBandingstateId[] = {"start","insert1","match","delete1","end"};
+const string _AminoAcidAlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _AminoAcidAlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
+const string _AminoAcidAlignWithBandingtransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
+const string _AminoAcidAlignWithBandingtransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
+const string _AminoAcidAlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
+const string _AminoAcidAlignWithBandingtransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _AminoAcidAlignWithBandingoutputId[] = {"sequence1","sequence2"};
+const string _AminoAcidAlignWithBandingempty = "";
+const int _AminoAcidAlignWithBandingstateNum = 5;
+const int _AminoAcidAlignWithBandingemitNum = 4;
+const int _AminoAcidAlignWithBandingtransNum = 13;
+const int _AminoAcidAlignWithBandingoutputNum = 2;
+
+
+
+
+bfloat ForwardBanding(AminoAcidAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemoryaaBlock2withbandingTo;
+ const bfloat *CurStateMemoryaaBlock1From;
+ const bfloat *CurStateMemoryaaBlock2withbandingFrom;
+ bfloat *CurStateMemoryaaBlock3To;
+ const bfloat *CurStateMemoryaaBlock3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidAlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemoryaaBlock1.write()[0] = 1.0;
+ dp.StateMemoryaaBlock1.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.forwardIterator();
+ bool bLastSlowCoordInited = false;
+ int iLastSlowCoord = -1;
+ do {
+ if (bLastSlowCoordInited) {
+ if (iLastSlowCoord > position[1]) {
+ cout << "WARNING: Banding (forward): Slowest coordinate should be nondecreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ } else {
+ bLastSlowCoordInited = true;
+ }
+ iLastSlowCoord = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+-1>=0)) {
+ iSymbol[0] = iSequence2[position[1]+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+-1>=0)) {
+ iSymbol[1] = iSequence1[position[0]+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock2withbandingTo = dp.StateMemoryaaBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+0<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ CurStateMemoryaaBlock2withbandingTo[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
+ }
+ if ((position[1]+-1>=0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
+ CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ CurStateMemoryaaBlock2withbandingTo[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
+ }
+ if ((position[0]+-1>=0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ CurStateMemoryaaBlock2withbandingTo[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
+ }
+ if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
+ CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ }
+ dp.StateMemoryaaBlock2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextForward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ CurStateMemoryaaBlock3To = dp.StateMemoryaaBlock3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock3To[0] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ CurStateMemoryaaBlock3To[0] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ CurStateMemoryaaBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ }
+ dp.StateMemoryaaBlock3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
+ iTempProb[0] = CurStateMemoryaaBlock3From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidAlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelchBanding(AminoAcidAlignWithBandingBaumWelch& bw,AminoAcidAlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ const bfloat *CurStateMemoryaaBlock3Secondary;
+ bfloat iTransition[13];
+ bfloat *CurStateMemoryaaBlock2withbandingTo;
+ const bfloat *CurStateMemoryaaBlock2withbandingSecondary;
+ const bfloat *CurStateMemoryaaBlock2withbandingFrom;
+ unsigned char alphaSymbolaminoacid[20] = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'};
+ unsigned char alphaIndexaminoacid[256];
+ const bfloat *CurStateMemoryaaBlock3From;
+ bfloat *CurStateMemoryaaBlock1To;
+ const bfloat *CurStateMemoryaaBlock1Secondary;
+ const bfloat *CurStateMemoryaaBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ AminoAcidAlignWithBandingFoldedDPTable dp(iLen1,2);
+ AminoAcidAlignWithBandingDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexaminoacid[i]=0;
+ }
+
+// for (int i=0; i<20; i++) {
+// alphaIndexaminoacid[alphaSymbolaminoacid[i]]=i;
+// }
+ for (int i=0; i<20; i++) {
+ alphaIndexaminoacid[tolower (alphaSymbolaminoacid[i])] = i;
+ alphaIndexaminoacid[toupper (alphaSymbolaminoacid[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemoryaaBlock3.write()[0] = 1.0;
+ dp.StateMemoryaaBlock3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock3Secondary = dp2.StateMemoryaaBlock3.read();
+ iTempProb[2] = CurStateMemoryaaBlock3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != position[1]) {
+ dp.StateMemoryaaBlock2withbanding.clear(position[1]);
+ }
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock2withbandingTo = dp.StateMemoryaaBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaBlock2withbandingSecondary = dp2.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaBlock2withbandingTo[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2withbandingTo[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2withbandingTo[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemoryaaBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
+ CurStateMemoryaaBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemoryaaBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemoryaaBlock2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
+ CurStateMemoryaaBlock1Secondary = dp2.StateMemoryaaBlock1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemoryaaBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ iTempProb[0] = CurStateMemoryaaBlock1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBanding(AminoAcidAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemoryaaBlock2withbandingTo;
+ const bfloat *CurStateMemoryaaBlock2withbandingFrom;
+ const bfloat *CurStateMemoryaaBlock3From;
+ bfloat *CurStateMemoryaaBlock1To;
+ const bfloat *CurStateMemoryaaBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'D'] = 2;
+ iTranslate[(unsigned)'d'] = 2;
+ iTranslate[(unsigned)'E'] = 3;
+ iTranslate[(unsigned)'e'] = 3;
+ iTranslate[(unsigned)'F'] = 4;
+ iTranslate[(unsigned)'f'] = 4;
+ iTranslate[(unsigned)'G'] = 5;
+ iTranslate[(unsigned)'g'] = 5;
+ iTranslate[(unsigned)'H'] = 6;
+ iTranslate[(unsigned)'h'] = 6;
+ iTranslate[(unsigned)'I'] = 7;
+ iTranslate[(unsigned)'i'] = 7;
+ iTranslate[(unsigned)'K'] = 8;
+ iTranslate[(unsigned)'k'] = 8;
+ iTranslate[(unsigned)'L'] = 9;
+ iTranslate[(unsigned)'l'] = 9;
+ iTranslate[(unsigned)'M'] = 10;
+ iTranslate[(unsigned)'m'] = 10;
+ iTranslate[(unsigned)'N'] = 11;
+ iTranslate[(unsigned)'n'] = 11;
+ iTranslate[(unsigned)'P'] = 12;
+ iTranslate[(unsigned)'p'] = 12;
+ iTranslate[(unsigned)'Q'] = 13;
+ iTranslate[(unsigned)'q'] = 13;
+ iTranslate[(unsigned)'R'] = 14;
+ iTranslate[(unsigned)'r'] = 14;
+ iTranslate[(unsigned)'S'] = 15;
+ iTranslate[(unsigned)'s'] = 15;
+ iTranslate[(unsigned)'T'] = 16;
+ iTranslate[(unsigned)'t'] = 16;
+ iTranslate[(unsigned)'V'] = 17;
+ iTranslate[(unsigned)'v'] = 17;
+ iTranslate[(unsigned)'W'] = 18;
+ iTranslate[(unsigned)'w'] = 18;
+ iTranslate[(unsigned)'Y'] = 19;
+ iTranslate[(unsigned)'y'] = 19;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ AminoAcidAlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemoryaaBlock3.write()[0] = 1.0;
+ dp.StateMemoryaaBlock3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock2withbandingTo = dp.StateMemoryaaBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaBlock2withbandingTo[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ CurStateMemoryaaBlock2withbandingTo[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ CurStateMemoryaaBlock2withbandingTo[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
+ CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
+ }
+ dp.StateMemoryaaBlock2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemoryaaBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemoryaaBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
+ }
+ dp.StateMemoryaaBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
+ iTempProb[0] = CurStateMemoryaaBlock1From[0];
+ }
+ }
+ *ppOutTable = new AminoAcidAlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/aminoaciddp.h b/src/fsa/aminoaciddp.h
new file mode 100644
index 0000000..c3f641b
--- /dev/null
+++ b/src/fsa/aminoaciddp.h
@@ -0,0 +1,315 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file aminoacid.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:18 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _aminoaciddp_h_
+#define _aminoaciddp_h_
+
+
+#include "dptables.h"
+#include "algebras.h"
+#include <string>
+
+#include <map>
+
+using std::map;
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesaaBlock2;
+typedef States<bfloat,1> StatesaaBlock1;
+typedef States<bfloat,1> StatesaaBlock3;
+
+class AminoAcidAlignDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesaaBlock2,2> StateMemoryaaBlock2;
+ DPTable<StatesaaBlock1,0> StateMemoryaaBlock1;
+ DPTable<StatesaaBlock3,0> StateMemoryaaBlock3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidAlignDPTable(int iLen1,int iLen2);
+ ~AminoAcidAlignDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat AminoAcidAlignReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double AminoAcidAlignShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesaaBlock2;
+typedef States<bfloat,1> StatesaaBlock3;
+typedef States<bfloat,1> StatesaaBlock1;
+
+class AminoAcidAlignFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesaaBlock2,2> StateMemoryaaBlock2;
+ DPTable<StatesaaBlock3,0> StateMemoryaaBlock3;
+ DPTable<StatesaaBlock1,0> StateMemoryaaBlock1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidAlignFoldedDPTable(int iLen1,int iLen2);
+ ~AminoAcidAlignFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class AminoAcidAlignBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ AminoAcidAlignBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[13];
+ static int transitionIdentifier00[13];
+ static const int transitionDimension00 = 13;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[20][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[20][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[20][20][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[13];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesaaBlock2withbanding;
+typedef States<bfloat,1> StatesaaBlock1;
+typedef States<bfloat,1> StatesaaBlock3;
+
+class AminoAcidAlignWithBandingDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesaaBlock2withbanding,2> StateMemoryaaBlock2withbanding;
+ DPTable<StatesaaBlock1,0> StateMemoryaaBlock1;
+ DPTable<StatesaaBlock3,0> StateMemoryaaBlock3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidAlignWithBandingDPTable(int iLen1,int iLen2);
+ ~AminoAcidAlignWithBandingDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat AminoAcidAlignWithBandingReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double AminoAcidAlignWithBandingShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesaaBlock2withbanding;
+typedef States<bfloat,1> StatesaaBlock3;
+typedef States<bfloat,1> StatesaaBlock1;
+
+class AminoAcidAlignWithBandingFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesaaBlock2withbanding,2> StateMemoryaaBlock2withbanding;
+ DPTable<StatesaaBlock3,0> StateMemoryaaBlock3;
+ DPTable<StatesaaBlock1,0> StateMemoryaaBlock1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ AminoAcidAlignWithBandingFoldedDPTable(int iLen1,int iLen2);
+ ~AminoAcidAlignWithBandingFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class AminoAcidAlignWithBandingBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ AminoAcidAlignWithBandingBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[13];
+ static int transitionIdentifier00[13];
+ static const int transitionDimension00 = 13;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[20][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[20][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[20][20][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[13];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+bfloat Forward(AminoAcidAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat BackwardBaumWelch(AminoAcidAlignBaumWelch& bw,AminoAcidAlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat Backward(AminoAcidAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat ForwardBanding(AminoAcidAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBaumWelchBanding(AminoAcidAlignWithBandingBaumWelch& bw,AminoAcidAlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBanding(AminoAcidAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+#endif // _aminoaciddp_h_
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/anchors.cc b/src/fsa/anchors.cc
new file mode 100644
index 0000000..8505db8
--- /dev/null
+++ b/src/fsa/anchors.cc
@@ -0,0 +1,1536 @@
+
+/**
+ * \file anchors.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <unistd.h>
+#include <cstdio>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <algorithm>
+
+#include "seq/alignment.h"
+#include "fsa/anchors.h"
+
+#define FILENAME_PREFIX "fsa_tmp_seq"
+#define TMP_DIR "/tmp"
+
+#define GUI_FILENAME_ANCHORS_SUFFIX ".anchors"
+
+using namespace fsa;
+
+// Note that unless specified otherwise, we use a 0-based coordinate system.
+// The SparseMatrix code uses a 1-based system, but its constructor expects
+// 0-based coordinates as input and the conversion happens behind the scenes.
+
+// constructor
+Anchor::Anchor (Interval xcoords, Interval ycoords)
+ : xcoords (xcoords), ycoords (ycoords),
+ __score (-1.),
+ __external_scoring (false),
+ __immutable (false) {
+
+ update();
+
+}
+
+// constructor
+Anchor::Anchor (Interval xcoords, Interval ycoords, double score)
+ : xcoords (xcoords), ycoords (ycoords),
+ __score (score),
+ __external_scoring (false),
+ __immutable (false) {
+
+ update();
+
+}
+
+void Anchor::update() {
+
+ // ensure valid coordinates
+ assert ((xcoords.start >= 0) && (xcoords.end >= xcoords.start));
+ assert ((ycoords.start >= 0) && (ycoords.end >= ycoords.start));
+ assert ((xcoords.end - xcoords.start) == (ycoords.end - ycoords.start));
+
+ x = static_cast<unsigned> (std::floor (0.5 * (xcoords.end + xcoords.start)));
+ y = static_cast<unsigned> (std::floor (0.5 * (ycoords.end + ycoords.start)));
+
+ assert (x - y == xcoords.end - ycoords.end);
+
+ length = xcoords.end - xcoords.start + 1;
+ assert (length > 0);
+
+}
+
+double Anchor::p_value (const std::string& xseq, const std::string& yseq) const {
+ return p_value (&xseq, &yseq);
+}
+
+double Anchor::p_value (const std::string* xseq, const std::string* yseq) const {
+
+ // extract anchored subseqs
+ const std::string& xsubseq = xseq->substr (xcoords.start, length);
+ const std::string& ysubseq = yseq->substr (ycoords.start, length);
+
+ // calculate hamming distance (# of mismatches)
+ size_t h = 0;
+ for (size_t i = 0; i < length; ++i) {
+ if (xsubseq[i] != ysubseq[i])
+ ++h;
+ }
+
+ // get p-value (normalize to [0,1])
+ const double pval = 1.0 - static_cast<double> (length) / static_cast<double> (std::max (xseq->length(), yseq->length()));
+ assert ((pval >= 0.) && (pval <= 1.0));
+
+ return pval;
+}
+
+void Anchors::show (std::ostream& o) const {
+ for (std::vector<Anchor>::const_iterator anchor = begin(); anchor != end(); ++anchor)
+ o << *anchor << endl;
+}
+
+void Anchors::write_gui_output (std::ostream& o, const size_t xidx, const size_t yidx) const {
+ for (std::vector<Anchor>::const_iterator anchor = this->begin(); anchor != this->end(); ++anchor)
+ o << "(" << xidx << " ~ " << yidx << ") == " << *anchor << endl;
+}
+
+Anchors Anchors::convert_constraints_to_anchors (const Constraints& constraints, const Sequence& xseq_orig, const Sequence& yseq_orig, const bool hardmasked) {
+
+ Anchors anchors;
+ for (std::vector<Constraint>::const_iterator constraint = constraints.begin(); constraint != constraints.end(); ++constraint) {
+
+ // left end
+ Anchor left (Interval (constraint->xcoords.start, constraint->xcoords.start),
+ Interval (constraint->ycoords.start, constraint->ycoords.start));
+ left.set_immutable();
+
+ // right end
+ Anchor right (Interval (constraint->xcoords.end, constraint->xcoords.end),
+ Interval (constraint->ycoords.end, constraint->ycoords.end));
+ right.set_immutable();
+
+ // move anchors if necessary to get out of hardmasked region
+ bool is_anchor_entirely_hardmasked = false;
+ if (hardmasked) {
+
+ // if necessary, increment left boundary along the sequences until it doesn't fall in a hardmasked region
+ bool shifted = false; // for logging
+ while (xseq_orig.is_pos_hardmasked (left.x) || yseq_orig.is_pos_hardmasked (left.y)) {
+ shifted = true;
+ left.xcoords.start = left.xcoords.end = (left.x + 1);
+ left.ycoords.start = left.ycoords.end = (left.y + 1);
+ left.update();
+ // check whether the increment boundary is valid
+ // (falls within sequence limits and not past right-hand boundary)
+ if ((left.x >= xseq_orig.length()) || (left.x >= right.x)) {
+ is_anchor_entirely_hardmasked = true;
+ break;
+ }
+ }
+
+ if (shifted && !is_anchor_entirely_hardmasked)
+ CTAG(6,ANCHORING) << "WARNING: Shifted Mercator constraint boundary which fell in hardmasked region; new left-hand boundary is: " << left << endl;
+
+ // if necessary, decrement right boundary along the sequences until doesn't fall in a hardmasked region
+ shifted = false;
+ while (xseq_orig.is_pos_hardmasked (right.x) || yseq_orig.is_pos_hardmasked (right.y)) {
+ shifted = true;
+ right.xcoords.start = right.xcoords.end = (right.x - 1);
+ right.ycoords.start = right.ycoords.end = (right.y - 1);
+ right.update();
+ if ((right.x >= xseq_orig.length()) || (left.x >= right.x)) {
+ is_anchor_entirely_hardmasked = true;
+ break;
+ }
+ }
+
+ if (shifted && !is_anchor_entirely_hardmasked)
+ CTAG(6,ANCHORING) << "WARNING: Shifted Mercator constraint boundary which fell in hardmasked region; new right-hand boundary is: " << right << endl;
+
+ }
+
+ // if anchor is entirely hardmasked in one sequence, then ignore it
+ if (is_anchor_entirely_hardmasked) {
+ CTAG(6,ANCHORING) << "WARNING: Mercator constraint fell entirely within a hardmasked region; ignoring it entirely." << endl;
+ continue;
+ }
+
+ // store anchors
+ anchors.store (left);
+ anchors.store (right);
+
+ }
+
+ // if hardmasking, map Mercator coordinates to stripped sequence
+ if (hardmasked) {
+ for (std::vector<Anchor>::iterator anchor = anchors.begin(); anchor != anchors.end(); ++anchor) {
+ anchor->xcoords.start = xseq_orig.map_orig_to_stripped (anchor->xcoords.start);
+ anchor->xcoords.end = xseq_orig.map_orig_to_stripped (anchor->xcoords.end);
+ anchor->ycoords.start = yseq_orig.map_orig_to_stripped (anchor->ycoords.start);
+ anchor->ycoords.end = yseq_orig.map_orig_to_stripped (anchor->ycoords.end);
+ anchor->update();
+ // sanity check
+ if ((anchor->xcoords.end == xseq_orig.length()) || (anchor->ycoords.end == yseq_orig.length())) {
+ THROWEXPR ("ERROR: Mercator constraint falls in a hardmasked interval:" << endl << *anchor);
+ }
+ }
+ }
+
+ return anchors;
+
+}
+
+const Post_probs Anchors::convert_to_post_probs() const {
+
+ // store each Anchor as an entry
+ Post_probs post_probs;
+ for (std::vector<Anchor>::const_iterator anchor = begin(); anchor != end(); ++anchor)
+ post_probs.push_back (Post_prob (anchor->x, anchor->y, anchor->get_score()));
+
+ // now enforce lexical ordering on centroids
+ // (required by SparseMatrix constructor)
+ // forgetting this step caused me BIG PAIN!
+ std::sort (post_probs.begin(), post_probs.end());
+
+ return post_probs;
+}
+
+bool Anchors::create_spanning_map() {
+
+ __spanning_map.clear();
+
+ bool nondegen = true;
+ for (size_t i = 0; i < this->size(); ++i)
+ nondegen = __spanning_map.insert (std::make_pair (std::make_pair ((*this)[i].x, (*this)[i].y), i)).second;
+
+ return nondegen;
+}
+
+size_t Anchors::exists_spanning_anchor (const unsigned x, const unsigned y) const {
+
+ if (__spanning_map.find (std::make_pair (x, y)) != __spanning_map.end())
+ return (*__spanning_map.find (std::make_pair (x, y))).second;
+
+ return size();
+
+}
+
+const Anchor Anchors::get_spanning_anchor (const unsigned x, const unsigned y) {
+
+ const size_t idx = exists_spanning_anchor (x, y);
+ assert (idx < this->size());
+ assert (((*this)[idx].xcoords.start <= x) && ((*this)[idx].xcoords.end >= x));
+ assert (((*this)[idx].ycoords.start <= y) && ((*this)[idx].ycoords.end >= y));
+ return (*this)[idx];
+
+}
+
+bool Anchors::resolve_parallel (const size_t max_join_distance /* = 0 */, const bool concatenate_immutable /* = false */) {
+
+ CTAG (6,ANCHORING ANCHORING_VERBOSE) << "Resolving parallel anchors." << endl;
+
+ // catch case of no anchors (very important!)
+ if (size() == 0)
+ return true;
+
+ // lexical sort in x coordinate (essential)
+ // we get this automatically from MUMmer if not using translated anchors,
+ // but must do it by hand if using translated anchors
+ std::sort (begin(), end(), Anchor::lexical_comparison_x);
+
+ // first deal with overlapping degenerate parallel anchors
+ Anchors resolved (this->xseq, this->yseq);
+ std::vector<bool> processed (size(), false);
+ for (size_t i = 0; i < this->size(); ++i) {
+
+ // if we've already dealt with this anchor, ignore it and go to the next
+ if (processed[i])
+ continue;
+ // else mark as processed
+ else
+ processed[i] = true; // this actually isn't necessary but it makes me happy
+
+ Anchor& curr = (*this)[i];
+
+ // don't concatenate immutable anchors unless so requested; leave them disjoint
+ // this is crucial when concatenating parallel anchors prior to performing anchor annealing:
+ // if two original immutable anchors abut and one is concatenated so
+ // as to give a centroid overlapping the centroid of the other immutable anchor,
+ // then we will get negative gap posterior errors
+ // => very very bad
+ // So: just store current (immutable) anchor
+ if (curr.is_immutable() && !concatenate_immutable) {
+ resolved.store (curr);
+ continue;
+ }
+
+ // right-hand x boundary of the current anchor
+ unsigned currright = curr.xcoords.end;
+
+ // look for overlapping parallel anchors
+ for (size_t j = i + 1; j < this->size(); ++j) { // i + 1 because lexical sorting
+
+ const Anchor& overlap = (*this)[j];
+
+ // don't concatenate immutable anchors unless so requested; leave them disjoint
+ if (overlap.is_immutable() && !concatenate_immutable)
+ continue;
+
+ // does this anchor overlap or is it within max_join_distance of the previous?
+ unsigned overlapleft = overlap.xcoords.start;
+ unsigned overlapright = overlap.xcoords.end;
+ if (static_cast<int> (overlapleft - currright) > static_cast<int> (max_join_distance)) // if not, then stop;
+ break; // lexical ordering means there can be no other overlaps or acceptably adjacent anchors
+
+ // is this anchor parallel with the current anchor?
+ if (!curr.is_parallel (overlap)) // if not, then go on to the next
+ continue;
+ else
+ processed[j] = true; // else mark as processed and deal with it
+
+ // if this overlapping anchor is completely degenerate (contained within anchor curr),
+ // then just ignore it (conveys no new information)
+ // (although handle special cases of immutable anchors)
+ if (overlapright <= currright) {
+
+ // handle case of immutable anchor
+ // deal with it by marking the containing anchor as immutable
+ // and ignoring (implicitly dropping) the original immutable anchor
+ if (overlap.is_immutable() && concatenate_immutable) {
+ curr.set_immutable();
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Marking anchor containing immutable anchor as immutable itself:" << endl
+ << curr << endl;
+ }
+ }
+
+ // handle case of external_scoring anchor
+ // deal with it by marking the containing anchor as external_scoring
+ // and ignoring (implicitly dropping) the original external_scoring anchor
+ if (overlap.is_external_scoring()) {
+ curr.set_external_scoring();
+ curr.set_score (overlap.get_score()); // won't affect immutable anchors
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Marking anchor containing externally-scored anchor as externally-scored itself:" << endl
+ << curr << endl;
+ }
+ }
+
+ // else ignore (implicitly drop) the degenerate anchor
+ else {
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Dropping degenerate first anchor in favor of second:" << endl
+ << overlap << endl
+ << curr << endl;
+ }
+ }
+
+ continue;
+ }
+
+ // else increment boundaries of current anchor as appropriate
+ // (although handle special cases of immutable anchors)
+ else {
+
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Concatenating these two parallel anchors:" << endl
+ << curr << endl
+ << overlap << endl;
+ }
+
+ // increment coordinates for current anchor
+ curr.xcoords.end = overlap.xcoords.end;
+ curr.ycoords.end = overlap.ycoords.end;
+ currright = curr.xcoords.end;
+
+ // handle case of immutable anchor
+ // deal with it by marking the current anchor as immutable
+ if (overlap.is_immutable() && concatenate_immutable) {
+ curr.set_immutable();
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Marking anchor containing immutable anchor as immutable itself:" << endl
+ << curr << endl;
+ }
+ }
+
+ // handle case of external_scoring anchor
+ // deal with it by marking the current anchor as external_scoring
+ if (overlap.is_external_scoring()) {
+ curr.set_external_scoring();
+ curr.set_score (overlap.get_score()); // won't affect immutable anchors
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Marking anchor containing externally-scored anchor as externally-scored itself:" << endl
+ << curr << endl;
+ }
+ }
+
+ }
+
+ }
+
+ // update and store current anchor
+ curr.update();
+ resolved.store (curr);
+ resolved.update_score (resolved.size() - 1);
+
+ }
+
+ // store the results
+ __anchors.assign (resolved.begin(), resolved.end());
+
+ // enforce immutable unique
+ // (we can't call create_spanning_map directly before enforce_immutable_unique
+ // because we need to ensure that the immutable anchors are nondegenerate first)
+ enforce_immutable_unique();
+
+ // now re-create the spanning_map
+ return create_spanning_map();
+
+}
+
+void Anchors::enforce_immutable_unique() {
+
+ std::set<unsigned> immutable_x;
+ std::set<unsigned> immutable_y;
+
+ // get immutable coordinates
+ const Anchors immutable_anchors;
+ for (std::vector<Anchor>::const_iterator anchor = begin(); anchor != end(); ++anchor) {
+ if (anchor->is_immutable()) {
+ immutable_x.insert (anchor->x);
+ immutable_y.insert (anchor->y);
+ }
+ }
+
+ // if there are no immutable anchors, then we're done!
+ if (!immutable_x.size())
+ return;
+
+ Anchors passed;
+ for (std::vector<Anchor>::const_iterator anchor = begin(); anchor != end(); ++anchor) {
+
+ // if immutable, store and continue
+ if (anchor->is_immutable()) {
+ passed.store (*anchor);
+ continue;
+ }
+
+ // else see if it overlaps an immutable anchor
+ else {
+
+ // drop it if overlaps with immutable
+ if ((immutable_x.find (anchor->x) != immutable_x.end()) || (immutable_y.find (anchor->y) != immutable_y.end())) {
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Dropping anchor which overlaps an immutable anchor:" << endl
+ << *anchor << endl;
+ }
+ continue;
+ }
+
+ // else keep it
+ else {
+ passed.store (*anchor);
+ }
+
+ }
+
+ }
+
+ __anchors.assign (passed.begin(), passed.end());
+
+}
+
+void Anchors::remove_overlaps (const size_t minlen /* = ANCHOR_NUC_MINLEN_DEFAULT */) {
+
+ // the x and y coordinates are handled separately in the hope of greater efficiency
+ // (since pruning x means pruning y as well => fewer possiblities for overlapping anchors)
+
+ // sort by x, prune by x
+ std::sort (begin(), end(), Anchor::lexical_comparison_x);
+ remove_overlaps (minlen, 0);
+
+ // sort by x, prune by y
+ std::sort (begin(), end(), Anchor::lexical_comparison_x);
+ remove_overlaps (minlen, 1);
+
+ // sort by y, prune by x
+ std::sort (begin(), end(), Anchor::lexical_comparison_y);
+ remove_overlaps (minlen, 0);
+
+ // sort by y, prune by y
+ std::sort (begin(), end(), Anchor::lexical_comparison_y);
+ remove_overlaps (minlen, 1);
+
+}
+
+void Anchors::remove_overlaps (const size_t minlen, const unsigned which) {
+
+ // loop over all anchors:
+ // for each anchor i
+ // find all overlapping anchors
+ // for each overlapping anchor j
+ // if anchor j scores below the current anchor i, then prune the left-hand boundary of j
+ // if anchor j scores above the current anchor i, then prune the right-hand boundary of i; break
+ // (break because the lexical sorting means that anchor j will be the lefthand-most overlapping anchor)
+
+ // We require both lexical ordering and consistency of anchors.
+ // Lexical ordering guarantees that the anchors are sorted by increasing left-hand x coordinate.
+
+ std::vector<bool> is_dead (size(), false);
+ for (size_t i = 0; i < size(); ++i) {
+
+ // skip if dead
+ if (is_dead[i])
+ continue;
+
+ Anchor& curr = (*this)[i]; // must be a reference so that we aren't just modifying a copy!
+
+ // right-hand x boundary of the current anchor
+ unsigned xright = (which == 0) ? curr.xcoords.end : curr.ycoords.end;
+
+ // assemble list of overlapping anchors
+ std::list<size_t> xoverlaps;
+ unsigned xleftmost = xright; // leftmost boundary of overlaps
+ for (size_t j = i + 1; j < size(); ++j) { // i + 1 because lexical sorting
+
+ // ignore dead anchors
+ if (is_dead[j])
+ continue;
+
+ // does this anchor overlap with the previous?
+ unsigned jxleft = (which == 0) ? (*this)[j].xcoords.start : (*this)[j].ycoords.start;
+ if (jxleft > xright) // if it doesn't overlap, then stop;
+ break; // lexical ordering means there can be no other overlaps
+
+ // store and increment boundaries
+ xoverlaps.push_back (j);
+ if (jxleft < xleftmost)
+ xleftmost = jxleft;
+
+ }
+
+ // if there are overlaps, make sure that coordinate boundaries are sane
+ if (xoverlaps.size())
+ assert (xleftmost <= xright);
+ // if no overlaps, go to the next anchor
+ else
+ continue;
+
+ // go through the list of overlapping coordinates:
+ // at each overlapping anchor, choose in favor of either current anchor i or overlapping anchor *overlap
+ // prune anchors as appropriate
+ assert (xright >= xleftmost);
+ for (unsigned s = 0; s <= xright - xleftmost; ++s) { // s is the distance "within" anchor i
+ unsigned x = xleftmost + s; // x is the actual x coordinate
+
+ assert (x <= ((which == 0) ? curr.xcoords.end : curr.ycoords.end));
+
+ std::list<size_t>::iterator overlapidx = xoverlaps.begin(); // use STL erase-remove idiom
+ while (overlapidx != xoverlaps.end()) { // *overlapidx is index of overlapping anchor in (*this)
+
+ Anchor& overlap = (*this)[*overlapidx]; // must be a reference so that we aren't just modifying a copy!
+
+ // does this anchor overlap at coordinate x?
+ // if not, then go on to the next
+ if (((which == 0) && overlap.xcoords.start > x) || (!(which == 0) && overlap.ycoords.start > x)) {
+ ++overlapidx;
+ continue;
+ }
+
+ // log before
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE)) {
+ if (which == 0)
+ CL << "Overlapping anchors (x = " << x << "):" << endl
+ << curr << endl
+ << overlap << endl;
+ else
+ CL << "Overlapping anchors (y = " << x << "):" << endl
+ << curr << endl
+ << overlap << endl;
+
+ }
+
+ // if anchor overlap is a new best,
+ // then prune the right-hand boundary of current anchor i here
+ // and end loop over coordinates (because we're done with anchor i)
+ if (overlap.get_score() > curr.get_score()) {
+
+ // calculate distance to prune anchor
+#ifndef NDEBUG
+ if (which == 0)
+ assert (static_cast<int> (curr.xcoords.end) - (x - 1) >= 0);
+ else
+ assert (static_cast<int> (curr.ycoords.end) - (x - 1) >= 0);
+#endif // NDEBUG
+ const unsigned delta = ((which == 0) ? curr.xcoords.end : curr.ycoords.end) - (x - 1);
+
+ // catch case of current anchor being shorter than the distance to prune
+ // or new length shorter than minlen
+ // (note that this always includes the case of length-1 (transitive) anchors)
+ // if so, then mark it as dead
+ if ((curr.length <= delta) || ((curr.length - delta) < minlen)) {
+ assert (!curr.is_immutable() || overlap.is_immutable()); // sanity check: either the current anchor must not be immutable,
+ is_dead[i] = true; // or the better overlapping anchor must be
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE))
+ CL << "Pruned by removing first anchor." << endl;
+ }
+ // else prune the current anchor *iter
+ else {
+ curr.xcoords.end -= delta;
+ curr.ycoords.end -= delta;
+ curr.update();
+ update_score (i);
+ // log after
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Pruned as:" << endl
+ << curr << endl
+ << overlap << endl;
+ }
+ }
+ // if we found a better overlapping anchor, then stop the loop over overlaps
+ // as well as coordinates
+ // (because we've already pruned and are done with the current anchor)
+ goto FOUND_BETTER;
+
+ }
+
+ // otherwise overlapping anchor overlap isn't as good,
+ // so prune its left-hand boundary and drop it from the list of overlaps
+ else {
+
+ // calculate distance to prune anchor
+#ifndef NDEBUG
+ if (which == 0)
+ assert (static_cast<int> (curr.xcoords.end + 1) - overlap.xcoords.start);
+ else
+ assert (static_cast<int> (curr.ycoords.end + 1) - overlap.ycoords.start);
+#endif // NDEBUG
+ const unsigned delta = (which == 0) ? ((curr.xcoords.end + 1) - overlap.xcoords.start) : ((curr.ycoords.end + 1) - overlap.ycoords.start);
+
+ // catch case of *overlap being shorter than the distance to prune
+ // or new length shorter than minlen
+ // (note that this always includes the case of length-1 (transitive) anchors)
+ // if so, then erase *overlap entirely
+ if ((overlap.length <= delta) || ((overlap.length - delta) < minlen)) {
+ assert (!overlap.is_immutable() || curr.is_immutable()); // sanity check: either the current anchor must not be immutable,
+ is_dead[*overlapidx] = true; // or the better overlapping anchor must be
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE))
+ CL << "Pruned by removing second anchor." << endl;
+ }
+ // else prune overlap
+ else {
+ overlap.ycoords.start += delta;
+ overlap.xcoords.start += delta;
+ overlap.update();
+ update_score (*overlapidx);
+ // log after
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Pruned as:" << endl
+ << curr << endl
+ << overlap << endl;
+ }
+ }
+ // we're done with anchor *overlap; drop it from the list
+ overlapidx = xoverlaps.erase (overlapidx);
+
+ }
+
+ // Note that we don't need to explicitly increment overlapidx here at all:
+ // If *overlap is better than the curren anchor *iter, then we break out of
+ // the overlapidx loop with an explicit goto FOUND_BETTER.
+ // If *overlap is worse, then we prune it, remove it from the list of overlaps
+ // and reset overlapidx when using erase.
+
+ } // end loop over overlapping anchors
+
+ } // end loop over coordinates
+
+ FOUND_BETTER:
+ ; // hack to get around requirement of a statement post-label
+
+ }
+
+ // assemble and store list of pruned anchors
+ Anchors pruned (this->xseq, this->yseq);
+ for (size_t i = 0; i < size(); ++i) {
+ if (!is_dead[i])
+ pruned.store ((*this)[i]);
+ }
+
+ // store list of pruned anchors
+ __anchors.assign (pruned.begin(), pruned.end());
+
+}
+
+
+// to do: fix this for proper scoring
+// pull out the anchored subseqs, get hamming distance (mismatches)
+// and use BLAST theory / forward approximation
+void Anchors::update_score (const size_t idx) {
+
+ assert ((idx >= 0) && (idx < size()));
+
+ Anchor& anchor = (*this)[idx];
+
+ // compute anchor score as (1 - p_value)
+ if (!anchor.is_external_scoring()) {
+ anchor.set_score (1.0 - anchor.p_value (this->xseq, this->yseq));
+ assert ((anchor.get_score() >= 0.0) && (anchor.get_score() <= 1.0));
+ }
+
+}
+
+void Anchors::impose_normalized_probability_distribution() {
+
+ // sum of scores of anchors with particular coordinates
+ std::vector<double> sum_scorex (xseq->length(), 0.);
+ std::vector<double> sum_scorey (yseq->length(), 0.);
+
+ // max of scores of anchors with particular coordinates
+ std::vector<double> max_scorex (xseq->length(), 0.);
+ std::vector<double> max_scorey (yseq->length(), 0.);
+
+ // accumulate counts for normalization
+ for (size_t i = 0; i < size(); ++i) {
+
+ // update score
+ update_score (i);
+
+ const Anchor& anchor = (*this)[i];
+
+ // check sane
+ assert ((anchor.get_score() >= 0.0) && (anchor.get_score() <= 1.0));
+
+ // accumulate counts for normalization
+ sum_scorex[anchor.x] += anchor.get_score();
+ sum_scorey[anchor.y] += anchor.get_score();
+
+ max_scorex[anchor.x] = max (anchor.get_score(), max_scorex[anchor.x]);
+ max_scorey[anchor.y] = max (anchor.get_score(), max_scorey[anchor.y]);
+
+ }
+
+ for (size_t i = 0; i < size(); ++i) {
+
+ Anchor& anchor = (*this)[i];
+
+ if (anchor.is_immutable())
+ continue;
+
+ // sanity check for finiteness
+ assert ((sum_scorex[anchor.x] > 0) && (sum_scorey[anchor.y] > 0));
+
+ // reweight scores
+ anchor.set_score (max_scorex[anchor.x] * (anchor.get_score() / sum_scorex[anchor.x]));
+ anchor.set_score (max_scorey[anchor.y] * (anchor.get_score() / sum_scorey[anchor.y]));
+
+ // check sane
+ assert ((anchor.get_score() >= 0.0) && (anchor.get_score() <= 1.0));
+
+ }
+
+}
+
+Anchors Cabbage_adapter::get_candidate_anchors() const {
+
+ CTAG (6,ANCHORING ANCHORING_VERBOSE) << "Getting candidate anchors for sequence pair '" << xseq.name << "' and '" << yseq.name << "'." << endl;
+
+ Anchors anchors (xseq.seq, yseq.seq);
+
+ // (90,110) -- (190,210) => 100 -- 200; 0.1
+ // (140,160) -- (170,190) => 150 -- 180; 0.2
+ // (240,260) -- (290,310) => 250 -- 300; 0.3
+ // Because we use a 0-based coordinate system,
+ // these anchor the first "different" nucleotides starting a new sequence
+ // (rather than the last "same" ending the old sequence).
+
+ Anchor one (Interval (90, 110), Interval (190, 210), .1);
+ Anchor two (Interval (140, 160), Interval (170, 190), .2);
+ Anchor three (Interval (240, 260), Interval (290, 310), .3);
+
+ anchors.store (one);
+ anchors.store (two);
+ anchors.store (three);
+
+ if (!anchors.create_spanning_map())
+ THROWEXPR ("ERROR: Degenerate anchors.");
+
+ return anchors;
+}
+
+// Wrapper for call_exonerate.
+Anchors Exonerate_adapter::get_candidate_anchors (const int minscore /* = EXONERATE_MINSCORE_DEFAULT */) const {
+
+ CTAG (8,ANCHORING ANCHORING_VERBOSE) << "Getting candidate anchors (with exonerate) for sequence pair '" << xseq.name << "' and '" << yseq.name << "'." << endl;
+
+ Anchors anchors = call_exonerate (xseq.seq, yseq.seq, minscore);
+ return anchors;
+
+}
+
+Anchors Exonerate_adapter::call_exonerate (const std::string& xseq, const std::string& yseq, const int minscore /* = EXONERATE_MINSCORE_DEFAULT */) const {
+
+ // check that exonerate executable is properly defined;
+ // if not, then die
+#ifndef EXONERATE_EXEC
+ THROWEXPR ("ERROR: exonerate executable isn't defined; try recompiling and specifying the exonerate path.");
+ // else call exonerate!
+#else
+
+ // get pid of current process for unique filenames
+ pid_t curr_pid = getpid();
+
+ // write sequence files to scratch directory
+ std::string xfile = std::string (TMP_DIR) + "/" + FILENAME_PREFIX + "_" + Util::to_string (curr_pid) + "_x.fa";
+ std::string yfile = std::string (TMP_DIR) + "/" + FILENAME_PREFIX + "_" + Util::to_string (curr_pid) + "_y.fa";
+ // X
+ std::ofstream filestream;
+ filestream.open (xfile.c_str());
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << xfile << "'.");
+ filestream << ">X" << endl;
+ filestream << xseq << endl;
+ filestream.close();
+ // Y
+ filestream.open (yfile.c_str());
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << yfile << "'.");
+ filestream << ">Y" << endl;
+ filestream << yseq << endl;
+ filestream.close();
+
+ // create exonerate executable string
+ // prepare for use with execv()
+ // (which requires null-terminated string)
+ std::string exec;
+ exec = std::string (EXONERATE_EXEC)
+ + " " + xfile + " " + yfile
+ + " --querytype dna --targettype dna "
+ + " --score " + Util::to_string (minscore) + " --gappedextension false "
+ + " --saturatethreshold 5 "
+ + " --bigseq true "
+ + " --showvulgar false --showalignment false ";
+ if (__softmasked)
+ exec += " --softmaskquery true --softmasktarget true ";
+ if (__use_translated)
+ exec += " --model ungapped:trans --proteinsubmat blosum62 ";
+ else
+ exec += " --model ungapped ";
+
+ std::vector<std::string> exonerate_args = Util::split (exec);
+ exonerate_args.push_back (static_cast<std::string> ("--ryo")); // this hack is necessary to prevent splitting the --ryo args
+ exonerate_args.push_back (static_cast<std::string> ("%qab %qae %qS %tab %tae %tS %s\\n")); // note that this is NOT enclosed in double quotes
+ // these are only necessary for command-line usage
+ // (to prevent the shell from splitting the argument)
+
+ char* exonerate_argv [exonerate_args.size() + 1];
+ for (size_t i = 0; i < exonerate_args.size(); ++i)
+ exonerate_argv[i] = static_cast<char*> (const_cast<char*> (exonerate_args[i].c_str()));
+ exonerate_argv[exonerate_args.size()] = static_cast<char*> (0);
+ if (CTAGGING(6,ANCHORING ANCHORING_VERBOSE)) {
+ std::string exec_line;
+ for (std::vector<std::string>::iterator iter = exonerate_args.begin(); iter != exonerate_args.end(); ++iter)
+ exec_line += ' ' + *iter;
+ CTAG (6,ANCHORING ANCHORING_VERBOSE) << "Calling exonerate as '" << exec_line << "'" << endl;
+ }
+
+ // run exonerate
+ pid_t exonerate_pid;
+
+ // clear cin
+ std::cin.clear();
+
+ // tmp file to hold exonerate output
+ std::string output_file = std::string (TMP_DIR) + "/" + FILENAME_PREFIX + "_" + Util::to_string (curr_pid) + "_output";
+
+ // fork and call exonerate
+ int exonerate_status = 0;
+ if ((exonerate_pid = fork()) < 0) { // a negative PID indicates failure
+ THROWEXPR ("ERROR: Couldn't start fork; exiting.");
+ }
+ else if (exonerate_pid == 0) { // a 0 PID indicates the child process
+ freopen (output_file.c_str(), "w", stdout); // capture stdout (send to file output_file) to store exonerate results
+ freopen ("/dev/null", "a", stderr); // capture stderr (send to trash) so that it doesn't mess up our logging
+ if (execv (exonerate_argv[0], exonerate_argv) == -1) // replace child fork with a new process
+ THROWEXPR ("ERROR: Couldn't run exonerate (execv problem).");
+ fclose (stdout);
+ fclose (stderr);
+ }
+ else { // a positive PID indicates the parent process
+ waitpid (exonerate_pid, &exonerate_status, 0); // wait for child process to end
+ if (exonerate_status) // did it work?
+ THROWEXPR ("ERROR: Running exonerate failed with exit code " << exonerate_status << ".");
+ }
+
+ // read output_file and parse results to get anchors
+ // exonerate output format is:
+ // 564000 563704 - 243683 243386 - 168
+ // xstart xend xstrand ystart yend ystrand raw_score
+ // NB exonerate uses 0-based, half-open coordinates [start, end);
+ // we convert from this format to our 0-based, closed interval coordinates
+ Anchors anchors (xseq, yseq);
+ std::ifstream output_stream (output_file.c_str(), std::ifstream::in);
+ std::string line;
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE_VERBOSE))
+ CL << "exonerate output:" << endl;
+
+ while (!output_stream.eof()) {
+
+ getline (output_stream, line);
+ if (line.length() == 0) // skip empty lines
+ continue;
+
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE_VERBOSE))
+ CL << line;
+ std::string buffer;
+ std::stringstream ss (line);
+ std::vector<std::string> tokens; // vector to hold whitespace-separated tokens (words)
+ while (ss >> buffer)
+ tokens.push_back (buffer);
+
+ // skip exonerate's progress messages
+ if ((tokens.size() > 0) && ((tokens[0] == "Command") || (tokens[0] == "Hostname:") || (tokens[0] == "Message:") || (tokens[0] == "--")))
+ continue;
+
+ // now parse tokens into anchors
+ if (tokens.size() == 7) {
+
+ // parse output
+ const unsigned xstart = atoi (tokens[0].c_str()); // 0-based, half-open coordinates [start, end)
+ const unsigned xend = atoi (tokens[1].c_str()) - 1;
+ assert (tokens[2].length() == 1); // assert single character indicating strand
+ const char xstrand = (tokens[2])[0];
+ const unsigned ystart = atoi (tokens[3].c_str());
+ const unsigned yend = atoi (tokens[4].c_str()) - 1;
+ assert (tokens[5].length() == 1); // assert single character indicating strand
+ const char ystrand = (tokens[5])[0];
+ const double raw_score = static_cast<double> (atoi (tokens[6].c_str()));
+
+ // only consider collinear hits on forward strand
+ if ((xstrand != '+') || (ystrand != '+'))
+ continue;
+
+ // check sane
+ assert (xstart <= xend);
+ assert (ystart <= yend);
+ assert (raw_score >= minscore - DOUBLE_TINY);
+
+ // create anchor for ungapped aligned intervalval
+ anchors.store (Anchor (Interval (xstart, xend),
+ Interval (ystart, yend),
+ raw_score));
+
+ // mark the anchor as scored externally (no score updating later on)
+ anchors.back().set_external_scoring();
+
+ } else if (tokens.size() == 0) {
+ continue;
+ } else {
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE))
+ CL << "WARNING: I don't know how to parse exonerate output line: " << line;
+ continue;
+ }
+ }
+
+ output_stream.close();
+
+ // clean up temporary files
+ if (remove (xfile.c_str()) != 0)
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "WARNING: Couldn't delete temporary file '" << xfile << "'." << endl;
+ if (remove (yfile.c_str()) != 0)
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "WARNING: Couldn't delete temporary file '" << yfile << "'." << endl;
+ if (remove (output_file.c_str()) != 0)
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "WARNING: Couldn't delete temporary file '" << output_file << "'." << endl;
+
+ return anchors;
+
+#endif /* EXONERATE_EXEC */
+
+}
+
+
+// Wrapper for call_mummer.
+Anchors Mummer_adapter::get_candidate_anchors (size_t minlen /* = ANCHOR_NUC_MINLEN_DEFAULT */) const {
+
+ CTAG (8,ANCHORING ANCHORING_VERBOSE) << "Getting candidate anchors (with MUMmer) for sequence pair '" << xseq.name << "' and '" << yseq.name << "'." << endl;
+
+ Anchors anchors (xseq.seq, yseq.seq);
+
+ // anchoring on translated sequences in protein space
+ if (__use_translated) {
+
+ // get translated sequences
+ const Translated_sequence tr_x (xseq);
+ const Translated_sequence tr_y (yseq);
+
+ // forward strand for all frame combinations
+ for (size_t fx = 0; fx < 3; ++fx) {
+ for (size_t fy = 0; fy < 3; ++fy) {
+
+ // get anchors
+ Anchors tr_anchors = call_mummer (tr_x.get_forward (fx).seq, tr_y.get_forward (fy).seq, minlen);
+
+ // map anchor coordinates back to nucleotide sequence
+ for (std::vector<Anchor>::iterator anchor = tr_anchors.begin(); anchor != tr_anchors.end(); ++anchor) {
+ anchor->xcoords = tr_x.map_interval_to_orig (true, fx, anchor->xcoords);
+ anchor->ycoords = tr_y.map_interval_to_orig (true, fy, anchor->ycoords);
+ anchor->update();
+ // sanity check on mapping
+ assert (anchor->xcoords.end < xseq.length());
+ assert (anchor->ycoords.end < yseq.length());
+ // store anchor
+ anchors.store (*anchor);
+ anchors.update_score (anchors.size() - 1);
+ }
+
+ }
+ }
+
+// // reverse strand for all frame combinations
+// for (size_t fx = 0; fx < 3; ++fx) {
+// for (size_t fy = 0; fy < 3; ++fy) {
+//
+// // get anchors
+// Anchors tr_anchors = call_mummer (tr_x.reverse[fx], tr_y.reverse[fy], minlen);
+//
+// // map anchor coordinates back to nucleotide sequence
+// for (std::vector<Anchor>::iterator anchor = tr_anchors.begin(); anchor != tr_anchors.end(); ++anchor) {
+// anchor->xcoords = tr_x.map_interval_to_orig (false, fx, anchor->xcoords);
+// anchor->ycoords = tr_y.map_interval_to_orig (false, fy, anchor->ycoords);
+// anchor->update();
+// // store anchor
+// anchors.store (*anchor);
+// anchors.update_score (anchors.size() - 1);
+// }
+//
+// }
+// }
+// reverse strand doesn't convey much more information
+// -- RKB 10/11/08
+
+ }
+
+ // anchoring on nucleotide sequence
+ else {
+ anchors = call_mummer (xseq.seq, yseq.seq, minlen);
+ }
+
+ return anchors;
+
+}
+
+// I originally wrote this function using pipes to redirect the child process (mummer) stdout
+// to the parent process stdin. For some inscrutable reason, it only worked the first
+// time it was called; subsequent calls had nothing in cin.
+// This was very weird; I was saving and restoring the original stdin and stdout, but
+// it happened anyways.
+// Hence the current way, where I redirect stdout of the child process to a file.
+Anchors Mummer_adapter::call_mummer (const std::string& xseq, const std::string& yseq, size_t minlen /* = ANCHOR_NUC_MINLEN_DEFAULT */) const {
+
+ // check that MUMmer executable is properly defined;
+ // if not, then die
+#ifndef MUMMER_EXEC
+ THROWEXPR ("ERROR: MUMmer executable isn't defined; try recompiling and specifying the MUMmer path.");
+ // else call MUMmer!
+#else
+
+ // get pid of current process for unique filenames
+ const pid_t curr_pid = getpid();
+
+ // write sequence files to scratch directory
+ std::string xfile = std::string (TMP_DIR) + "/" + FILENAME_PREFIX + "_" + Util::to_string (curr_pid) + "_x.fa";
+ std::string yfile = std::string (TMP_DIR) + "/" + FILENAME_PREFIX + "_" + Util::to_string (curr_pid) + "_y.fa";
+ // X
+ std::ofstream filestream;
+ filestream.open (xfile.c_str());
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << xfile << "'.");
+ filestream << ">X" << endl;
+ filestream << xseq << endl;
+ filestream.close();
+ // Y
+ filestream.open (yfile.c_str());
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << yfile << "'.");
+ filestream << ">Y" << endl;
+ filestream << yseq << endl;
+ filestream.close();
+
+ // create mummer executable string
+ // prepare for use with execv()
+ // (which requires null-terminated string)
+ std::string exec = std::string (MUMMER_EXEC)
+ + " -mum -l " + Util::to_string (minlen)
+ + " " + xfile + " " + yfile;
+ const std::vector<std::string> mummer_args = Util::split (exec);
+ char* mummer_argv [mummer_args.size() + 1];
+ for (size_t i = 0; i < mummer_args.size(); ++i)
+ mummer_argv[i] = static_cast<char*> (const_cast<char*> (mummer_args[i].c_str()));
+ mummer_argv[mummer_args.size()] = static_cast<char*> (0);
+ if (CTAGGING(6,ANCHORING ANCHORING_VERBOSE))
+ CTAG (6,ANCHORING ANCHORING_VERBOSE) << "Calling MUMmer as '" << exec << "'" << endl;
+
+ // run mummer
+ pid_t mummer_pid;
+
+ // clear cin
+ std::cin.clear();
+
+ // tmp file to hold mummer output
+ std::string output_file = std::string (TMP_DIR) + "/" + FILENAME_PREFIX + "_" + Util::to_string (curr_pid) + "_output";
+
+ // fork and call mummer
+ int mummer_status = 0;
+ if ((mummer_pid = fork()) < 0) { // a negative PID indicates failure
+ THROWEXPR ("ERROR: Couldn't start fork; exiting.");
+ }
+ else if (mummer_pid == 0) { // a 0 PID indicates the child process
+ freopen (output_file.c_str(), "w", stdout); // capture stdout (send to file output_file) to store mummer results
+ freopen ("/dev/null", "a", stderr); // capture stderr (send to trash) so that it doesn't mess up our logging
+ if (execv (mummer_argv[0], mummer_argv) == -1) // replace child fork with a new process
+ THROWEXPR ("ERROR: Couldn't run MUMmer (execv problem).");
+ fclose (stdout);
+ fclose (stderr);
+ }
+ else { // a positive PID indicates the parent process
+ waitpid (mummer_pid, &mummer_status, 0); // wait for child process to end
+ if (mummer_status) // did it work?
+ THROWEXPR ("ERROR: Running MUMmer failed with exit code " << mummer_status << ".");
+ }
+
+ // read output_file and parse results to get anchors
+ // mummer output format is:
+ // >seqname
+ // xpos ypos match_length
+ // (position in reference sequence /t position in query sequence /t length of match)
+ // Note that we convert from 1-based (MUMmer's output) to 0-based coordinates here
+ Anchors anchors (xseq, yseq);
+ std::ifstream output_stream (output_file.c_str(), std::ifstream::in);
+ std::string line;
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE_VERBOSE))
+ CL << "MUMmer output:" << endl;
+ while (!output_stream.eof()) {
+ getline (output_stream, line);
+ // log
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE_VERBOSE))
+ CL << line;
+ std::string buffer;
+ // skip comments and sequence names
+ if ((line.length() > 0) && ((line[0] == '#') || (line[0] == '>')))
+ continue;
+ std::stringstream ss (line);
+ std::vector<std::string> tokens; // vector to hold whitespace-separated tokens (words)
+ while (ss >> buffer)
+ tokens.push_back (buffer);
+
+ // now parse tokens into anchors
+ if (tokens.size() == 3) {
+ unsigned xstart = atoi (tokens[0].c_str()) - 1; // convert from 1-based to 0-based coordinates
+ unsigned ystart = atoi (tokens[1].c_str()) - 1;
+ size_t length = atoi (tokens[2].c_str());
+ assert (length >= minlen);
+ anchors.store (Anchor (Interval (xstart, xstart + length - 1),
+ Interval (ystart, ystart + length - 1))); // -1 because closed interval
+ anchors.update_score (anchors.size() - 1);
+ } else if (tokens.size() == 0) {
+ continue;
+ } else {
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE))
+ CL << "WARNING: I don't know how to parse MUMmer output line: " << line;
+ continue;
+ }
+ }
+
+ output_stream.close();
+
+ // clean up temporary files
+ if (remove (xfile.c_str()) != 0)
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "WARNING: Couldn't delete temporary file '" << xfile << "'." << endl;
+ if (remove (yfile.c_str()) != 0)
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "WARNING: Couldn't delete temporary file '" << yfile << "'." << endl;
+ if (remove (output_file.c_str()) != 0)
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "WARNING: Couldn't delete temporary file '" << output_file << "'." << endl;
+
+ return anchors;
+
+#endif /* MUMMER_EXEC */
+
+}
+
+void Anchor_resolver::add_mercator_constraints (const std::string& filename) {
+
+ // read Mercator file
+ __constraints_set.read_mercator (filename);
+
+}
+
+const std::vector<Anchors> Anchor_resolver::get_resolved_anchors (const size_t minlen /* = ANCHOR_NUC_MINLEN_DEFAULT */, const size_t max_join_distance /* = 0 */, bool const use_translated /* = false */,
+ const bool use_exonerate /* = false */, const int minscore /* = EXONERATE_MINSCORE_DEFAULT */, const bool softmasked /* = false */,
+ const bool hardmasked /* = true */,
+ const size_t num_refinement_steps /* = 0 */,
+ const bool output_for_gui /* = false */, const std::string gui_prefix /* = "" */) const {
+
+ // initialize dummy Tree_weights (returns all weights as 1.0)
+ Tree_weights tree_weights;
+ return get_resolved_anchors (tree_weights,
+ minlen, max_join_distance, use_translated,
+ use_exonerate, minscore, softmasked,
+ hardmasked,
+ num_refinement_steps,
+ output_for_gui, gui_prefix);
+
+}
+
+const std::vector<Anchors> Anchor_resolver::get_resolved_anchors (const Tree_weights& tree_weights,
+ const size_t minlen /* = ANCHOR_NUC_MINLEN_DEFAULT */, const size_t max_join_distance /* = 0 */, const bool use_translated /* false */,
+ const bool use_exonerate /* = false */, const int minscore /* = EXONERATE_MINSCORE_DEFAULT */, const bool softmasked /* = false */,
+ const bool hardmasked /* = true */,
+ const size_t num_refinement_steps /* = 0 */,
+ const bool output_for_gui /* = false */, std::string gui_prefix /* = "" */) const {
+
+ // store all candidate anchors for later recovery
+ std::vector<Anchors> candidate_anchors_list (seq_pairs.size());
+
+ // This proceeds as:
+ // - get candidate anchors for all sequence pairs we're considering
+ // - create and store Post_probs objects for each sequence pair
+ // - create "reduced" sequences, where a reduced sequence is obtained from
+ // the original sequence by taking only positions corresponding to the
+ // centroids of candidate anchors
+ // - perform anchor annealing on the reduced sequences
+ // - map the resolved anchors back to the original sequence coordinates
+
+ // information to build reduced sequences:
+ // set of positions within the sequence which correspond to candidate anchors
+ std::vector<std::set<unsigned> > anchored_positions (seq_db.size());
+
+ // get list of candidate anchors
+ // list of Post_probs for each sequence pair
+ std::vector<Post_probs> post_probs_list (seq_pairs.size());
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt) {
+
+ // get sequence indices for this sequence pair
+ const size_t i = seq_pairs[cnt].first;
+ const size_t j = seq_pairs[cnt].second;
+
+ const Sequence& xseq = seq_db_internal.get_seq (i);
+ const Sequence& yseq = seq_db_internal.get_seq (j);
+
+ // if one of the seqs is empty, don't try to find anchors
+ // (MUMmer doesn't handle empty sequences gracefully)
+ if (!xseq.length() || !yseq.length())
+ continue;
+
+ // get candidate anchors
+ const Mummer_adapter mummer_adapter (xseq, yseq, use_translated); // find in protein space if requested
+ candidate_anchors_list[cnt] = mummer_adapter.get_candidate_anchors (minlen);
+
+ // if present, add Mercator constraint information as anchors
+ if (__constraints_set.size()) {
+ const Sequence& xseq_orig = seq_db.get_seq (i);
+ const Sequence& yseq_orig = seq_db.get_seq (j);
+ const Anchors constraints_anchors = Anchors::convert_constraints_to_anchors (__constraints_set.get_constraints (i, j), xseq_orig, yseq_orig, hardmasked);
+ // store constraints as anchors
+ candidate_anchors_list[cnt].store (constraints_anchors);
+ }
+
+ // get exonerate anchors if so requested
+ if (use_exonerate) {
+ const Exonerate_adapter exonerate_adapter (xseq, yseq, use_translated, softmasked);
+ const Anchors exonerate_anchors = exonerate_adapter.get_candidate_anchors (minscore);
+ candidate_anchors_list[cnt].store (exonerate_anchors);
+ }
+
+ // enforce immutable unique
+ // important that we do this before any other manipulations
+ // (otherwise, e.g., resolve_parallel might fail)
+ candidate_anchors_list[cnt].enforce_immutable_unique();
+
+ // resolve parallel anchors:
+ // remove degenerate anchors, merge overlapping anchors and concatenate adjacent anchors if requested
+ // essential if using translated anchors
+ if (!candidate_anchors_list[cnt].resolve_parallel (max_join_distance, false)) // don't concatenate immutable anchors
+ THROWEXPR ("ERROR: Couldn't resolve parallel anchors.");
+
+ // record the centroids of the candidate anchors to later build the reduced sequences
+ for (std::vector<Anchor>::const_iterator anchor = candidate_anchors_list[cnt].begin(); anchor != candidate_anchors_list[cnt].end(); ++anchor) {
+ anchored_positions[i].insert (anchor->x);
+ anchored_positions[j].insert (anchor->y);
+ }
+
+ }
+
+ // now properly normalize the scores of externally-scored anchors:
+ // first get the maximum score for an externally-scored anchor
+ // over the anchors for /all/ sequence pairs
+ double max_external_score = 0;
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt) {
+ for (std::vector<Anchor>::const_iterator anchor = candidate_anchors_list[cnt].begin(); anchor != candidate_anchors_list[cnt].end(); ++anchor) {
+ if (anchor->is_external_scoring() && (anchor->get_score() > max_external_score))
+ max_external_score = anchor->get_score();
+ }
+ }
+
+ // then use this max score as a normalization constant
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt) {
+ for (std::vector<Anchor>::iterator anchor = candidate_anchors_list[cnt].begin(); anchor != candidate_anchors_list[cnt].end(); ++anchor) {
+ if (anchor->is_external_scoring())
+ anchor->set_score ((anchor->get_score() / max_external_score) - DOUBLE_TINY); // (ensure all scores < 1.0)
+ // check sane after normalization to [0,1]
+ assert ((anchor->get_score() >= 0.0) && (anchor->get_score() <= 1.0));
+ }
+ }
+
+ // now finish pre-processing the anchors prior to anchor annealing and log them
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt) {
+
+ // convert score distribution over anchors to a normalized probability distribution
+ candidate_anchors_list[cnt].impose_normalized_probability_distribution();
+
+ // convert candidate anchors to Post_probs format
+ post_probs_list[cnt] = candidate_anchors_list[cnt].convert_to_post_probs();
+
+ // get sequence indices for this sequence pair
+ const size_t i = seq_pairs[cnt].first;
+ const size_t j = seq_pairs[cnt].second;
+
+ const Sequence& xseq = seq_db_internal.get_seq (i);
+ const Sequence& yseq = seq_db_internal.get_seq (j);
+
+ // log candidate anchors
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE)) {
+ CL << "Sequences '" << xseq.name << "' and '" << yseq.name << "' have candidate anchors:" << endl;
+ candidate_anchors_list[cnt].show (CL);
+ }
+
+ // log
+ size_t num_anchors = candidate_anchors_list[cnt].size();
+ CTAG (7,ANCHORING ANCHORING_VERBOSE) << "Found " << num_anchors << " candidate anchors for sequence pair '" << xseq.name << "' and '" << yseq.name << "'." << endl;
+
+ }
+
+ // create reduced_seq_db to hold actual reduced sequences
+ Sequence_database reduced_seq_db;
+ for (size_t i = 0; i < seq_db.size(); ++i) {
+ const Sequence& sequence = seq_db.get_seq (i);
+ std::string seq (anchored_positions[i].size(), 'R'); // R for Rob!
+ reduced_seq_db.add_seq (Sequence (sequence.name, seq));
+ }
+
+ // create map from positions in "reduced" sequences to positions in actual sequences
+ // note that the anchor positions in anchored_positions[i] are already sorted because it's a set
+ std::vector<std::map<unsigned, unsigned> > reduced_position_map (seq_db.size()); // map reduced -> original
+ std::vector<std::map<unsigned, unsigned> > reduced_position_reverse_map (seq_db.size()); // map original -> reduced
+ if (CTAGGING(-1,ANCHORING_VERBOSE))
+ CL << "reduced_position_map:" << endl;
+ for (size_t i = 0; i < seq_db.size(); ++i) {
+ unsigned ii = 0;
+ for (std::set<unsigned>::iterator x = anchored_positions[i].begin(); x != anchored_positions[i].end(); ++x, ++ii) { // ii is the position within the reduced sequence
+ reduced_position_map[i].insert (std::make_pair (ii, *x)); // x is the position within the original sequence
+ reduced_position_reverse_map[i].insert (std::make_pair (*x, ii));
+ if (CTAGGING(-1,ANCHORING_VERBOSE))
+ CL << "(" << i << ", " << *x << ") == " << ii << endl;
+ }
+ }
+
+ // store sparse matrices on reduced sequences for anchor annealing
+ std::vector<std::vector<SparseMatrix*> > sparse_matrices (seq_db.size(), std::vector<SparseMatrix*> (seq_db.size(), reinterpret_cast<SparseMatrix*> (NULL)));
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt) {
+
+ // get sequence indices for this sequence pair
+ const size_t i = seq_pairs[cnt].first;
+ const size_t j = seq_pairs[cnt].second;
+
+ // map the original sequence positions to the new reduced ones
+ for (Post_probs::iterator post = post_probs_list[cnt].begin(); post != post_probs_list[cnt].end(); ++post) {
+ (*post).x = reduced_position_reverse_map[i][(*post).x];
+ (*post).y = reduced_position_reverse_map[j][(*post).y];
+ }
+
+ // if reduced seqs are length 0, then leave null
+ if ((anchored_positions[i].size() == 0) || (anchored_positions[j].size() == 0))
+ continue;
+
+ // else create corresponding sparse matrix and store transpose
+ sparse_matrices[i][j] = new SparseMatrix (i, j,
+ anchored_positions[i].size(), anchored_positions[j].size(), post_probs_list[cnt]);
+ sparse_matrices[j][i] = sparse_matrices[i][j]->ComputeTranspose();
+
+ }
+
+ // do database stuff
+ // create empty database manager
+ Manager manager;
+
+ // now resolve anchors
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "Performing anchor annealing to resolve anchors." << endl;
+
+ // do anchor annealing
+ // It's important to perform use gap-factor 0;
+ // otherwise the result will depend heavily on how we scale the scores for the HSPs.
+ // This way will give the maximal set (well, a greedy version thereof) of consistent anchors.
+ Alignment_DAG dag (reduced_seq_db);
+ dag.anneal (sparse_matrices, tree_weights,
+ manager,
+ false, // use_tgf = false
+ 0, true, 0, // gap_factor = 0, enable_dynamic_weights = true, edge_weight_threshold = 0
+ num_refinement_steps,
+ false, ""); // output_for_gui = false, gui_prefix = ""
+ dag.dfs_topological_sort(); // this isn't really necessary but it does force removal of dead columns, which is nice
+
+ // convert the annealed alignment into a set of pairwise anchors
+ // initialize them with sequence lengths for score calculation
+ std::vector<Anchors> resolved_anchors_list;
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt)
+ resolved_anchors_list.push_back (Anchors (seq_db_internal.get_seq (seq_pairs[cnt].first).seq, seq_db_internal.get_seq (seq_pairs[cnt].second).seq));
+
+ // we need a mapping from sequence pairs to the corresponding index in seq_pairs
+ // -1 means not present; otherwise is the index
+ std::map<std::pair<size_t, size_t>, size_t> seq_pair_lookup;
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt)
+ seq_pair_lookup.insert (std::make_pair (std::make_pair (seq_pairs[cnt].first, seq_pairs[cnt].second), cnt));
+
+ // loop over columns of the alignment,
+ // interpreting aligned characters as constituting a resolved anchor
+
+ // don't store an anchor more than once:
+ // candidate_anchors_added[cnt][a] = true indicates that candidate_anchors_list[cnt][a]
+ // has already been added as a resolved anchor
+ std::vector<std::vector<bool> > candidate_anchors_added (candidate_anchors_list.size(), std::vector<bool> ());
+ for (size_t cnt = 0; cnt < candidate_anchors_list.size(); ++cnt)
+ candidate_anchors_added[cnt].assign (candidate_anchors_list[cnt].size(), false);
+
+ // now loop over columns of the DAG to look for aligned positions
+ const std::vector<Column*>& columns = dag.get_columns();
+ for (std::vector<Column*>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
+
+ // there shouldn't be any dead columns here
+ assert (!(*col)->is_dead());
+
+ const Seq_pos_map seq_pos_map = (*col)->get_seq_pos_map();
+
+ // if no aligned positions, continue on to the next column
+ if (seq_pos_map.size() < 2)
+ continue;
+
+ // create a pairwise anchor for each pair of aligned characters
+ for (Seq_pos_map::const_iterator seq_pos1 = seq_pos_map.begin(); seq_pos1 != seq_pos_map.end(); ++seq_pos1) {
+ for (Seq_pos_map::const_iterator seq_pos2 = seq_pos_map.begin(); seq_pos2 != seq_pos_map.end(); ++seq_pos2) {
+
+ // sequence indices
+ const size_t i = seq_pos1->first;
+ const size_t j = seq_pos2->first;
+ assert ((i < seq_db.size()) && (j < seq_db.size()));
+
+ // require i < j to prevent duplicates
+ if (i >= j)
+ continue;
+
+ // make sure that the sequence pair (i, j) is in the list seq_pairs of sequence pairs to process;
+ // if not, then continue on to the next pair
+ if (seq_pair_lookup.find (std::make_pair (i, j)) == seq_pair_lookup.end())
+ continue;
+ const size_t cnt = seq_pair_lookup[std::make_pair (i, j)];
+
+ const unsigned x = (reduced_position_map[i])[(*seq_pos1).second]; // map from positions within the reduced sequences to the original sequences
+ const unsigned y = (reduced_position_map[j])[(*seq_pos2).second]; // (*seq_pos1).second -> reduced_position_map[j][(*seq_pos1).second]
+ assert ((x < seq_db.get_seq (i).length()) && (y < seq_db.get_seq (j).length()));
+
+ // here "transitive anchoring" comes into play:
+ // If it's a "transitive anchor" then we won't have information stored for it
+ // (ie no entry in candidate_anchors[cnt]), but we don't want to discard the transitive information either.
+ // We therefore should do a lookup to see if a candidate anchor (x,y) exists for seq. pair cnt;
+ // if not, then just create an anchor of length one with midpoints (x,y) and store it.
+ const size_t candidate_index = candidate_anchors_list[cnt].exists_spanning_anchor (x, y);
+ if (candidate_index != candidate_anchors_list[cnt].size()) { // if there is a spanning candidate anchor
+ if (!candidate_anchors_added[cnt][candidate_index]) { // if it hasn't already been added, then add it
+ resolved_anchors_list[cnt].store (candidate_anchors_list[cnt].get_spanning_anchor (x, y));
+ candidate_anchors_added[cnt][candidate_index] = true;
+ } else // else we've already added it, so just continue
+ continue;
+ } else { // if there is no spanning candidate anchor
+ resolved_anchors_list[cnt].store (Anchor (Interval (x, x), Interval (y, y)));
+ resolved_anchors_list[cnt].update_score (resolved_anchors_list[cnt].size() - 1);
+ }
+
+ }
+ }
+
+ }
+
+ // log resolved anchors
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE)) {
+ for (size_t cnt = 0; cnt < resolved_anchors_list.size(); ++cnt) {
+ CL << "Resolved anchors after anchor annealing for '" << seq_db_internal.get_seq (seq_pairs[cnt].first).name << "' and '" << seq_db_internal.get_seq (seq_pairs[cnt].second).name << "':" << endl;
+ resolved_anchors_list[cnt].show (CL);
+ }
+ }
+
+ // perform various administrative tasks:
+ // - resolve adjacent parallel anchors
+ // - enforce immutable anchors unique
+ // - prune overlapping anchors
+ // because we have already resolved candidate parallel anchors before anchor annealing,
+ // this should be relevant only for catching adjacent parallel anchors which arise due to transitive anchoring
+ // also sort lexically
+ for (size_t cnt = 0; cnt < resolved_anchors_list.size(); ++cnt) {
+ resolved_anchors_list[cnt].enforce_immutable_unique();
+ if (!resolved_anchors_list[cnt].resolve_parallel (max_join_distance, true)) // concatenate immutable anchors
+ THROWEXPR ("ERROR: Couldn't resolve parallel anchors.");
+ resolved_anchors_list[cnt].remove_overlaps (use_translated ? 3 * minlen : minlen); // remove pruned anchors which are shorter than minlen
+ }
+
+ // debugging
+ if (CTAGGING(-1,ANCHORING ANCHORING_VERBOSE_VERBOSE)) {
+ dag.get_stockholm().write_stockholm (CL);
+ }
+
+ // log resolved anchors
+ if (CTAGGING(4,ANCHORING ANCHORING_VERBOSE)) {
+ for (size_t cnt = 0; cnt < resolved_anchors_list.size(); ++cnt) {
+ CL << "Resolved anchors for '" << seq_db_internal.get_seq (seq_pairs[cnt].first).name << "' and '" << seq_db_internal.get_seq (seq_pairs[cnt].second).name << "':" << endl;
+ resolved_anchors_list[cnt].show (CL);
+ }
+ }
+
+ // write GUI output if requested
+ if (output_for_gui) {
+ std::string gui_filename = std::string (gui_prefix) + GUI_FILENAME_ANCHORS_SUFFIX;
+ std::ofstream gui_file;
+ gui_file.open (gui_filename.c_str());
+ if (!gui_file.is_open())
+ THROWEXPR ("ERROR: Couldn't create file with name '" << gui_filename << "'.");
+ for (size_t cnt = 0; cnt < resolved_anchors_list.size(); ++cnt) {
+ gui_file << "; Resolved anchors after concatenation for '" << seq_db_internal.get_seq (seq_pairs[cnt].first).name << "' and '" << seq_db_internal.get_seq (seq_pairs[cnt].second).name << "'." << endl
+ << "; Format is " << endl
+ << "; (0 ~ 1) == [1,6] ~ [3,8] => 0.9" << endl
+ << "; meaning that sequences 0 and 1 have an ungapped anchor " << endl
+ << "; which spans [1,6] in sequence 0 and [3,8] in sequence 1" << endl
+ << "; and has a score of 0.9." << endl
+ << "; sequence is 0-based and position is 0-based" << endl
+ << endl;
+ resolved_anchors_list[cnt].write_gui_output (gui_file, seq_pairs[cnt].first, seq_pairs[cnt].second);
+ gui_file << endl;
+ }
+ gui_file.close();
+ CTAG (9,ANCHORING ANCHORING_VERBOSE) << "Created GUI output file '" << gui_filename << "'" << endl;
+ }
+
+ // impose normalized probability distribution
+ for (size_t cnt = 0; cnt < resolved_anchors_list.size(); ++cnt)
+ resolved_anchors_list[cnt].impose_normalized_probability_distribution();
+
+ return resolved_anchors_list;
+}
diff --git a/src/fsa/anchors.h b/src/fsa/anchors.h
new file mode 100644
index 0000000..85ad22e
--- /dev/null
+++ b/src/fsa/anchors.h
@@ -0,0 +1,818 @@
+
+/**
+ * \file anchors.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef FSA_ANCHORS_INCLUDED
+#define FSA_ANCHORS_INCLUDED
+
+#include <iostream>
+#include <fstream>
+
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+#include "annealing/dotplot.h"
+#include "annealing/SparseMatrix.h"
+#include "annealing/alignment_DAG.h"
+#include "fsa/constraints.h"
+#include "fsa/model.h"
+#include "fsa/sequence_pair_selector.h"
+
+#define MEGABYTE 1048576
+
+#define ANCHOR_NUC_MINLEN_DEFAULT 10
+#define ANCHOR_AA_MINLEN_DEFAULT 7
+
+#define EXONERATE_MINSCORE_DEFAULT 100
+
+namespace fsa {
+
+ /**
+ * \brief Represent a single ungapped anchor.
+ *
+ * Assumes a 0-based coordinate system and a fully-closed interval.
+ */
+ struct Anchor {
+
+ public:
+
+ Interval xcoords; ///< interval of the anchor in sequence X
+ Interval ycoords; ///< interval of the anchor in sequence Y
+ unsigned x; ///< center of the interval xcoords
+ unsigned y; ///< center of the interval ycoords
+ size_t length; ///< length of the (ungapped) matched sequence
+
+ private:
+
+ double __score; ///< score of the anchor (higher is better)
+ bool __external_scoring; ///< was the anchor scored according to some external measure?
+ bool __immutable; ///< an anchor which should never be pruned or re-scored
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ Anchor() { }
+
+ /**
+ * \brief Constructor.
+ */
+ Anchor (Interval xcoords, Interval ycoords);
+
+ /**
+ * \brief Constructor.
+ */
+ Anchor (Interval xcoords, Interval ycoords, double score);
+
+ /**
+ * \brief Set score.
+ *
+ * Immutable anchors cannot be rescored.
+ * \param score new score
+ */
+ inline void set_score (const double score) {
+ if (!is_immutable())
+ __score = score;
+ }
+
+ /**
+ * \brief Get score.
+ */
+ inline double get_score() const {
+ return __score;
+ }
+
+ /**
+ * \brief Was the anchor scored according to some external measure?
+ *
+ * If so, then it shouldn't be updated according to length.
+ */
+ inline bool is_external_scoring() const {
+ return __external_scoring;
+ }
+
+ /**
+ * \brief Mark the score as external.
+ */
+ inline void set_external_scoring() {
+ __external_scoring = true;
+ }
+
+ /**
+ * \brief Mark anchor as immutable.
+ *
+ * Immutable anchors should never be pruned or rescored.
+ * Useful primarily for constraints which we want to force
+ * (we assume that they are consistent,
+ * although nothing will break if they are not).
+ * Sets anchor score to 1.0 - DOUBLE_VERY_TINY.
+ */
+ inline void set_immutable() {
+ __score = 1.0 - DOUBLE_VERY_TINY;
+ __immutable = true;
+ }
+
+ /**
+ * \brief Is the anchor score immutable?
+ */
+ inline bool is_immutable() const {
+ return __immutable;
+ }
+
+ /**
+ * \brief Is it parallel to another anchor?
+ */
+ inline bool is_parallel (const Anchor& a) const {
+ return (xcoords.start - a.xcoords.start == ycoords.start - a.ycoords.start);
+ }
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Anchor& anchor) {
+ o << "[" << anchor.xcoords.start << ", " << anchor.xcoords.end << "] ~ ["
+ << anchor.ycoords.start << ", " << anchor.ycoords.end << "]"
+ << " : " << anchor.x << " ~ " << anchor.y
+ << " => " << std::setprecision (PRECISION_DEFAULT) << anchor.get_score();
+ if (anchor.is_external_scoring())
+ o << " (external_scoring)";
+ if (anchor.is_immutable())
+ o << " (immutable)";
+ return o;
+ }
+
+ /**
+ * \brief Re-calculate x, y and length.
+ */
+ void update();
+
+ /**
+ * \brief Map score to a high probability.
+ *
+ * Linear map from a score in the interval [0,1] to a
+ * high probability in [1 - 0.01, 1].
+ * The point of this is: When performing anchor annealing, we want an actual
+ * score/probability distribution on candidate anchors.
+ * However, post-anchor annealing, the probability distribution over anchored
+ * characters is a series of step functions, ie all the mass is concentrated
+ * in single aligned pairs. We therefore no longer want the 'score'
+ * but rather a probability near 1, where the mapping preserves
+ * the ordering of the scores.
+ * \return probability of anchor
+ * \see FSA::build_anchored_multiple_alignment
+ */
+ inline double score_to_prob() const {
+ return ((1.0 - DOUBLE_TINY) + DOUBLE_TINY * get_score());
+ }
+
+ /**
+ * \brief Compute the p-value associated with two anchored subsequences.
+ *
+ * Computed p-value is that associated with the null model,
+ * so a lower p-value is more significant.
+ * \param xseq complete sequence X
+ * \param yseq complete sequence Y
+ * \return p-value of anchored subseqs under a null model
+ */
+ double p_value (const std::string& xseq, const std::string& yseq) const;
+
+ /**
+ * \brief Compute the p-value associated with two anchored subsequences.
+ *
+ * Computed p-value is that associated with the null model,
+ * so a lower p-value is more significant.
+ * \param xseq complete sequence X
+ * \param yseq complete sequence Y
+ * \return p-value of anchored subseqs under a null model
+ */
+ double p_value (const std::string* xseq, const std::string* yseq) const;
+
+ /**
+ * \brief Lexical order, preferring x coordinate, on the left-hand boundaries.
+ *
+ * Sorted first by the left-hand x coordinate,
+ * then the left-hand y coordinate.
+ */
+ bool operator< (const Anchor& r) const {
+ return lexical_comparison_x (*this, r);
+ }
+
+ /**
+ * \brief Equality.
+ */
+ bool operator== (const Anchor& r) const {
+ if ((xcoords.start == r.xcoords.start) && (xcoords.end == r.xcoords.end) && (ycoords.start == r.ycoords.start) && (ycoords.end == r.ycoords.end))
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * \brief Lexical order on x coordinate.
+ */
+ static bool lexical_comparison_x (const Anchor& l, const Anchor& r) {
+ if (l.xcoords.start == r.xcoords.start)
+ return (l.xcoords.end < r.xcoords.end);
+ else
+ return (l.xcoords.start < r.xcoords.start);
+ }
+
+ /**
+ * \brief Lexical order on y coordinate.
+ */
+ static bool lexical_comparison_y (const Anchor& l, const Anchor& r) {
+ if (l.ycoords.start == r.ycoords.start)
+ return (l.ycoords.end < r.ycoords.end);
+ else
+ return (l.ycoords.start < r.ycoords.start);
+ }
+
+ /**
+ * \brief Lexical order, preferring x, then y, on the left-hand boundaries.
+ */
+ static bool lexical_comparison_x_y (const Anchor& l, const Anchor& r) {
+ if (l.xcoords.start == r.xcoords.start)
+ return (l.ycoords.start < r.ycoords.start);
+ else
+ return (l.xcoords.start < r.xcoords.start);
+ }
+
+ /**
+ * \brief Lexical order, preferring y coordinate, then x, on the left-hand boundaries.
+ */
+ static bool lexical_comparison_y_x (const Anchor& l, const Anchor& r) {
+ if (l.ycoords.start == r.ycoords.start)
+ return (l.xcoords.start < r.xcoords.start);
+ else
+ return (l.ycoords.start < r.ycoords.start);
+ }
+
+ /**
+ * \brief Lexical order, preferring x, then y, on the centroids.
+ */
+ static bool lexical_comparison_x_y_centroid (const Anchor& l, const Anchor& r) {
+ if (l.x == r.x)
+ return (l.y < r.y);
+ else
+ return (l.x < r.x);
+ }
+
+ };
+
+
+ /**
+ * \brief A vector of anchors for two sequences.
+ */
+ struct Anchors {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ Anchors()
+ : xseq (NULL), yseq (NULL) { }
+
+ /**
+ * \brief Constructor.
+ * \param xseq sequence X
+ * \param yseq sequence Y
+ */
+ Anchors (const std::string& xseq, const std::string& yseq)
+ : xseq (&xseq), yseq (&yseq) { }
+
+ /**
+ * \brief Constructor.
+ * \param xseq sequence X
+ * \param yseq sequence Y
+ */
+ Anchors (const std::string* xseq, const std::string* yseq)
+ : xseq (xseq), yseq (yseq) { }
+
+ /**
+ * \brief Convert constraints to anchors.
+ *
+ * For every constraint, creates an anchor for each end of the constraint.
+ * If sequence is hardmasked, then constraints whose ends fall in
+ * hardmasked regions are pruned until they don't.
+ * Sequences are for hardmasking.
+ * \param xseq_orig Sequence for sequence X
+ * \param yseq_orig Sequence for sequence Y
+ * \param hardmasked sequence is hardmasked
+ */
+ static Anchors convert_constraints_to_anchors (const Constraints& constraints,
+ const Sequence& xseq_orig, const Sequence& yseq_orig,
+ const bool hardmasked);
+
+ /**
+ * Display.
+ */
+ void show (std::ostream& o) const;
+
+ /**
+ * \brief Output formatted for GUI.
+ *
+ * Format is
+ * (0 ~ 1) == [1,6] ~ [3,8] => 0.9
+ * meaning that sequences 0 and 1 have an anchor which
+ * spans [1,6] in sequence 0 (X) and [3,8] in sequence 1 (Y)
+ * and has a score of 0.9.
+ * \param xidx index of sequence X
+ * \param yidx index of sequence Y
+ */
+ void write_gui_output (std::ostream& o, const size_t xidx, const size_t yidx) const;
+
+ /**
+ * \brief Convert these anchors to a Post_probs format.
+ *
+ * Enforces lexical ordering, preferring x coordinate, on centroids of anchors.
+ * For subsequent conversion to a SparseMatrix object.
+ * Recommended function; memory-efficient.
+ */
+ const Post_probs convert_to_post_probs() const;
+
+ /**
+ * \brief Creates a map from centroid coordinates x and y specified by an anchor to the anchor index in (*this).
+ *
+ * A set of anchors is nondegenerate if the centroids x and y
+ * of anchors uniquely specify the containing anchor.
+ * \return false if the set of anchors is degenerate (more than one spanning anchor in (*this)).
+ */
+ bool create_spanning_map();
+
+ /**
+ * \brief Returns the anchor index if an anchor which anchors coordinates x and y exists; returns this->size() otherwise.
+ *
+ * \param x coordinate anchored in first sequence X
+ * \param y coordinate anchored in second sequence Y
+ */
+ size_t exists_spanning_anchor (const unsigned x, const unsigned y) const;
+
+ /**
+ * \brief Returns the anchor which anchors coordinates x and y.
+ *
+ * Assumes that exists_spanning_anchor (x, y) has been used
+ * to check that such an anchor does exist.
+ * Calls exists_spanning_anchor (x, y).
+ * \param x coordinate anchored in first sequence X
+ * \param y coordinate anchored in second sequence Y
+ * \return anchor which anchors coordinates x and y
+ */
+ const Anchor get_spanning_anchor (const unsigned x, const unsigned y);
+
+ /**
+ * \brief Resolve parallel degenerate, overlapping and adjacent anchors.
+ *
+ * Drop degenerate anchors which are entirely spanned by a larger parallel anchor.
+ * Merge overlapping parallel anchors.
+ * Concatenate nearby (semi-adjacent) parallel anchors which are separated by <= max_join_distance (ungapped).
+ * If degenerate anchors are immutable,
+ * then the degenerate anchor is kept and the containing anchor discarded
+ * (the presumption being that immutable anchors are "special").
+ * Calls enforce_immutable_unique and rebuilds the spanning_map.
+ * \param max_join_distance maximum separation between parallel anchors to concatenate
+ * \return true if non-degenerate spanning map created successfully
+ * \see enforce_immutable_unique
+ */
+ bool resolve_parallel (const size_t max_join_distance = 0, const bool concatenate_immutable = false);
+
+ /**
+ * \brief Remove anchors whose centroids overlap with the immutable anchors.
+ *
+ * This must be called before impose_normalized_probability_distribution
+ * in order to make sure that the distribution can be normalized.
+ * Does not rebuild the spanning_map.
+ */
+ void enforce_immutable_unique();
+
+ /**
+ * \brief Remove overlaps between anchors.
+ *
+ * Resolve overlapping anchors favor of the highest-scoring one.
+ * Internally enforces lexical ordering of anchors.
+ * This is absolutely crucial for efficient DP on unanchored regions.
+ * Does not rebuild the spanning_map!
+ * \param minlen minimum anchor length
+ */
+ void remove_overlaps (const size_t minlen = ANCHOR_NUC_MINLEN_DEFAULT);
+
+ /**
+ * \brief Remove overlaps in X coordinate between anchors.
+ *
+ * Assumes that the anchors are already properly sorted.
+ * This is the responsibility of the calling function.
+ * \param minlen minimum anchor length
+ * \param which 0 for X, 1 for Y
+ */
+ void remove_overlaps (const size_t minlen, const unsigned which);
+
+ /**
+ * \brief Update score of an anchor and map to [0,1].
+ *
+ * Updates the score of the anchor (*this)[idx].
+ * Scores are computed as (1 - p_value) of the anchor.
+ * They therefore fall in the interval [0,1] and can be interpreted as probabilities,
+ * but do NOT generally form a probability distribution over anchored positions.
+ * The scores for a particular sequence position aren't required to be normalized to sum to <= 1.
+ * \param idx index of the anchor in (*this)
+ * \see impose_normalized_probability_distribution()
+ */
+ void update_score (const size_t idx);
+
+ /**
+ * \brief Convert scores to a normalized probability distribution.
+ *
+ * Calls update_score() on all anchors.
+ * Guarantees that the distribution over anchor centroids is normalized, ie
+ * sum_j P(x_i ~ y_j) <= 1 for every i
+ * sum_i P(x_i ~ y_j) <= 1 for every j
+ * where x_i and y_j are centroids of anchored intervals.
+ * This normalization is accomplished as follows:
+ * If we have candidate anchors A ~ A1 and A ~ A2,
+ * X .....A.......
+ * Y ..A1.....A2..
+ * then P(A ~ A1) and P(A ~ A2) as reported by update_score()
+ * are scaled by their fractional respective weights.
+ * More precisely, an anchor with score P(x_i ~ y_k) becomes
+ * max_j P(x_i ~ y_j) * ( P(x_i ~ y_k) / sum_j P(x_i ~ y_j) )
+ * This transformation has the properties:
+ * - if there is no overlap, then the score is unchanged
+ * - if one anchor has a much higher score than overlapping ones,
+ * then its score is only reduced a little bit, whereas the scores
+ * of the others are drastically reduced
+ * - it maps to [0, 1] (assuming that the scores are originally in [0, 1])
+ * Because each can be individually interpreted as probabilities (<= 1),
+ * this guarantees a normalized distribution.
+ * This transformation penalizes non-unique (overlapping) anchors while
+ * maintaining their relative ordering.
+ * IMPORTANT: The scores of immutable anchors cannot be changed,
+ * so this will NOT give a normalized distribution if immutable anchors
+ * overlap other anchors. enforce_immutable_unique must be called first.
+ * \see ensure_immutable_unique
+ */
+ void impose_normalized_probability_distribution();
+
+ /**
+ * \brief Number of anchors.
+ */
+ size_t size() const { return __anchors.size(); }
+
+ /**
+ * \brief Store an anchor.
+ */
+ void store (const Anchor& a) {
+ __anchors.push_back (a);
+ }
+
+ /**
+ * \brief Store anchors.
+ */
+ void store (const Anchors& new_anchors) {
+ __anchors.insert (__anchors.end(),
+ new_anchors.begin(), new_anchors.end());
+ }
+
+ /**
+ * \brief Data access operator.
+ */
+ const Anchor& operator[] (const size_t i) const {
+ assert (i < __anchors.size());
+ return __anchors[i];
+ }
+
+ /**
+ * \brief Data access operator.
+ */
+ Anchor& operator[] (const size_t i) {
+ assert (i < __anchors.size());
+ return __anchors[i];
+ }
+
+ /**
+ * \brief Get reference to last anchor.
+ */
+ Anchor& back() {
+ return __anchors.back();
+ }
+
+ /**
+ * \brief Get iterator to start of __anchors.
+ */
+ std::vector<Anchor>::iterator begin() {
+ return __anchors.begin();
+ }
+
+ /**
+ * \brief Get iterator to start of __anchors.
+ */
+ std::vector<Anchor>::const_iterator begin() const {
+ return __anchors.begin();
+ }
+
+ /**
+ * \brief Get iterator to end of __anchors.
+ */
+ std::vector<Anchor>::iterator end() {
+ return __anchors.end();
+ }
+
+ /**
+ * \brief Get iterator to end of __anchors.
+ */
+ std::vector<Anchor>::const_iterator end() const {
+ return __anchors.end();
+ }
+
+
+ private:
+
+ // pointers are ugly but necessary to have an assignment operator :(
+ const std::string* xseq; ///< first sequence X
+ const std::string* yseq; ///< second sequence Y
+
+ std::vector<Anchor> __anchors; ///< hold Anchor objects
+ /**
+ * \brief Map from the anchored coordinates x and y specified by an anchor to the anchor index in (*this).
+ *
+ * If coordinates x and y are anchored by an anchor A, then we
+ * say that anchor A "spans" x and y.
+ */
+ std::map<std::pair<unsigned, unsigned>, size_t, Util::Duple_less<unsigned, unsigned> > __spanning_map;
+
+ };
+
+
+ /**
+ * \brief Toy anchoring.
+ *
+ * Use with toy file anchors_cabbage.fasta.
+ */
+ struct Cabbage_adapter {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ Cabbage_adapter (const Sequence& xseq, const Sequence& yseq)
+ : xseq (xseq), yseq (yseq) { }
+
+ /**
+ * \brief Get a set of anchors.
+ */
+ Anchors get_candidate_anchors() const;
+
+ private:
+
+ /**
+ * \brief Named sequences.
+ */
+ const Sequence& xseq;
+ const Sequence& yseq;
+
+ };
+
+
+ /**
+ * \brief Anchoring with MUMmer.
+ *
+ * Called as 'mummer -mum'.
+ */
+ struct Mummer_adapter {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ *
+ * \param xseq sequence X
+ * \param yseq sequence Y
+ */
+ Mummer_adapter (const Sequence& xseq, const Sequence& yseq,
+ bool use_translated = false)
+ : xseq (xseq), yseq (yseq),
+ __use_translated (use_translated) { }
+
+ /**
+ * \brief Get a set of anchors.
+ *
+ * Wrapper function for call_mummer();
+ * needed to handle case of using translated anchors.
+ * Anchors may be degenerate, overlapping, etc.
+ * Does NOT call create_spanning_map() before returning list of anchors.
+ * \param minlen minimum length of an exact match
+ */
+ Anchors get_candidate_anchors (const size_t minlen = ANCHOR_NUC_MINLEN_DEFAULT) const;
+
+ private:
+
+ /**
+ * \brief Actually call MUMmer and parse output.
+ *
+ * Forks a MUMmer process and reads from STDOUT via a pipe.
+ * Note that the parameters xseq and yseq are NOT necessarily the same
+ * as the member variables xseq and yseq.
+ * \param xseq sequence X to run on
+ * \param yseq sequence Y to run on
+ * \return Anchors found by MUMmer
+ */
+ Anchors call_mummer (const std::string& xseq, const std::string& yseq, const size_t minlen = ANCHOR_NUC_MINLEN_DEFAULT) const;
+
+ const Sequence& xseq; ///< Sequence X
+ const Sequence& yseq; ///< Sequence Y
+
+ /**
+ * \brief find anchors in protein space
+ *
+ * This should only be set if the sequences are nucleotide sequence!
+ * Otherwise results will be meaningless.
+ */
+ const bool __use_translated;
+
+ };
+
+ /**
+ * \brief Anchoring with exonerate.
+ *
+ * Called as '--querytype dna --targettype dna --gappedextension false
+ * --saturatethreshold 5 --bigseq true --showvulger false --showalignment false
+ * --ryo "%qab %qae %qS %tab %tae %tS %s\n"'.
+ */
+ struct Exonerate_adapter {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ *
+ * \param xseq sequence X
+ * \param yseq sequence Y
+ */
+ Exonerate_adapter (const Sequence& xseq, const Sequence& yseq,
+ bool use_translated = false, bool softmasked = false)
+ : xseq (xseq), yseq (yseq),
+ __use_translated (use_translated), __softmasked (softmasked) { }
+
+ /**
+ * \brief Get a set of anchors.
+ *
+ * Wrapper function for call_exonerate.
+ * Anchors may be degenerate, overlapping, etc.
+ * Does NOT call create_spanning_map before returning list of anchors.
+ * \param minscore minimum score of an alignment
+ */
+ Anchors get_candidate_anchors (const int minscore = EXONERATE_MINSCORE_DEFAULT) const;
+
+ private:
+
+ /**
+ * \brief Actually call exonerate and parse output.
+ *
+ * Forks an exonerate process and reads from STDOUT via a pipe.
+ * Note that the parameters xseq and yseq are NOT necessarily the same
+ * as the member variables xseq and yseq.
+ * \param xseq sequence X to run on
+ * \param yseq sequence Y to run on
+ * \return alignments found by exonerate
+ */
+ Anchors call_exonerate (const std::string& xseq, const std::string& yseq,
+ const int minscore = EXONERATE_MINSCORE_DEFAULT) const;
+
+ const Sequence& xseq; ///< Sequence X
+ const Sequence& yseq; ///< Sequence Y
+
+ /**
+ * \brief find anchors in protein space
+ *
+ * This should only be called if the sequences are nucleotide sequence!
+ * Otherwise results will be meaningless.
+ */
+ const bool __use_translated;
+
+ /**
+ * \brief is the sequence softmasked?
+ *
+ * exonerate uses softmasking information if present.
+ */
+ const bool __softmasked;
+
+ };
+
+
+ /**
+ * \brief Adapter class to perform anchor annealing.
+ *
+ * Note that the sequence information containers
+ * hold sequences with the case preserved.
+ * This is ok for MUMmer, since it is case-insensitive,
+ * and is essential for preserving softmasking for exonerate.
+ */
+ struct Anchor_resolver {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ *
+ * \param seq_db sequence data
+ * \param seq_db_internal sequence data (hardmasked, nondegenerate)
+ * \param seq_pairs sequence pairs in seq_db and seq_db_internal to consider
+ */
+ Anchor_resolver (const Sequence_database& seq_db, const Sequence_database& seq_db_internal,
+ const Sequence_pairs& seq_pairs)
+ : seq_db (seq_db), seq_db_internal (seq_db_internal),
+ seq_pairs (seq_pairs),
+ __constraints_set (Constraints_set (seq_db))
+ { }
+
+ /**
+ * \brief Add Mercator constraints.
+ *
+ * \param filename filename of Mercator constraint file
+ */
+ void add_mercator_constraints (const std::string& filename);
+
+ /**
+ * \brief Perform anchor annealing using sequence pair weights to get a set of consistent anchors.
+ *
+ * Each entry in std::vector<Anchors> corresponds to a set of pairwise anchors;
+ * all anchors in the corresponding complete "multiple anchoring" are consistent.
+ * Anchor annealing is performed on the "reduced" sequences obtained by
+ * storing only the positions corresponding to the centroids of candidate anchors
+ * (this dramatically speeds up depth-first search on the sequences).
+ * While the same algorithm is used, anchor annealing is qualitatively different
+ * from sequence annealing. The reason is this: Sequence annealing is designed
+ * for the case where we have information P (x ~ y) that characters are aligned.
+ * In anchor annealing, in contrast, we have p-values of anchors occuring
+ * under a null model rather than an actual probability distribution over
+ * anchored positions. We therefore want to greedily call anchors with the smallest
+ * p-values and ignore "gap" information entirely (which isn't well-defined
+ * for anchors). We can do exactly this by using the maxstep weighting scheme
+ * with a gap factor of 0 (yes, it's a bit of a hack).
+ * Note that we always call Anchors::impose_normalized_probability_distribution
+ * before performing anchor annealing in order to heuristically reduce
+ * the p-values associated with non-unique anchors.
+ * \param tree_weights weights for sequence pairs during anchor annealing
+ * \param minlen minimum length of anchor
+ * \param max_join_distance maximum separation between parallel anchors to concatenate
+ * \param use_translated find anchors in protein space
+ * \param use_exonerate call exonerate to find anchors
+ * \param softmasked sequence is softmasked (used by exonerate)
+ * \param hardmasked sequence is hardmasked (used for Mercator coord mapping)
+ * \param num_refinement_steps number of iterative refinement steps
+ * \param output_for_gui output anchoring information for MAD GUI
+ * \param gui_prefix prefix for GUI output filename
+ * \return set of resolved anchors
+ * \see Anchors::impose_normalized_probability_distribution()
+ */
+ const std::vector<Anchors> get_resolved_anchors (const Tree_weights& tree_weights,
+ const size_t minlen = ANCHOR_NUC_MINLEN_DEFAULT, const size_t max_join_distance = 0, bool const use_translated = false,
+ const bool use_exonerate = false, const int minscore = EXONERATE_MINSCORE_DEFAULT, const bool softmasked = false,
+ const bool hardmasked = true,
+ const size_t num_refinement_steps = 0,
+ const bool output_for_gui = false, const std::string gui_prefix = "") const;
+ /**
+ * \brief Perform anchor annealing on an equidistant star phylogeny to get a set of consistent anchors.
+ *
+ * All sequence pairs are weighted equally.
+ */
+ const std::vector<Anchors> get_resolved_anchors (const size_t minlen = ANCHOR_NUC_MINLEN_DEFAULT, const size_t max_join_distance = 0, bool const use_translated = false,
+ const bool use_exonerate = false, const int minscore = EXONERATE_MINSCORE_DEFAULT, const bool softmasked = false,
+ const bool hardmasked = true,
+ const size_t num_refinement_steps = 0,
+ const bool output_for_gui = false, const std::string gui_prefix = "") const;
+
+
+ private:
+
+ /**
+ * \brief Hold all input sequence data.
+ */
+ const Sequence_database& seq_db;
+
+ /**
+ * \brief Hold all input sequence data (hardmasked & nondegenerate).
+ */
+ const Sequence_database& seq_db_internal;
+
+ /**
+ * \brief Hold sequence pairs to find pairwise anchors for.
+ *
+ * Indices refer to sequences in seq_db and seq_db_internal
+ * (they are indexed identically).
+ */
+ const Sequence_pairs& seq_pairs;
+
+ /**
+ * \brief Constraint information.
+ */
+ Constraints_set __constraints_set;
+
+ };
+
+}
+
+#endif /* FSA_ANCHORS_INCLUDED */
diff --git a/src/fsa/constraints.cc b/src/fsa/constraints.cc
new file mode 100644
index 0000000..e2f1e71
--- /dev/null
+++ b/src/fsa/constraints.cc
@@ -0,0 +1,101 @@
+
+/**
+ * \file constraints.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include "util/logfile.h"
+#include "fsa/constraints.h"
+
+using namespace fsa;
+
+void Constraints::write_mercator (std::ostream& o) const {
+
+ for (std::vector<Constraint>::const_iterator constraint = begin(); constraint != end(); ++constraint)
+ constraint->write_mercator (__xname, __yname, o);
+
+}
+
+
+Constraints_set::Constraints_set (const Sequence_database& seq_db)
+ : seq_db (seq_db)
+{ }
+
+void Constraints_set::read_mercator (const std::string& filename) {
+
+ std::ifstream filestream (filename.c_str(), std::ifstream::in);
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't open file '" << filename << "'.");
+
+ std::string line;
+ while (!filestream.eof()) {
+ getline (filestream, line);
+ // log
+ if (CTAGGING(-1,CONSTRAINTS_VERBOSE))
+ CL << line;
+ std::string buffer;
+ // skip comments and sequence names
+ std::stringstream ss (line);
+ std::vector<std::string> tokens; // vector to hold whitespace-separated tokens (words)
+ while (ss >> buffer)
+ tokens.push_back (buffer);
+
+ // now parse tokens into constraints
+ // sample line:
+ // drosophila_melanogaster-5.0 30 1344 drosophila_yakuba-2.0 413 1727
+ // Note that Mercator constraints are 0-based half-open [start, end).
+ if (tokens.size() == 6) {
+ std::string xname = tokens[0];
+ unsigned xstart = atoi (tokens[1].c_str()); // [start, end)
+ unsigned xend = atoi (tokens[2].c_str()) - 1;
+ std::string yname = tokens[3];
+ unsigned ystart = atoi (tokens[4].c_str());
+ unsigned yend = atoi (tokens[5].c_str()) - 1;
+
+ // sanity checks on sequence names
+ if (!seq_db.exists_seq (xname) || !seq_db.exists_seq (yname))
+ THROWEXPR ("ERROR: I don't recognize the sequence names '" << xname << "' and '" << yname << "' in constraint file '" << filename << "'.");
+
+ // map sequence names to indices
+ size_t i = seq_db.get_seq_index (xname);
+ size_t j = seq_db.get_seq_index (yname);
+
+ // be consistent
+ if (i > j) {
+ std::swap (i, j);
+ std::swap (xname, yname);
+ std::swap (xstart, ystart);
+ std::swap (xend, yend);
+ }
+
+ // if no constraint information for this sequence pair,
+ // create a new Constraints object
+ if (constraints_list.find (std::make_pair (i, j)) == constraints_list.end())
+ constraints_list.insert (std::make_pair (std::make_pair (i, j), Constraints (xname, yname)));
+
+ // store constraint
+ (constraints_list.find (std::make_pair (i, j)))->second.store (Constraint (Interval (xstart, xend), Interval (ystart, yend)));
+
+ } else if (tokens.size() == 0) {
+ continue;
+ } else {
+ if (CTAGGING(4,CONSTRAINTS))
+ CL << "WARNING: I don't know how to parse Mercator output line " << line << "; skipping it." << endl;
+ continue;
+ }
+ }
+
+ filestream.close();
+
+ // log
+ CTAG(8,CONSTRAINTS) << "Read Mercator constraints file '" << filename << "'." << endl;
+
+}
+
+void Constraints_set::write_mercator (std::ostream& o) const {
+
+ for (std::map<std::pair<size_t, size_t>, Constraints>::const_iterator iter = constraints_list.begin(); iter != constraints_list.end(); ++iter)
+ iter->second.write_mercator (o);
+
+}
diff --git a/src/fsa/constraints.h b/src/fsa/constraints.h
new file mode 100644
index 0000000..647589f
--- /dev/null
+++ b/src/fsa/constraints.h
@@ -0,0 +1,195 @@
+
+/**
+ * \file constraints.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef FSA_CONSTRAINTS_INCLUDED
+#define FSA_CONSTRAINTS_INCLUDED
+
+#include <iostream>
+#include <fstream>
+
+#include <map>
+
+#include "util/misc.h"
+#include "seq/sequence.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represents a single constraint.
+ *
+ * Assumes a 0-based coordinate system and a fully-closed interval.
+ * Constraints are like Anchors, but they are assumed to already be consistent.
+ */
+ struct Constraint {
+
+ Interval xcoords; ///< interval of the constraint in sequence X
+ Interval ycoords; ///< interval of the constraint in sequence Y
+
+ /**
+ * \brief Constructor.
+ */
+ Constraint (const Interval& xcoords, const Interval& ycoords)
+ : xcoords (xcoords), ycoords (ycoords) { }
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Constraint& constraint) {
+ o << "[" << constraint.xcoords.start << ", " << constraint.xcoords.end << "] ~ ["
+ << constraint.ycoords.start << ", " << constraint.ycoords.end << "]";
+ return o;
+ }
+
+ /**
+ * \brief Write constraint in Mercator format.
+ *
+ * Note that Mercator constraints are 0-based half-open [start, end),
+ * whereas we represent them as [start, end].
+ */
+ inline void write_mercator (const std::string& xname, const std::string& yname, std::ostream& o) const {
+ o << xname << ' ' << xcoords.start << ' ' << xcoords.end + 1 << ' '
+ << yname << ' ' << ycoords.start << ' ' << ycoords.end + 1 << endl;
+ }
+
+ };
+
+ /**
+ * \brief Hold a vector of constraints for two sequences.
+ */
+ struct Constraints {
+
+ /**
+ * \brief Constructor.
+ */
+ Constraints() { }
+
+ /**
+ * Constructor.
+ *
+ * \param xname name of sequence X
+ * \param yname name of sequence X
+ */
+ Constraints (const std::string& xname, const std::string& yname)
+ : __xname (xname), __yname (yname) { }
+
+ /**
+ * \brief Write constraint file in Mercator format.
+ */
+ void write_mercator (std::ostream& o) const;
+
+ /**
+ * \brief Number of constraints.
+ */
+ size_t size() const { return __constraints.size(); }
+
+ /**
+ * \brief Store a constraint.
+ */
+ void store (const Constraint& c) {
+ __constraints.push_back (c);
+ }
+
+ /**
+ * \brief Get iterator to start of __constraints.
+ */
+ std::vector<Constraint>::iterator begin() {
+ return __constraints.begin();
+ }
+
+ /**
+ * \brief Get iterator to start of __constraints.
+ */
+ std::vector<Constraint>::const_iterator begin() const {
+ return __constraints.begin();
+ }
+
+ /**
+ * \brief Get iterator to end of __constraints.
+ */
+ std::vector<Constraint>::iterator end() {
+ return __constraints.end();
+ }
+
+ /**
+ * \brief Get iterator to end of __constraints.
+ */
+ std::vector<Constraint>::const_iterator end() const {
+ return __constraints.end();
+ }
+
+
+ private:
+
+ const std::string __xname; ///< name of sequence X
+ const std::string __yname; ///< name of sequence Y
+
+ std::vector<Constraint> __constraints; ///< Contraint objects
+
+ };
+
+ /**
+ * \brief Represent a set of contraints for many sequences.
+ */
+ struct Constraints_set {
+
+ /**
+ * \brief Constructor.
+ *
+ * \param seq_db input sequence data
+ */
+ Constraints_set (const Sequence_database& seq_db);
+
+ /**
+ * \brief Read constraints from a Mercator file.
+ *
+ * Note that Mercator constraints are 0-based half-open [start, end).
+ */
+ void read_mercator (const std::string& filename);
+
+ /**
+ * \brief Write constraints to a Mercator-format file.
+ *
+ * Note that Mercator constraints are 0-based half-open [start, end).
+ */
+ void write_mercator (std::ostream& o) const;
+
+ /**
+ * \brief Get constraints for a particular sequence std::pair.
+ *
+ * \param i index for first sequence
+ * \param j index for second sequence
+ */
+ inline Constraints get_constraints (unsigned i, unsigned j) const {
+ if (constraints_list.find (std::make_pair (i, j)) == constraints_list.end())
+ return Constraints();
+ return (*constraints_list.find (std::make_pair (i, j))).second;
+ }
+
+ /**
+ * \brief Number of sequence std::pairs which we have constraints for.
+ */
+ inline size_t size() const {
+ return constraints_list.size();
+ }
+
+ private:
+
+ /**
+ * \brief Hold all input sequence data.
+ */
+ const Sequence_database& seq_db;
+
+ /**
+ * \brief constraints for sequence std::pairs
+ */
+ std::map<std::pair<size_t, size_t>, Constraints> constraints_list;
+
+ };
+
+}
+
+#endif /* FSA_CONSTRAINTS_INCLUDED */
diff --git a/src/fsa/dptables.h b/src/fsa/dptables.h
new file mode 100644
index 0000000..cabc25c
--- /dev/null
+++ b/src/fsa/dptables.h
@@ -0,0 +1,438 @@
+/*
+ * This file is part of HMMoC 1.3, a hidden Markov model compiler.
+ * Copyright (C) 2007 by Gerton Lunter, Oxford University.
+ *
+ * HMMoC 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * HMMOC 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 HMMoC; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+\*/
+/*
+ *
+ * dptables.h -- ordinary and sparse dynamic programming tables
+ *
+ * Gerton Lunter, 1 Oct 2006
+ *
+ * Modified for GCC 4.0.2 and Microsoft Visual Studio 2005 by Aaron Darling, 2007
+ *
+ */
+
+#ifndef __dptable_h_
+#define __dptable_h_
+
+
+#include <map>
+#include <cassert>
+
+
+#ifdef __GNUC__
+ #define HAVE_HASH_MAP
+ #if __GNUC__ < 3
+ #include <hash_map.h>
+ namespace Sgi { using ::hash_map; }; // inherit globals
+ #else
+ #include <ext/hash_map>
+ #if __GNUC_MINOR__ + __GNUC__ == 3
+ namespace Sgi = std; // GCC 3.0
+ #else
+ namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later
+ #endif
+ #endif
+#else // ...there are other compilers, right?
+#ifdef _MSC_VER
+// visual studio 2005 has no hash map. older versions did.
+#else
+// default for all other compilers
+#define HAVE_HASH_MAP
+namespace Sgi = std;
+#endif
+#endif
+
+
+using std::map;
+#ifdef HAVE_HASH_MAP
+using Sgi::hash_map;
+#endif
+
+// Define aliases for two maps: red-black trees, and hashes
+// (GNU C++ does not define a hash function for long long int, so we have to define our own)
+
+template<class key>
+struct _hash {
+ size_t operator()(long long x) const { return x; }
+};
+
+// typedefs can't be templated
+
+template<class key, class value>
+class treemap : public map<key,value> {};
+
+#ifdef HAVE_HASH_MAP
+template<class key, class value>
+class hashmap : public hash_map<key,value,_hash<key> > {};
+#endif
+
+// select one of the maps (the hash map is faster and appears to use less memory)
+
+#ifdef HAVE_HASH_MAP
+#define _mymap hashmap
+#else
+#define _mymap treemap
+#endif
+
+//
+// Public interface for the banding iterator
+//
+// Not strictly part of the DP table definitions, but cannot be made part of the
+// main .h file either, because of circular inclusions in case DP tables
+// refer to this class
+//
+
+template < int dim >
+class Banding {
+
+public:
+ typedef int Position[dim];
+
+ virtual ~Banding() {};
+ virtual Position& forwardIterator() = 0; // Initializes the position for forward iteration, and returns a reference to it
+ virtual Position& backwardIterator() = 0; // Same for backward iteration
+
+ virtual bool hasNextForward() = 0; // Advances the position, and returns true if successful
+ virtual bool hasNextBackward() = 0; // Same for backward iteration
+
+ virtual bool lastColumnEntry() = 0; // true if next call to hasNext[FW/BW] advances the slow coordinate
+
+ virtual void warning() {}; // gets called when iterator loops out of range
+
+ // Traversals must be such that when v is visited, all positions of the form v-e either have already been
+ // visited, or will not be. Here, e is any nonzero vector with all entries nonnegative (forward iteration)
+ // or nonpositive (backward iteration).
+ //
+ // It is crucial that the forwardIterator and backwardIterator visit identical sets of states (although the order
+ // in which they're visited need not be their precise mirror image). If not, the basic assumption that the forward
+ // and backward iterations yield the same total likelihood is not satifsfied, and BaumWelch will not work properly.
+ //
+};
+
+
+
+
+// States are stored in a self-initializing array
+
+template<class Real,int size> class States;
+
+template<int size>
+class States<double,size> {
+private:
+ double data[size];
+public:
+ enum { length = size }; // to know the size, just in case
+ States() { for (int i=0; i<size; i++) data[i]=0; } // initialization
+ operator double* () { return data; } // cast to actual array
+ operator const double* () const { return data; }
+};
+
+template<class Real, int size>
+class States {
+private:
+ Real data[size];
+public:
+ enum { length = size }; // to know the size, just in case
+ States() { for (int i=0; i<size; i++) data[i].clear(); } // initialization
+ operator Real* () { return data; } // cast to actual array
+ operator const Real* () const { return data; }
+};
+
+
+
+// Define index types to serve as keys to the DP table position
+
+template<int dim> class _index {};
+template<> class _index<1> { public: typedef unsigned int t; };
+template<> class _index<2> { public: typedef unsigned long t; };
+template<> class _index<3> { public: typedef unsigned long long t; };
+template<> class _index<4> { public: typedef unsigned long long t; };
+
+
+//
+// Base classes for a dynamic programming table
+//
+// DP tables provide the following methods:
+//
+// const States& read(...) : read access to state array
+// States& write(...) : write access to state array
+// void written() : signal that write access is finished
+// void allocate(...) : inform table about its dimensions; must be called before read/write access
+// void clear() : empties the table; keeps its dimensions
+// void clear(int) : empties one column of a (folded) DP table
+// void absolve() : ensures that table does not delete its data; another table with reference to the data,
+// which is created by the default copy constructor, is now responsible. Not allowed for
+// folded tables
+//
+
+template<class States>
+class _DPT { // base class, keeps track of the responsibility for the data
+ private:
+ void clear(int i) {} // placeholder, to allow dummy definition for non-folded tables
+ protected:
+ bool isInCharge; // true if this class' destructor destroys the data
+ public:
+ typedef States states_type;
+ _DPT() : isInCharge(true) {}
+ void absolve() { isInCharge=false; } // take away the responsibility of destroying the data
+ void written() {} // signal that we're done writing -- used by extensions
+};
+
+template<template<typename,int> class DPTable, class States, int dim> // Wrapper for memory-efficient Fw/Bw/Baum-Welch
+class _FoldedTable : public _DPT<States> {
+ protected:
+ DPTable<States,dim-1>* aTables[2];
+ public:
+ _FoldedTable() { aTables[0] = new DPTable<States,dim-1>(); aTables[1] = new DPTable<States,dim-1>(); }
+ ~_FoldedTable() { assert(_DPT<States>::isInCharge); delete aTables[0]; delete aTables[1]; } // do not allow data to be retained
+ void clear(int i) { aTables[i%2]->clear(); }
+};
+
+template<class States, int dim>
+class DPTable {};
+
+template<class States, int dim>
+class SparseDPTable {};
+
+template<template<typename,int> class DPTable, class States, int dim>
+class FoldedTable {};
+
+
+
+// Explicit partial specializations for up to 4 spatial dimensions
+
+
+template<template<typename,int> class DPTable, class States>
+class FoldedTable<DPTable, States, 0> : public _FoldedTable<DPTable, States, 1> {
+ public:
+ void allocate() { this->aTables[0]->allocate(); };
+ const States& read() const { return this->aTables[0]->read(); }
+ States& write() { return this->aTables[0]->write(); }
+ void written() { this->aTables[0]->written(); }
+};
+
+
+template<template<typename,int> class DPTable, class States>
+class FoldedTable<DPTable, States, 1> : public _FoldedTable<DPTable, States, 1> {
+ int z;
+ public:
+ void allocate(int a) { this->aTables[0]->allocate(); this->aTables[1]->allocate(); };
+ const States& read(int a) const { return this->aTables[a%2]->read(); }
+ States& write(int a) { return this->aTables[z=a%2]->write(); }
+ void written() { this->aTables[z]->written(); }
+};
+
+
+template<template<typename,int> class DPTable, class States>
+class FoldedTable<DPTable, States, 2> : public _FoldedTable<DPTable, States, 2> {
+ int z;
+ public:
+ void allocate(int a, int b) { this->aTables[0]->allocate(a); this->aTables[1]->allocate(a); };
+ const States& read(int a, int b) const { return this->aTables[b%2]->read(a); }
+ States& write(int a, int b) { return this->aTables[z=b%2]->write(a); }
+ void written() { this->aTables[z]->written(); }
+};
+
+
+template<template<typename,int> class DPTable, class States>
+class FoldedTable<DPTable, States, 3> : public _FoldedTable<DPTable, States, 3> {
+ int z;
+ public:
+ void allocate(int a, int b, int c) { this->aTables[0]->allocate(a,b); this->aTables[1]->allocate(a,b); };
+ const States& read(int a, int b, int c) const { return this->aTables[c%2]->read(a,b); }
+ States& write(int a, int b, int c) { return this->aTables[z=c%2]->write(a,b); }
+ void written() { this->aTables[z]->written(); }
+};
+
+
+template<template<typename,int> class DPTable, class States>
+class FoldedTable<DPTable, States, 4> : public _FoldedTable<DPTable, States, 4> {
+ int z;
+ public:
+ void allocate(int a, int b, int c, int d) { this->aTables[0]->allocate(a,b,c); this->aTables[1]->allocate(a,b,c); };
+ const States& read(int a, int b, int c, int d) const { return this->aTables[d%2]->read(a,b,c); }
+ States& write(int a, int b, int c, int d) { return this->aTables[z=d%2]->write(a,b,c); }
+ void written() { this->aTables[z]->written(); }
+};
+
+
+template<class States>
+class DPTable<States,0> : public _DPT<States> {
+private:
+ States *pTable;
+public:
+ DPTable() { pTable = 0; };
+ ~DPTable() { if (pTable && _DPT<States>::isInCharge) delete pTable; };
+ void allocate() { pTable = new States(); };
+ void clear() { delete pTable; allocate(); };
+ const States& read() const { return *pTable; }
+ States& write() { return *pTable; }
+};
+
+
+template<class States>
+class DPTable<States,1> : public _DPT<States> {
+private:
+ States *pTable;
+ int maxa;
+public:
+ DPTable() { pTable = 0; }
+ ~DPTable() { if (pTable && _DPT<States>::isInCharge ) { delete[] pTable; } }
+ void allocate(int a) { maxa = a; pTable = new States[a]; }
+ void clear() { delete[] pTable; allocate(maxa); };
+ const States& read(int a) const { return pTable[a]; }
+ States& write(int a) { return pTable[a]; }
+};
+
+
+template<class States>
+class DPTable<States,2> : public _DPT<States> {
+private:
+ States *pTable;
+ int maxa, maxb;
+public:
+ DPTable() { pTable = 0; }
+ ~DPTable() { if (pTable && _DPT<States>::isInCharge ) { delete[] pTable; } }
+ void allocate(int a, int b) { maxa = a; maxb = b; pTable = new States[a*b]; }
+ void clear() { delete[] pTable; allocate(maxa,maxb); };
+ const States& read(int a, int b) const { return pTable[a+maxa*b]; }
+ States& write(int a, int b) { return pTable[a+maxa*b]; }
+};
+
+
+template<class States>
+class DPTable<States,3> : public _DPT<States> {
+private:
+ States *pTable;
+ int maxa, maxb, maxc;
+public:
+ DPTable() { pTable = 0; }
+ ~DPTable() { if (pTable && _DPT<States>::isInCharge ) { delete[] pTable; } }
+ void allocate(int a, int b, int c) { maxa = a; maxb = b; maxc = c; pTable = new States[a*b*c]; }
+ void clear() { delete[] pTable; allocate(maxa,maxb,maxc); };
+ const States& read(int a, int b, int c) const { return pTable[a+maxa*(b+maxb*c)]; }
+ States& write(int a, int b, int c) { return pTable[a+maxa*(b+maxb*c)]; }
+};
+
+
+template<class States>
+class DPTable<States,4> : public _DPT<States> {
+private:
+ States *pTable;
+ int maxa, maxb, maxc, maxd;
+public:
+ DPTable() { pTable = 0; }
+ ~DPTable() { if (pTable && _DPT<States>::isInCharge ) { delete[] pTable; } }
+ void allocate(int a, int b, int c, int d) { maxa = a; maxb = b; maxc = c; maxd = d; pTable = new States[a*b*c*d]; }
+ void clear() { delete[] pTable; allocate(maxa,maxb,maxc,maxd); };
+ const States& read(int a, int b, int c, int d) const { return pTable[a+maxa*(b+maxb*(c+maxc*d))]; }
+ States& write(int a, int b, int c, int d) { return pTable[a+maxa*(b+maxb*(c+maxc*d))]; }
+};
+
+
+template<class States>
+class SparseDPTable<States,0> : public DPTable<States,0> {};
+
+
+template<class States>
+class SparseDPTable<States,1> : public _DPT<States> {
+private:
+ typedef _index<1>::t idx;
+ _mymap<idx,States> &table;
+ const States zero;
+public:
+ SparseDPTable() : table(*new _mymap<_index<1>::t,States>), zero() {};
+ ~SparseDPTable() { if (_DPT<States>::isInCharge) delete &table; };
+ void allocate(int a) {};
+ void clear() { table.clear(); }
+ States& write(int a) { return table[idx(a)]; }
+ const States& read(int a) const {
+ _mymap<_index<1>::t,char>::iterator iter2;
+ typename _mymap<idx,States>::const_iterator iter = table.find(idx(a));
+ if (iter == table.end()) return zero;
+ return iter->second;
+ }
+};
+
+
+template<class States>
+class SparseDPTable<States,2> : public _DPT<States> {
+private:
+ typedef _index<2>::t idx;
+ _mymap<idx,States> &table;
+ idx maxa;
+ const States zero;
+public:
+ SparseDPTable() : table(*new _mymap<idx,States>), zero() {};
+ ~SparseDPTable() { if (_DPT<States>::isInCharge) delete &table; };
+ void allocate(int a, int b) { maxa = a; };
+ void clear() { table.clear(); }
+ States& write(int a, int b) { return table[idx(a)+maxa*idx(b)]; }
+ const States& read(int a, int b) const {
+ typename _mymap<idx,States>::const_iterator iter = table.find(unsigned(a)+maxa*unsigned(b));
+ if (iter == table.end()) return zero;
+ return iter->second;
+ }
+};
+
+
+template<class States>
+class SparseDPTable<States,3> : public _DPT<States> {
+
+private:
+ typedef _index<3>::t idx;
+ _mymap<idx,States> &table;
+ idx maxa, maxb;
+ const States zero;
+public:
+ SparseDPTable() : table(*new _mymap<idx,States>), zero() {};
+ ~SparseDPTable() { if (_DPT<States>::isInCharge) delete &table; };
+ void allocate(int a, int b, int c) { maxa = a; maxb = b; };
+ void clear() { table.clear(); }
+ States& write(int a, int b, int c) { return table[idx(a)+maxa*(idx(b)+maxb*idx(c))]; }
+ const States& read(int a, int b, int c) const {
+ typename _mymap<idx,States>::const_iterator iter = table.find(unsigned(a)+maxa*(unsigned(b)+maxb*unsigned(c)));
+ if (iter == table.end()) return zero;
+ return iter->second;
+ }
+};
+
+
+template<class States>
+class SparseDPTable<States,4> : public _DPT<States> {
+private:
+ typedef _index<4>::t idx;
+ _mymap<idx,States> &table;
+ idx maxa, maxb, maxc;
+ const States zero;
+public:
+ SparseDPTable() : table(*new _mymap<idx,States>), zero() {};
+ ~SparseDPTable() { if (_DPT<States>::isInCharge) delete &table; };
+ void allocate(int a, int b, int c, int d) { maxa=a; maxb=b; maxc=c; }
+ void clear() { table.clear(); }
+ States& write(int a, int b, int c, int d) { return table[unsigned(a)+maxa*(unsigned(b)+maxb*(unsigned(c)+maxc*unsigned(d)))]; }
+ const States& read(int a, int b, int c, int d) const {
+ typename _mymap<idx,States>::const_iterator iter = table.find(unsigned(a)+maxa*(unsigned(b)+maxb*(unsigned(c)+maxc*unsigned(d))));
+ if (iter == table.end()) return zero;
+ return iter->second;
+ }
+};
+
+
+#endif
+
diff --git a/src/fsa/fsa.cc b/src/fsa/fsa.cc
new file mode 100644
index 0000000..0fe6c2f
--- /dev/null
+++ b/src/fsa/fsa.cc
@@ -0,0 +1,1887 @@
+
+/**
+ * \file fsa.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ * Jaeyoung Do wrote the parallelization and database code.
+ */
+
+#include "math/mst.h"
+#include "seq/similarity_matrix.h"
+#include "fsa/fsa.h"
+
+using namespace fsa;
+
+FSA::FSA (int argc, char** argv) :
+ opts (argc, argv),
+ alphabet (DNA_alphabet()),
+ tree_weights (Tree_weights()), // default constructor sets all weights to 1.0
+ w_worker (false)
+{ }
+
+void FSA::init_opts() {
+
+ opts.newline();
+ INIT_CONSTRUCTED_OPTS_LIST (opts, -1, "[options] <sequence file(s)>", "Distance-based alignment of DNA, RNA and proteins.");
+
+ opts.print_title ("Output options");
+ opts.add ("-stockholm", write_stockholm = false, "output Stockholm alignments (default is multi-FASTA format)", false);
+ opts.add ("-gui", output_for_gui = false, "record alignment & statistical model for interactive Java GUI", false);
+ opts.add ("-write-params", write_params = false, "write learned emission distributions (substitution matrices) to disk", false);
+ opts.add ("-write-posteriors", write_dotplots = false, "write learned pairwise posterior alignment probability matrices to disk", false);
+ // --write-divergences option disabled for now (9/14/08)
+ // opts.add ("-write-divergences", write_divergences = false, "write pairwise divergences using log-det transform on learned substitution matrices to disk", false);
+ write_divergences = false;
+ opts.newline();
+
+ opts.print_title ("Parallelization options");
+#if defined(HAVE_CONDOR)
+ opts.add ("-parallelize", num_parallelized_jobs = 0, "collect pairwise posterior probabilities and candidate edges simultaneously", false);
+ opts.add ("-noannealing", noannealing = false, "disable annealing", false);
+ opts.print (" Note that --parallelize is only relevant when database connection options are given;"); opts.newline();
+ opts.print (" similarly, --noannealing is only relevant when --parallelize is set."); opts.newline();
+#else
+ opts.print ("(Parallelization not available; please see the manual for more information.)");
+ opts.newline();
+ num_parallelized_jobs = 0;
+ noannealing = false;
+#endif
+ opts.newline();
+
+ opts.print_title ("Database options");
+#if defined(HAVE_POSTGRES)
+ opts.add ("-db-maxram", db_max_ram = 0, "maximum RAM to use when the database mode (in megabytes)", true);
+ opts.add ("-hostname", db_hostname = "", "database server host name", false);
+ opts.add ("-hostaddr", db_hostaddr = "", "database server host IP address", false);
+ opts.add ("-dbname", db_name = "", "database name", false);
+ opts.add ("-port", db_port = 0, "database server port", false);
+ opts.add ("-user", db_user = "", "database username", false);
+ opts.add ("-password", db_password = "", "database password", false);
+ opts.add ("-noposteriors", read_posteriors_from_db = false, "do not compute posteriors; instead read them from database", false);
+ opts.print (" Note that to access the database server, you must provide at least --hostname and --dbname.");
+ opts.newline();
+#else
+ opts.print ("(Database not available; please see the manual for more information.)");
+ opts.newline();
+#endif
+ opts.newline();
+
+ opts.print_title ("Pair HMM model options");
+ opts.add ("-nucprot", nucprot = false, "align input nucleotide sequences (must all be nucleotide) in protein space", false);
+ opts.add ("-indel2", is_indel2 = true, "(default) use two sets of indel states in Pair HMM (use --noindel2 to use 1 set only)", false);
+ opts.add ("-gapopen1", gap_open1 = 0., "initial gap-open probability (for set 1 of indel states)", false); // the command-line values, if passed, are used in init_indel()
+ opts.add ("-gapextend1", gap_extend1 = 0., "initial gap-extend probability (for set 1 of indel states)", false);
+ opts.add ("-gapopen2", gap_open2 = 0., "initial gap-open probability (for set 2 of indel states)", false);
+ opts.add ("-gapextend2", gap_extend2 = 0., "initial gap-extend probability (for set 2 of indel states)", false);
+ // --raggedends option disabled for now (8/6/08)
+ // opts.add ("-raggedends", ragged_ends = false, "favor padding indels at starts and ends of sequences", true);
+ ragged_ends = false;
+ opts.add ("-model", model = MODEL_DEFAULT, "initial substitution model: 0 = Jukes-Cantor, 1 = Tamura-Nei / BLOSUM62-like (proteins)", true);
+ opts.add ("-time", time = TIME_DEFAULT, "Jukes-Cantor/Tamura-Nei evolutionary time parameter", true);
+ opts.add ("-alphar", alpha_R = ALPHA_R_DEFAULT, "Tamura-Nei rate alpha_R (transition: purine)", true);
+ opts.add ("-alphay", alpha_Y = ALPHA_Y_DEFAULT, "Tamura-Nei rate alpha_Y (transition: pyrimidine)", true);
+ opts.add ("-beta", beta = BETA_DEFAULT, "Tamura-Nei rate beta (transversion)", true);
+ opts.add ("-load-probs", load_probs_file = "", "load pairwise posterior probabilities from a file rather than performing inference with Pair HMM", false);
+ opts.newline();
+
+ opts.print_title ("Parameter estimation options");
+ opts.add ("-learngap", learn_gap, "estimate indel probabilities for each pair of sequences (--nolearngap to disable)", true);
+ opts.add ("-learnemit-bypair", learn_emit_bypair, "(default for DNA and RNA) estimate emission probabilities for each pair of sequences (--nolearnemit-bypair to disable)", false);
+ opts.add ("-learnemit-all", learn_emit_all, "(default for proteins) estimate emission probabilities averaged over all sequences (--nolearnemit-all to disable)", false);
+ opts.add ("-nolearn", nolearn = false, "disable ALL parameter learning (use ProbCons defaults)", false);
+ opts.add ("-regularize", regularize = true, "regularize learned emission and gap probabilities with Dirichlet prior", true);
+ opts.add ("-regularization-gapscale", regularization_transition_scale, "scaling factor for transition prior", false);
+ opts.add ("-regularization-emitscale", regularization_emission_scale, "scaling factor for emission Dirichlet prior", false);
+ opts.add ("-mininc", em_min_inc = EM_MIN_INC_DEFAULT, "minimum fractional increase in log-likelihood per round of EM", true);
+ opts.add ("-maxrounds", em_max_iter = EM_MAX_ITER_DEFAULT, "maximum number of iterations of EM", true);
+ opts.add ("-mingapdata", min_gap_training_data, "minimum amount of sequence data (# of aligned pairs of characters) for training gap probs", false);
+ opts.add ("-minemitdata", min_emit_training_data, "minimum amount of sequence data (# of aligned pairs of characters) for training emission probs", false);
+ opts.newline();
+
+ opts.print_title ("Multiple alignment options: sequence annealing");
+ opts.add ("-refinement", num_refinement_steps = -1, "number of iterative refinement steps (default is unlimited; 0 for none)", false);
+ opts.add ("-maxsn", maxsn = false, "maximum sensitivity (instead of highest accuracy)", false);
+ // hack to use #define directive
+ std::string opt_string_hack = "gap factor; 0 for highest sensitivity (the internal effective minimum is " + Util::to_string (DEFAULT_POSTERIOR_PROB_CUTOFF) + "); >1 for higher specificity";
+ opts.add ("-gapfactor", gap_factor = 1, opt_string_hack.c_str(), true);
+ opts.add ("-dynamicweights", enable_dynamic_weights = true, "enable dynamic edge re-weighting", true);
+ opts.add ("-treeweights", tree_weights_file = "", "weights for sequence pairs based on a tree", false);
+ opts.add ("-require-homology", require_homology = false, "require that there be some detectable homology between all input sequences", true);
+ opts.newline();
+
+ opts.print_title ("Alignment speedup options: many sequences");
+ opts.add ("-fast", fast_defaults = false, "fast alignment: use 5 * Erdos-Renyi threshold percent of sequence pairs for alignment and 2 * for learning", false);
+ opts.add ("-refalign", refalign = false, "alignment to a reference sequence only (reference must be first sequence in file)", false);
+ opts.add ("-mst-min", num_minimum_spanning_trees = 3, "build --mst-min minimum spanning trees on input sequences for pairwise comparisons", true);
+ opts.add ("-mst-max", num_maximum_spanning_trees = 0, "build --mst-max maximum spanning trees on input sequences for pairwise comparisons", true);
+ opts.add ("-mst-palm", num_minimum_spanning_palm_trees = 0, "build --mst-palm minimum spanning palm trees on input sequences for pairwise comparisons", true);
+ opts.add ("-degree", degree = 0, "use --degree number of pairwise comparisons between closest sequences", true);
+ opts.add ("-kmer", kmer_length = 0, "length of k-mers to use when determining sequence similarity", false);
+ opts.add ("-alignment-fraction", fraction_alignment_pairs = 1., "randomized fraction of all (n choose 2) pairs of sequences to consider during alignment inference", true);
+ opts.add ("-alignment-number", num_alignment_pairs = 0, "total number of (randomized) pairs of sequences to consider during alignment inference", false);
+ opts.newline();
+
+ opts.print_title ("Alignment speedup options: long sequences (MUMmer)");
+#ifdef MUMMER_EXEC
+ opts.add ("-anchored", anchored = false, "use anchoring (--noanchored to disable)", false);
+ opts.add ("-translated", use_translated = false, "perform anchoring in protein space", true);
+ opts.add ("-minlen", anchor_minlen, "minimum length of exact matches for anchoring", false);
+ opts.add ("-maxjoinlen", anchor_max_join_length = 2, "maximum ungapped separation of parallel adjacent anchors to join", true);
+ // hack to use #define directive
+ opt_string_hack.clear(); opt_string_hack = "leave hardmasked sequence >" + Util::to_string (MIN_HARDMASK_LENGTH) + " nt unaligned instead of randomizing it (default for long DNA)";
+ opts.add ("-hardmasked", hardmasked = false, opt_string_hack.c_str(), false);
+#else
+ anchored = false;
+ use_translated = false;
+ hardmasked = false;
+ opts.print ("(MUMmer not available; please see the manual for more information.)");
+ opts.newline();
+#endif
+ opts.newline();
+
+ opts.print_title ("Alignment speedup options: long sequences (exonerate)");
+#ifdef EXONERATE_EXEC
+ opts.add ("-exonerate", exonerate = false, "call exonerate to get anchors (implies --anchored)", false);
+ opts.add ("-minscore", exonerate_minscore = EXONERATE_MINSCORE_DEFAULT, "minimum score of alignments found by exonerate", true);
+ opts.add ("-softmasked", softmasked = false, "input sequences are softmasked", false);
+#else
+ exonerate = false;
+ softmasked = false;
+ opts.print ("(exonerate not available; please see the manual for more information.)");
+ opts.newline();
+#endif
+ opts.newline();
+
+ opts.print_title ("Alignment speedup options: long sequences (Mercator)");
+ opts.add ("-mercator", mercator_constraint_file = "", "input Mercator constraints", false);
+ opts.newline();
+
+ opts.print_title ("Memory savings");
+ opts.add ("-maxram", max_ram = (total_ram() > 0 ? static_cast<int> (0.8 * total_ram()) : -1), "maximum RAM to use (in megabytes)", true); // use 80% of max RAM by default
+ opts.add ("-bandwidth", bandwidth = 0, "banding (default is no banding)", false);
+ opts.add ("-minprob", minprob = DEFAULT_POSTERIOR_PROB_CUTOFF, "minimum posterior probability to store", true);
+ opts.newline();
+
+ opts.newline();
+ opts.print ("Input sequence file(s) must be in FASTA format."); opts.newline();
+ opts.newline();
+ opts.print ("FSA attempts to automatically figure out appropriate settings;"); opts.newline();
+ opts.print ("you can override its automated choices with the above options."); opts.newline();
+ opts.newline();
+
+ opts.print ("Please contact the FSA team at fsa at math.berkeley.edu with any questions or comments.");
+
+}
+
+void FSA::input_data() {
+
+ // get sequence filenames
+ const std::vector<sstring>& seq_filename = opts.get_not_opts();
+
+ // check for at least one sequence file
+ if (seq_filename.size() == 0) {
+ cerr << opts.short_help() << endl
+ << "ERROR: Please specify at least one sequence file." << endl;
+ exit (1);
+ }
+ // read all files into a single Sequence_database
+ for (std::vector<sstring>::const_iterator sf = seq_filename.begin(); sf != seq_filename.end(); ++sf)
+ seq_db.read_fasta (*sf, &Alignment::is_gap_char,
+ false, // strip_leading_chr
+ true); // verbose
+
+ // calculate some statistics
+ num_seqs = seq_db.size();
+ num_seq_pairs = num_seqs * (num_seqs - 1) / 2;
+ if (num_seqs < 2)
+ THROWEXPR (opts.short_help() << "You must include at least 2 sequences to be aligned.");
+ CTAG(9,FSA) << "Read " << num_seqs << " sequences." << endl;
+
+ // figure out which alphabet we're using
+ if (seq_db.matches_alphabet (DNA_alphabet()) || seq_db.matches_alphabet (RNA_alphabet())) {
+ is_dna = true;
+ is_protein = false;
+ alphabet = DNA_alphabet();
+ // store alphabet as string
+ // NB can't use e.g. Alphabet::chars_uc because not alphabetical sorting (which we require).
+ alphabet_string = DNA_ALPHABET_STRING;
+ }
+ else if (seq_db.matches_alphabet (Protein_alphabet())) {
+ is_dna = false;
+ is_protein = true;
+ alphabet = Protein_alphabet();
+ alphabet_string = PROTEIN_ALPHABET_STRING;
+ }
+ else {
+ THROWEXPR ("ERROR: This doesn't seem to be nucleotide or amino acid sequence; I'm bailing.");
+ }
+
+ // get gui filename
+ gui_prefix = *(seq_filename.begin());
+
+}
+
+void FSA::set_up_defaults() {
+
+ // set regularization scales to defaults
+ regularization_transition_scale = is_dna ? REGULARIZATION_NUC_TRANSITION_SCALE_DEFAULT : REGULARIZATION_AA_TRANSITION_SCALE_DEFAULT;
+ regularization_emission_scale = is_dna ? REGULARIZATION_NUC_EMISSION_SCALE_DEFAULT : REGULARIZATION_AA_EMISSION_SCALE_DEFAULT;
+
+ // set training data cutoffs to defaults
+ min_emit_training_data = is_dna ? MIN_NUC_EMISSION_TRAINING_DATA : MIN_AA_EMISSION_TRAINING_DATA;
+ min_gap_training_data = is_dna ? MIN_NUC_TRANSITION_TRAINING_DATA : MIN_AA_TRANSITION_TRAINING_DATA;
+
+ // set up anchoring defaults
+ anchor_minlen = is_dna ? ANCHOR_NUC_MINLEN_DEFAULT : ANCHOR_AA_MINLEN_DEFAULT;
+
+ const size_t meanlen = static_cast<size_t> (std::floor (seq_db.meanlength()));
+
+ // model
+ const bool dna_defaults = (is_dna && (meanlen <= LONG_DNA_DEFAULT)) ? true : false;
+ const bool longdna_defaults = (is_dna && (meanlen > LONG_DNA_DEFAULT)) ? true : false;
+ const bool protein_defaults = (is_protein) ? true : false;
+
+ // It's best to set the minimal number of options here:
+ // Only set things which are /different/ from the initialization
+ // in init_opts.
+ // - explicitly turn on anchoring if desired, but don't turn it off
+ // For example, I used to explicitly set
+ // model = MODEL_DEFAULT
+ // but it's best to just leave this job to init_opts.
+
+ // small DNA
+ if (dna_defaults) {
+ learn_gap = true;
+ learn_emit_bypair = true;
+ learn_emit_all = false;
+ hardmasked = true;
+ }
+
+ // same as dna_defaults, but with anchoring
+ if (longdna_defaults) {
+ learn_gap = true;
+ learn_emit_bypair = true;
+ learn_emit_all = false;
+ anchored = true;
+ hardmasked = true;
+ }
+
+ // protein:
+ if (protein_defaults) {
+ learn_gap = (num_seq_pairs * meanlen > static_cast<size_t> (min_gap_training_data)) ? true : false;
+ learn_emit_bypair = false;
+ learn_emit_all = (num_seq_pairs * meanlen > static_cast<size_t> (min_emit_training_data)) ? true : false;
+ }
+
+ // warning about anchoring (MUMmer)
+#ifndef MUMMER_EXEC
+ if (meanlen > 5000) {
+ CTAG(9,FSA) << endl << "WARNING: MUMmer is not available, so we are running in unanchored mode; inference may be slow or even fail." << endl << endl;
+ anchored = false;
+ }
+#endif
+
+ // set up default word length to use for sequence similarity comparisons
+ kmer_length = Sequence_kmer_counts::choose_minimum_word_length (seq_db,
+ alphabet);
+
+}
+
+void FSA::parse_opts() {
+
+ // parse command-line options
+ opts.parse_or_die();
+
+
+ /***********************************************
+ * Output options
+ ***********************************************/
+
+ // no point in writing divergences unless learning by pair
+ if (!learn_emit_bypair && write_divergences)
+ THROWEXPR ("ERROR: Writing divergences doesn't make sense unless --learnemit-bypair is set.");
+
+
+ /***********************************************
+ * Parallelization options
+ ***********************************************/
+
+ // ensure valid number of parallelized jobs
+ if ((static_cast<size_t> (num_parallelized_jobs) > num_seq_pairs) || (static_cast<size_t> (num_parallelized_jobs) > MAX_NUM_PARALLELIZED_JOBS)) {
+ CTAG(9,FSA) << "WARNING: Reducing --parallelize " << num_parallelized_jobs << " to ";
+ if (MAX_NUM_PARALLELIZED_JOBS < num_seq_pairs) {
+ CL << MAX_NUM_PARALLELIZED_JOBS <<", the maximum number of parallelized jobs" << endl;
+ num_parallelized_jobs = MAX_NUM_PARALLELIZED_JOBS;
+ } else {
+ CTAG(9,FSA) << num_seq_pairs <<", the maximum possible number of unique sequence pairs." << endl;
+ num_parallelized_jobs = num_seq_pairs;
+ }
+ }
+ else if (num_parallelized_jobs != 0 && num_parallelized_jobs < MIN_NUM_PARALLELIZED_JOBS) {
+ CTAG(9,FSA) << "WARNING: Increasing --parallelize " << num_parallelized_jobs << " to " << MIN_NUM_PARALLELIZED_JOBS <<", the minimum number of parallelized jobs" << endl;
+ num_parallelized_jobs = MIN_NUM_PARALLELIZED_JOBS;
+ }
+ parallelizing = (num_parallelized_jobs > 0) ? true : false;
+
+ /***********************************************
+ * Database options
+ ***********************************************/
+
+ write_db = !read_posteriors_from_db && (db_name.length() > 0);
+
+
+ /***********************************************
+ * Pair HMM model options
+ ***********************************************/
+
+ // handle nucprot option
+ if (nucprot) {
+
+ // sanity checks
+ if (!is_dna)
+ THROWEXPR ("ERROR: Input sequences must be nucleotide in order to use --nucprot option.");
+ if (output_for_gui)
+ THROWEXPR ("ERROR: You currently cannot view GUI output for --nucprot alignments. Sorry!");
+ if (mercator_constraint_file != "")
+ THROWEXPR ("ERROR: You cannot specify Mercator constraints for --nucprot alignments.");
+ if (hardmasked) {
+ CTAG(9,FSA) << "WARNING: Hardmasking is not allowed for --nucprot alignments; I'm disabling hardmasking." << endl;
+ hardmasked = false;
+ }
+ if (anchored) {
+ CTAG(9,FSA) << "WARNING: Anchoring is not allowed for --nucprot alignments; I'm disabling anchoring." << endl;
+ anchored = false;
+ }
+
+ // fix the alphabet as appropriate
+ is_dna = false;
+ is_protein = true;
+ alphabet = Protein_alphabet();
+ alphabet_string = PROTEIN_ALPHABET_STRING;
+
+ // warn if learning strategy isn't acceptable.
+ if (learn_emit_bypair) {
+ CTAG(9,FSA) << "WARNING: You cannot use --learnemit-bypair with --nucprot; I'm disabling --learnemit-bypair and enabling --learnemit-all." << endl;
+ learn_emit_bypair = false;
+ }
+
+ // now set default options all over again (but for proteins)
+ // NB this prevent users from changing some options on the command line
+ set_up_defaults();
+
+ }
+
+ // sane parameters to Tamura-Nei
+ if ((time < 0) || (alpha_R < 0) || (alpha_Y < 0) || (beta < 0))
+ THROWEXPR ("ERROR: Jukes-Cantor and Tamura-Nei parameters --time, --alphar, --alphay and --beta must be positive.");
+
+
+ /***********************************************
+ * Parameter estimation options
+ ***********************************************/
+
+ // don't allow too many iterations of EM
+ if (em_max_iter > EM_MAX_ITER_DEFAULT) {
+ CL << "Reducing max rounds of EM to " << EM_MAX_ITER_DEFAULT << endl;
+ em_max_iter = EM_MAX_ITER_DEFAULT;
+ }
+
+ // enforce no learning if so requested
+ // initialize parameters to defaults which don't depend on the data:
+ // ProbCons defaults for RNA and BLOSUM62 for protein
+ if (nolearn) {
+ learn_emit_all = learn_emit_bypair = learn_gap = false;
+ model = 5;
+ }
+
+ // check learning strategy is consistent
+ if (learn_emit_all && learn_emit_bypair)
+ THROWEXPR ("ERROR: You cannot learn both across all sequences and by pairs of sequences. Please tell me which to ignore with --nolearnemit-all or --nolearnemit-bypair.");
+
+ // check that regularization is sane
+ if ((regularization_transition_scale < 0) || (regularization_emission_scale < 0))
+ THROWEXPR ("ERROR: Regularization scales must be >= 0.");
+
+ // can't learn by all if anchored
+ if (learn_emit_all && anchored)
+ THROWEXPR ("ERROR: Only --learnemit-bypair is allowed for anchoring; try using --nolearnemit-all or --nolearn.");
+
+
+ /***********************************************
+ * Multiple alignment options: sequence annealing
+ ***********************************************/
+
+ // refinement
+ if (num_refinement_steps == -1)
+ num_refinement_steps = 99999999;
+
+ // warning about low gap factor
+ if (gap_factor < minprob)
+ CL << "A gap factor < " << minprob << " is not meaningful; " << minprob << " will be used internally instead." << endl;
+
+ // maximum sensitivity option
+ if (maxsn)
+ gap_factor = 0;
+
+ // use tgf weighting always
+ // (originally the maxsn option triggered maxstep weighting,
+ // but empirically I found that tgf weighting gave essentially identical performance
+ // + is truly steepest-ascent => use tgf weighting, even for maxsn mode)
+ use_tgf = true;
+
+
+ /***********************************************
+ * Alignment speedup options: many sequences
+ ***********************************************/
+
+ // recommendation to use --fast
+ if (!fast_defaults && (num_seqs > 100))
+ CTAG(9,FSA) << endl << "WARNING: It is highly recommended that you invoke the --fast option when aligning many sequences. If you do not, then inference may take a very long time or even fail." << endl << endl;
+
+ // k-mer length must be > 0
+ // (catch the case of k = 0, which occurs automatically if the median sequence length is 0)
+ if (kmer_length <= 0) {
+ if (seq_db.median_length() != 0)
+ THROWEXPR ("ERROR: k-mer word length must be > 0.");
+ }
+
+ // degree must be >= 0
+ if (degree < 0)
+ THROWEXPR ("ERROR: The requested --degree setting must be in 0, ..., (N - 1).");
+ // and less than N
+ if (degree > static_cast<int> (seq_db.size() - 1))
+ degree = seq_db.size() - 1;
+
+ // can't have both refalign and fast
+ if (refalign) {
+ if (fast_defaults)
+ THROWEXPR ("ERROR: You can't select both --fast and --refalign; please choose one or the other.");
+ num_minimum_spanning_trees = 0;
+ num_maximum_spanning_trees = 0;
+ num_minimum_spanning_palm_trees = 0;
+ degree = 0;
+ }
+
+ // fast options:
+ // Scaled by 5 (so we do ~90% of all (10 choose 2) pairs for an alignment of 15 sequences)
+ if (fast_defaults)
+ fraction_alignment_pairs = 5 * Sequence_pair_selector::erdos_renyi_p_cutoff (num_seqs);
+
+ // if alignment to a reference, use minimal number of sequence pairs
+ if (refalign)
+ num_alignment_pairs = num_seqs - 1;
+
+ // convert from fraction to absolute number of pairs for inference
+ // if num_alignment_pairs not specified, then initialize with
+ // fraction_alignment_pairs if specified
+ // all pairs if not
+ if (num_alignment_pairs < DOUBLE_TINY)
+ num_alignment_pairs = static_cast<int> (std::floor (num_seq_pairs * fraction_alignment_pairs));
+
+ // make sure that we can generate a spanning tree to get a complete alignment
+ if (static_cast<size_t> (num_alignment_pairs) < (num_seqs - 1)) {
+ CTAG(9,FSA) << "WARNING: Increasing --alignment-number to (N - 1) = " << num_seqs - 1 << " to ensure a complete alignment." << endl;
+ num_alignment_pairs = num_seqs - 1;
+ }
+
+ // make sure that a reasonable number of alignment pairs are requested
+ if (static_cast<size_t> (num_alignment_pairs) > num_seq_pairs) {
+ // only warn if --fast wasn't invoked
+ if (!fast_defaults)
+ CTAG(9,FSA) << "WARNING: Reducing --alignment-number " << num_alignment_pairs << " to " << num_seq_pairs << ", the maximum possible number of unique sequence pairs." << endl;
+ num_alignment_pairs = num_seq_pairs;
+ }
+
+ // now store fractions (used for logging)
+ fraction_alignment_pairs = static_cast<double> (num_alignment_pairs) / num_seq_pairs;
+
+
+
+ /***********************************************
+ * Alignment speedup options: long sequences (MUMmer)
+ ***********************************************/
+
+ // Exonerate implies anchoring
+ if (exonerate)
+ anchored = true;
+
+ // check sane
+#ifndef MUMMER_EXEC
+ if (anchored)
+ THROWEXPR ("ERROR: FSA was compiled without MUMmer support. Please recompile with MUMmer if you wish to use anchoring.");
+#endif
+
+ // don't try to translate sequence if we're already in protein space
+ if (is_protein && use_translated)
+ use_translated = false;
+
+ // translated implies anchoring
+ if (use_translated)
+ anchored = true;
+
+ // set up proper minlen if doing translated anchoring
+ if (use_translated)
+ anchor_minlen = ANCHOR_AA_MINLEN_DEFAULT;
+
+ // no hardmasking for protein sequence
+ if (!is_dna && hardmasked)
+ THROWEXPR ("ERROR: Hardmasking is only available for nucleotide sequence.");
+
+ /***********************************************
+ * Alignment speedup options: long sequences (exonerate)
+ ***********************************************/
+
+ // check sane
+#ifndef EXONERATE_EXEC
+ if (exonerate)
+ THROWEXPR ("ERROR: FSA was compiled without exonerate support. Please recompile with exonerate if you wish to use exonerate for anchoring.");
+#endif
+
+ // recommend softmasking
+ if (exonerate && !softmasked)
+ CTAG(9,FSA) << endl << "WARNING: It is HIGHLY RECOMMENDED that you softmask sequence and use the --softmasked option when calling exonerate." << endl << endl;
+
+ // warning about anchoring (exonerate)
+ if ((seq_db.meanlength() > 50000) && !exonerate) {
+ CTAG(9,FSA) << endl << "WARNING: Unless you are aligning well-conserved sequences, it is highly recommend that you invoke the exonerate program (as well as MUMmer) when aligning very long sequences." << endl << endl;
+ }
+
+ /***********************************************
+ * Alignment speedup options: long sequences (Mercator)
+ ***********************************************/
+
+
+ /***********************************************
+ * Memory savings
+ ***********************************************/
+
+ // check that bandwidth is sane
+ if (bandwidth < 0)
+ THROWEXPR ("ERROR: Please specify a positive banding width.");
+
+}
+
+void FSA::init_indel_params (Params& params) {
+
+ params.is_indel2 = is_indel2;
+ params.to_end = DOUBLE_TINY;
+
+ // if nucleotide
+ if (is_dna) {
+ if (!is_indel2) {
+ params.gap_open1 = 0.02;
+ params.gap_extend1 = 0.3;
+ params.gap_open2 = 0;
+ params.gap_extend2 = 0;
+ } else {
+ params.gap_open1 = 0.012; // have mixture components still sum to gap_open prob of 0.02 as above
+ params.gap_extend1 = 0.4;
+ params.gap_open2 = 0.008;
+ params.gap_extend2 = 0.9;
+ }
+ }
+
+ // if amino acid (ProbCons defaults for these -- taken from probcons/Defaults.h)
+ else if (is_protein) {
+ if (!is_indel2) {
+ params.gap_open1 = 0.01993141696f;
+ params.gap_extend1 = 0.7943345308f;
+ params.gap_open2 = 0;
+ params.gap_extend2 = 0;
+ } else {
+ params.gap_open1 = 0.0119511066f;
+ params.gap_extend1 = 0.3965826333f;
+ params.gap_open2 = 0.008008334786f;
+ params.gap_extend2 = 0.8988758326f;
+ }
+ }
+
+ // unreachable code
+ else {
+ THROWEXPR ("ERROR: These don't seem to be nucleotide or amino acid sequences! This message should never occur.");
+ }
+
+ // initialize indel params to command-line values if passed
+ if (gap_open1 > DOUBLE_TINY)
+ params.gap_open1 = gap_open1;
+ if (gap_extend1 > DOUBLE_TINY)
+ params.gap_extend1 = gap_extend1;
+ if (gap_open2 > DOUBLE_TINY)
+ params.gap_open2 = gap_open2;
+ if (gap_extend2 > DOUBLE_TINY)
+ params.gap_extend2 = gap_extend2;
+
+ // log seed params
+ if (CTAGGING(-1,FSAEM)) {
+ CL << "Seed indel parameters:" << endl;
+ params.show_transition_matrix (CL);
+ }
+
+}
+
+
+void FSA::init_subst_params (Params& params, const std::vector<double>& char_freq, const unsigned model /* = MODEL_DEFAULT */, const double time /* = TIME_DEFAULT */) {
+
+ // time parameter
+ params.time = time;
+
+ // alphabet_string
+ params.alphabet_string = alphabet_string;
+
+ // allocate memory
+ params.single_dist.resize (alphabet_string.length());
+ params.pair_dist.resize (alphabet_string.length());
+ for (size_t i = 0; i < alphabet_string.length(); i++)
+ params.pair_dist[i].resize (alphabet_string.length());
+
+ // init nuc models
+ if (is_dna) {
+
+ // ProbConsRNA defaults (taken from probconsRNA/Defaults.h)
+ const double probcons_single[4] = {
+ 0.2270790040f, 0.2422080040f, 0.2839320004f, 0.2464679927f };
+ const double probcons_pair[4][4] = {
+ { 0.1487240046f, 0.0184142999f, 0.0361397006f, 0.0238473993f },
+ { 0.0184142999f, 0.1583919972f, 0.0275536999f, 0.0389291011f },
+ { 0.0361397006f, 0.0275536999f, 0.1979320049f, 0.0244289003f },
+ { 0.0238473993f, 0.0389291011f, 0.0244289003f, 0.1557479948f } };
+
+
+ // now set up the substitution model
+ switch (model) {
+
+ case 0: // Jukes-Cantor model
+ for (size_t i = 0; i < 4; i++) {
+ params.single_dist[i] = 1 / 4.0;
+ for (size_t j = 0; j < 4; j++) {
+ if (i == j) {
+ params.pair_dist[i][j] = params.single_dist[i] * (1/4.0 + (3/4.0) * std::exp (-4.0 * time / 3.0));
+ } else {
+ params.pair_dist[i][j] = params.single_dist[i] * (1/4.0 - (1/4.0) * std::exp (-4.0 * time / 3.0));
+ }
+ }
+ }
+ break;
+
+ case 1: // Tamura-Nei model
+ // empirical char freqs
+ params.single_dist.assign (char_freq.begin(), char_freq.end());
+ for (size_t i = 0; i < 4; i++) {
+ for (size_t j = 0; j < 4; j++) {
+ const double alphai = (i == 0 || i == 2) ? alpha_R : alpha_Y;
+ const double pj = (j == 0 || j == 2) ? (char_freq[0] + char_freq[2]) : (char_freq[1] + char_freq[3]); // piR or piY, as appropriate for j
+ assert (alphai > 0 && pj > 0);
+ // if no change
+ if (i == j) {
+ params.pair_dist[i][j] = std::exp (-(alphai + beta) * time)
+ + std::exp (-beta * time) * (1 - std::exp (-alphai * time)) * (char_freq[j] / pj)
+ + (1 - std::exp (-beta * time)) * char_freq[j];
+ params.pair_dist[i][j] *= char_freq[i]; // convert from subst. prob. to joint prob.
+ }
+ // else if transition
+ // else if (std::abs (static_cast<int> (static_cast<int> (i) - j)) == 2) {
+ else if (abs (static_cast<int> (static_cast<int> (i) - j)) == 2) {
+ params.pair_dist[i][j] = 0.
+ + std::exp (-beta * time) * (1 - std::exp (-alphai * time)) * (char_freq[j] / pj)
+ + (1 - std::exp (-beta * time)) * char_freq[j];
+ params.pair_dist[i][j] *= char_freq[i];
+ }
+ // else transversion
+ else {
+ params.pair_dist[i][j] = 0.
+ + 0.
+ + (1 - std::exp (-beta * time)) * char_freq[j];
+ params.pair_dist[i][j] *= char_freq[i];
+ }
+ }
+ }
+ break;
+
+ case 5: // ProbCons
+ for (size_t i = 0; i < 4; i++) {
+ params.single_dist[i] = probcons_single[i];
+ for (size_t j = 0; j < 4; j++) {
+ params.pair_dist[i][j] = probcons_pair[i][j];
+ }
+ }
+ break;
+
+ default:
+ THROWEXPR ("ERROR: Model " << model << " does not exist. Please choose a valid model." << endl);
+ }
+
+ }
+
+ // proteins
+ else {
+
+ // BLOSUM62 matrix (taken from probcons/Defaults.h and converted per my AA sorting)
+ double BLOSUM62_single[20] = {
+ 0.07831005, 0.02189704, 0.05130349, 0.05615771, 0.04463228, 0.07783433, 0.02601093, 0.06511648, 0.05877077, 0.09716489, 0.02438117, 0.04433257, 0.03940142, 0.03585766, 0.05246024, 0.05849916, 0.05115306, 0.07343426, 0.01203523, 0.03124726 };
+ double BLOSUM62_pair[20][20] = {
+ { 0.02373072, 0.00145515, 0.00223549, 0.00332218, 0.00165004, 0.00597898, 0.00114353, 0.00318853, 0.00331693, 0.00449576, 0.00148878, 0.00210228, 0.00230618, 0.00219102, 0.00244502, 0.00631752, 0.00389995, 0.00533241, 0.00039119, 0.0013184 },
+ { 0.00145515, 0.0101347, 0.00036798, 0.00037956, 0.00052274, 0.00071206, 0.00026421, 0.0009404, 0.00046951, 0.00138494, 0.00037421, 0.00042479, 0.00034766, 0.00032102, 0.00044701, 0.00094867, 0.00073798, 0.00119152, 0.00010666, 0.00036626 },
+ { 0.00223549, 0.00036798, 0.01911178, 0.004968, 0.00069041, 0.00235249, 0.00097077, 0.00105355, 0.00252518, 0.00161966, 0.00047808, 0.0035354, 0.00125381, 0.00176784, 0.00161657, 0.00285226, 0.00180488, 0.00127915, 0.00016015, 0.00066005 },
+ { 0.00332218, 0.00037956, 0.004968, 0.01676565, 0.00078814, 0.0021486, 0.00131767, 0.00124207, 0.0042842, 0.00222063, 0.00076105, 0.00224738, 0.0015155, 0.00345128, 0.00268865, 0.00293898, 0.0021676, 0.00178697, 0.00023815, 0.00092548 },
+ { 0.00165004, 0.00052274, 0.00069041, 0.00078814, 0.01661038, 0.00115204, 0.00072545, 0.00279948, 0.00087222, 0.00533369, 0.00116111, 0.00084658, 0.00060701, 0.00059248, 0.00090768, 0.00119036, 0.00107595, 0.00256159, 0.00085751, 0.00368739 },
+ { 0.00597898, 0.00071206, 0.00235249, 0.0021486, 0.00115204, 0.04062876, 0.00103704, 0.0014252, 0.00259311, 0.00212853, 0.00066504, 0.00288882, 0.00155601, 0.00142432, 0.00194865, 0.00381962, 0.00214841, 0.00194579, 0.00038786, 0.00089301 },
+ { 0.00114353, 0.00026421, 0.00097077, 0.00131767, 0.00072545, 0.00103704, 0.00867996, 0.00059716, 0.00121376, 0.00111754, 0.00042237, 0.00141205, 0.00049078, 0.00113901, 0.00132105, 0.00116422, 0.00077747, 0.00071553, 0.00019097, 0.00131038 },
+ { 0.00318853, 0.0009404, 0.00105355, 0.00124207, 0.00279948, 0.0014252, 0.00059716, 0.01778263, 0.00157852, 0.01071834, 0.00224097, 0.00104273, 0.00103767, 0.00100883, 0.00138145, 0.00173565, 0.00248968, 0.01117956, 0.00039549, 0.00127857 },
+ { 0.00331693, 0.00046951, 0.00252518, 0.0042842, 0.00087222, 0.00259311, 0.00121376, 0.00157852, 0.01612228, 0.00259626, 0.0009612, 0.0025731, 0.00154836, 0.00312308, 0.0059565, 0.00312633, 0.00250862, 0.00210897, 0.00028448, 0.00100817 },
+ { 0.00449576, 0.00138494, 0.00161966, 0.00222063, 0.00533369, 0.00212853, 0.00111754, 0.01071834, 0.00259626, 0.03583921, 0.00461939, 0.00160275, 0.0015731, 0.00180553, 0.00246811, 0.00250962, 0.00302273, 0.0091446, 0.00076736, 0.00219713 },
+ { 0.00148878, 0.00037421, 0.00047808, 0.00076105, 0.00116111, 0.00066504, 0.00042237, 0.00224097, 0.0009612, 0.00461939, 0.00409522, 0.00063401, 0.00046718, 0.00075546, 0.00076734, 0.00087787, 0.00093371, 0.00197461, 0.00016253, 0.00054105 },
+ { 0.00210228, 0.00042479, 0.0035354, 0.00224738, 0.00084658, 0.00288882, 0.00141205, 0.00104273, 0.0025731, 0.00160275, 0.00063401, 0.01281864, 0.00100282, 0.00158223, 0.00207782, 0.00301397, 0.00220144, 0.00136609, 0.00021006, 0.0007496 },
+ { 0.00230618, 0.00034766, 0.00125381, 0.0015155, 0.00060701, 0.00155601, 0.00049078, 0.00103767, 0.00154836, 0.0015731, 0.00046718, 0.00100282, 0.01846071, 0.00090111, 0.00106268, 0.00180037, 0.00147982, 0.00135781, 0.00015674, 0.00047608 },
+ { 0.00219102, 0.00032102, 0.00176784, 0.00345128, 0.00059248, 0.00142432, 0.00113901, 0.00100883, 0.00312308, 0.00180553, 0.00075546, 0.00158223, 0.00090111, 0.00756604, 0.00253532, 0.00191155, 0.00154526, 0.00132844, 0.00020592, 0.00070192 },
+ { 0.00244502, 0.00044701, 0.00161657, 0.00268865, 0.00090768, 0.00194865, 0.00132105, 0.00138145, 0.0059565, 0.00246811, 0.00076734, 0.00207782, 0.00106268, 0.00253532, 0.01775118, 0.0022454, 0.00186053, 0.00169359, 0.00029139, 0.0009943 },
+ { 0.00631752, 0.00094867, 0.00285226, 0.00293898, 0.00119036, 0.00381962, 0.00116422, 0.00173565, 0.00312633, 0.00250962, 0.00087787, 0.00301397, 0.00180037, 0.00191155, 0.0022454, 0.01346609, 0.00487295, 0.00241601, 0.00026525, 0.00102648 },
+ { 0.00389995, 0.00073798, 0.00180488, 0.0021676, 0.00107595, 0.00214841, 0.00077747, 0.00248968, 0.00250862, 0.00302273, 0.00093371, 0.00220144, 0.00147982, 0.00154526, 0.00186053, 0.00487295, 0.01299436, 0.00343452, 0.00024961, 0.00094759 },
+ { 0.00533241, 0.00119152, 0.00127915, 0.00178697, 0.00256159, 0.00194579, 0.00071553, 0.01117956, 0.00210897, 0.0091446, 0.00197461, 0.00136609, 0.00135781, 0.00132844, 0.00169359, 0.00241601, 0.00343452, 0.02075171, 0.00038538, 0.00148001 },
+ { 0.00039119, 0.00010666, 0.00016015, 0.00023815, 0.00085751, 0.00038786, 0.00019097, 0.00039549, 0.00028448, 0.00076736, 0.00016253, 0.00021006, 0.00015674, 0.00020592, 0.00029139, 0.00026525, 0.00024961, 0.00038538, 0.00563625, 0.00069226 },
+ { 0.0013184, 0.00036626, 0.00066005, 0.00092548, 0.00368739, 0.00089301, 0.00131038, 0.00127857, 0.00100817, 0.00219713, 0.00054105, 0.0007496, 0.00047608, 0.00070192, 0.0009943, 0.00102648, 0.00094759, 0.00148001, 0.00069226, 0.00999315 } };
+
+
+ switch (model) {
+
+ case 1: // BLOSUM62, but converted to empirical target aa frequencies
+ params.single_dist.assign (char_freq.begin(), char_freq.end());
+ for (size_t i = 0; i < 20; i++) {
+ for (size_t j = 0; j < 20; j++) {
+ params.pair_dist[i][j] = BLOSUM62_pair[i][j] * (char_freq[i] * char_freq[j]) / (BLOSUM62_single[i] * BLOSUM62_single[j]);
+ }
+ }
+ params.normalize();
+ break;
+
+ case 5: // BLOSUM62
+ for (size_t i = 0; i < 20; i++) {
+ params.single_dist[i] = BLOSUM62_single[i];
+ for (size_t j = 0; j < 20; j++) {
+ params.pair_dist[i][j] = BLOSUM62_pair[i][j];
+ }
+ }
+ break;
+
+ default:
+ THROWEXPR ("ERROR: Model " << model << " does not exist. Please choose a valid model." << endl);
+ }
+
+ }
+
+ params.assert_normalized();
+
+ // log seed params
+ if (CTAGGING(-1,FSAEM)) {
+ CL << "Seed emit parameters:" << endl;
+ params.show_emission (CL);
+ }
+
+ params.assert_normalized();
+
+}
+
+void FSA::init_pseudocounts (Params& pseudo, const Params& seed, double transition_scale, double emission_scale) {
+
+ if (CTAGGING(2,FSA))
+ CL << "Initializing pseudocounts." << endl;
+
+ // get seed distributions
+ pseudo.copy_all (seed);
+
+ // now scale to get counts
+ pseudo.gap_open1 *= transition_scale;
+ pseudo.gap_open2 *= transition_scale;
+ pseudo.gap_extend1 *= transition_scale;
+ pseudo.gap_extend2 *= transition_scale;
+ for (size_t i = 0; i < pseudo.pair_dist.size(); ++i) {
+ pseudo.single_dist[i] *= emission_scale;
+ for (size_t j = 0; j < pseudo.pair_dist.size(); ++j)
+ pseudo.pair_dist[i][j] *= emission_scale;
+ }
+
+}
+
+bool FSA::train_params (Params& params, const Sequence_database& seq_db_train, const Sequence_pairs& subset,
+ bool left_match, bool right_match, bool ragged_ends,
+ const Params& pseudocounts, bool learn_emit) {
+
+ // enforce max_ram cutoff
+ for (Sequence_pairs::const_iterator pair = subset.begin(); pair != subset.end(); ++pair) {
+ const size_t i = pair->first;
+ const size_t j = pair->second;
+ const size_t needed = estimate_ram_needed (seq_db_train.get_seq (i).seq.length(), seq_db_train.get_seq (j).seq.length());
+ if ((max_ram > 0) && (static_cast<int> (needed) > max_ram)) {
+ CTAG(9,FSAEM) << "WARNING: Skipping inference step because estimated memory usage (" << needed << " MB) "
+ << "is greater than specified limit (" << max_ram << " MB)." << endl
+ << "Offending sequences are '" << seq_db_train.get_seq (i).name << "' and '" << seq_db_train.get_seq (j).name << "'." << endl;
+ return false;
+ }
+ }
+
+ // without banding
+ if (bandwidth == 0) {
+ if (is_dna && !is_indel2)
+ return Model::train_params_engine<NucleotideWithoutBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else if (is_dna && is_indel2)
+ return Model::train_params_engine<NucleotideIndel2WithoutBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else if (!is_dna && !is_indel2)
+ return Model::train_params_engine<AminoAcidWithoutBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else if (!is_dna && is_indel2)
+ return Model::train_params_engine<AminoAcidIndel2WithoutBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else
+ THROWEXPR ("ERROR: Unreachable code.");
+ }
+ // with banding
+ else {
+ if (is_dna && !is_indel2)
+ return Model::train_params_engine<NucleotideWithBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else if (is_dna && is_indel2)
+ return Model::train_params_engine<NucleotideIndel2WithBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else if (!is_dna && !is_indel2)
+ return Model::train_params_engine<AminoAcidWithBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else if (!is_dna && is_indel2)
+ return Model::train_params_engine<AminoAcidIndel2WithBanding> (params, seq_db_train, subset,
+ left_match, right_match, ragged_ends,
+ learn_gap, learn_emit, regularize, pseudocounts, em_max_iter, em_min_inc);
+ else
+ THROWEXPR ("ERROR: Unreachable code.");
+ }
+
+}
+
+Dotplot FSA::get_pairwise_dotplot (Params& params, const Sequence& xseq, const Sequence& yseq,
+ bool left_match, bool right_match, bool ragged_ends) {
+
+ // enforce max_ram cutoff
+ size_t needed = estimate_ram_needed (xseq.length(), yseq.length());
+ if ((max_ram > 0) && (static_cast<int> (needed) > max_ram)) {
+ CTAG(9,FSAEM) << "WARNING: Skipping inference step because estimated memory usage (" << needed << " MB) "
+ << "is greater than specified limit (" << max_ram << " MB)." << endl
+ << "Offending sequences are '" << xseq.name << "' and '" << yseq.name << "'." << endl;
+ return Dotplot (xseq.length(), yseq.length());
+ }
+
+ // without banding
+ if (bandwidth == 0) {
+ if (is_dna && !is_indel2)
+ return Model::get_pairwise_dotplot_engine<NucleotideWithoutBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else if (is_dna && is_indel2)
+ return Model::get_pairwise_dotplot_engine<NucleotideIndel2WithoutBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && !is_indel2)
+ return Model::get_pairwise_dotplot_engine<AminoAcidWithoutBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && is_indel2)
+ return Model::get_pairwise_dotplot_engine<AminoAcidIndel2WithoutBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else
+ THROWEXPR ("ERROR: Unreachable code.");
+ }
+ // with banding
+ else {
+ if (is_dna && !is_indel2)
+ return Model::get_pairwise_dotplot_engine<NucleotideWithBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else if (is_dna && is_indel2)
+ return Model::get_pairwise_dotplot_engine<NucleotideIndel2WithBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && !is_indel2)
+ return Model::get_pairwise_dotplot_engine<AminoAcidWithBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && is_indel2)
+ return Model::get_pairwise_dotplot_engine<AminoAcidIndel2WithBanding> (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+ else
+ THROWEXPR ("ERROR: Unreachable code.");
+ }
+
+}
+
+Post_probs FSA::get_pairwise_post_probs (Params& params, const Sequence& xseq, const Sequence& yseq,
+ bool left_match, bool right_match, bool ragged_ends) {
+
+ // enforce max_ram cutoff
+ const size_t needed = estimate_ram_needed (xseq.length(), yseq.length());
+ if ((max_ram > 0) && (needed > static_cast<size_t> (max_ram))) {
+ CTAG(9,FSAEM) << "WARNING: Skipping inference step because estimated memory usage (" << needed << " MB) "
+ << "is greater than specified limit (" << max_ram << " MB)." << endl
+ << "Offending sequences are '" << xseq.name << "' and '" << yseq.name << "'." << endl;
+ return Post_probs();
+ }
+
+ // without banding
+ if (bandwidth == 0) {
+ if (is_dna && !is_indel2)
+ return Model::get_pairwise_post_probs_engine<NucleotideWithoutBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else if (is_dna && is_indel2)
+ return Model::get_pairwise_post_probs_engine<NucleotideIndel2WithoutBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && !is_indel2)
+ return Model::get_pairwise_post_probs_engine<AminoAcidWithoutBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && is_indel2)
+ return Model::get_pairwise_post_probs_engine<AminoAcidIndel2WithoutBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else
+ THROWEXPR ("ERROR: Unreachable code.");
+ }
+ // with banding
+ else {
+ if (is_dna && !is_indel2)
+ return Model::get_pairwise_post_probs_engine<NucleotideWithBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else if (is_dna && is_indel2)
+ return Model::get_pairwise_post_probs_engine<NucleotideIndel2WithBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && !is_indel2)
+ return Model::get_pairwise_post_probs_engine<AminoAcidWithBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else if (!is_dna && is_indel2)
+ return Model::get_pairwise_post_probs_engine<AminoAcidIndel2WithBanding> (params, xseq, yseq,
+ minprob,
+ left_match, right_match, ragged_ends);
+ else
+ THROWEXPR ("ERROR: Unreachable code.");
+ }
+
+}
+
+void FSA::show_divergences (std::ostream& o) const {
+
+ // first compute a matrix of divergences (-1 for no information)
+ std::vector<std::vector<double> > distmat (num_seqs, std::vector<double> (num_seqs, -1));
+ for (size_t cnt = 0; cnt < alignment_seq_pairs.size(); ++cnt) {
+ const size_t i = alignment_seq_pairs[cnt].first;
+ const size_t j = alignment_seq_pairs[cnt].second;
+ distmat[i][j] = alignment_params[cnt].branch_length (0);
+ distmat[j][i] = alignment_params[cnt].branch_length (1);
+ }
+
+ // now display: first get width
+ size_t width = 0;
+ for (size_t i = 0; i < seq_db_internal.size(); ++i)
+ width = max (width, seq_db_internal.get_seq (i).name.length());
+ width += 2;
+
+ // state label row
+ o.width (width); o << "";
+ for (size_t i = 0; i < num_seqs; ++i) {
+ o.width (width);
+ o << seq_db_internal.get_seq (i).name;
+ }
+ o << endl;
+ // divergences
+ for (size_t i = 0; i < num_seqs; ++i) {
+ o.width (width);
+ o << seq_db_internal.get_seq (i).name;
+ for (size_t j = 0; j < num_seqs; ++j) {
+ o.width (width);
+ if (i == j)
+ o << 0.;
+ else
+ o << std::setprecision (PRECISION_DEFAULT) << distmat[i][j];
+ }
+ o << endl;
+ }
+
+}
+
+size_t FSA::estimate_ram_needed (size_t xlen, size_t ylen) const {
+
+ size_t needed = static_cast<size_t> (std::floor (((xlen + 1.0) / (1.0 * MEGABYTE)) * (ylen + 1) * static_cast<double> (sizeof (bfloat))));
+ needed *= is_indel2 ? 5 : 3; // hardcode in size of Pair HMM state space (not counting state and end)
+ needed *= 2; // factor of 2 for when we store both forward and backward DP matrices (for posterior decoding)
+
+ return needed;
+}
+
+void FSA::assemble_sequence_data() {
+
+ // assemble clean sequence data
+ // (hardmasked sequence stripped if so requested and degenerate characters randomized)
+ for (size_t i = 0; i < num_seqs; ++i) {
+
+ // get original sequence data
+ Sequence& sequence = seq_db.get_seq (i);
+
+ // if hardmasked, keep track of hardmasking
+ if (hardmasked)
+ sequence.init_hardmasking (MIN_HARDMASK_LENGTH, DNA_alphabet::is_hardmask_char);
+
+ // if hardmasking, store stripped sequence
+ std::string orig_seq = hardmasked ? sequence.get_stripped_sequence().seq : sequence.seq;
+
+ // remove degenerate characters
+ std::string nondegen_seq;
+ if (nucprot) // handle case of nucprot (store the translated sequence)
+ nondegen_seq = Protein_alphabet().get_nondegen ((Translated_sequence (Sequence (sequence.name, orig_seq))).get_forward (0).seq);
+ else
+ nondegen_seq = alphabet.get_nondegen (orig_seq);
+
+ // store
+ Sequence* nondegen_sequence = new Sequence (sequence.name, nondegen_seq);
+ seq_db_internal.add_seq (nondegen_sequence);
+ }
+
+}
+
+void FSA::choose_seq_pairs() {
+
+ // initialize Sequence_pair_selector
+ Sequence_pair_selector sequence_pair_selector (seq_db_internal,
+ alphabet,
+ kmer_length);
+
+ // refalign first
+ if (refalign) {
+
+ // first sequence lies at the center if --refalign is select
+ sequence_pair_selector.choose_palm_tree (seq_db_internal.get_seq (0).name);
+
+ }
+
+ // if all are requested, then go ahead and select all pairs
+ else if (static_cast<size_t> (num_alignment_pairs) == num_seq_pairs) {
+
+ sequence_pair_selector.choose_all();
+
+ }
+
+ // else select sequence pairs
+ // order as:
+ // - minimum spanning tree
+ // - maximum spanning tree
+ // - minimum spanning palm tree
+ // - degree per sequence
+ // - randomly-chosen pairs
+ else {
+
+ // first add sequence pairs in a structured manner
+ if (num_minimum_spanning_trees > 0)
+ sequence_pair_selector.choose_minimum_spanning_tree (num_minimum_spanning_trees);
+ if (num_maximum_spanning_trees > 0)
+ sequence_pair_selector.choose_maximum_spanning_tree (num_maximum_spanning_trees);
+ if (num_minimum_spanning_palm_trees > 0)
+ sequence_pair_selector.choose_minimum_spanning_palm_tree (num_minimum_spanning_palm_trees);
+ if (degree > 0)
+ sequence_pair_selector.choose_kmer_similarity (degree);
+
+ // then add randomly until we hit the requested num_alignment_pairs target
+ const size_t num_selected = sequence_pair_selector.num_selected();
+ if (num_selected < static_cast<size_t> (num_alignment_pairs))
+ sequence_pair_selector.choose_random (num_alignment_pairs - num_selected);
+
+ }
+
+ // now actually store the pairs
+ Sequence_pairs selected_sequence_pairs = sequence_pair_selector.get_chosen_sequence_pairs();
+ assert (selected_sequence_pairs.size() == static_cast<size_t> (num_alignment_pairs));
+ size_t num_added_alignment_pairs = 0;
+ for (Sequence_pairs::const_iterator sequence_pair = selected_sequence_pairs.begin(); sequence_pair != selected_sequence_pairs.end(); ++sequence_pair) {
+
+ const size_t i = sequence_pair->first;
+ const size_t j = sequence_pair->second;
+ assert (i < j);
+
+ // now actually store the sequence pair
+ // if a worker, do we store this seq pair?
+ if (w_worker) {
+ if (is_valid_worker_seq_pair (++num_added_alignment_pairs, i, j))
+ alignment_seq_pairs.push_back (*sequence_pair);
+ }
+
+ // if not parallelizing, just store it
+ else
+ alignment_seq_pairs.push_back (*sequence_pair);
+
+ }
+
+}
+
+bool FSA::is_valid_worker_seq_pair (const int cnt, const int i, const int j) const {
+
+ int start_pos = (int) (w_start_seq_pair.first * (2 * num_seqs - w_start_seq_pair.first - 1) / 2) + (w_start_seq_pair.second - w_start_seq_pair.first);
+ int input_pos = (int) (i * (2 * num_seqs - i - 1) / 2) + (j - i);
+
+ if (cnt != -1) {
+ if (w_prev_seq_pairs_sum <= cnt && cnt < (w_prev_seq_pairs_sum + w_num_seq_pairs))
+ return true;
+ } else {
+ if (start_pos <= input_pos && input_pos < (start_pos + w_num_seq_pairs))
+ return true;
+ }
+ return false;
+}
+
+void FSA::init_for_mw_worker (const std::pair<int, int> start_seq_pair, const int prev_seq_pairs_sum, const int num_seq_pairs) {
+ w_start_seq_pair = start_seq_pair;
+ w_prev_seq_pairs_sum = prev_seq_pairs_sum;
+ w_num_seq_pairs = num_seq_pairs;
+ w_worker = true;
+}
+
+Post_probs FSA::perform_pairwise_inference (Params& params, const Sequence& xseq, const Sequence& yseq,
+ const bool left_match, const bool right_match, const bool ragged_ends,
+ const Params& pseudocounts) {
+
+ const size_t xlen = xseq.length();
+ const size_t ylen = yseq.length();
+
+ Sequence_database seq_db_pair;
+ seq_db_pair.add_seq (xseq);
+ seq_db_pair.add_seq (yseq);
+ Sequence_pairs both;
+ both.push_back (std::make_pair (0, 1));
+
+ // train params and get alignment posteriors:
+ // only train if there is enough sequence data
+ if (learn_gap || learn_emit_bypair) {
+ // 2 cases where we learn:
+ // 1) learn emit and possibly gap:
+ // only learn emit if there's enough sequence data (which implies sufficient data for learning gap)
+ // 2) learn only gap
+ // only learn gap if there's enough sequence data
+ if (learn_emit_bypair && ((0.5 * (xlen + ylen)) > min_emit_training_data))
+ train_params (params, seq_db_pair, both,
+ left_match, right_match, ragged_ends,
+ pseudocounts, learn_emit_bypair);
+ else if (learn_gap && ((0.5 * (xlen + ylen)) > min_gap_training_data))
+ train_params (params, seq_db_pair, both,
+ left_match, right_match, ragged_ends,
+ pseudocounts, false);
+ }
+
+ // perform inference
+ // note that we don't need to enforce lexical ordering here (it's guaranteed by get_pairwise_post_probs())
+ return get_pairwise_post_probs (params, xseq, yseq,
+ left_match, right_match, ragged_ends);
+
+}
+
+Post_probs FSA::perform_anchored_pairwise_inference (const Params& params_seed, const Sequence& xseq, const Sequence& yseq,
+ const Params& pseudocounts,
+ const Anchors& anchors) {
+
+ const size_t xlen = xseq.length();
+ const size_t ylen = yseq.length();
+
+ // hold posterior information for this sequence pair
+ Post_probs post_probs;
+
+ // parameters for anchored subsequence pairs
+ // (modified for each pair)
+ Params params;
+
+ // loop through the anchors for this sequence pair:
+ // look at the subsequence from the previous to the current anchor
+ // This all relies on the list of anchors being properly sorted, but we guarantee this
+ // during our anchor resolution.
+ unsigned xprevright = 0; // right-hand X coordinate of previous anchor (closed interval)
+ unsigned yprevright = 0; // set to fake value before sequence start
+ for (size_t a = 0; a <= anchors.size(); ++a) { // we're going over the bound of Anchors anchors here
+ // in order to catch the last anchored subsequence pair
+
+ // specify homology assumptions beyond (to left and right of) current subsequences
+ // note that this gives appropriate settings for the case of no anchors as well
+ bool left_match = true; // for interior anchored pairs, homology is assumed to both left and right
+ bool right_match = true;
+ if (a == 0) // if first anchored pair, then no homology assumed to left
+ left_match = false;
+ if (a == anchors.size()) // if last anchored pair, then no homology assumed to right
+ right_match = false;
+
+ // to do:
+ // make concrete decision about whether to use {left,right}_match information
+ // for now don't force homology
+ left_match = right_match = false;
+
+ // calculate the minimum required subsequence length
+ // (left_match forces Start -> Match and right_match forces Match -> End)
+ const size_t minsublen = static_cast<size_t> (left_match) + static_cast<size_t> (right_match);
+
+ // get coordinates for current anchor, making sure to catch end case,
+ // for which we have no right-anchoring information
+ unsigned xcurrleft, xcurrright; // current anchor is the closed interval [xcurrleft, xcurrright]
+ unsigned ycurrleft, ycurrright;
+ if (a == anchors.size()) { // if last anchored pair,
+ xcurrleft = xlen; // create a fake anchor which lies just beyond the sequence boundaries (0-based indexing)
+ xcurrright = xlen - 1; // (fake value)
+ ycurrleft = ylen;
+ ycurrright = ylen - 1;
+ } else {
+ xcurrleft = anchors[a].xcoords.start;
+ xcurrright = anchors[a].xcoords.end;
+ ycurrleft = anchors[a].ycoords.start;
+ ycurrright = anchors[a].ycoords.end;
+ }
+
+ // catch the case of the last real anchor (a == anchors.size() - 1) ending at a sequence boundary
+ // (no need to perform inference since overhanging sequence will be left unaligned regardless)
+ if (a == anchors.size()
+ && ((xprevright == xlen) || (yprevright == ylen)))
+ continue;
+
+ // assert that anchors are non-overlapping (at a pairwise level)
+ if (a != 0) {
+ if (xprevright >= xcurrleft)
+ THROWEXPR ("ERROR: Overlapping anchors: xprevright = " << xprevright << "; xcurrleft = " << xcurrleft << endl
+ << anchors[a]);
+ if (yprevright >= ycurrleft)
+ THROWEXPR ("ERROR: Overlapping anchors: yprevright = " << yprevright << "; ycurrleft = " << ycurrleft << endl
+ << anchors[a]);
+ }
+
+ // create subsequences (xsubleft + xsublen) and (ysubleft + ysublen)
+
+ unsigned xsubleft, ysubleft; // left coordinate of closed interval
+ unsigned xsublen, ysublen; // length of closed interval
+
+ // if first anchored pair, then make sure to get first character in subseq
+ xsubleft = xprevright + (a != 0 ? 1 : 0); // this catches the case of an anchor beginning at the coordinate 0,
+ ysubleft = yprevright + (a != 0 ? 1 : 0); // since we initialize these to 0 before looping over anchors (so we don't want to increment the boundary)
+
+ // cover case of abutting (adjacent) anchors
+ xsubleft = (xsubleft > xcurrleft) ? xcurrleft : xsubleft;
+ ysubleft = (ysubleft > ycurrleft) ? ycurrleft : ysubleft;
+
+ xsublen = xcurrleft - xsubleft; // we don't include the anchors themselves
+ ysublen = ycurrleft - ysubleft; // the subseq [xsubleft + xsublen] is a closed interval (this is important to remember!)
+
+ // subsequence names and subsequences themselves
+ // cast to int to cover the case of 0-length subseqs at the beginning,
+ // in which case the second coordinate is negative
+ const Sequence xsubseq (xseq.name + "_[" + Util::to_string (xsubleft) + "-" + Util::to_string (static_cast<int> (xsubleft + xsublen) - 1) + "]", xseq.seq.substr (xsubleft, xsublen));
+ const Sequence ysubseq (yseq.name + "_[" + Util::to_string (ysubleft) + "-" + Util::to_string (static_cast<int> (ysubleft + ysublen) - 1) + "]", yseq.seq.substr (ysubleft, ysublen));
+
+ Sequence_database subseq_pair;
+ subseq_pair.add_seq (xsubseq);
+ subseq_pair.add_seq (ysubseq);
+ Sequence_pairs both;
+ both.push_back (std::make_pair (0, 1));
+
+ // cover case of empty subsequences:
+ // (occur when anchors begin or end at sequence boundaries or are adjacent)
+ // store anchor indices and update posteriors,
+ // then continue to next anchor
+ if ((xsublen <= minsublen) || (ysublen <= minsublen)) {
+ // update posteriors to record current anchor info if not a fake anchor
+ if (a < anchors.size()) {
+ for (unsigned x = 0; x <= xcurrright - xcurrleft; ++x) // closed interval!
+ post_probs.push_back (Post_prob (xcurrleft + x, ycurrleft + x, anchors[a].score_to_prob())); // force high probability for anchor
+ }
+ // increment the anchor indices
+ xprevright = xcurrright;
+ yprevright = ycurrright;
+ // log (but only if at least one sequence has length > 0)
+ if (xsublen + ysublen > 0) {
+ const double anchors_done = 100.0 * (a + 1) / (anchors.size() + 1);
+ if (CTAGGING(6,FSA))
+ CTAG(6,FSA) << "Processed anchored subsequence pair '" << xsubseq.name << "' and '" << ysubseq.name << "'; "
+ << std::floor (anchors_done + 0.5) << "% (" << a + 1 << "/" << anchors.size() + 1 << ") complete."
+ << endl;
+ }
+ // skip inference step
+ continue;
+ }
+
+ // re-initialize params for this anchored pair of subseqs
+ params.copy_all (params_seed);
+
+ // train params and get alignment posteriors
+ // only train if there is enough sequence data
+ if (learn_gap || learn_emit_bypair) {
+ // 2 cases where we learn:
+ // 1) learn emit and possibly gap:
+ // only learn emit if there's enough sequence data (which implies sufficient data for learning gap)
+ // 2) learn only gap
+ // only learn gap if there's enough sequence data
+ if (learn_emit_bypair && ((0.5 * (xsublen + ysublen)) > min_emit_training_data))
+ train_params (params, subseq_pair, both,
+ left_match, right_match, ragged_ends,
+ pseudocounts, learn_emit_bypair);
+ else if (learn_gap && ((0.5 * (xsublen + ysublen)) > min_gap_training_data))
+ train_params (params, subseq_pair, both,
+ left_match, right_match, ragged_ends,
+ pseudocounts, false);
+ }
+
+ // perform inference
+ Post_probs subseq_post_probs = get_pairwise_post_probs (params, xsubseq, ysubseq,
+ left_match, right_match, ragged_ends);
+
+ // store this subsequence information in the posterior maps for the entire sequence pair:
+ // first store the posteriors calculated for these subsequences
+ for (Post_probs::iterator iter = subseq_post_probs.begin(); iter != subseq_post_probs.end(); ++iter) {
+ const unsigned subx = iter->x; // coordinates within the subseqs
+ const unsigned suby = iter->y;
+ const double& p = iter->prob;
+ const unsigned x = xsubleft + subx; // coordinates for the entire sequences
+ const unsigned y = ysubleft + suby;
+ assert (x < xlen); // (0-based coordinates)
+ assert (y < ylen);
+ post_probs.push_back (Post_prob (x, y, p));
+ }
+
+ // then fix the current anchors
+ // (unless we're at the end case, for which we've created a fake anchor beyond the sequence boundaries)
+ if (a < anchors.size()) {
+ for (unsigned x = 0; x <= xcurrright - xcurrleft; ++x) // closed interval!
+ post_probs.push_back (Post_prob (xcurrleft + x, ycurrleft + x, anchors[a].score_to_prob())); // force high probability for anchor
+ }
+
+ // log progress through anchors
+ const unsigned anchors_done = static_cast<unsigned> (std::floor ((100.0 * (a+1) / (anchors.size() + 1)) + 0.5));
+ if (CTAGGING(6,FSA))
+ CTAG(6,FSA) << "Processed anchored subsequence pair '" << xsubseq.name << "' and '" << ysubseq.name << "'; "
+ << anchors_done << "% (" << a+1 << "/" << anchors.size() + 1 << ") complete."
+ << endl;
+
+ // increment the anchor indices
+ xprevright = xcurrright;
+ yprevright = ycurrright;
+
+ }
+
+ // Enforce lexical ordering of post_probs:
+ // Unfortunately, storing anchor posteriors before subsequence posteriors isn't sufficient to preserve
+ // lexical ordering; overlapping anchors will still cause problems. We therefore force a sort
+ // before constructing the SparseMatrix. This costs O (n log n) time, but is unavoidable
+ // unless we deal more cleverly with overlapping anchors.
+ std::sort (post_probs.begin(), post_probs.end());
+
+ return post_probs;
+
+}
+
+void FSA::load_probabilities_from_file (const std::string& filename,
+ std::vector<std::vector<SparseMatrix*> >& sparse_matrices) {
+
+ CTAG(8,FSA) << "Reading posterior probabilities file '" << filename << "'." << endl;
+
+ // format is:
+ // ; match posteriors
+ // (0, 0) ~ (1, 0) => 0.999999
+ // ; gap posteriors
+ // (0, 0) ~ (1, -1) => 0.0001
+ Regexp re_probs ("^[ \t]*\\([ \t]*([0-9]+)[ \t]*,[ \t]*([0-9]+)[ \t]*\\)[ \t]*~[ \t]*\\([ \t]*([0-9]+)[ \t]*,[ \t]*([0-9]+)[ \t]*\\)[ \t]*=>[ \t]*(.*)$");
+
+ std::vector<std::vector<Post_probs> > post_probs_storage (num_seqs, std::vector<Post_probs> (num_seqs));
+
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open())
+ THROWEXPR ("ERROR: Couldn't open file '" << filename << "' for reading.")
+
+ std::string line;
+ while (!filestream.eof()) {
+
+ getline (filestream, line);
+ Util::chomp (line);
+ if (!line.length()) { continue; }
+
+ // are we at a match line?
+ if (re_probs.Match (line.c_str())) {
+
+ // check that format is correct
+ if (re_probs.SubStrings() != 5) {
+ CTAG(8,FSA) << "WARNING: Couldn't parse line: " << line << endl;
+ continue;
+ }
+
+ // pull out data
+ const size_t i = static_cast<size_t> (atoi (re_probs[1].c_str()));
+ const unsigned ii = static_cast<unsigned> (atoi (re_probs[2].c_str()));
+ const size_t j = static_cast<size_t> (atoi (re_probs[3].c_str()));
+ const unsigned jj = static_cast<unsigned> (atoi (re_probs[4].c_str()));
+ const float prob = atof (re_probs[5].c_str());
+
+ // check sane
+ if (i >= num_seqs || j >= num_seqs)
+ THROWEXPR ("ERROR: Invalid sequence indices i = " << i << ", j = " << j << ".");
+ if (ii >= seq_db.get_seq (i).length())
+ THROWEXPR ("ERROR: Sequence position out of bounds: (" << i << ", " << ii << ").");
+ if (jj >= seq_db.get_seq (j).length())
+ THROWEXPR ("ERROR: Sequence position out of bounds: (" << j << ", " << jj << ").");
+
+ // store
+ post_probs_storage[i][j].push_back (Post_prob (ii, jj, prob));
+
+ }
+
+ }
+ filestream.close();
+
+ // initialize SparseMatrix objects
+ for (size_t i = 0; i < num_seqs; ++i) {
+ for (size_t j = 0; j < num_seqs; ++j) {
+ Post_probs& post_probs = post_probs_storage[i][j];
+ // ensure we don't attempt to store empty data (potentially overwriting good data)
+ if (i == j || !post_probs.size())
+ continue;
+ // must sort before initializing SparseMatrix
+ std::sort (post_probs.begin(), post_probs.end());
+ sparse_matrices[i][j] = new SparseMatrix (i, j,
+ seq_db.get_seq (i).length(), seq_db.get_seq (j).length(),
+ post_probs);
+ // clean up as we go to save memory
+ post_probs.clear();
+ // get transpose too
+ sparse_matrices[j][i] = sparse_matrices[i][j]->ComputeTranspose();
+
+ // check that we've actually created a matrix!
+ if (!sparse_matrices[i][j]->size())
+ THROWEXPR ("ERROR: Failed to create sparse matrix of posterior probabilities.");
+
+ }
+ }
+
+}
+
+void FSA::build_multiple_alignment() {
+
+ // read in weights for sequence pairs if information present
+ if (tree_weights_file != "")
+ tree_weights.from_file (seq_db, tree_weights_file);
+
+ // set up model topology
+ bool left_match = false; // do not require homology beyond sequence boundaries
+ bool right_match = false;
+
+ // initialize parameter seed
+ Params params_seed;
+ const std::vector<double> char_freq_total (Model::count_char_freq (seq_db_internal, this->alphabet_string, is_dna));
+ params_seed.bandwidth = bandwidth;
+ init_indel_params (params_seed);
+ init_subst_params (params_seed, char_freq_total, model, time);
+
+ // initialize pseudocounts (for regularization) according to the params_seed distribution
+ Params pseudocounts;
+ init_pseudocounts (pseudocounts, params_seed, regularization_transition_scale, regularization_emission_scale);
+
+ // if requested, learn params_seed over alignment_seq_pairs
+ if (learn_emit_all) {
+ train_params (params_seed, seq_db_internal, alignment_seq_pairs,
+ left_match, right_match, ragged_ends,
+ pseudocounts, learn_emit_all);
+ }
+
+ // store sparse matrices for annealing: store only sparse matrices for memory efficiency
+ std::vector<std::vector<SparseMatrix*> > sparse_matrices (num_seqs, std::vector<SparseMatrix*> (num_seqs, reinterpret_cast<SparseMatrix*> (NULL)));
+
+ // option list to be used for a database connection
+ DB_opts db_opts;
+ db_opts.copy_opts (this);
+
+ // create database manager
+ Manager manager (seq_db_internal, db_opts);
+
+ if (parallelizing)
+ manager.mw_master_run (opts.init_argc, opts.init_argv, params_seed, pseudocounts);
+ else if (write_db)
+ manager.mw_single_worker_run (params_seed, pseudocounts);
+
+ if (noannealing)
+ return;
+
+ // if available, get pairwise posterior probabilities from the database
+ if (manager.is_sparse_matrices_available()) {
+#if defined(HAVE_CONDOR) || defined(HAVE_POSTGRES)
+ CTAG(9,FSA) << "Getting pairwise posterior probabilities from database." << endl;
+ manager.get_sparse_matrices (sparse_matrices);
+ CTAG(8,FSA) << "Got pairwise posterior probabilities." << endl;
+#endif
+ }
+
+ // if requested, load pairwise probabilities from a file
+ // rather than re-estimating them with DP
+ else if (load_probs_file.length()) {
+
+ load_probabilities_from_file (load_probs_file,
+ sparse_matrices);
+
+ }
+
+ // else perform alignment as usual
+ else {
+
+ // initialize params for each alignment_seq_pair
+ alignment_params.resize (alignment_seq_pairs.size());
+ for (size_t cnt = 0; cnt < alignment_seq_pairs.size(); ++cnt)
+ alignment_params[cnt].copy_all (params_seed);
+
+ // now do all-pairs comparison
+ CTAG(9,FSA) << "Collecting pairwise posterior probabilities." << endl;
+
+ // loop through sequence database
+ for (size_t cnt = 0; cnt < alignment_seq_pairs.size(); ++cnt) {
+
+ // get the sequence indices
+ const size_t i = alignment_seq_pairs[cnt].first;
+ const size_t j = alignment_seq_pairs[cnt].second;
+
+ // initialize all the sequence data
+ const Sequence& xseq = seq_db_internal.get_seq (i);
+ const Sequence& yseq = seq_db_internal.get_seq (j);
+
+ // if there is an empty sequence, then skip inference
+ if (!xseq.length() || !yseq.length())
+ continue;
+
+ // perform pairwise inference
+ Post_probs post_probs = perform_pairwise_inference (alignment_params[cnt], xseq, yseq,
+ left_match, right_match, ragged_ends,
+ pseudocounts);
+
+ // we need the original sequences in case we've been hardmasking
+ const Sequence& xseq_orig = seq_db.get_seq (i);
+ const Sequence& yseq_orig = seq_db.get_seq (j);
+
+ // if hardmasking, map coords back to original sequence
+ if (hardmasked) {
+ for (Post_probs::iterator p = post_probs.begin(); p != post_probs.end(); ++p) {
+ p->x = xseq_orig.map_stripped_to_orig (p->x);
+ p->y = yseq_orig.map_stripped_to_orig (p->y);
+ }
+ }
+
+ // create sparse matrix for sequence pair
+ sparse_matrices[i][j] = new SparseMatrix (i, j,
+ xseq_orig.length(), yseq_orig.length(),
+ post_probs);
+ sparse_matrices[j][i] = sparse_matrices[i][j]->ComputeTranspose(); // pre-compute the transpose for speed
+
+ // check for success (whether we hit max_ram limit)
+ // throw error if so
+ if (!sparse_matrices[i][j]->size() && xseq_orig.length() && yseq_orig.length()) {
+ CTAG(9,FSA) << "WARNING: Unable to detect any homology between sequences '" << xseq.name << "' and '" << yseq.name << "'."
+ << " This may be due to RAM constraints; check --maxram or try using anchoring." << endl;
+ if (require_homology)
+ THROWEXPR ("ERROR: Alignment failure.");
+ }
+
+ // log progress through sequence pairs
+ const unsigned percent_done = static_cast<unsigned> (std::floor ((100.0 * (cnt+1) / alignment_seq_pairs.size()) + 0.5));
+ if (CTAGGING(7,FSA))
+ CTAG(7,FSA) << "Processed sequence pair '" << xseq.name << "' and '" << yseq.name << "'; "
+ << percent_done << "% (" << cnt+1 << "/" << alignment_seq_pairs.size() << ") complete."
+ << endl;
+
+ } // end loop over sequences
+
+ // log
+ CTAG(8,FSA) << "Processed a total of " << std::floor ((100.0 * alignment_seq_pairs.size() / num_seq_pairs) + 0.5) << "% ("
+ << alignment_seq_pairs.size() << "/" << num_seq_pairs << ") of all sequence pairs."
+ << endl;
+
+ }
+
+ // write trained params and/or dotplots for all seq pairs if requested
+ if (write_params || write_dotplots) {
+ CTAG(8,FSA) << "Writing learned parameters and/or dotplots to disk." << endl;
+ std::string filename;
+
+ for (size_t cnt = 0; cnt < alignment_seq_pairs.size(); ++cnt) {
+ const Sequence& xseq = seq_db_internal.get_seq (alignment_seq_pairs[cnt].first);
+ const Sequence& yseq = seq_db_internal.get_seq (alignment_seq_pairs[cnt].second);
+
+ if (write_params) {
+ // emission in human-readable format
+ filename.clear();
+ filename = std::string ("params.emission.learned")
+ + "." + xseq.name + "-" + yseq.name;
+ alignment_params[cnt].write_emission (filename);
+
+ // emission in .dat format
+ filename.clear();
+ filename = std::string ("params.emission.learned")
+ + "." + xseq.name + "-" + yseq.name
+ + ".dat";
+ alignment_params[cnt].write_emission_dat (filename);
+
+ // transition in human-readable format
+ filename.clear();
+ filename = std::string ("params.transition.learned")
+ + "." + xseq.name + "-" + yseq.name;
+ alignment_params[cnt].write_transition (filename);
+ }
+
+ if (write_dotplots) {
+ filename.clear();
+ filename = std::string ("posterior.final.")
+ + xseq.name + '-' + yseq.name;
+ get_pairwise_dotplot (alignment_params[cnt], xseq, yseq,
+ left_match, right_match, ragged_ends).write_dotplot (filename);
+ }
+
+ }
+ }
+
+ // write pairwise distance estimates
+ if (write_divergences) {
+ CTAG(8,FSA) << "Writing distance matrix to disk." << endl;
+ const std::string filename = "divergences";
+ std::ofstream file (filename.c_str());
+ if (!file)
+ THROWEXPR ("ERROR: Couldn't create file with name '" << filename << "'.");
+ show_divergences (file);
+ file.close();
+ }
+
+ // now do sequence annealing
+ // handle case of nucprot
+ // who knows why, but I got weird memory errors when I didn't explicitly create
+ // a reference like this...
+ const Sequence_database& aa_db = nucprot
+ ? seq_db.translate()
+ : Sequence_database();
+
+ Alignment_DAG dag (nucprot ? aa_db : seq_db);
+ dag.anneal (sparse_matrices, tree_weights,
+ manager,
+ use_tgf,
+ gap_factor, enable_dynamic_weights, 0, // edge_weight_threshold = 0
+ num_refinement_steps,
+ output_for_gui, gui_prefix);
+ dag.dfs_topological_sort();
+
+ // we're done!
+ Stockholm stock = nucprot
+ ? dag.get_stockholm (sparse_matrices, tree_weights).get_codon_from_aa_alignment (seq_db)
+ : dag.get_stockholm (sparse_matrices, tree_weights);
+
+ if (write_stockholm)
+ stock.write_stockholm (cout);
+ else
+ stock.write_mfa (cout);
+
+}
+
+void FSA::build_anchored_multiple_alignment() {
+
+ // read in weights for sequence pairs if information present
+ if (tree_weights_file != "")
+ tree_weights.from_file (seq_db, tree_weights_file);
+
+ // initialize parameter seed
+ Params params_seed;
+ const std::vector<double> char_freq_total (Model::count_char_freq (seq_db_internal, this->alphabet_string, is_dna));
+ params_seed.bandwidth = bandwidth;
+ init_indel_params (params_seed);
+ init_subst_params (params_seed, char_freq_total, model, time);
+
+ // initialize pseudocounts (for regularization) according to the params_seed distribution
+ Params pseudocounts;
+ init_pseudocounts (pseudocounts, params_seed, regularization_transition_scale, regularization_emission_scale);
+
+ // store sparse matrices for annealing: store only sparse matrices for memory efficiency
+ std::vector<std::vector<SparseMatrix*> > sparse_matrices (num_seqs, std::vector<SparseMatrix*> (num_seqs, reinterpret_cast<SparseMatrix*> (NULL)));
+
+ // option list to be used for a database connection
+ DB_opts db_opts;
+ db_opts.copy_opts (this);
+
+ // create database manager
+ Manager manager (seq_db_internal, db_opts);
+
+ if (parallelizing)
+ manager.mw_master_run (opts.init_argc, opts.init_argv, params_seed, pseudocounts);
+ else if (write_db)
+ manager.mw_single_worker_run (params_seed, pseudocounts);
+
+ if (noannealing)
+ return;
+
+ // if available, get pairwise posterior probabilities from the database
+ if (manager.is_sparse_matrices_available()) {
+#if defined(HAVE_CONDOR) || defined(HAVE_POSTGRES)
+ CTAG(9,FSA) << "Getting pairwise posterior probabilities from database." << endl;
+ manager.get_sparse_matrices (sparse_matrices);
+ CTAG(8,FSA) << "Got pairwise posterior probabilities." << endl;
+#endif
+ }
+
+ // if requested, load pairwise probabilities from a file
+ // rather than re-estimating them with DP
+ else if (load_probs_file.length()) {
+
+ load_probabilities_from_file (load_probs_file,
+ sparse_matrices);
+
+ }
+
+ // else perform alignment as usual
+ else {
+
+ // no need to bother with alignment_params
+ // (different parameters are learned for each anchored subsequence pair)
+
+ // handle case of nucprot
+ const Sequence_database& aa_db = nucprot
+ ? seq_db.translate()
+ : Sequence_database();
+
+ // get resolved anchors for the sequence pairs which we're going use for alignment
+ Anchor_resolver anchor_resolver = nucprot
+ ? Anchor_resolver (aa_db, seq_db_internal, alignment_seq_pairs)
+ : Anchor_resolver (seq_db, seq_db_internal, alignment_seq_pairs);
+
+ // add Mercator constraints if present
+ if (mercator_constraint_file != "")
+ anchor_resolver.add_mercator_constraints (mercator_constraint_file);
+
+ // get resolved anchors
+ CTAG(9,FSA) << "Getting anchors for " << std::floor ((100.0 * alignment_seq_pairs.size() / num_seq_pairs) + 0.5)
+ << "% (" << alignment_seq_pairs.size() << "/" << num_seq_pairs << ") of all sequence pairs."
+ << endl;
+
+ // now actually get resolved anchors
+ std::vector<Anchors> resolved_anchors_list = anchor_resolver.get_resolved_anchors (tree_weights,
+ anchor_minlen, anchor_max_join_length, use_translated,
+ exonerate, exonerate_minscore, softmasked,
+ hardmasked,
+ num_refinement_steps,
+ output_for_gui, gui_prefix);
+
+ // now align the subsequences between the anchors:
+ // do all-pairs comparison
+
+ // log
+ CTAG(9,FSA) << "Collecting pairwise posterior probabilities for each anchored subsequence pair." << endl;
+
+ // loop through sequence database
+ for (size_t cnt = 0; cnt < alignment_seq_pairs.size(); ++cnt) {
+
+ // initialize all the sequence data
+ const size_t i = alignment_seq_pairs[cnt].first;
+ const size_t j = alignment_seq_pairs[cnt].second;
+
+ const Sequence& xseq = seq_db_internal.get_seq (i);
+ const Sequence& yseq = seq_db_internal.get_seq (j);
+
+ // if there is an empty sequence, then skip inference
+ if (!xseq.length() || !yseq.length())
+ continue;
+
+ // perform anchored pairwise inference
+ Post_probs post_probs = perform_anchored_pairwise_inference (params_seed, xseq, yseq,
+ pseudocounts,
+ resolved_anchors_list[cnt]);
+
+ // we need the original sequences in case we've been hardmasking
+ const Sequence& xseq_orig = seq_db.get_seq (i);
+ const Sequence& yseq_orig = seq_db.get_seq (j);
+
+ // if hardmasking, map coords back to original sequence
+ if (hardmasked) {
+ for (Post_probs::iterator p = post_probs.begin(); p != post_probs.end(); ++p) {
+ p->x = xseq_orig.map_stripped_to_orig (p->x);
+ p->y = yseq_orig.map_stripped_to_orig (p->y);
+ }
+ }
+
+ // create sparse matrix for sequence pair
+ sparse_matrices[i][j] = new SparseMatrix (i, j,
+ xseq_orig.length(), yseq_orig.length(), post_probs);
+ sparse_matrices[j][i] = sparse_matrices[i][j]->ComputeTranspose();
+
+ // check for success (whether we hit max_ram limit)
+ // throw error if so
+ if (!sparse_matrices[i][j]->size() && xseq_orig.length() && yseq_orig.length()) {
+ CTAG(9,FSA) << "WARNING: Unable to detect any homology between sequences '" << xseq.name << "' and '" << yseq.name << "'."
+ << " This may be due to RAM constraints; check --maxram or try using anchoring." << endl;
+ if (require_homology)
+ THROWEXPR ("ERROR: Alignment failure.");
+ }
+
+ // log progress through sequence pairs
+ const unsigned percent_done = static_cast<unsigned> (std::floor ((100.0 * (cnt+1) / alignment_seq_pairs.size()) + 0.5));
+ if (CTAGGING(7,FSA))
+ CTAG(7,FSA) << "Processed sequence pair '" << xseq.name << "' and '" << yseq.name << "'; "
+ << percent_done << "% (" << cnt+1 << "/" << alignment_seq_pairs.size() << ") complete."
+ << endl;
+
+ } // end loop over sequences
+
+ // log
+ CTAG(8,FSA) << "Processed a total of " << std::floor ((100.0 * alignment_seq_pairs.size() / num_seq_pairs) + 0.5) << "% ("
+ << alignment_seq_pairs.size() << "/" << num_seq_pairs << ") of all sequence pairs."
+ << endl;
+ }
+
+ // now do sequence annealing
+ // handle case of nucprot
+ // who knows why, but I got weird memory errors when I didn't explicitly create
+ // a reference like this...
+ const Sequence_database& aa_db = nucprot
+ ? seq_db.translate()
+ : Sequence_database();
+
+ Alignment_DAG dag (nucprot ? aa_db : seq_db);
+ dag.anneal (sparse_matrices, tree_weights,
+ manager,
+ use_tgf,
+ gap_factor, enable_dynamic_weights, 0, // edge_weight_threshold = 0
+ num_refinement_steps,
+ output_for_gui, gui_prefix);
+ dag.dfs_topological_sort();
+
+ // we're done!
+ Stockholm stock = nucprot
+ ? dag.get_stockholm (sparse_matrices, tree_weights).get_codon_from_aa_alignment (seq_db)
+ : dag.get_stockholm (sparse_matrices, tree_weights);
+
+ if (write_stockholm)
+ stock.write_stockholm (cout);
+ else
+ stock.write_mfa (cout);
+
+}
+
+int FSA::run() {
+
+ try {
+ // It's important that we input the data /before/ parsing the command-line options.
+ // This allows us to set preset values for DNA, RNA and proteins and then let
+ // them be overriden by the command-line options.
+ init_opts();
+ input_data();
+ set_up_defaults();
+ parse_opts();
+ assemble_sequence_data();
+ choose_seq_pairs();
+ if (anchored)
+ build_anchored_multiple_alignment();
+ else
+ build_multiple_alignment();
+ }
+
+ catch (const Dart_exception& e) {
+ CLOGERR << e.what();
+ THROWEXPR ("ERROR: Exception thrown.");
+ }
+
+ return 0;
+}
diff --git a/src/fsa/fsa.h b/src/fsa/fsa.h
new file mode 100644
index 0000000..7d06bae
--- /dev/null
+++ b/src/fsa/fsa.h
@@ -0,0 +1,406 @@
+
+/**
+ * \file fsa.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ * Jaeyoung Do wrote the parallelization and database code.
+ *
+ * All nucleotide sequences are treated internally as DNA, meaning that 'U' gets converted to 'T'
+ * (this is done when degenerate characters are randomized in build_multiple_alignment).
+ * Messing this up will make bad things happen!
+ * NB: The case of the input sequences is preserved (in order to not destroy potential softmasking);
+ * however, the inference engines treat upper and lower-case characters identically.
+ *
+ * Dirichlet regularization scales:
+ * The emission regularization scales correspond precisely to the total number of
+ * pseudocount emissions because the seed distribution for pseudocount calculation
+ * is normalized to 1.
+ * The default values are (approximately) equal to the number of free parameters in a
+ * symmetric pair emission matrix
+ * = 1/2 * n * (n - 1) + n
+ * => 1/2 * 4 * 3 + 4 = 10 for nucleotides
+ * => 1/2 * 20 * 19 + 20 = 210 for amino acids
+ * The transition regularization scale is chosen completely arbitrarily.
+ */
+
+#ifndef FSA_FSA_INCLUDED
+#define FSA_FSA_INCLUDED
+
+
+#define DNA_ALPHABET_STRING "ACGT"
+#define PROTEIN_ALPHABET_STRING "ACDEFGHIKLMNPQRSTVWY"
+
+#define MODEL_DEFAULT 1
+#define TIME_DEFAULT 0.4
+#define ALPHA_R_DEFAULT 1.3
+#define ALPHA_Y_DEFAULT 1.3
+#define BETA_DEFAULT 1.
+
+#define EM_MIN_INC_DEFAULT 0.1
+#define EM_MAX_ITER_DEFAULT 3
+#define REGULARIZATION_NUC_TRANSITION_SCALE_DEFAULT 3.
+#define REGULARIZATION_NUC_EMISSION_SCALE_DEFAULT 10.
+#define REGULARIZATION_AA_TRANSITION_SCALE_DEFAULT 3.
+#define REGULARIZATION_AA_EMISSION_SCALE_DEFAULT 210.
+
+#define MIN_NUC_EMISSION_TRAINING_DATA 60
+#define MIN_NUC_TRANSITION_TRAINING_DATA 60
+#define MIN_AA_EMISSION_TRAINING_DATA 1596
+#define MIN_AA_TRANSITION_TRAINING_DATA 60
+
+#define LONG_DNA_DEFAULT 500 ///< length to trigger anchoring
+
+#define DEFAULT_POSTERIOR_PROB_CUTOFF 0.01 ///< minimum posterior probability value that is maintained in the sparse matrix representation
+#define DEFAULT_DEGREE 5 ///< default number of pairwise comparisons to use per sequence
+
+#define MAX_NUM_PARALLELIZED_JOBS 100
+#define MIN_NUM_PARALLELIZED_JOBS 1
+
+#define MIN_HARDMASK_LENGTH 10
+
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+
+#include "util/misc.h"
+#include "util/opts_list.h"
+#include "util/memcheck.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+#include "fsa/anchors.h"
+#include "fsa/model.h"
+
+#include "annealing/alignment_DAG.h"
+#include "annealing/dotplot.h"
+#include "annealing/SparseMatrix.h"
+#include "annealing/tree_weights.h"
+
+#include "manager/manager.h"
+
+
+namespace fsa {
+
+ /**
+ * \brief Represent a running FSA program.
+ */
+ struct FSA {
+
+ // options
+ Opts_list opts; ///< options list
+
+ // output
+ bool write_stockholm; ///< output Stockholm instead of MFA
+ bool write_params; ///< write bubbleplot-format files showing emission parameters during training
+ bool write_divergences; ///< write divergences to file
+ bool write_dotplots; ///< write dotplot-format files showing post. prob. matrices
+ bool output_for_gui; ///< log intermediate alignments formatted for GUI displayer
+ std::string gui_prefix; ///< prefix for gui output file
+
+ // model options
+ bool nucprot; ///< align nucleotide sequence in protein space
+ bool is_indel2; ///< 1 or 2 sets of indel states
+ double gap_open1; ///< gap-open probability of set 1 of indel states
+ double gap_extend1; ///< gap-extend probability of set 1 of indel states
+ double gap_open2; ///< gap-open probability of set 2 of indel states
+ double gap_extend2; ///< gap-extend probability of set 2 of indel states
+ bool ragged_ends; ///< allow for easy insertions and deletions at ends of sequences
+ int model; ///< substitution model (also used as seed for learning)
+ double time; ///< Jukes-Cantor/Tamura-Nei evolutionary time parameter
+ double alpha_R; ///< Tamura-Nei alpha_R parameter
+ double alpha_Y; ///< Tamura-Nei alpha_Y parameter
+ double beta; ///< Tamura-Nei beta parameter
+ sstring load_probs_file; ///< load pairwise posterior probabilities from file
+
+ // parameter estimation options
+ bool learn_gap; ///< learn indel parameters
+ bool learn_emit_all; ///< learn emit parameters over all sequences
+ bool learn_emit_bypair; ///< learn emit parameters for each pair
+ bool nolearn; ///< no learning (redundant but convenient)
+ bool regularize; ///< regularize learned parameters with Dirichlet distribution specified by model
+ double regularization_emission_scale; ///< scaling factor (per sequence pair) for the Dirichlet pseudocounts for emissions (nuc or aa)
+ double regularization_transition_scale; ///< scaling factor (per sequence pair) for the Dirichlet pseudocounts for transitions (nuc or aa)
+ double em_min_inc; ///< minimal fractional increase in log-likelihood per round EM
+ int em_max_iter; ///< max number of rounds of EM
+ int min_emit_training_data; ///< minimum amount of sequence data for training emission probs
+ int min_gap_training_data; ///< minimum amount of sequence data for training indel probs
+
+ // sequence annealing options
+ int num_refinement_steps; ///< number of iterative refinement steps
+ bool maxsn; ///< maximum sensitivity
+ bool use_tgf; ///< use tgf or maxstep heuristic for weighting (no command-line control)
+ double gap_factor; ///< the gap factor
+ bool enable_dynamic_weights; ///< dynamic edge-weight calculation
+ double minprob; ///< minimum posterior probability to store in sparse matrix
+ sstring tree_weights_file; ///< weights for sequence pairs
+ bool require_homology; ///< require some (potential) homology between all sequences considered
+
+ // alignment speedup options
+ int bandwidth; ///< banding width
+ bool fast_defaults; ///< only look at 10 * Erdos-Renyi threshold percent of sequence pairs for alignment
+ int num_minimum_spanning_trees; ///< number of minimum spanning trees to use for alignment
+ int num_maximum_spanning_trees; ///< number of maximum spanning trees to use for alignment
+ int num_minimum_spanning_palm_trees; ///< number of minimum spanning palm trees to use for alignment
+ int degree; ///< number of closest sequences to use for alignment
+ int kmer_length; ///< length of k-mers to use when determining sequence similarity
+ bool refalign; ///< minimal alignment (star)
+ double fraction_alignment_pairs; ///< fraction of all (n choose 2) pairs to consider during alignment inference
+ int num_alignment_pairs; ///< total number of all (n choose 2) pairs to consider during alignment inference
+ int max_ram; ///< maximum RAM (in megabytes) to use for DP
+
+ // anchoring options
+ bool anchored; ///< use anchor annealing
+ bool use_translated; ///< perform anchoring in protein space
+ int anchor_minlen; ///< minimum anchor length
+ int anchor_max_join_length; ///< maximum separation of parallel, adjacent anchor to concatenate
+ bool hardmasked; ///< sequence is hardmasked
+ sstring mercator_constraint_file; ///< input Mercator constraints
+ bool exonerate; ///< use exonerate
+ int exonerate_minscore; ///< minimum score for exonerate anchors
+ bool softmasked; ///< sequence is softmasked
+
+ // parallelization options
+ bool parallelizing; ///< collect post. prob. matrices and cand. edges simutaneously
+ int num_parallelized_jobs; ///< number of jobs to run simultaneously
+ bool noannealing; ///< false when the annealing step is not needed
+
+ // database options
+ sstring db_hostname; ///< database server host name
+ sstring db_hostaddr; ///< database server host IP address
+ sstring db_name; ///< database name
+ int db_port; ///< database server port
+ sstring db_user; ///< database user name
+ sstring db_password; ///< database password
+ bool read_posteriors_from_db; ///< do not compute posteriors; instead read them from database
+ int db_max_ram; ///< maximum RAM (in megabytes) to use when the database mode
+ bool write_db; ///< write post. prob. matrices and candidate edges to database
+
+ // sequence composition
+ bool is_dna; ///< is it nucleotide sequence?
+ bool is_protein; ///< is it amino acid sequence?
+
+ // sequence alphabet
+ Alphabet alphabet; ///< store alphabet for randomizing degenerate characters, etc.
+ std::string alphabet_string; ///< store alphabet in alphabetical order
+
+ // sequence data
+ Sequence_database seq_db; ///< hold all input sequence data
+ Sequence_database seq_db_internal; ///< hold all processed (nondegenerate, etc.) input sequence data (FSA's internal format)
+ Sequence_pairs alignment_seq_pairs; ///< hold sequence pairs to be used for alignment
+ Tree_weights tree_weights; ///< weights for sequence pairs during anchor and sequence annealing
+ size_t num_seqs; ///< total number of input sequences
+ size_t num_seq_pairs; ///< total number of possible input sequence pairs
+
+ // parallelization
+ int w_num_seq_pairs; ///< the number of seq pairs to be considered
+ int w_prev_seq_pairs_sum; ///< the number of seq pairs that have been considered by other workers
+ bool w_worker; ///< is this run by a worker?
+ std::pair<int, int> w_start_seq_pair; ///< the first pair of sequences to be considered
+
+ // parameters
+ std::vector<Params> alignment_params; ///< hold (trained) parameters for each alignment_seq_pair
+
+ /**
+ * \brief Constructor.
+ */
+ FSA (int argc, char** argv);
+
+ /**
+ * \brief Initialize command-line options.
+ */
+ void init_opts();
+
+ /**
+ * \brief Input sequence data.
+ *
+ * Detects whether nucleotide (DNA or RNA) or amino acid sequence.
+ * Also adjusts the default regularization scales as appropriate.
+ */
+ void input_data();
+
+ /**
+ * \brief Construct preset options for DNA, RNA and proteins.
+ *
+ * Sets up default HMM structure (1 or 2 sets of indel states),
+ * learning strategy and memory and speed usage before command-line
+ * options (which may override these values) are parsed.
+ */
+ void set_up_defaults();
+
+ /**
+ * \brief Parse options.
+ *
+ * Provides opportunity for command-line options to override defaults.
+ */
+ void parse_opts();
+
+ /**
+ * \brief Strip hardmasked sequence, randomize degenerate characters, etc.
+ */
+ void assemble_sequence_data();
+
+ /**
+ * \brief Choose sequence pairs to consider for inference and alignment.
+ * \see Sequence_pair_selector
+ */
+ void choose_seq_pairs();
+
+ /**
+ * \brief Build multiple alignment.
+ */
+ void build_multiple_alignment();
+
+ /**
+ * \brief Build anchored multiple alignment.
+ */
+ void build_anchored_multiple_alignment();
+
+ /**
+ * \brief Run FSA!
+ */
+ int run();
+
+ /**
+ * \brief Init indel parameters.
+ *
+ * This is a bit weird: It initializes the values to the defaults,
+ * then checks to see if command-line values were passed. If so,
+ * then it uses those instead.
+ */
+ void init_indel_params (Params& params);
+
+ /**
+ * \brief Init substitution parameters (both nuc and amino acid).
+ *
+ * \param params parameters to initialize
+ * \param char_freq empirical character frequencies
+ * \param model substitution model to use
+ * \param time evolutionary time parameter of substitution model
+ */
+ void init_subst_params (Params& params, const std::vector<double>& char_freq, const unsigned model = MODEL_DEFAULT, const double time = TIME_DEFAULT);
+
+ /**
+ * \brief Init pseudocounts, scaled versions of the passed seed distribution.
+ *
+ * Pseudocounts for a single pairwise alignment.
+ * \param pseudo pseodocounts object
+ * \param seed seed distribution (scaled to get pseudocounts)
+ * \param transition_scale scaling factor for transition pseudocounts
+ * \param emission_scale scaling factor for emission pseudocounts
+ */
+ void init_pseudocounts (Params& pseudo, const Params& seed, const double transition_scale, const double emit_scale);
+
+ /**
+ * \brief Interface to Model::train_params_engine.
+ *
+ * Decides whether to learn gap parameters based on FSA::learn_gap.
+ * Doesn't learn if the estimated memory usage is greater than max_ram.
+ * \param params Params object to train
+ * \param seq_db_train sequence data
+ * \param subset sequence pairs to consider
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ * \param ragged_ends
+ * \param pseudocounts pseudocounts
+ * \param learn_emit learn emission parameters
+ * \return whether training completed
+ * \see Model::train_params_engine
+ */
+ bool train_params (Params& params, const Sequence_database& seq_db_train, const Sequence_pairs& subset,
+ const bool left_match, const bool right_match, const bool ragged_ends,
+ const Params& pseudocounts, bool learn_emit);
+
+ /**
+ * \brief Interface to Model::get_alignment_post_probs_engine.
+ *
+ * \param params parameters
+ * \param xseq first sequence
+ * \param yseq second sequence
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ * \param ragged_ends
+ * \return computed Post_probs object
+ * \see Model::get_pairwise_post_probs_engine
+ */
+ Post_probs get_pairwise_post_probs (Params& params, const Sequence& xseq, const Sequence& yseq,
+ const bool left_match, const bool right_match, const bool ragged_ends);
+
+ /**
+ * \brief Interface to Model::get_pairwise_dotplot_engine.
+ *
+ * \param params parameters
+ * \param xseq first sequence
+ * \param yseq second sequence
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ * \param ragged_ends
+ * \return computed Dotplot object
+ * \see Model::get_pairwise_dotplot_engine
+ */
+ Dotplot get_pairwise_dotplot (Params& params, const Sequence& xseq, const Sequence& yseq,
+ const bool left_match, const bool right_match, const bool ragged_ends);
+
+ /**
+ * \brief Perform pairwise inference.
+ *
+ * Train parameters and compute posterior alignment probabilities.
+ * \see train_params
+ * \see get_pairwise_post_probs
+ */
+ Post_probs perform_pairwise_inference (Params& params, const Sequence& xseq, const Sequence& yseq,
+ const bool left_match, const bool right_match, const bool ragged_ends,
+ const Params &pseudocounts);
+
+ /**
+ * \brief Perform anchored pairwise inference.
+ *
+ * Train parameters and compute posterior alignment probabilities for
+ * all anchored subsequences.
+ * \see train_params
+ * \see get_pairwise_post_probs
+ */
+ Post_probs perform_anchored_pairwise_inference (const Params& params_seed, const Sequence& xseq, const Sequence& yseq,
+ const Params& pseudocounts,
+ const Anchors& anchors);
+
+ /**
+ * \brief Load pairwise probabilities of alignment from a file.
+ *
+ * File must be formatted as the .probs files created by FSA.
+ * \param sparse_matrices populate this object with SparseMatrix* read from file
+ */
+ void load_probabilities_from_file (const std::string& filename,
+ std::vector<std::vector<SparseMatrix*> >& sparse_matrices);
+
+ /**
+ * \brief Show pairwise distance estimates.
+ *
+ * Reports a pairwise divergence of -1 if the calculation wasn't done
+ * or the substitution matrix wasn't positive definite.
+ */
+ void show_divergences (std::ostream& o) const;
+
+ /**
+ * \brief Estimates the amount of RAM (in Mb) needed for DP.
+ *
+ * Size of state space is hard-coded in.
+ * \param xlen length of first sequence X
+ * \param ylen length of second second Y
+ * \return Estimated lower-bound on size of DP matrix in megabytes.
+ */
+ size_t estimate_ram_needed (size_t xlen, size_t ylen) const;
+
+ void init_for_mw_worker (const std::pair<int, int> start_seq_pair, const int prev_seq_pairs_sum, const int num_seq_pairs);
+
+ /**
+ * \brief Do we store a sequence pair for alignment?
+ *
+ * Handles case of parallelization.
+ */
+ bool is_valid_worker_seq_pair (const int cnt, const int i, const int j) const;
+
+ };
+
+}
+
+#endif /* FSA_FSA_INCLUDED */
diff --git a/src/fsa/model.cc b/src/fsa/model.cc
new file mode 100644
index 0000000..7fadbff
--- /dev/null
+++ b/src/fsa/model.cc
@@ -0,0 +1,392 @@
+
+/**
+ * \file model.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include "fsa/model.h"
+
+using namespace fsa;
+
+Params::Params() {
+
+ // initialize state names
+ states.resize (NUM_HMM_STATES);
+ states[0] = "Start"; states[1] = "Match"; states[2] = "Insert1"; states[3] = "Delete1"; states[4] = "Insert2"; states[5] = "Delete2"; states[6] = "End";
+
+ // initialize transition matrix
+ transition_matrix.assign (NUM_HMM_STATES, vector<double> (NUM_HMM_STATES, 0.));
+
+ // initialize stationary distribution
+ stat_dist.assign (NUM_HMM_STATES, 0.);
+
+}
+
+void Params::init_transition_matrix (bool left_match /* = false */, bool right_match /* = false */, bool ragged_ends /* = false */) {
+
+ // these must manually be set to 0 because they are re-estimated
+ // by train_params even if the HMM only has 1 set of indel states
+ // (sanity checks against divide-by-zero errors give it a non-zero value)
+ if (!is_indel2)
+ gap_open2 = gap_extend2 = 0.;
+
+ // calculate stationary distribution of chain
+ stat_dist[1] = (1 - gap_extend1) * (1 -gap_extend2) / ((1 - gap_extend1) * (1 - gap_extend2) + (gap_open1 / 2) * (1 - gap_extend2) + (gap_open2 / 2) * (1 - gap_extend1));
+ stat_dist[2] = stat_dist[3] = ((gap_open1 / 2) / (2 * (1 - gap_extend1))) * stat_dist[1];
+ stat_dist[4] = stat_dist[5] = ((gap_open2 / 2) / (2 * (1 - gap_extend2))) * stat_dist[1];
+
+ // Start
+ transition_matrix[0][1] = left_match ? 1.0 : 1.0 - gap_open1 - gap_open2; // Start -> Match
+ transition_matrix[0][2] = transition_matrix[0][3] = left_match ? 0. : gap_open1 / 2; // -> Insert1 | Delete1
+ transition_matrix[0][4] = transition_matrix[0][5] = left_match ? 0. : gap_open2 / 2; // -> Insert2 | Delete2
+
+ // Match
+ transition_matrix[1][1] = 1.0 - gap_open1 - gap_open2 - to_end; // Match -> Match
+ transition_matrix[1][2] = transition_matrix[1][3] = gap_open1 / 2; // -> Insert1 | Delete1
+ transition_matrix[1][4] = transition_matrix[1][5] = gap_open2 / 2; // -> Insert2 | Delete2
+ transition_matrix[1][6] = to_end; // -> End
+
+ // Insert1 and Delete1
+ transition_matrix[2][2] = transition_matrix[3][3] = gap_extend1; // Insert1 -> Insert1
+ transition_matrix[2][1] = transition_matrix[3][1] = right_match ? 1.0 - gap_extend1 : 1.0 - gap_extend1 - to_end; // -> Match
+ transition_matrix[2][6] = transition_matrix[3][6] = right_match ? 0. : to_end; // -> End
+
+ // Insert2 and Delete2
+ transition_matrix[4][4] = transition_matrix[5][5] = gap_extend2; // Insert2 -> Insert2
+ transition_matrix[4][1] = transition_matrix[5][1] = right_match ? 1.0 - gap_extend2 : 1.0 - gap_extend2 - to_end; // -> Match
+ transition_matrix[4][6] = transition_matrix[5][6] = right_match ? 0. : to_end; // -> End
+
+ assert_transition_matrix_valid();
+
+}
+
+void Params::normalize_transition_matrix() {
+
+ for (size_t i = 0; i < transition_matrix.size(); ++i) {
+ if (i == 6) // don't try to normalize transitions from End
+ continue;
+ double total = 0;
+ for (size_t j = 0; j < transition_matrix[i].size(); ++j) {
+ assert (transition_matrix[i][j] >= 0.);
+ total += transition_matrix[i][j];
+ }
+ for (size_t j = 0; j < transition_matrix[i].size(); ++j)
+ transition_matrix[i][j] /= total;
+ }
+
+}
+
+void Params::assert_transition_matrix_valid() {
+
+#ifndef NDEBUG
+ for (size_t i = 0; i < transition_matrix.size(); ++i)
+ for (size_t j = 0; j < transition_matrix.size(); ++j)
+ if (transition_matrix[i][j] < 0 || transition_matrix[i][j] > 1) {
+ show_transition_matrix (CL);
+ THROWEXPR ("ERROR: Invalid probabilities in transition matrix.");
+ }
+#endif
+
+}
+
+void Params::copy_all (const Params& from) {
+ copy_indel (from);
+ copy_subst (from);
+ bandwidth = from.bandwidth;
+}
+
+void Params::copy_indel (const Params& from) {
+ is_indel2 = from.is_indel2;
+ gap_open1 = from.gap_open1;
+ gap_open2 = from.gap_open2;
+ gap_extend1 = from.gap_extend1;
+ gap_extend2 = from.gap_extend2;
+ to_end = from.to_end;
+ transition_matrix.assign (from.transition_matrix.begin(), from.transition_matrix.end());
+}
+
+void Params::copy_subst (const Params& from) {
+ time = from.time;
+ single_dist.assign (from.single_dist.begin(), from.single_dist.end());
+ pair_dist.assign (from.pair_dist.begin(), from.pair_dist.end());
+ alphabet_string = from.alphabet_string;
+}
+
+void Params::show_transition_matrix (std::ostream& o) const {
+
+ // show raw params
+ o << "gap_open1 = " << gap_open1 << endl;
+ o << "gap_extend1 = " << gap_extend1 << endl;
+ o << "gap_open2 = " << gap_open2 << endl;
+ o << "gap_extend2 = " << gap_extend2 << endl;
+ o << "to_end = " << to_end << endl;
+ o << endl;
+
+ // now show transition matrix
+ const size_t width = 15;
+ // state label row
+ o.width (width); o << "";
+ for (size_t i = 0; i < states.size(); ++i) {
+ if (!is_indel2 && ((i == 4) || (i == 5)))
+ continue;
+ o.width (width);
+ o << states[i];
+ }
+ o << endl;
+ // transition matrix
+ for (size_t i = 0; i < states.size(); ++i) {
+ if (!is_indel2 && ((i == 4) || (i == 5)))
+ continue;
+ o.width (width);
+ o << states[i];
+ for (size_t j = 0; j < states.size(); ++j) {
+ if (!is_indel2 && ((j == 4) || (j == 5)))
+ continue;
+ o.width (width);
+ o << std::setprecision (PRECISION_DEFAULT) << transition_matrix[i][j];
+ }
+ o << endl;
+ }
+
+}
+
+void Params::show_emission (std::ostream& o) const {
+
+ const size_t width = 10;
+
+ // single distribution
+ // character label row
+ o.width (width); o << "";
+ for (size_t i = 0; i < single_dist.size(); ++i) {
+ o.width (width);
+ o << alphabet_string[i];
+ }
+ o << endl;
+ // actual entries
+ o.width (width); o << "";
+ for (size_t i = 0; i < single_dist.size(); ++i) {
+ o.width (width);
+ const double p = (single_dist[i] > DOUBLE_VERY_TINY) ? single_dist[i] : DOUBLE_VERY_TINY;
+ o << std::setprecision (PRECISION_DEFAULT) << p;
+ }
+ o << endl; o << endl;
+
+ // pair distribution
+ // character label row
+ o.width (width); o << "";
+ for (size_t i = 0; i < single_dist.size(); ++i) {
+ o.width (width);
+ o << alphabet_string[i];
+ }
+ o << endl;
+ // actual entries
+ for (size_t i = 0; i < pair_dist.size(); ++i) {
+ o.width (width);
+ o << alphabet_string[i];
+ for (size_t j = 0; j < pair_dist.size(); ++j) {
+ o.width (width);
+ const double p = (pair_dist[i][j] > DOUBLE_VERY_TINY) ? pair_dist[i][j] : DOUBLE_VERY_TINY;
+ o << std::setprecision (PRECISION_DEFAULT) << p;
+ }
+ o << endl;
+ }
+
+}
+
+void Params::show (std::ostream& o) const {
+ show_transition_matrix (o);
+ show_emission (o);
+}
+
+void Params::write_transition (const std::string& filename) const {
+ std::ofstream file (filename.c_str());
+ if (!file)
+ THROWEXPR ("ERROR: Couldn't create file with name '" << filename << "'.");
+ show_transition_matrix (file);
+ file.close();
+}
+
+void Params::write_emission (const std::string& filename) const {
+ std::ofstream file (filename.c_str());
+ if (!file)
+ THROWEXPR ("ERROR: Couldn't create file with name '" << filename << "'.");
+ show_emission (file);
+ file.close();
+}
+
+void Params::write_emission_dat (const std::string& filename) const {
+ std::ofstream file (filename.c_str());
+ if (!file)
+ THROWEXPR ("ERROR: Couldn't create file with name '" << filename << "'.");
+ // print single_dist
+ for (size_t i = 0; i < single_dist.size(); ++i)
+ file << i+1 << ' ' << single_dist[i] << endl; // viewParams.pl wants 1-based indexing
+ // print pair_dist
+ for (size_t i = 0; i < single_dist.size(); ++i)
+ for (size_t j = 0; j < single_dist.size(); ++j)
+ file << i+1 << ' ' << j+1 << ' ' << pair_dist[i][j] << endl;
+
+ file.close();
+}
+
+bool Params::is_biological() const {
+ for (size_t i = 0; i < pair_dist.size(); ++i) {
+ const double match_odds = pair_dist[i][i] / (single_dist[i] * single_dist[i]);
+ for (size_t j = i + 1; j < pair_dist.size(); ++j) {
+ const double mismatch_odds = max (pair_dist[i][j] / (single_dist[i] * single_dist[j]), pair_dist[j][i] / (single_dist[i] * single_dist[j]));
+ if (match_odds < mismatch_odds)
+ return false;
+ }
+ }
+ return true;
+}
+
+double Params::branch_length (const unsigned which) const {
+ vector<double> freq (pair_dist.size(), 0.);
+ vector<vector<double> > submat (pair_dist.begin(), pair_dist.end());
+
+ assert ((which == 0) || (which == 1));
+ if (which == 0) {
+ // assemble frequencies implied by pair_dist P(x,y):
+ // sum over second index to get frequency of first index P(x)
+ for (size_t i = 0; i < pair_dist.size(); ++i)
+ for (size_t j = 0; j < pair_dist.size(); ++j)
+ freq[i] += pair_dist[i][j];
+ // convert to conditional substitution matrix:
+ // divide each entry by frequency of first index => P(x,y) / P(x) = P(y|x)
+ // giving a distribution over the /second/ index
+ // (yes, this is counter-intuitive, but it makes sense in terms of the Ps)
+ for (size_t i = 0; i < pair_dist.size(); ++i)
+ for (size_t j = 0; j < pair_dist.size(); ++j)
+ submat[i][j] /= freq[i];
+ } else {
+ for (size_t i = 0; i < pair_dist.size(); ++i)
+ for (size_t j = 0; j < pair_dist.size(); ++j)
+ freq[i] += pair_dist[j][i];
+ for (size_t i = 0; i < pair_dist.size(); ++i)
+ for (size_t j = 0; j < pair_dist.size(); ++j)
+ submat[i][j] /= freq[j];
+ }
+
+ // check that the probabilities sum appropriately, ie
+ // that we actually do have a stochastic matrix
+ if (which == 0) {
+ for (size_t i = 0; i < submat.size(); ++i) {
+ double sum = 0.;
+ for (size_t j = 0; j < submat.size(); ++j)
+ sum += submat[i][j];
+ assert (std::abs (1.0 - sum) < DOUBLE_VERY_TINY);
+ }
+ } else {
+ for (size_t i = 0; i < pair_dist.size(); ++i) {
+ double sum = 0;
+ for (size_t j = 0; j < pair_dist.size(); ++j)
+ sum += submat[j][i];
+ assert (std::abs (1.0 - sum) < DOUBLE_VERY_TINY);
+ }
+ }
+
+ return logdet (submat);
+}
+
+double Params::logdet (const vector<vector<double> >& matrix) {
+ const double det = determinant (matrix);
+ return (det > 0.) ? (-std::log (det)) : -1;
+}
+
+double Params::determinant (const vector<vector<double> >& matrix) {
+ double det = 0;
+ const size_t dim = matrix.size();
+ assert (dim >= 2);
+
+ if (dim == 2)
+ det = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
+ else {
+ for (size_t j1 = 0; j1 < dim; ++j1) {
+ vector<vector<double> > minor_mat (dim-1, vector<double> (dim-1));
+ for (size_t i = 1; i < dim; ++i) {
+ size_t j2 = 0;
+ for (size_t j = 0; j < dim; ++j) {
+ if (j == j1)
+ continue;
+ minor_mat[i-1][j2] = matrix[i][j];
+ ++j2;
+ }
+ }
+ det += ((j1 % 2 == 0) ? 1 : -1) * matrix[0][j1] * determinant (minor_mat);
+ }
+ }
+
+ return det;
+}
+
+void Params::assert_normalized() const {
+ double single_total = 0;
+ double pair_total = 0;
+ for (size_t i = 0; i < pair_dist.size(); ++i) {
+ assert (!(single_dist[i] < 0));
+ single_total += single_dist[i];
+ for (size_t j = 0; j < pair_dist.size(); ++j) {
+ assert (!(pair_dist[i][j] < 0));
+ pair_total += pair_dist[i][j];
+ }
+ }
+ assert (std::abs (1. - single_total ) < DOUBLE_TINY);
+ assert (std::abs (1. - pair_total ) < DOUBLE_TINY);
+}
+
+void Params::normalize() {
+ double single_total = 0;
+ double pair_total = 0;
+ for (size_t i = 0; i < pair_dist.size(); ++i) {
+ assert (!(single_dist[i] < 0));
+ single_total += single_dist[i];
+ for (size_t j = 0; j < pair_dist.size(); ++j) {
+ assert (!(pair_dist[i][j] < 0));
+ pair_total += pair_dist[i][j];
+ }
+ }
+ for (size_t i = 0; i < pair_dist.size(); ++i) {
+ single_dist[i] /= single_total;
+ for (size_t j = 0; j < pair_dist.size(); ++j) {
+ pair_dist[i][j] /= pair_total;
+ }
+ }
+ assert_normalized();
+}
+
+vector<double> Model::count_char_freq (const Sequence_database& seq_db, const std::string& alphabet_string, bool is_dna) {
+
+ if (CTAGGING(5,FSA))
+ CL << "Counting empirical character frequencies." << endl;
+
+ map<char, size_t> char_cnt;
+ for (size_t c = 0; c < alphabet_string.length(); ++c)
+ char_cnt[alphabet_string[c]] = 0;
+
+ double total = DOUBLE_TINY * alphabet_string.length(); // account for tiny values (ensure proper normalization)
+ for (size_t i = 0; i < seq_db.size(); ++i) {
+ const std::string& seq = seq_db.get_seq (i).seq;
+ for (size_t c = 0; c < seq.length(); ++c) {
+ char ch = toupper (seq[c]); // ensure upper-case (alphabet_string is upper-case)
+ if (is_dna && (ch == 'U')) // handle case of 'U'
+ ch = 'T';
+ ++char_cnt[ch];
+ }
+ total += seq.length();
+ }
+ vector<double> char_freq (alphabet_string.length(), 0.);
+ for (size_t c = 0; c < alphabet_string.length(); ++c)
+ char_freq[c] = (DOUBLE_TINY + char_cnt[alphabet_string[c]]) / total;
+
+ // log if requested
+ if (CTAGGING(-1,FSAEM)) {
+ CL << "Character frequencies:" << endl;
+ // character label row
+ for (size_t c = 0; c < alphabet_string.length(); ++c)
+ CL << "char_freq[" << alphabet_string[c] << "] = " << char_freq[c] << endl;
+ }
+
+ return char_freq;
+}
diff --git a/src/fsa/model.h b/src/fsa/model.h
new file mode 100644
index 0000000..3ba615f
--- /dev/null
+++ b/src/fsa/model.h
@@ -0,0 +1,915 @@
+
+/**
+ * \file model.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef FSA_MODEL_INCLUDED
+#define FSA_MODEL_INCLUDED
+
+#define NUM_HMM_STATES 7
+
+#include <iostream>
+#include <fstream>
+#include <cmath>
+#include <algorithm>
+
+#include "util/misc.h"
+#include "util/opts_list.h"
+#include "util/memcheck.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+#include "fsa/mybanding.h"
+#include "fsa/nucleotidedp.h"
+#include "fsa/aminoaciddp.h"
+#include "fsa/nucleotide_indel2dp.h"
+#include "fsa/aminoacid_indel2dp.h"
+#include "fsa/sequence_pair_selector.h"
+
+#include "annealing/dotplot.h"
+#include "annealing/SparseMatrix.h"
+#include "annealing/alignment_DAG.h"
+
+namespace fsa {
+
+ /**
+ * \param A struct to hold the alignment parameters and the DP bandwidth.
+ *
+ * Distributions aren't required to be normalized, so they can be used to hold pseudocounts as well.
+ */
+ struct Params {
+
+ public:
+ size_t bandwidth; ///< banding width (of DP matrix)
+
+ double gap_open1; ///< gap-open probability (set 1 of indel states)
+ double gap_extend1; ///< gap-extend probability (set 1 of indel states)
+
+ double gap_open2; ///< gap-open probability (set 2 of indel states)
+ double gap_extend2; ///< gap-extend probability (set 2 of indel states)
+
+ double to_end; ///< probability to transition to End state of HMM (basically irrelevant)
+
+ double time; ///< evolutionary time parameter (for Jukes-Cantor & Tamura-Nei)
+ std::vector<double> single_dist; ///< distribution over single nucleotides (for Insert and Delete states)
+ std::vector<std::vector<double> > pair_dist; ///< distribution over pairs of aligned nucleotides (for Match state)
+
+ /**
+ * \brief Alphabet of the HMM.
+ *
+ * We must store the alphabet like this for sorting later on.
+ * (HMMoC-generated DP code demands alphabetical sorting.)
+ */
+ std::string alphabet_string;
+
+ bool is_indel2; ///< one or two sets of indel states?
+
+ std::vector<std::string> states; ///< states of Pair HMM
+
+ /**
+ * \brief Transition probabilities of Pair HMM.
+ *
+ * 0 1 2 3 4 5 6
+ * Start Match Insert1 Delete1 Insert2 Delete2 End
+ */
+ std::vector<std::vector<double> > transition_matrix;
+
+ /**
+ * \brief Stationary distribution over states of the Pair HMM.
+ */
+ std::vector<double> stat_dist;
+
+ /**
+ * \brief Constructor.
+ */
+ Params();
+
+ /**
+ * \brief Initialize transition probabilities of Pair HMM.
+ *
+ * Initialize the transition matrix with the desired HMM structure.
+ * If left_match is set, then a transition Start -> Match is forced.
+ * This is appropriate if you know there is homology to the "left."
+ * If right_match is set, then only the {Insert, Delete} -> End transitions
+ * are disallowed. This is appropriate if you know
+ * there is homology to the "right."
+ * Note that this transition matrix is NOT symmetric, but rather
+ * favors aligments which "begin" with homologous regions and end
+ * with possibly non-homologous regions. This is intentional and reflects
+ * the implicit assumptions most people make when constructing alignments.
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ */
+ void init_transition_matrix (bool left_match = false, bool right_match = false, bool ragged_ends = false);
+
+ /**
+ * \brief Normalize transition matrix to be a (left) stochastic matrix.
+ */
+ void normalize_transition_matrix();
+
+ /**
+ * \brief Assert that entries in the transition matrix are valid probabilities.
+ */
+ void assert_transition_matrix_valid();
+
+ /**
+ * \brief Copy all parameters.
+ *
+ * \param from Params template
+ */
+ void copy_all (const Params& from);
+
+ /**
+ * \brief Copy indel parameters (for transition probabilities).
+ *
+ * \param from Params template
+ */
+ void copy_indel (const Params& from);
+
+ /**
+ * \brief Copy emission distributions.
+ *
+ * \param from Params template
+ */
+ void copy_subst (const Params& from);
+
+ /**
+ * \brief Show indel parameters and the corresponding transition matrix.
+ */
+ void show_transition_matrix (std::ostream& o) const;
+
+ /**
+ * \brief Show emit distributions in human-readable format.
+ */
+ void show_emission (std::ostream& o) const;
+
+ /**
+ * \brief Show all parameters.
+ */
+ void show (std::ostream& o) const;
+
+ /**
+ * \brief Write transition probs to disk.
+ * \param filename filename
+ */
+ void write_transition (const std::string& filename) const;
+
+ /**
+ * \brief Write emission probs to disk.
+ * \param filename filename
+ */
+ void write_emission (const std::string& filename) const;
+
+ /**
+ * \brief Write emission probs in .dat-format file to disk for viewParams.pl to use.
+ * \param filename filename
+ */
+ void write_emission_dat (const std::string& filename) const;
+
+ /**
+ * \brief Are the parameters biologically meaningful?
+ *
+ * Returns false if odds (match) < odds (mismatch),
+ * where odds (mismatch) = P (a ~ c) / (P (a) * P (c)), etc.
+ */
+ bool is_biological() const;
+
+ /**
+ * \brief Compute branch-length based on log-det transform.
+ *
+ * which specifies which index (0 = first => columns, 1 = second => rows) of pair_dist
+ * is the ancestral sequence. It follows that
+ * which = 0 gives a right stochastic matrix,
+ * where summing over the second index (rows) of the conditional matrix submat gives 1.
+ * which = 1 gives a left stochastic matrix,
+ * where summing over the first index (columns) of the conditional matrix submat gives 1.
+ * \param which specifies which index is the ancestral sequence
+ */
+ double branch_length (unsigned which) const;
+
+ /**
+ * \brief Compute -log det.
+ *
+ * \return -1 if undefined (if determinant < 0).
+ */
+ static double logdet (const std::vector<std::vector<double> >& matrix);
+
+ /**
+ * \brief Compute the determinant of the substitution matrix.
+ * \param matrix matrix of interest
+ */
+ static double determinant (const std::vector<std::vector<double> >& matrix);
+
+ /**
+ * \brief Assert distributions normalized.
+ */
+ void assert_normalized() const;
+
+ /**
+ * \brief Normalize distributions.
+ */
+ void normalize();
+
+ };
+
+ /**
+ * \brief The statistical model.
+ */
+ struct Model {
+
+ /**
+ * \brief Create alignment dotplot from DP matrices.
+ *
+ * \param params parameters
+ * \param xseq first sequence X
+ * \param yseq second sequence Y
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ * \return Dotplot
+ */
+ template<class T>
+ static Dotplot get_pairwise_dotplot_engine (Params& params, const Sequence& xseq, const Sequence& yseq,
+ bool left_match, bool right_match, bool ragged_ends);
+
+ /**
+ * \brief Create an alignment posterior probability Post_probs from DP matrices.
+ *
+ * The construction of the Post_probs object guarantees proper lexical sorting.
+ * \param params parameters
+ * \param xseq first sequence X
+ * \param yseq second sequence Y
+ * \param minprob minimum posterior probability to store
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ * \return Post_probs (format expected by SparseMatrix constructor).
+ */
+ template<class T>
+ static Post_probs get_pairwise_post_probs_engine (Params& params, const Sequence& xseq, const Sequence& yseq,
+ double minprob,
+ bool left_match, bool right_match, bool ragged_ends);
+
+ /**
+ * \brief Use Baum-Welch training to estimate transition (indel) and emission parameters.
+ *
+ * Unsupervised training on the passed list of sequences.
+ * Returns the total forward likelihood.
+ * Dirichlet regularization according to the passed pseudocounts (held in a Params object, but not normalized).
+ * \param params parameters
+ * \param seq_db sequence data
+ * \param seq_pairs sequence pairs to consider
+ * \param left_match force homology at start of sequences
+ * \param right_match force homology at end of sequences
+ * \param learn_gap learn indel parameters
+ * \param learn_emit learn emit parameters
+ * \param regularize regularize parameters
+ * \param pseudocounts pseudocounts for emission regularization with a Dirichlet
+ * \param iterations maximum number of rounds of EM
+ * \param min_inc minimum fractional increase in log-likelihood before termination
+ */
+ template<class T>
+ static bool train_params_engine (Params& params, const Sequence_database& seq_db, const Sequence_pairs& seq_pairs,
+ bool left_match, bool right_match, bool ragged_ends,
+ bool learn_gap, bool learn_emit, bool regularize, const Params& pseudocounts, size_t iterations, double min_inc);
+
+ /**
+ * \brief Get character frequencies.
+ *
+ * Force tiny value for all characters, even if absent.
+ * NB: We CANNOT use seq_db.get_null_model (alphabet.size())
+ * because it will return an answer sorted non-alphabetically =>
+ * will give us WRONG results!
+ * Assumes that the alphabet is not case-sensitive and that the
+ * alphabet_string is upper-case.
+ * \param seq_db sequence data
+ * \param alphabet_string (ordered) characters in the alphabet
+ * \param is_dna is the alphabet DNA or protein
+ */
+ static std::vector<double> count_char_freq (const Sequence_database& seq_db, const std::string& alphabet_string, bool is_dna);
+
+ };
+
+ template<class T>
+ Dotplot Model::get_pairwise_dotplot_engine (Params& params, const Sequence& xseq, const Sequence& yseq,
+ bool left_match, bool right_match, bool ragged_ends) {
+
+ // print log message
+ if (CTAGGING(6,FSA))
+ CTAG(6,FSA) << "Summing over alignments of '" << xseq.name << "' and '" << yseq.name << "' to get posterior probs." << endl;
+
+ const size_t xlen = xseq.length();
+ const size_t ylen = yseq.length();
+
+ // initialize transition matrix
+ params.init_transition_matrix (left_match, right_match, ragged_ends);
+
+ // ensure that left_match and right_match are reasonable
+ assert (xlen >= static_cast<size_t> (left_match) + static_cast<size_t> (right_match));
+ assert (ylen >= static_cast<size_t> (left_match) + static_cast<size_t> (right_match));
+
+ // calculate the Forward and Backward tables, to compute posteriors
+ typename T::DPTable *pFW, *pBW;
+ const bfloat fw = T::Forward (&pFW, params, xseq.seq, yseq.seq);
+ T::Backward (&pBW, params, xseq.seq, yseq.seq);
+
+ if (CTAGGING(5,FSA))
+ CTAG(5,FSA) << "Per-site log-likelihood = " << log (fw) / (xseq.length() + yseq.length()) << "." << endl;
+
+ Dotplot dotplot (xseq, yseq);
+ const std::string inner_seq = "sequence2";
+ const int match_id = pBW->getId ("match");
+
+ // the first coordinate in getProb refers to the fastest coordinate (inner loop), sequence2;
+ // therefore switch x and y when calling getProb if necessary
+ if (pFW->outputId[0] == inner_seq) {
+
+ const bfloat total = pBW->getProb ("start", 0, 0);
+ for (unsigned x = 0; x < xlen; ++x) {
+ for (unsigned y = 0; y < ylen; ++y) {
+ double& p = dotplot (x, y);
+ p += pFW->getProb (match_id, y + 1, x + 1) * pBW->getProb (match_id, y + 1, x + 1) / total; // HMMoC DP accessor code is 1-based
+ }
+ }
+
+ }
+ // else don't
+ else {
+
+ const bfloat total = pBW->getProb ("start", 0, 0);
+ for (unsigned x = 0; x < xlen; ++x) {
+ for (unsigned y = 0; y < ylen; ++y) {
+ double& p = dotplot (x, y);
+ p += pFW->getProb (match_id, x + 1, y + 1) * pBW->getProb (match_id, x + 1, y + 1) / total; // HMMoC DP accessor code is 1-based
+ }
+ }
+
+ }
+
+ // finished, so clean up
+ delete pFW;
+ delete pBW;
+
+ return dotplot;
+ }
+
+ template<class T>
+ Post_probs Model::get_pairwise_post_probs_engine (Params& params, const Sequence& xseq, const Sequence& yseq,
+ double minprob,
+ bool left_match, bool right_match, bool ragged_ends) {
+
+ // print log message
+ if (CTAGGING(6,FSA))
+ CTAG(6,FSA) << "Summing over alignments of '" << xseq.name << "' and '" << yseq.name << "' to get posterior probs." << endl;
+
+ const size_t xlen = xseq.length();
+ const size_t ylen = yseq.length();
+
+ // initialize transition matrix
+ params.init_transition_matrix (left_match, right_match, ragged_ends);
+
+ // ensure that left_match and right_match are reasonable
+ assert (xlen >= static_cast<size_t> (left_match) + static_cast<size_t> (right_match));
+ assert (ylen >= static_cast<size_t> (left_match) + static_cast<size_t> (right_match));
+
+ // calculate the Forward and Backward tables, to compute posteriors
+ typename T::DPTable *pFW, *pBW;
+ const bfloat fw = T::Forward (&pFW, params, xseq.seq, yseq.seq);
+ T::Backward (&pBW, params, xseq.seq, yseq.seq);
+
+ if (CTAGGING(5,FSA))
+ CTAG (5,FSA) << "Per-site log-likelihood = " << log (fw) / (xlen + ylen) << "." << endl;
+
+ // first assemble posterior vector from post prob information
+ Post_probs post_probs;
+
+ const std::string inner_seq = "sequence2";
+ const int match_id = pBW->getId ("match");
+
+ // the first coordinate in getProb refers to the fastest coordinate (inner loop), sequence2;
+ // therefore switch x and y when calling getProb if necessary
+ if (pFW->outputId[0] == inner_seq) {
+
+ const bfloat total = pBW->getProb ("start", 0, 0);
+ for (unsigned x = 0; x < xlen; ++x) {
+ for (unsigned y = 0; y < ylen; ++y) {
+ double p = pFW->getProb (match_id, y + 1, x + 1) * pBW->getProb (match_id, y + 1, x + 1) / total; // HMMoC DP accessor code is 1-based
+ // sparse storage
+ if (p >= minprob)
+ post_probs.push_back (Post_prob (x, y, p));
+ }
+ }
+
+ }
+ // else don't
+ else {
+
+ const bfloat total = pBW->getProb ("start", 0, 0);
+ for (unsigned x = 0; x < xlen; ++x) {
+ for (unsigned y = 0; y < ylen; ++y) {
+ double p = pFW->getProb (match_id, x + 1, y + 1) * pBW->getProb (match_id, x + 1, y + 1) / total; // HMMoC DP accessor code is 1-based
+ // sparse storage
+ if (p >= minprob)
+ post_probs.push_back (Post_prob (x, y, p));
+ }
+ }
+
+ }
+
+ // finished, so clean up
+ delete pFW;
+ delete pBW;
+
+ return post_probs;
+ }
+
+ template<class T>
+ bool Model::train_params_engine (Params& params, const Sequence_database& seq_db, const Sequence_pairs& seq_pairs,
+ bool left_match, bool right_match, bool ragged_ends,
+ bool learn_gap, bool learn_emit, bool regularize, const Params& pseudocounts, size_t iterations, double min_inc) {
+
+ // get number of seqs
+ const size_t num_seqs = seq_db.size();
+ const size_t num_seq_pairs = seq_pairs.size();
+
+ // log
+ assert (num_seqs >= 2);
+ std::string what_training;
+ if (learn_gap && learn_emit)
+ what_training = "gap and emit";
+ else if (learn_gap && !learn_emit)
+ what_training = "gap";
+ else if (!learn_gap && learn_emit)
+ what_training = "emit";
+ else
+ what_training = "nothing; why am I training?";
+ if ((num_seqs == 2) && CTAGGING(6,FSAEM))
+ CTAG(6,FSAEM) << "Training parameters (" << what_training << ") for '" << seq_db.get_seq (0).name << "' and '" << seq_db.get_seq (1).name << "'." << endl;
+ else if ((num_seqs != 2) && CTAGGING(9,FSAEM))
+ CTAG(9,FSAEM) << "Training parameters (" << what_training << ") for " << seq_db.size() << " sequences (using " << num_seq_pairs << "/" << num_seqs * (num_seqs - 1) / 2 << " possible sequence pairs)." << endl;
+
+ // get alphabet size and alphabet
+ const size_t alphabet_size = params.alphabet_string.length();
+
+ // init DP tables
+ typename T::DPTable* pFW;
+ typename T::BaumWelchCounters baum_welch;
+
+ bfloat curr_fw_total = 0;
+ bfloat prev_fw_total = 0;
+
+ const std::string emit1 = "emit1";
+ const std::string emit2 = "emit2";
+ const std::string emit12 = "emit12";
+
+ for (size_t iter = 1; iter <= iterations; ++iter) { // 1-based for easy logging
+
+ // initialize transition matrix
+ params.init_transition_matrix (left_match, right_match, ragged_ends);
+
+ // reset counts and begin round of EM
+ baum_welch.resetCounts();
+ curr_fw_total = 0;
+ size_t sites = 0;
+
+ if ((num_seqs == 2) && CTAGGING(6,FSAEM))
+ CTAG(6,FSAEM) << "Beginning EM round " << iter << "/" << iterations << endl;
+ else if ((num_seqs != 2) && CTAGGING(7,FSAEM))
+ CTAG(7,FSAEM) << "Beginning EM round " << iter << "/" << iterations << endl;
+
+ // accumulate counts for all sequence pairs
+ for (size_t cnt = 0; cnt < seq_pairs.size(); ++cnt) {
+ const size_t i = seq_pairs[cnt].first;
+ const size_t j = seq_pairs[cnt].second;
+
+ sites += seq_db.get_seq (i).length() + seq_db.get_seq (j).length();
+
+ // ensure that left_match and right_match are reasonable
+ assert (seq_db.get_seq (i).length() >= static_cast<size_t> (left_match) + static_cast<size_t> (right_match));
+ assert (seq_db.get_seq (j).length() >= static_cast<size_t> (left_match) + static_cast<size_t> (right_match));
+
+ // calculate the forward DP table
+ const bfloat fw = T::Forward (&pFW, params, seq_db.get_seq (i).seq, seq_db.get_seq (j).seq);
+ curr_fw_total += fw;
+
+ if (CTAGGING(4,FSAEM))
+ CTAG(4,FSAEM) << "Adding counts for '" << seq_db.get_seq (i).name << "' and '" << seq_db.get_seq (j).name << "' (per-site log-likelihood = " << log (fw) / (seq_db.get_seq (i).length() + seq_db.get_seq (j).length()) << ")" << endl;
+
+ // calculate the Baum-Welch estimated transition counts
+ const bfloat bw = T::BackwardBaumWelch (baum_welch, pFW, params, seq_db.get_seq (i).seq, seq_db.get_seq (j).seq);
+
+ // log progress
+ if (num_seqs > 2) {
+ const unsigned percent_done = static_cast<unsigned> (std::floor ((100.0 * (cnt+1) / num_seq_pairs) + 0.5));
+ if (CTAGGING(7,FSA))
+ CTAG(7,FSA) << "Processed sequence pair '" << seq_db.get_seq (i).name << "' and '" << seq_db.get_seq (j).name << "' (" << percent_done << "% complete)." << endl;
+ }
+
+ // remove the forward table
+ delete pFW;
+ }
+
+ if (learn_gap) {
+
+ // get the expected transition counts
+ const double trMM = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trMM")];
+ const double trMI1 = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trMI1")];
+ const double trMD1 = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trMD1")];
+
+ // these guys don't exist if only 1 set of indel states, so do this to avoid a segfault...
+ const double trMI2 = params.is_indel2 ? (double) baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trMI2")] : 0.;
+ const double trMD2 = params.is_indel2 ? (double) baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trMD2")] : 0.;
+
+ const double trI1I1 = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trI1I1")];
+ const double trI1M = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trI1M")];
+ const double trD1D1 = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trD1D1")];
+ const double trD1M = baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trD1M")];
+
+ const double trI2I2 = params.is_indel2 ? (double) baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trI2I2")] : 0.;
+ const double trI2M = params.is_indel2 ? (double) baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trI2M")] : 0.;
+ const double trD2D2 = params.is_indel2 ? (double) baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trD2D2")] : 0.;
+ const double trD2M = params.is_indel2 ? (double) baum_welch.transitionBaumWelchCount00[baum_welch.transitionIndex ("trD2M")] : 0.;
+
+ // add DOUBLE_TINY to ensure sanity
+ double match_to_indel1 = trMI1 + trMD1 + DOUBLE_TINY;
+ double indel1_to_indel1 = trI1I1 + trD1D1 + DOUBLE_TINY;
+ double match_to_indel2 = trMI2 + trMD2 + DOUBLE_TINY;
+ double indel2_to_indel2 = trI2I2 + trD2D2 + DOUBLE_TINY;
+ double from_match = trMM + match_to_indel1 + match_to_indel2 + DOUBLE_TINY;
+ double from_indel1 = trI1I1 + trI1M + trD1D1 + trD1M + DOUBLE_TINY;
+ double from_indel2 = trI2I2 + trI2M + trD2D2 + trD2M + DOUBLE_TINY;
+
+ // log transition counts
+ if (CTAGGING(-1,FSAEM)) {
+ CL << "Transition counts:" << endl
+ << "match_to_indel1 = " << match_to_indel1 << endl
+ << "match_to_indel2 = " << match_to_indel2 << endl
+ << "indel1_to_indel1 = " << indel1_to_indel1 << endl
+ << "indel2_to_indel2 = " << indel2_to_indel2 << endl
+ << "from_match = " << from_match << endl
+ << "from_indel1 = " << from_indel1 << endl
+ << "from_indel2 = " << from_indel2 << endl;
+ }
+
+ // regularization
+ if (regularize) {
+ // add pseudocounts, scaled by the number of sequence pairs
+ if (CTAGGING(2,FSAEM))
+ CL << "Adding transition pseudocounts" << endl;
+ match_to_indel1 += pseudocounts.gap_open1 * num_seq_pairs;
+ match_to_indel2 += pseudocounts.gap_open2 * num_seq_pairs;
+ from_match += pseudocounts.gap_open1 * num_seq_pairs + pseudocounts.gap_open2 * num_seq_pairs;
+ indel1_to_indel1 += pseudocounts.gap_extend1 * num_seq_pairs;
+ indel2_to_indel2 += pseudocounts.gap_extend2 * num_seq_pairs;
+ from_indel1 += pseudocounts.gap_extend1 * num_seq_pairs;
+ from_indel2 += pseudocounts.gap_extend2 * num_seq_pairs;
+
+ // log counts post-regularization
+ if (CTAGGING(-1,FSAEM)) {
+ CL << "Transition counts after regularization:" << endl
+ << "match_to_indel1 = " << match_to_indel1 << endl
+ << "match_to_indel2 = " << match_to_indel2 << endl
+ << "indel1_to_indel1 = " << indel1_to_indel1 << endl
+ << "indel2_to_indel2 = " << indel2_to_indel2 << endl
+ << "from_match = " << from_match << endl
+ << "from_indel1 = " << from_indel1 << endl
+ << "from_indel2 = " << from_indel2 << endl;
+ }
+ }
+
+ // re-estimate indel parameters
+ params.gap_open1 = match_to_indel1 / from_match;
+ params.gap_extend1 = indel1_to_indel1 / from_indel1;
+ params.gap_open2 = match_to_indel2 / from_match;
+ params.gap_extend2 = indel2_to_indel2 / from_indel2;
+
+ // force indel parameters to be sane:
+ // Problems can arise b/c the Insert->Match transitions are calculated internally in the DP code as
+ // 1.0 - gap_extend - to_end
+ // and Match->Match probs as
+ // 1.0 - gap_open - to_end
+ // If gap_extend becomes 1 (as is wont to happen), then this quantity becomes negative and Very Bad Things can happen.
+ // Make sure that it doesn't:
+ // Force all transition probabilities to be in the range [DOUBLE_TINY, 1.0 - DOUBLE_TINY].
+
+ // gap-open probability
+ params.gap_open1 = (params.gap_open1 > (1.0 - DOUBLE_TINY)) ? 1.0 - DOUBLE_TINY : params.gap_open1;
+ params.gap_open1 = (params.gap_open1 < DOUBLE_TINY) ? DOUBLE_TINY : params.gap_open1;
+ params.gap_open2 = (params.gap_open2 > (1.0 - DOUBLE_TINY)) ? 1.0 - DOUBLE_TINY : params.gap_open2;
+ params.gap_open2 = (params.gap_open2 < DOUBLE_TINY) ? DOUBLE_TINY : params.gap_open2;
+
+ // gap-extend probability
+ params.gap_extend1 = (params.gap_extend1 > (1.0 - DOUBLE_TINY)) ? 1.0 - DOUBLE_TINY : params.gap_extend1;
+ params.gap_extend1 = (params.gap_extend1 < DOUBLE_TINY) ? DOUBLE_TINY : params.gap_extend1;
+ params.gap_extend2 = (params.gap_extend2 > (1.0 - DOUBLE_TINY)) ? 1.0 - DOUBLE_TINY : params.gap_extend2;
+ params.gap_extend2 = (params.gap_extend2 < DOUBLE_TINY) ? DOUBLE_TINY : params.gap_extend2;
+
+ // gap-close probability
+ if (1.0 - params.gap_extend1 - DOUBLE_TINY < DOUBLE_TINY) // hardcode in parameter to_end = DOUBLE_TINY
+ params.gap_extend1 -= DOUBLE_TINY;
+ if (1.0 - params.gap_extend2 - DOUBLE_TINY < DOUBLE_TINY) // hardcode in parameter to_end = DOUBLE_TINY
+ params.gap_extend2 -= DOUBLE_TINY;
+
+ // match->match probability
+ if (1.0 - params.gap_open1 - params.gap_open2 - DOUBLE_TINY < 0) { // hardcode in parameter to_end = DOUBLE_TINY
+ params.gap_open1 -= DOUBLE_TINY / 2;
+ params.gap_open2 -= DOUBLE_TINY / 2;
+ }
+
+ // assert sane
+ assert (params.gap_open1 >= 0. && params.gap_open1 <= 1.);
+ assert (params.gap_extend1 >= 0. && params.gap_extend1 <= 1.);
+ assert (params.gap_open2 >= 0. && params.gap_open2 <= 1.);
+ assert (params.gap_extend2 >= 0. && params.gap_extend2 <= 1.);
+
+ }
+
+ // re-estimate emission parameters
+ if (learn_emit) {
+
+ // accumulate total counts for normalization and log expected counts
+ double singletotal = 0;
+ double pairtotal = 0;
+ if (CTAGGING(-1,FSAEM))
+ CL << "Emission counts:" << endl;
+ for (size_t i = 0; i < alphabet_size; ++i) {
+ if (CTAGGING(-1,FSAEM)) {
+ CL << " " << emit1 << "[" << params.alphabet_string[i] << "]: " << baum_welch.emissionBaumWelchCount10[i][baum_welch.emissionIndex (emit1)] << endl
+ << " " << emit2 << "[" << params.alphabet_string[i] << "]: " << baum_welch.emissionBaumWelchCount01[i][baum_welch.emissionIndex (emit2)] << endl;
+ }
+ singletotal += baum_welch.emissionBaumWelchCount10[i][baum_welch.emissionIndex (emit1)] + baum_welch.emissionBaumWelchCount01[i][baum_welch.emissionIndex (emit2)];
+ }
+ for (size_t i = 0; i < alphabet_size; ++i) {
+ for (size_t j = 0; j < alphabet_size; ++j) {
+ if (CTAGGING(-1,FSAEM))
+ CL << " " << emit12 << "[" << params.alphabet_string[i] << params.alphabet_string[j] << "]: " << baum_welch.emissionBaumWelchCount11[i][j][baum_welch.emissionIndex (emit12)] << endl;
+ pairtotal += baum_welch.emissionBaumWelchCount11[i][j][baum_welch.emissionIndex (emit12)];
+ }
+ }
+
+ // regularization
+ if (regularize) {
+ // add pseudocounts, scaled by the number of sequence pairs
+ if (CTAGGING(2,FSAEM))
+ CL << "Adding emission pseudocounts" << endl;
+ for (size_t i = 0; i < alphabet_size; ++i) {
+ baum_welch.emissionBaumWelchCount10[i][baum_welch.emissionIndex (emit1)] += pseudocounts.single_dist[i] * num_seq_pairs; // scale by number of sequence pairs b/c pseudocounts are for a single pairwise comparison
+ baum_welch.emissionBaumWelchCount01[i][baum_welch.emissionIndex (emit2)] += pseudocounts.single_dist[i] * num_seq_pairs;
+ singletotal += 2 * pseudocounts.single_dist[i] * num_seq_pairs;
+ for (size_t j = 0; j < alphabet_size; ++j) {
+ baum_welch.emissionBaumWelchCount11[i][j][baum_welch.emissionIndex (emit12)] += pseudocounts.pair_dist[i][j] * num_seq_pairs;
+ pairtotal += pseudocounts.pair_dist[i][j] * num_seq_pairs;
+ }
+ }
+
+ // log counts post-regularization
+ if (CTAGGING(-1,FSAEM)) {
+ CL << "Emission counts after regularization:" << endl;
+ for (size_t i = 0; i < alphabet_size; ++i) {
+ CL << " " << emit1 << "[" << params.alphabet_string[i] << "]: " << baum_welch.emissionBaumWelchCount10[i][baum_welch.emissionIndex (emit1)] << endl
+ << " " << emit2 << "[" << params.alphabet_string[i] << "]: " << baum_welch.emissionBaumWelchCount01[i][baum_welch.emissionIndex (emit2)] << endl;
+ }
+ for (size_t i = 0; i < alphabet_size; ++i)
+ for (size_t j = 0; j < alphabet_size; ++j)
+ CL << " " << emit12 << "[" << params.alphabet_string[i] << params.alphabet_string[j] << "]: " << baum_welch.emissionBaumWelchCount11[i][j][baum_welch.emissionIndex (emit12)] << endl;
+ }
+
+ }
+
+ // re-estimate emission params
+ for (size_t i = 0; i < alphabet_size; ++i) {
+ params.single_dist[i] = (baum_welch.emissionBaumWelchCount10[i][baum_welch.emissionIndex (emit1)] + baum_welch.emissionBaumWelchCount01[i][baum_welch.emissionIndex (emit2)]) / singletotal;
+ for (size_t j = 0; j < alphabet_size; ++j)
+ params.pair_dist[i][j] = baum_welch.emissionBaumWelchCount11[i][j][baum_welch.emissionIndex (emit12)] / pairtotal;
+ }
+
+ }
+
+ // log all new params
+ if (CTAGGING(1,FSAEM)) {
+ CL << "Parameter estimates after EM round " << iter << "/" << iterations << endl;
+ if (learn_gap)
+ params.show_transition_matrix (CL);
+ if (learn_emit)
+ params.show_emission (CL);
+ }
+
+ params.assert_normalized();
+
+ // check that fractional increase in log-likelihood is sufficient to continue
+ // (conditional to cover case of first iteration)
+ // in below function, we DON'T use std::log in order to get compiler to call Algebra<BFloatMethods>'s friend method log
+ const double inc = std::abs (static_cast<double> (log (curr_fw_total) / ((std::abs (log (prev_fw_total)) < DOUBLE_TINY) ? 1.0 : log (prev_fw_total)) - 1.0));
+ if ((curr_fw_total <= prev_fw_total) || (inc < min_inc)) // fractional improvement too low, so stop
+ {
+ // did our probabilities fail to increase?
+ if ((curr_fw_total + DOUBLE_TINY < prev_fw_total) && CTAGGING(7,FSAEM)) // ignore rounding errors
+ CL << "WARNING: per-site log-likelihood dropped from " << log (prev_fw_total) / sites
+ << " to " << log (curr_fw_total) / sites << " during EM." << endl;
+ if (CTAGGING(4,FSAEM))
+ CL << "Failed EM fractional improvement threshold of " << min_inc << "; stopping (inc = " << inc << ")." << endl;
+ break;
+ }
+ prev_fw_total = curr_fw_total;
+
+ }
+
+ return true;
+ }
+
+
+ /**
+ * \brief Accessor classes for the standard DP algorithms (nucleotide).
+ */
+ class NucleotideWithoutBanding {
+
+ public:
+
+ typedef NucleotideAlignDPTable DPTable;
+ typedef NucleotideAlignBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Forward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Backward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelch (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the banded DP algorithms (nucleotide).
+ */
+ class NucleotideWithBanding {
+
+ public:
+
+ typedef NucleotideAlignWithBandingDPTable DPTable;
+ typedef NucleotideAlignWithBandingBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::ForwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelchBanding (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the standard DP algorithms (amino acid).
+ */
+ class AminoAcidWithoutBanding {
+
+ public:
+
+ typedef AminoAcidAlignDPTable DPTable;
+ typedef AminoAcidAlignBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Forward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Backward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelch (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the banded DP algorithms (amino acid).
+ */
+ class AminoAcidWithBanding {
+
+ public:
+
+ typedef AminoAcidAlignWithBandingDPTable DPTable;
+ typedef AminoAcidAlignWithBandingBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::ForwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelchBanding (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the standard DP algorithms (nucleotide with 2 sets of indel states).
+ */
+ class NucleotideIndel2WithoutBanding {
+
+ public:
+
+ typedef NucleotideIndel2AlignDPTable DPTable;
+ typedef NucleotideIndel2AlignBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Forward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Backward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelch (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the banded DP algorithms (nucleotide with 2 sets of indel states).
+ */
+ class NucleotideIndel2WithBanding {
+
+ public:
+
+ typedef NucleotideIndel2AlignWithBandingDPTable DPTable;
+ typedef NucleotideIndel2AlignWithBandingBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::ForwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelchBanding (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the standard DP algorithms (amino acid with 2 sets of indel states).
+ */
+ class AminoAcidIndel2WithoutBanding {
+
+ public:
+
+ typedef AminoAcidIndel2AlignDPTable DPTable;
+ typedef AminoAcidIndel2AlignBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Forward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::Backward (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelch (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix);
+ }
+
+ };
+
+ /**
+ * \brief Accessor classes for the banded DP algorithms (amino acid with 2 sets of indel states).
+ */
+ class AminoAcidIndel2WithBanding {
+
+ public:
+
+ typedef AminoAcidIndel2AlignWithBandingDPTable DPTable;
+ typedef AminoAcidIndel2AlignWithBandingBaumWelch BaumWelchCounters;
+
+ static bfloat Forward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::ForwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat Backward (DPTable** ppOutTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBanding (ppOutTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ static bfloat BackwardBaumWelch (BaumWelchCounters& bw, DPTable* pInTable, Params& params, const std::string& iSequence1, const std::string& iSequence2) {
+ return ::BackwardBaumWelchBanding (bw, pInTable, iSequence1, iSequence2, params.single_dist, params.pair_dist, params.transition_matrix, params.bandwidth);
+ }
+
+ };
+
+}
+
+#endif /* FSA_MODEL_INCLUDED */
diff --git a/src/fsa/mybanding.h b/src/fsa/mybanding.h
new file mode 100644
index 0000000..59fd1fa
--- /dev/null
+++ b/src/fsa/mybanding.h
@@ -0,0 +1,111 @@
+
+/*
+ * This file is part of HMMoC 1.3, a hidden Markov model compiler.
+ * Copyright (C) 2007 by Gerton Lunter, Oxford University.
+ *
+ * HMMoC 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * HMMOC 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 HMMoC; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+\*/
+
+#ifndef MYBANDING_INCLUDED
+#define MYBANDING_INCLUDED
+
+#include <iostream>
+#include "fsa/dptables.h"
+
+using std::endl;
+using std::cout;
+using std::min;
+using std::max;
+
+// Implements a traversal of the dynamic programming table along a diagonal band.
+// The band should remain (diagonally) connected even if iWidth==1, and the forward
+// and backward iterations must visit the same sites - these two requirements made the
+// implementation slightly tricky.
+
+class MyBanding : Banding<2> {
+
+ private:
+
+ int iLen0, iLen1;
+ int iWidth;
+ Position pos;
+ int iLastRow;
+
+ int diagonal(int p1) { return (p1 * iLen0 + iLen1/2) / iLen1; }
+
+ public:
+
+ MyBanding( int iLen0, int iLen1, int iWidth ) : iLen0(iLen0), iLen1(iLen1), iWidth(iWidth) {}
+
+ Position& forwardIterator() {
+
+ pos[0] = pos[1] = 0;
+ iLastRow = iLen0;
+ return pos;
+
+ }
+
+ Position& backwardIterator() {
+
+ pos[0] = iLen0;
+ pos[1] = iLen1;
+ iLastRow = 0;
+ return pos;
+
+ }
+
+ bool hasNextForward() {
+
+ if (pos[0] < iLen0 && pos[0] < (iWidth-1)/2 + max( diagonal(pos[1]+1)-1, diagonal(pos[1]))) {
+ ++pos[0];
+ return true;
+ }
+ if (pos[1]<iLen1) {
+ ++pos[1];
+ pos[0] = max(0, diagonal(pos[1]) - iWidth/2);
+ return true;
+ }
+ return false;
+ }
+
+ bool hasNextBackward() {
+
+ if (pos[0] > 0 && pos[0] > diagonal(pos[1]) - iWidth/2) {
+ --pos[0];
+ return true;
+ }
+ if (pos[1]>0) {
+ --pos[1];
+ pos[0] = min(iLen0, (iWidth-1)/2 + max( diagonal(pos[1]+1)-1, diagonal(pos[1])));
+ return true;
+ }
+ return false;
+ }
+
+ bool lastColumnEntry() {
+
+ return pos[0] == iLastRow;
+
+ }
+
+ void warning() {
+
+ cout << "Warning - out of bounds at position (" << pos[0] << "," << pos[1] << ")" << endl;
+
+ }
+
+};
+
+#endif /* MYBANDING_INCLUDED */
diff --git a/src/fsa/nucleotide_indel2dp.cc b/src/fsa/nucleotide_indel2dp.cc
new file mode 100644
index 0000000..e85fad3
--- /dev/null
+++ b/src/fsa/nucleotide_indel2dp.cc
@@ -0,0 +1,2253 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file nucleotide_indel2.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:17 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "nucleotide_indel2dp.h"
+
+#include "mybanding.h"
+
+const extern string _NucleotideIndel2AlignstateId[];
+const extern string _NucleotideIndel2AlignemissionId[];
+const extern string _NucleotideIndel2AligntransitionId[];
+const extern string _NucleotideIndel2AligntransF[];
+const extern string _NucleotideIndel2AligntransT[];
+const extern string _NucleotideIndel2AligntransP[];
+const extern string _NucleotideIndel2AligntransE[];
+const extern string _NucleotideIndel2AlignoutputId[];
+const extern string _NucleotideIndel2Alignempty;
+const extern int _NucleotideIndel2AlignstateNum;
+const extern int _NucleotideIndel2AlignemitNum;
+const extern int _NucleotideIndel2AligntransNum;
+const extern int _NucleotideIndel2AlignoutputNum;
+
+NucleotideIndel2AlignDPTable::NucleotideIndel2AlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideIndel2AlignstateId), emissionId(_NucleotideIndel2AlignemissionId), transitionId(_NucleotideIndel2AligntransitionId), transitionFrom(_NucleotideIndel2AligntransF), transitionTo(_NucleotideIndel2AligntransT), transitionProb(_NucleotideIndel2AligntransP), transitionEmit(_NucleotideIndel2AligntransE), outputId(_NucleotideIndel2AlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucIndel2Block2.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucIndel2Block1.allocate();
+ StateMemorynucIndel2Block3.allocate();
+}
+
+
+NucleotideIndel2AlignDPTable::~NucleotideIndel2AlignDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucIndel2Block2.absolve();
+ StateMemorynucIndel2Block1.absolve();
+ StateMemorynucIndel2Block3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideIndel2AlignDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideIndel2AligntransNum ? _NucleotideIndel2AligntransitionId[id] : _NucleotideIndel2Alignempty; }
+const string& NucleotideIndel2AlignDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideIndel2AlignemitNum ? _NucleotideIndel2AlignemissionId[id] : _NucleotideIndel2Alignempty; }
+const string& NucleotideIndel2AlignDPTable::getStateId(int id) { return id>=0 && id<_NucleotideIndel2AlignstateNum ? _NucleotideIndel2AlignstateId[id] : _NucleotideIndel2Alignempty; }
+const string& NucleotideIndel2AlignDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideIndel2AlignoutputNum ? _NucleotideIndel2AlignoutputId[id] : _NucleotideIndel2Alignempty; }
+int NucleotideIndel2AlignDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideIndel2AlignstateNum;i++) {
+ (*pmId)[_NucleotideIndel2AlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignemitNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AligntransNum; i++) {
+ (*pmId)[_NucleotideIndel2AligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignoutputNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideIndel2AlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideIndel2AlignDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideIndel2AlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucIndel2Block1Secondary;
+ const bfloat *CurStateMemorynucIndel2Block2Secondary;
+ const bfloat *CurStateMemorynucIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucIndel2Block1Secondary = this->StateMemorynucIndel2Block1.read();
+ return CurStateMemorynucIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2Secondary = this->StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucIndel2Block2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block3Secondary = this->StateMemorynucIndel2Block3.read();
+ return CurStateMemorynucIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _NucleotideIndel2AlignstateId[];
+const extern string _NucleotideIndel2AlignemissionId[];
+const extern string _NucleotideIndel2AligntransitionId[];
+const extern string _NucleotideIndel2AligntransF[];
+const extern string _NucleotideIndel2AligntransT[];
+const extern string _NucleotideIndel2AligntransP[];
+const extern string _NucleotideIndel2AligntransE[];
+const extern string _NucleotideIndel2AlignoutputId[];
+const extern string _NucleotideIndel2Alignempty;
+const extern int _NucleotideIndel2AlignstateNum;
+const extern int _NucleotideIndel2AlignemitNum;
+const extern int _NucleotideIndel2AligntransNum;
+const extern int _NucleotideIndel2AlignoutputNum;
+
+NucleotideIndel2AlignFoldedDPTable::NucleotideIndel2AlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideIndel2AlignstateId), emissionId(_NucleotideIndel2AlignemissionId), transitionId(_NucleotideIndel2AligntransitionId), transitionFrom(_NucleotideIndel2AligntransF), transitionTo(_NucleotideIndel2AligntransT), transitionProb(_NucleotideIndel2AligntransP), transitionEmit(_NucleotideIndel2AligntransE), outputId(_NucleotideIndel2AlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucIndel2Block2.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucIndel2Block3.allocate();
+ StateMemorynucIndel2Block1.allocate();
+}
+
+
+NucleotideIndel2AlignFoldedDPTable::~NucleotideIndel2AlignFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucIndel2Block2.absolve();
+ StateMemorynucIndel2Block3.absolve();
+ StateMemorynucIndel2Block1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideIndel2AlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideIndel2AligntransNum ? _NucleotideIndel2AligntransitionId[id] : _NucleotideIndel2Alignempty; }
+const string& NucleotideIndel2AlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideIndel2AlignemitNum ? _NucleotideIndel2AlignemissionId[id] : _NucleotideIndel2Alignempty; }
+const string& NucleotideIndel2AlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_NucleotideIndel2AlignstateNum ? _NucleotideIndel2AlignstateId[id] : _NucleotideIndel2Alignempty; }
+const string& NucleotideIndel2AlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideIndel2AlignoutputNum ? _NucleotideIndel2AlignoutputId[id] : _NucleotideIndel2Alignempty; }
+int NucleotideIndel2AlignFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideIndel2AlignstateNum;i++) {
+ (*pmId)[_NucleotideIndel2AlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignemitNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AligntransNum; i++) {
+ (*pmId)[_NucleotideIndel2AligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignoutputNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideIndel2AlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideIndel2AlignFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideIndel2AlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucIndel2Block1Secondary;
+ const bfloat *CurStateMemorynucIndel2Block2Secondary;
+ const bfloat *CurStateMemorynucIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucIndel2Block1Secondary = this->StateMemorynucIndel2Block1.read();
+ return CurStateMemorynucIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2Secondary = this->StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucIndel2Block2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block3Secondary = this->StateMemorynucIndel2Block3.read();
+ return CurStateMemorynucIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int NucleotideIndel2AlignBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideIndel2AlignBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int NucleotideIndel2AlignBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideIndel2AlignBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void NucleotideIndel2AlignBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
+ for (int i=0; i<23; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AligntransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int NucleotideIndel2AlignBaumWelch::transitionIdentifier00[];
+int NucleotideIndel2AlignBaumWelch::emissionIdentifier00[];
+int NucleotideIndel2AlignBaumWelch::emissionIdentifier01[];
+int NucleotideIndel2AlignBaumWelch::emissionIdentifier10[];
+int NucleotideIndel2AlignBaumWelch::emissionIdentifier11[];
+
+void NucleotideIndel2AlignBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> NucleotideIndel2AlignBaumWelch::mId;
+int NucleotideIndel2AlignBaumWelch::atransitionIdx[];
+int NucleotideIndel2AlignBaumWelch::aemissionIdx[];
+
+const extern string _NucleotideIndel2AlignWithBandingstateId[];
+const extern string _NucleotideIndel2AlignWithBandingemissionId[];
+const extern string _NucleotideIndel2AlignWithBandingtransitionId[];
+const extern string _NucleotideIndel2AlignWithBandingtransF[];
+const extern string _NucleotideIndel2AlignWithBandingtransT[];
+const extern string _NucleotideIndel2AlignWithBandingtransP[];
+const extern string _NucleotideIndel2AlignWithBandingtransE[];
+const extern string _NucleotideIndel2AlignWithBandingoutputId[];
+const extern string _NucleotideIndel2AlignWithBandingempty;
+const extern int _NucleotideIndel2AlignWithBandingstateNum;
+const extern int _NucleotideIndel2AlignWithBandingemitNum;
+const extern int _NucleotideIndel2AlignWithBandingtransNum;
+const extern int _NucleotideIndel2AlignWithBandingoutputNum;
+
+NucleotideIndel2AlignWithBandingDPTable::NucleotideIndel2AlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideIndel2AlignWithBandingstateId), emissionId(_NucleotideIndel2AlignWithBandingemissionId), transitionId(_NucleotideIndel2AlignWithBandingtransitionId), transitionFrom(_NucleotideIndel2AlignWithBandingtransF), transitionTo(_NucleotideIndel2AlignWithBandingtransT), transitionProb(_NucleotideIndel2AlignWithBandingtransP), transitionEmit(_NucleotideIndel2 [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucIndel2Block2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucIndel2Block1.allocate();
+ StateMemorynucIndel2Block3.allocate();
+}
+
+
+NucleotideIndel2AlignWithBandingDPTable::~NucleotideIndel2AlignWithBandingDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucIndel2Block2withbanding.absolve();
+ StateMemorynucIndel2Block1.absolve();
+ StateMemorynucIndel2Block3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideIndel2AlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingtransNum ? _NucleotideIndel2AlignWithBandingtransitionId[id] : _NucleotideIndel2AlignWithBandingempty; }
+const string& NucleotideIndel2AlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingemitNum ? _NucleotideIndel2AlignWithBandingemissionId[id] : _NucleotideIndel2AlignWithBandingempty; }
+const string& NucleotideIndel2AlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingstateNum ? _NucleotideIndel2AlignWithBandingstateId[id] : _NucleotideIndel2AlignWithBandingempty; }
+const string& NucleotideIndel2AlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingoutputNum ? _NucleotideIndel2AlignWithBandingoutputId[id] : _NucleotideIndel2AlignWithBandingempty; }
+int NucleotideIndel2AlignWithBandingDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideIndel2AlignWithBandingstateNum;i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignWithBandingemitNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignWithBandingtransNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignWithBandingoutputNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideIndel2AlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideIndel2AlignWithBandingDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideIndel2AlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucIndel2Block1Secondary;
+ const bfloat *CurStateMemorynucIndel2Block2withbandingSecondary;
+ const bfloat *CurStateMemorynucIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucIndel2Block1Secondary = this->StateMemorynucIndel2Block1.read();
+ return CurStateMemorynucIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingSecondary = this->StateMemorynucIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucIndel2Block2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block3Secondary = this->StateMemorynucIndel2Block3.read();
+ return CurStateMemorynucIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _NucleotideIndel2AlignWithBandingstateId[];
+const extern string _NucleotideIndel2AlignWithBandingemissionId[];
+const extern string _NucleotideIndel2AlignWithBandingtransitionId[];
+const extern string _NucleotideIndel2AlignWithBandingtransF[];
+const extern string _NucleotideIndel2AlignWithBandingtransT[];
+const extern string _NucleotideIndel2AlignWithBandingtransP[];
+const extern string _NucleotideIndel2AlignWithBandingtransE[];
+const extern string _NucleotideIndel2AlignWithBandingoutputId[];
+const extern string _NucleotideIndel2AlignWithBandingempty;
+const extern int _NucleotideIndel2AlignWithBandingstateNum;
+const extern int _NucleotideIndel2AlignWithBandingemitNum;
+const extern int _NucleotideIndel2AlignWithBandingtransNum;
+const extern int _NucleotideIndel2AlignWithBandingoutputNum;
+
+NucleotideIndel2AlignWithBandingFoldedDPTable::NucleotideIndel2AlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideIndel2AlignWithBandingstateId), emissionId(_NucleotideIndel2AlignWithBandingemissionId), transitionId(_NucleotideIndel2AlignWithBandingtransitionId), transitionFrom(_NucleotideIndel2AlignWithBandingtransF), transitionTo(_NucleotideIndel2AlignWithBandingtransT), transitionProb(_NucleotideIndel2AlignWithBandingtransP), transitionEmit(_Nucl [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucIndel2Block2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucIndel2Block3.allocate();
+ StateMemorynucIndel2Block1.allocate();
+}
+
+
+NucleotideIndel2AlignWithBandingFoldedDPTable::~NucleotideIndel2AlignWithBandingFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucIndel2Block2withbanding.absolve();
+ StateMemorynucIndel2Block3.absolve();
+ StateMemorynucIndel2Block1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideIndel2AlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingtransNum ? _NucleotideIndel2AlignWithBandingtransitionId[id] : _NucleotideIndel2AlignWithBandingempty; }
+const string& NucleotideIndel2AlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingemitNum ? _NucleotideIndel2AlignWithBandingemissionId[id] : _NucleotideIndel2AlignWithBandingempty; }
+const string& NucleotideIndel2AlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingstateNum ? _NucleotideIndel2AlignWithBandingstateId[id] : _NucleotideIndel2AlignWithBandingempty; }
+const string& NucleotideIndel2AlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideIndel2AlignWithBandingoutputNum ? _NucleotideIndel2AlignWithBandingoutputId[id] : _NucleotideIndel2AlignWithBandingempty; }
+int NucleotideIndel2AlignWithBandingFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideIndel2AlignWithBandingstateNum;i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignWithBandingemitNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignWithBandingtransNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideIndel2AlignWithBandingoutputNum; i++) {
+ (*pmId)[_NucleotideIndel2AlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideIndel2AlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideIndel2AlignWithBandingFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideIndel2AlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucIndel2Block1Secondary;
+ const bfloat *CurStateMemorynucIndel2Block2withbandingSecondary;
+ const bfloat *CurStateMemorynucIndel2Block3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucIndel2Block1Secondary = this->StateMemorynucIndel2Block1.read();
+ return CurStateMemorynucIndel2Block1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingSecondary = this->StateMemorynucIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucIndel2Block2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucIndel2Block3Secondary = this->StateMemorynucIndel2Block3.read();
+ return CurStateMemorynucIndel2Block3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int NucleotideIndel2AlignWithBandingBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideIndel2AlignWithBandingBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int NucleotideIndel2AlignWithBandingBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideIndel2AlignWithBandingBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void NucleotideIndel2AlignWithBandingBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
+ for (int i=0; i<23; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignWithBandingtransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int NucleotideIndel2AlignWithBandingBaumWelch::transitionIdentifier00[];
+int NucleotideIndel2AlignWithBandingBaumWelch::emissionIdentifier00[];
+int NucleotideIndel2AlignWithBandingBaumWelch::emissionIdentifier01[];
+int NucleotideIndel2AlignWithBandingBaumWelch::emissionIdentifier10[];
+int NucleotideIndel2AlignWithBandingBaumWelch::emissionIdentifier11[];
+
+void NucleotideIndel2AlignWithBandingBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<23; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> NucleotideIndel2AlignWithBandingBaumWelch::mId;
+int NucleotideIndel2AlignWithBandingBaumWelch::atransitionIdx[];
+int NucleotideIndel2AlignWithBandingBaumWelch::aemissionIdx[];
+
+const string _NucleotideIndel2AlignstateId[] = {"start","delete2","delete1","insert1","match","insert2","end"};
+const string _NucleotideIndel2AlignemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _NucleotideIndel2AligntransitionId[] = {"trSM","trSI1","trSD1","trSI2","trSD2","trMM","trMI1","trMD1","trMI2","trMD2","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E","trI2M","trI2I2","trI2E","trD2M","trD2D2","trD2E"};
+const string _NucleotideIndel2AligntransF[] = {"start","start","start","start","start","match","match","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1","insert2","insert2","insert2","delete2","delete2","delete2"};
+const string _NucleotideIndel2AligntransT[] = {"match","insert1","delete1","insert2","delete2","match","insert1","delete1","insert2","delete2","end","match","insert1","end","match","delete1","end","match","insert2","end","match","delete2","end"};
+const string _NucleotideIndel2AligntransP[] = {"probSM","probSI1","probSD1","probSI2","probSD2","probMM","probMI1","probMD1","probMI2","probMD2","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E","probI2M","probI2I2","probI2E","probD2M","probD2D2","probD2E"};
+const string _NucleotideIndel2AligntransE[] = {"emit12","emit1","emit2","emit1","emit2","emit12","emit1","emit2","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _NucleotideIndel2AlignoutputId[] = {"sequence1","sequence2"};
+const string _NucleotideIndel2Alignempty = "";
+const int _NucleotideIndel2AlignstateNum = 7;
+const int _NucleotideIndel2AlignemitNum = 4;
+const int _NucleotideIndel2AligntransNum = 23;
+const int _NucleotideIndel2AlignoutputNum = 2;
+
+
+
+
+bfloat Forward(NucleotideIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemorynucIndel2Block2To;
+ const bfloat *CurStateMemorynucIndel2Block1From;
+ const bfloat *CurStateMemorynucIndel2Block2From;
+ bfloat *CurStateMemorynucIndel2Block3To;
+ const bfloat *CurStateMemorynucIndel2Block3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideIndel2AlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemorynucIndel2Block1.write()[0] = 1.0;
+ dp.StateMemorynucIndel2Block1.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=0; iPos1<iLen2+1; ++iPos1) {
+ for (int iPos0=0; iPos0<iLen1+1; ++iPos0) {
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ }
+ if (1) {
+ if ((iPos1+-1>=0)) {
+ iSymbol[0] = iSequence2[iPos1+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+-1>=0)) {
+ iSymbol[1] = iSequence1[iPos0+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block2To = dp.StateMemorynucIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+0<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ CurStateMemorynucIndel2Block2To[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ CurStateMemorynucIndel2Block2To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ }
+ if ((iPos1+-1>=0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
+ CurStateMemorynucIndel2Block2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[1] += ((iTransition[15])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ CurStateMemorynucIndel2Block2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[0] += ((iTransition[21])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ CurStateMemorynucIndel2Block2To[2] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ CurStateMemorynucIndel2Block2To[4] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ }
+ if ((iPos0+-1>=0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block2To[2] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ CurStateMemorynucIndel2Block2To[4] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[4] += ((iTransition[18])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ CurStateMemorynucIndel2Block2To[3] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ }
+ if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[20])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[14])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[17])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ }
+ dp.StateMemorynucIndel2Block2.written();
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemorynucIndel2Block3To = dp.StateMemorynucIndel2Block3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block3To[0] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[13])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[16])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[19])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ }
+ dp.StateMemorynucIndel2Block3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block3From = dp.StateMemorynucIndel2Block3.read();
+ iTempProb[0] = CurStateMemorynucIndel2Block3From[0];
+ }
+ }
+ *ppOutTable = new NucleotideIndel2AlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelch(NucleotideIndel2AlignBaumWelch& bw,NucleotideIndel2AlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ const bfloat *CurStateMemorynucIndel2Block3Secondary;
+ bfloat iTransition[23];
+ bfloat *CurStateMemorynucIndel2Block2To;
+ const bfloat *CurStateMemorynucIndel2Block2Secondary;
+ const bfloat *CurStateMemorynucIndel2Block2From;
+ unsigned char alphaSymbolnucleotide[4] = {'A', 'C', 'G', 'T'};
+ unsigned char alphaIndexnucleotide[256];
+ const bfloat *CurStateMemorynucIndel2Block3From;
+ bfloat *CurStateMemorynucIndel2Block1To;
+ const bfloat *CurStateMemorynucIndel2Block1Secondary;
+ const bfloat *CurStateMemorynucIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ NucleotideIndel2AlignFoldedDPTable dp(iLen1,2);
+ NucleotideIndel2AlignDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexnucleotide[i]=0;
+ }
+
+// for (int i=0; i<4; i++) {
+// alphaIndexnucleotide[alphaSymbolnucleotide[i]]=i;
+// }
+ for (int i=0; i<4; i++) {
+ alphaIndexnucleotide[tolower (alphaSymbolnucleotide[i])] = i;
+ alphaIndexnucleotide[toupper (alphaSymbolnucleotide[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemorynucIndel2Block3.write()[0] = 1.0;
+ dp.StateMemorynucIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block3Secondary = dp2.StateMemorynucIndel2Block3.read();
+ iTempProb[2] = CurStateMemorynucIndel2Block3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != iPos1) {
+ dp.StateMemorynucIndel2Block2.clear(iPos1);
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block2To = dp.StateMemorynucIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block2Secondary = dp2.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block2To[3] = iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[3] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[1] = iTempProb[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[1];
+ bw.transitionBaumWelchCount00[15] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[0] = iTempProb[1] = ((iTransition[21])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[0];
+ bw.transitionBaumWelchCount00[21] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block2To[2] = iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[3] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[3] += iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[4] = iTempProb[1] = ((iTransition[18])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[4];
+ bw.transitionBaumWelchCount00[18] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block2To[2] += iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[1] += iTempProb[1] = ((iTransition[14])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[1];
+ bw.transitionBaumWelchCount00[14] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[4] += iTempProb[1] = ((iTransition[17])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[4];
+ bw.transitionBaumWelchCount00[17] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[0] += iTempProb[1] = ((iTransition[20])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[0];
+ bw.transitionBaumWelchCount00[20] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[3] += iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemorynucIndel2Block3From = dp.StateMemorynucIndel2Block3.read();
+ CurStateMemorynucIndel2Block2To[2] += iTempProb[1] = ((iTransition[13])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[2];
+ bw.transitionBaumWelchCount00[13] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[1] += iTempProb[1] = ((iTransition[16])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[1];
+ bw.transitionBaumWelchCount00[16] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[4] += iTempProb[1] = ((iTransition[19])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[4];
+ bw.transitionBaumWelchCount00[19] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[0] += iTempProb[1] = ((iTransition[22])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[0];
+ bw.transitionBaumWelchCount00[22] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2To[3] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2Secondary[3];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemorynucIndel2Block2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block1To = dp.StateMemorynucIndel2Block1.write();
+ CurStateMemorynucIndel2Block1Secondary = dp2.StateMemorynucIndel2Block1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemorynucIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ iTempProb[0] = CurStateMemorynucIndel2Block1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat Backward(NucleotideIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemorynucIndel2Block2To;
+ const bfloat *CurStateMemorynucIndel2Block2From;
+ const bfloat *CurStateMemorynucIndel2Block3From;
+ bfloat *CurStateMemorynucIndel2Block1To;
+ const bfloat *CurStateMemorynucIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideIndel2AlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemorynucIndel2Block3.write()[0] = 1.0;
+ dp.StateMemorynucIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block2To = dp.StateMemorynucIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block2To[0] = ((iTransition[21])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ CurStateMemorynucIndel2Block2To[3] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ CurStateMemorynucIndel2Block2To[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block2To[2] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ CurStateMemorynucIndel2Block2To[4] = ((iTransition[18])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[0] += ((iTransition[20])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[4] += ((iTransition[17])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ CurStateMemorynucIndel2Block2To[1] += ((iTransition[14])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemorynucIndel2Block3From = dp.StateMemorynucIndel2Block3.read();
+ CurStateMemorynucIndel2Block2To[2] += ((iTransition[13])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2To[3] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2To[4] += ((iTransition[19])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2To[1] += ((iTransition[16])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ }
+ dp.StateMemorynucIndel2Block2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block1To = dp.StateMemorynucIndel2Block1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[0];
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[2])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[2];
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2From = dp.StateMemorynucIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemorynucIndel2Block2From[3];
+ }
+ dp.StateMemorynucIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ iTempProb[0] = CurStateMemorynucIndel2Block1From[0];
+ }
+ }
+ *ppOutTable = new NucleotideIndel2AlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+const string _NucleotideIndel2AlignWithBandingstateId[] = {"start","delete2","delete1","insert1","match","insert2","end"};
+const string _NucleotideIndel2AlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _NucleotideIndel2AlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trSI2","trSD2","trMM","trMI1","trMD1","trMI2","trMD2","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E","trI2M","trI2I2","trI2E","trD2M","trD2D2","trD2E"};
+const string _NucleotideIndel2AlignWithBandingtransF[] = {"start","start","start","start","start","match","match","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1","insert2","insert2","insert2","delete2","delete2","delete2"};
+const string _NucleotideIndel2AlignWithBandingtransT[] = {"match","insert1","delete1","insert2","delete2","match","insert1","delete1","insert2","delete2","end","match","insert1","end","match","delete1","end","match","insert2","end","match","delete2","end"};
+const string _NucleotideIndel2AlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probSI2","probSD2","probMM","probMI1","probMD1","probMI2","probMD2","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E","probI2M","probI2I2","probI2E","probD2M","probD2D2","probD2E"};
+const string _NucleotideIndel2AlignWithBandingtransE[] = {"emit12","emit1","emit2","emit1","emit2","emit12","emit1","emit2","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _NucleotideIndel2AlignWithBandingoutputId[] = {"sequence1","sequence2"};
+const string _NucleotideIndel2AlignWithBandingempty = "";
+const int _NucleotideIndel2AlignWithBandingstateNum = 7;
+const int _NucleotideIndel2AlignWithBandingemitNum = 4;
+const int _NucleotideIndel2AlignWithBandingtransNum = 23;
+const int _NucleotideIndel2AlignWithBandingoutputNum = 2;
+
+
+
+
+bfloat ForwardBanding(NucleotideIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemorynucIndel2Block2withbandingTo;
+ const bfloat *CurStateMemorynucIndel2Block1From;
+ const bfloat *CurStateMemorynucIndel2Block2withbandingFrom;
+ bfloat *CurStateMemorynucIndel2Block3To;
+ const bfloat *CurStateMemorynucIndel2Block3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideIndel2AlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemorynucIndel2Block1.write()[0] = 1.0;
+ dp.StateMemorynucIndel2Block1.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.forwardIterator();
+ bool bLastSlowCoordInited = false;
+ int iLastSlowCoord = -1;
+ do {
+ if (bLastSlowCoordInited) {
+ if (iLastSlowCoord > position[1]) {
+ cout << "WARNING: Banding (forward): Slowest coordinate should be nondecreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ } else {
+ bLastSlowCoordInited = true;
+ }
+ iLastSlowCoord = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+-1>=0)) {
+ iSymbol[0] = iSequence2[position[1]+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+-1>=0)) {
+ iSymbol[1] = iSequence1[position[0]+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block2withbandingTo = dp.StateMemorynucIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+0<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ CurStateMemorynucIndel2Block2withbandingTo[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ CurStateMemorynucIndel2Block2withbandingTo[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ }
+ if ((position[1]+-1>=0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[0] += ((iTransition[21])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ CurStateMemorynucIndel2Block2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[1] += ((iTransition[15])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ CurStateMemorynucIndel2Block2withbandingTo[2] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ CurStateMemorynucIndel2Block2withbandingTo[4] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ }
+ if ((position[0]+-1>=0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ CurStateMemorynucIndel2Block2withbandingTo[2] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[4] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[4] += ((iTransition[18])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ CurStateMemorynucIndel2Block2withbandingTo[3] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucIndel2Block1From[0];
+ }
+ if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[20])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[17])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[14])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ }
+ dp.StateMemorynucIndel2Block2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextForward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ CurStateMemorynucIndel2Block3To = dp.StateMemorynucIndel2Block3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block3To[0] = ((iTransition[13])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[19])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[16])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ CurStateMemorynucIndel2Block3To[0] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ }
+ dp.StateMemorynucIndel2Block3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block3From = dp.StateMemorynucIndel2Block3.read();
+ iTempProb[0] = CurStateMemorynucIndel2Block3From[0];
+ }
+ }
+ *ppOutTable = new NucleotideIndel2AlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelchBanding(NucleotideIndel2AlignWithBandingBaumWelch& bw,NucleotideIndel2AlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ const bfloat *CurStateMemorynucIndel2Block3Secondary;
+ bfloat iTransition[23];
+ bfloat *CurStateMemorynucIndel2Block2withbandingTo;
+ const bfloat *CurStateMemorynucIndel2Block2withbandingSecondary;
+ const bfloat *CurStateMemorynucIndel2Block2withbandingFrom;
+ unsigned char alphaSymbolnucleotide[4] = {'A', 'C', 'G', 'T'};
+ unsigned char alphaIndexnucleotide[256];
+ const bfloat *CurStateMemorynucIndel2Block3From;
+ bfloat *CurStateMemorynucIndel2Block1To;
+ const bfloat *CurStateMemorynucIndel2Block1Secondary;
+ const bfloat *CurStateMemorynucIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ NucleotideIndel2AlignWithBandingFoldedDPTable dp(iLen1,2);
+ NucleotideIndel2AlignWithBandingDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexnucleotide[i]=0;
+ }
+
+// for (int i=0; i<4; i++) {
+// alphaIndexnucleotide[alphaSymbolnucleotide[i]]=i;
+// }
+ for (int i=0; i<4; i++) {
+ alphaIndexnucleotide[tolower (alphaSymbolnucleotide[i])] = i;
+ alphaIndexnucleotide[toupper (alphaSymbolnucleotide[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemorynucIndel2Block3.write()[0] = 1.0;
+ dp.StateMemorynucIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block3Secondary = dp2.StateMemorynucIndel2Block3.read();
+ iTempProb[2] = CurStateMemorynucIndel2Block3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != position[1]) {
+ dp.StateMemorynucIndel2Block2withbanding.clear(position[1]);
+ }
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block2withbandingTo = dp.StateMemorynucIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucIndel2Block2withbandingSecondary = dp2.StateMemorynucIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[0] = iTempProb[1] = ((iTransition[21])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[21] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[1] = iTempProb[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[15] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[3] = iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[4] = iTempProb[1] = ((iTransition[18])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[4];
+ bw.transitionBaumWelchCount00[18] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[2] = iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[0] += iTempProb[1] = ((iTransition[20])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[20] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[1] += iTempProb[1] = ((iTransition[14])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[14] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[2] += iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[4] += iTempProb[1] = ((iTransition[17])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[4];
+ bw.transitionBaumWelchCount00[17] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemorynucIndel2Block3From = dp.StateMemorynucIndel2Block3.read();
+ CurStateMemorynucIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[3];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[0] += iTempProb[1] = ((iTransition[22])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[22] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[1] += iTempProb[1] = ((iTransition[16])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[16] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[2] += iTempProb[1] = ((iTransition[13])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[13] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucIndel2Block2withbandingTo[4] += iTempProb[1] = ((iTransition[19])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block2withbandingSecondary[4];
+ bw.transitionBaumWelchCount00[19] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemorynucIndel2Block2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block1To = dp.StateMemorynucIndel2Block1.write();
+ CurStateMemorynucIndel2Block1Secondary = dp2.StateMemorynucIndel2Block1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ iTempProb[1] *= CurStateMemorynucIndel2Block1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemorynucIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ iTempProb[0] = CurStateMemorynucIndel2Block1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBanding(NucleotideIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[23];
+ bfloat *CurStateMemorynucIndel2Block2withbandingTo;
+ const bfloat *CurStateMemorynucIndel2Block2withbandingFrom;
+ const bfloat *CurStateMemorynucIndel2Block3From;
+ bfloat *CurStateMemorynucIndel2Block1To;
+ const bfloat *CurStateMemorynucIndel2Block1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideIndel2AlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[0][4];
+
+ iTransition[4] = iT[0][5];
+
+ iTransition[5] = iT[1][1];
+
+ iTransition[6] = iT[1][2];
+
+ iTransition[7] = iT[1][3];
+
+ iTransition[8] = iT[1][4];
+
+ iTransition[9] = iT[1][5];
+
+ iTransition[10] = iT[1][6];
+
+ iTransition[11] = iT[2][1];
+
+ iTransition[12] = iT[2][2];
+
+ iTransition[13] = iT[2][6];
+
+ iTransition[14] = iT[3][1];
+
+ iTransition[15] = iT[3][3];
+
+ iTransition[16] = iT[3][6];
+
+ iTransition[17] = iT[4][1];
+
+ iTransition[18] = iT[4][4];
+
+ iTransition[19] = iT[4][6];
+
+ iTransition[20] = iT[5][1];
+
+ iTransition[21] = iT[5][5];
+
+ iTransition[22] = iT[5][6];
+ dp.StateMemorynucIndel2Block3.write()[0] = 1.0;
+ dp.StateMemorynucIndel2Block3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block2withbandingTo = dp.StateMemorynucIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[3] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ CurStateMemorynucIndel2Block2withbandingTo[0] = ((iTransition[21])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ CurStateMemorynucIndel2Block2withbandingTo[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ CurStateMemorynucIndel2Block2withbandingTo[2] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ CurStateMemorynucIndel2Block2withbandingTo[4] = ((iTransition[18])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[0] += ((iTransition[20])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[1] += ((iTransition[14])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ CurStateMemorynucIndel2Block2withbandingTo[4] += ((iTransition[17])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemorynucIndel2Block3From = dp.StateMemorynucIndel2Block3.read();
+ CurStateMemorynucIndel2Block2withbandingTo[3] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2withbandingTo[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2withbandingTo[2] += ((iTransition[13])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2withbandingTo[1] += ((iTransition[16])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ CurStateMemorynucIndel2Block2withbandingTo[4] += ((iTransition[19])*(iEmission[0]))*CurStateMemorynucIndel2Block3From[0];
+ }
+ dp.StateMemorynucIndel2Block2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucIndel2Block1To = dp.StateMemorynucIndel2Block1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[0];
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[2])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[2];
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[4];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucIndel2Block2withbandingFrom = dp.StateMemorynucIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucIndel2Block1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemorynucIndel2Block2withbandingFrom[3];
+ }
+ dp.StateMemorynucIndel2Block1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucIndel2Block1From = dp.StateMemorynucIndel2Block1.read();
+ iTempProb[0] = CurStateMemorynucIndel2Block1From[0];
+ }
+ }
+ *ppOutTable = new NucleotideIndel2AlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/nucleotide_indel2dp.h b/src/fsa/nucleotide_indel2dp.h
new file mode 100644
index 0000000..9a771ca
--- /dev/null
+++ b/src/fsa/nucleotide_indel2dp.h
@@ -0,0 +1,315 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file nucleotide_indel2.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:17 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _nucleotide_indel2dp_h_
+#define _nucleotide_indel2dp_h_
+
+
+#include "dptables.h"
+#include "algebras.h"
+#include <string>
+
+#include <map>
+
+using std::map;
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesnucIndel2Block2;
+typedef States<bfloat,1> StatesnucIndel2Block1;
+typedef States<bfloat,1> StatesnucIndel2Block3;
+
+class NucleotideIndel2AlignDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesnucIndel2Block2,2> StateMemorynucIndel2Block2;
+ DPTable<StatesnucIndel2Block1,0> StateMemorynucIndel2Block1;
+ DPTable<StatesnucIndel2Block3,0> StateMemorynucIndel2Block3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideIndel2AlignDPTable(int iLen1,int iLen2);
+ ~NucleotideIndel2AlignDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat NucleotideIndel2AlignReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double NucleotideIndel2AlignShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesnucIndel2Block2;
+typedef States<bfloat,1> StatesnucIndel2Block3;
+typedef States<bfloat,1> StatesnucIndel2Block1;
+
+class NucleotideIndel2AlignFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesnucIndel2Block2,2> StateMemorynucIndel2Block2;
+ DPTable<StatesnucIndel2Block3,0> StateMemorynucIndel2Block3;
+ DPTable<StatesnucIndel2Block1,0> StateMemorynucIndel2Block1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideIndel2AlignFoldedDPTable(int iLen1,int iLen2);
+ ~NucleotideIndel2AlignFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class NucleotideIndel2AlignBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ NucleotideIndel2AlignBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[23];
+ static int transitionIdentifier00[23];
+ static const int transitionDimension00 = 23;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[4][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[4][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[4][4][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[23];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesnucIndel2Block2withbanding;
+typedef States<bfloat,1> StatesnucIndel2Block1;
+typedef States<bfloat,1> StatesnucIndel2Block3;
+
+class NucleotideIndel2AlignWithBandingDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesnucIndel2Block2withbanding,2> StateMemorynucIndel2Block2withbanding;
+ DPTable<StatesnucIndel2Block1,0> StateMemorynucIndel2Block1;
+ DPTable<StatesnucIndel2Block3,0> StateMemorynucIndel2Block3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideIndel2AlignWithBandingDPTable(int iLen1,int iLen2);
+ ~NucleotideIndel2AlignWithBandingDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat NucleotideIndel2AlignWithBandingReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double NucleotideIndel2AlignWithBandingShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,5> StatesnucIndel2Block2withbanding;
+typedef States<bfloat,1> StatesnucIndel2Block3;
+typedef States<bfloat,1> StatesnucIndel2Block1;
+
+class NucleotideIndel2AlignWithBandingFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesnucIndel2Block2withbanding,2> StateMemorynucIndel2Block2withbanding;
+ DPTable<StatesnucIndel2Block3,0> StateMemorynucIndel2Block3;
+ DPTable<StatesnucIndel2Block1,0> StateMemorynucIndel2Block1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideIndel2AlignWithBandingFoldedDPTable(int iLen1,int iLen2);
+ ~NucleotideIndel2AlignWithBandingFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class NucleotideIndel2AlignWithBandingBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ NucleotideIndel2AlignWithBandingBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[23];
+ static int transitionIdentifier00[23];
+ static const int transitionDimension00 = 23;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[4][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[4][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[4][4][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[23];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+bfloat Forward(NucleotideIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat BackwardBaumWelch(NucleotideIndel2AlignBaumWelch& bw,NucleotideIndel2AlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat Backward(NucleotideIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat ForwardBanding(NucleotideIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBaumWelchBanding(NucleotideIndel2AlignWithBandingBaumWelch& bw,NucleotideIndel2AlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBanding(NucleotideIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+#endif // _nucleotide_indel2dp_h_
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/nucleotidedp.cc b/src/fsa/nucleotidedp.cc
new file mode 100644
index 0000000..5b1ff4c
--- /dev/null
+++ b/src/fsa/nucleotidedp.cc
@@ -0,0 +1,2013 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file nucleotide.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:16 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "nucleotidedp.h"
+
+#include "mybanding.h"
+
+const extern string _NucleotideAlignstateId[];
+const extern string _NucleotideAlignemissionId[];
+const extern string _NucleotideAligntransitionId[];
+const extern string _NucleotideAligntransF[];
+const extern string _NucleotideAligntransT[];
+const extern string _NucleotideAligntransP[];
+const extern string _NucleotideAligntransE[];
+const extern string _NucleotideAlignoutputId[];
+const extern string _NucleotideAlignempty;
+const extern int _NucleotideAlignstateNum;
+const extern int _NucleotideAlignemitNum;
+const extern int _NucleotideAligntransNum;
+const extern int _NucleotideAlignoutputNum;
+
+NucleotideAlignDPTable::NucleotideAlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignstateId), emissionId(_NucleotideAlignemissionId), transitionId(_NucleotideAligntransitionId), transitionFrom(_NucleotideAligntransF), transitionTo(_NucleotideAligntransT), transitionProb(_NucleotideAligntransP), transitionEmit(_NucleotideAligntransE), outputId(_NucleotideAlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucBlock2.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucBlock1.allocate();
+ StateMemorynucBlock3.allocate();
+}
+
+
+NucleotideAlignDPTable::~NucleotideAlignDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucBlock2.absolve();
+ StateMemorynucBlock1.absolve();
+ StateMemorynucBlock3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideAlignDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAligntransNum ? _NucleotideAligntransitionId[id] : _NucleotideAlignempty; }
+const string& NucleotideAlignDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignemitNum ? _NucleotideAlignemissionId[id] : _NucleotideAlignempty; }
+const string& NucleotideAlignDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignstateNum ? _NucleotideAlignstateId[id] : _NucleotideAlignempty; }
+const string& NucleotideAlignDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignoutputNum ? _NucleotideAlignoutputId[id] : _NucleotideAlignempty; }
+int NucleotideAlignDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideAlignstateNum;i++) {
+ (*pmId)[_NucleotideAlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideAlignemitNum; i++) {
+ (*pmId)[_NucleotideAlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideAligntransNum; i++) {
+ (*pmId)[_NucleotideAligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideAlignoutputNum; i++) {
+ (*pmId)[_NucleotideAlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideAlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideAlignDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideAlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucBlock1Secondary;
+ const bfloat *CurStateMemorynucBlock2Secondary;
+ const bfloat *CurStateMemorynucBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
+ return CurStateMemorynucBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock2Secondary = this->StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucBlock2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
+ return CurStateMemorynucBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _NucleotideAlignstateId[];
+const extern string _NucleotideAlignemissionId[];
+const extern string _NucleotideAligntransitionId[];
+const extern string _NucleotideAligntransF[];
+const extern string _NucleotideAligntransT[];
+const extern string _NucleotideAligntransP[];
+const extern string _NucleotideAligntransE[];
+const extern string _NucleotideAlignoutputId[];
+const extern string _NucleotideAlignempty;
+const extern int _NucleotideAlignstateNum;
+const extern int _NucleotideAlignemitNum;
+const extern int _NucleotideAligntransNum;
+const extern int _NucleotideAlignoutputNum;
+
+NucleotideAlignFoldedDPTable::NucleotideAlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignstateId), emissionId(_NucleotideAlignemissionId), transitionId(_NucleotideAligntransitionId), transitionFrom(_NucleotideAligntransF), transitionTo(_NucleotideAligntransT), transitionProb(_NucleotideAligntransP), transitionEmit(_NucleotideAligntransE), outputId(_NucleotideAlignoutputId) {
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucBlock2.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucBlock3.allocate();
+ StateMemorynucBlock1.allocate();
+}
+
+
+NucleotideAlignFoldedDPTable::~NucleotideAlignFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucBlock2.absolve();
+ StateMemorynucBlock3.absolve();
+ StateMemorynucBlock1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideAlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAligntransNum ? _NucleotideAligntransitionId[id] : _NucleotideAlignempty; }
+const string& NucleotideAlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignemitNum ? _NucleotideAlignemissionId[id] : _NucleotideAlignempty; }
+const string& NucleotideAlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignstateNum ? _NucleotideAlignstateId[id] : _NucleotideAlignempty; }
+const string& NucleotideAlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignoutputNum ? _NucleotideAlignoutputId[id] : _NucleotideAlignempty; }
+int NucleotideAlignFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideAlignstateNum;i++) {
+ (*pmId)[_NucleotideAlignstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideAlignemitNum; i++) {
+ (*pmId)[_NucleotideAlignemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideAligntransNum; i++) {
+ (*pmId)[_NucleotideAligntransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideAlignoutputNum; i++) {
+ (*pmId)[_NucleotideAlignoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideAlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideAlignFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideAlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucBlock1Secondary;
+ const bfloat *CurStateMemorynucBlock2Secondary;
+ const bfloat *CurStateMemorynucBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
+ return CurStateMemorynucBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock2Secondary = this->StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucBlock2Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
+ return CurStateMemorynucBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int NucleotideAlignBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideAlignBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int NucleotideAlignBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideAlignBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void NucleotideAlignBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ for (int i=0; i<13; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_NucleotideAligntransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int NucleotideAlignBaumWelch::transitionIdentifier00[];
+int NucleotideAlignBaumWelch::emissionIdentifier00[];
+int NucleotideAlignBaumWelch::emissionIdentifier01[];
+int NucleotideAlignBaumWelch::emissionIdentifier10[];
+int NucleotideAlignBaumWelch::emissionIdentifier11[];
+
+void NucleotideAlignBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> NucleotideAlignBaumWelch::mId;
+int NucleotideAlignBaumWelch::atransitionIdx[];
+int NucleotideAlignBaumWelch::aemissionIdx[];
+
+const extern string _NucleotideAlignWithBandingstateId[];
+const extern string _NucleotideAlignWithBandingemissionId[];
+const extern string _NucleotideAlignWithBandingtransitionId[];
+const extern string _NucleotideAlignWithBandingtransF[];
+const extern string _NucleotideAlignWithBandingtransT[];
+const extern string _NucleotideAlignWithBandingtransP[];
+const extern string _NucleotideAlignWithBandingtransE[];
+const extern string _NucleotideAlignWithBandingoutputId[];
+const extern string _NucleotideAlignWithBandingempty;
+const extern int _NucleotideAlignWithBandingstateNum;
+const extern int _NucleotideAlignWithBandingemitNum;
+const extern int _NucleotideAlignWithBandingtransNum;
+const extern int _NucleotideAlignWithBandingoutputNum;
+
+NucleotideAlignWithBandingDPTable::NucleotideAlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignWithBandingstateId), emissionId(_NucleotideAlignWithBandingemissionId), transitionId(_NucleotideAlignWithBandingtransitionId), transitionFrom(_NucleotideAlignWithBandingtransF), transitionTo(_NucleotideAlignWithBandingtransT), transitionProb(_NucleotideAlignWithBandingtransP), transitionEmit(_NucleotideAlignWithBandingtransE), outputId(_NucleotideAlignWith [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucBlock2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucBlock1.allocate();
+ StateMemorynucBlock3.allocate();
+}
+
+
+NucleotideAlignWithBandingDPTable::~NucleotideAlignWithBandingDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucBlock2withbanding.absolve();
+ StateMemorynucBlock1.absolve();
+ StateMemorynucBlock3.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideAlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingtransNum ? _NucleotideAlignWithBandingtransitionId[id] : _NucleotideAlignWithBandingempty; }
+const string& NucleotideAlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingemitNum ? _NucleotideAlignWithBandingemissionId[id] : _NucleotideAlignWithBandingempty; }
+const string& NucleotideAlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignWithBandingstateNum ? _NucleotideAlignWithBandingstateId[id] : _NucleotideAlignWithBandingempty; }
+const string& NucleotideAlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignWithBandingoutputNum ? _NucleotideAlignWithBandingoutputId[id] : _NucleotideAlignWithBandingempty; }
+int NucleotideAlignWithBandingDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideAlignWithBandingstateNum;i++) {
+ (*pmId)[_NucleotideAlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideAlignWithBandingemitNum; i++) {
+ (*pmId)[_NucleotideAlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideAlignWithBandingtransNum; i++) {
+ (*pmId)[_NucleotideAlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideAlignWithBandingoutputNum; i++) {
+ (*pmId)[_NucleotideAlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideAlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideAlignWithBandingDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideAlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucBlock1Secondary;
+ const bfloat *CurStateMemorynucBlock2withbandingSecondary;
+ const bfloat *CurStateMemorynucBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
+ return CurStateMemorynucBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingSecondary = this->StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucBlock2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
+ return CurStateMemorynucBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+const extern string _NucleotideAlignWithBandingstateId[];
+const extern string _NucleotideAlignWithBandingemissionId[];
+const extern string _NucleotideAlignWithBandingtransitionId[];
+const extern string _NucleotideAlignWithBandingtransF[];
+const extern string _NucleotideAlignWithBandingtransT[];
+const extern string _NucleotideAlignWithBandingtransP[];
+const extern string _NucleotideAlignWithBandingtransE[];
+const extern string _NucleotideAlignWithBandingoutputId[];
+const extern string _NucleotideAlignWithBandingempty;
+const extern int _NucleotideAlignWithBandingstateNum;
+const extern int _NucleotideAlignWithBandingemitNum;
+const extern int _NucleotideAlignWithBandingtransNum;
+const extern int _NucleotideAlignWithBandingoutputNum;
+
+NucleotideAlignWithBandingFoldedDPTable::NucleotideAlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignWithBandingstateId), emissionId(_NucleotideAlignWithBandingemissionId), transitionId(_NucleotideAlignWithBandingtransitionId), transitionFrom(_NucleotideAlignWithBandingtransF), transitionTo(_NucleotideAlignWithBandingtransT), transitionProb(_NucleotideAlignWithBandingtransP), transitionEmit(_NucleotideAlignWithBandingtransE), outputId(_Nucleot [...]
+ // init code:
+ this->iLen1 = iLen1;
+ this->iLen2 = iLen2;
+ StateMemorynucBlock2withbanding.allocate(1+iLen1, 1+iLen2);
+ StateMemorynucBlock3.allocate();
+ StateMemorynucBlock1.allocate();
+}
+
+
+NucleotideAlignWithBandingFoldedDPTable::~NucleotideAlignWithBandingFoldedDPTable() {
+ if (!isInCharge) {
+ // make sure data does not get deleted:
+ StateMemorynucBlock2withbanding.absolve();
+ StateMemorynucBlock3.absolve();
+ StateMemorynucBlock1.absolve();
+ } // if(!isInCharge)
+} // destructor
+
+const string& NucleotideAlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingtransNum ? _NucleotideAlignWithBandingtransitionId[id] : _NucleotideAlignWithBandingempty; }
+const string& NucleotideAlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingemitNum ? _NucleotideAlignWithBandingemissionId[id] : _NucleotideAlignWithBandingempty; }
+const string& NucleotideAlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignWithBandingstateNum ? _NucleotideAlignWithBandingstateId[id] : _NucleotideAlignWithBandingempty; }
+const string& NucleotideAlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignWithBandingoutputNum ? _NucleotideAlignWithBandingoutputId[id] : _NucleotideAlignWithBandingempty; }
+int NucleotideAlignWithBandingFoldedDPTable::getId(const string& sId)
+{
+ static bool bInit = false;
+ static map<string,int>* pmId;
+ if (!bInit) {
+ pmId = new map<string,int>();
+ for (int i=0;i<_NucleotideAlignWithBandingstateNum;i++) {
+ (*pmId)[_NucleotideAlignWithBandingstateId[i]] = i; // add state identifiers
+ }
+ for (int i=0; i<_NucleotideAlignWithBandingemitNum; i++) {
+ (*pmId)[_NucleotideAlignWithBandingemissionId[i]] = i; // add emission identifiers
+ }
+ for (int i=0; i<_NucleotideAlignWithBandingtransNum; i++) {
+ (*pmId)[_NucleotideAlignWithBandingtransitionId[i]] = i; // add transition identifiers
+ }
+ for (int i=0; i<_NucleotideAlignWithBandingoutputNum; i++) {
+ (*pmId)[_NucleotideAlignWithBandingoutputId[i]] = i; // finally, add output identifiers
+ }
+ bInit = true;
+ }
+ map<string,int>::iterator iter = pmId->find(sId);
+ if (iter == pmId->end()) {
+ if (sId == "_cleanup_") {
+ delete pmId;
+ } else {
+ cout << "NucleotideAlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
+ }
+ return -1;
+ }
+ return iter->second;
+}
+
+
+bfloat NucleotideAlignWithBandingFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
+{
+ return getProb(getId(sState) ,iPos0,iPos1);
+}
+
+
+bfloat NucleotideAlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
+{
+ const bfloat *CurStateMemorynucBlock1Secondary;
+ const bfloat *CurStateMemorynucBlock2withbandingSecondary;
+ const bfloat *CurStateMemorynucBlock3Secondary;
+ static const int blockTable[] = {0, 1, 1, 1, 2};
+ static const int stateTable[] = {0, 0, 1, 2, 0};
+ switch (blockTable[iState]) {
+ default:
+ return 0.0;
+ break;
+ case 0:
+ if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
+ return CurStateMemorynucBlock1Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 1:
+ if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingSecondary = this->StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ return CurStateMemorynucBlock2withbandingSecondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ break;
+ case 2:
+ if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
+ CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
+ return CurStateMemorynucBlock3Secondary[stateTable[iState]];
+ }
+ else {
+ return 0.0;
+
+ }
+ } // switch
+} // DPTable...::getProb(int,...)
+
+int NucleotideAlignWithBandingBaumWelch::transitionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideAlignWithBandingBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+int NucleotideAlignWithBandingBaumWelch::emissionIndex(string strId) const {
+ map<const string,int>::const_iterator iter = mId.find(strId);
+ if (iter == mId.end()) {
+ cout << "NucleotideAlignWithBandingBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
+ return -1;
+ }
+ return iter->second;
+}
+
+
+void NucleotideAlignWithBandingBaumWelch::resetCounts() {
+ static bool bInited = false;
+ if (!bInited) {
+ static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ for (int i=0; i<13; i++) {
+ transitionIdentifier00[i] = aTemp[i];
+ atransitionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignWithBandingtransitionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {2};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier00[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {1};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier01[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {3};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier10[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] = 0.0;
+ }
+ if (!bInited) {
+ static const int aTemp[] = {0};
+ for (int i=0; i<1; i++) {
+ emissionIdentifier11[i] = aTemp[i];
+ aemissionIdx[aTemp[i]] = i;
+ mId[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
+ }
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] = 0.0;
+ }
+ bInited = true;
+};
+
+
+int NucleotideAlignWithBandingBaumWelch::transitionIdentifier00[];
+int NucleotideAlignWithBandingBaumWelch::emissionIdentifier00[];
+int NucleotideAlignWithBandingBaumWelch::emissionIdentifier01[];
+int NucleotideAlignWithBandingBaumWelch::emissionIdentifier10[];
+int NucleotideAlignWithBandingBaumWelch::emissionIdentifier11[];
+
+void NucleotideAlignWithBandingBaumWelch::scaleCounts(bfloat scale) {
+ for (int i=0; i<13; i++) {
+
+ transitionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+
+ emissionBaumWelchCount00[i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount01[v10][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)
+ emissionBaumWelchCount10[v00][i] *= scale;
+ }
+ for (int i=0; i<1; i++) {
+ for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
+ emissionBaumWelchCount11[v00][v10][i] *= scale;
+ }
+}
+
+
+map<const string,int> NucleotideAlignWithBandingBaumWelch::mId;
+int NucleotideAlignWithBandingBaumWelch::atransitionIdx[];
+int NucleotideAlignWithBandingBaumWelch::aemissionIdx[];
+
+const string _NucleotideAlignstateId[] = {"start","insert1","match","delete1","end"};
+const string _NucleotideAlignemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _NucleotideAligntransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
+const string _NucleotideAligntransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
+const string _NucleotideAligntransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
+const string _NucleotideAligntransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
+const string _NucleotideAligntransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _NucleotideAlignoutputId[] = {"sequence1","sequence2"};
+const string _NucleotideAlignempty = "";
+const int _NucleotideAlignstateNum = 5;
+const int _NucleotideAlignemitNum = 4;
+const int _NucleotideAligntransNum = 13;
+const int _NucleotideAlignoutputNum = 2;
+
+
+
+
+bfloat Forward(NucleotideAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemorynucBlock2To;
+ const bfloat *CurStateMemorynucBlock1From;
+ const bfloat *CurStateMemorynucBlock2From;
+ bfloat *CurStateMemorynucBlock3To;
+ const bfloat *CurStateMemorynucBlock3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideAlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemorynucBlock1.write()[0] = 1.0;
+ dp.StateMemorynucBlock1.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=0; iPos1<iLen2+1; ++iPos1) {
+ for (int iPos0=0; iPos0<iLen1+1; ++iPos0) {
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ }
+ if (1) {
+ if ((iPos1+-1>=0)) {
+ iSymbol[0] = iSequence2[iPos1+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+-1>=0)) {
+ iSymbol[1] = iSequence1[iPos0+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock2To = dp.StateMemorynucBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+0<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ CurStateMemorynucBlock2To[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
+ }
+ if ((iPos1+-1>=0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
+ CurStateMemorynucBlock2To[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ CurStateMemorynucBlock2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ CurStateMemorynucBlock2To[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
+ }
+ if ((iPos0+-1>=0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock2To[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ CurStateMemorynucBlock2To[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ CurStateMemorynucBlock2To[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
+ }
+ if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
+ CurStateMemorynucBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ CurStateMemorynucBlock2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ CurStateMemorynucBlock2To[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ }
+ dp.StateMemorynucBlock2.written();
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemorynucBlock3To = dp.StateMemorynucBlock3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock3To[0] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ CurStateMemorynucBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ CurStateMemorynucBlock3To[0] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ }
+ dp.StateMemorynucBlock3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
+ iTempProb[0] = CurStateMemorynucBlock3From[0];
+ }
+ }
+ *ppOutTable = new NucleotideAlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelch(NucleotideAlignBaumWelch& bw,NucleotideAlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ const bfloat *CurStateMemorynucBlock3Secondary;
+ bfloat iTransition[13];
+ bfloat *CurStateMemorynucBlock2To;
+ const bfloat *CurStateMemorynucBlock2Secondary;
+ const bfloat *CurStateMemorynucBlock2From;
+ unsigned char alphaSymbolnucleotide[4] = {'A', 'C', 'G', 'T'};
+ unsigned char alphaIndexnucleotide[256];
+ const bfloat *CurStateMemorynucBlock3From;
+ bfloat *CurStateMemorynucBlock1To;
+ const bfloat *CurStateMemorynucBlock1Secondary;
+ const bfloat *CurStateMemorynucBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ NucleotideAlignFoldedDPTable dp(iLen1,2);
+ NucleotideAlignDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexnucleotide[i]=0;
+ }
+
+// for (int i=0; i<4; i++) {
+// alphaIndexnucleotide[alphaSymbolnucleotide[i]]=i;
+// }
+ for (int i=0; i<4; i++) {
+ alphaIndexnucleotide[tolower (alphaSymbolnucleotide[i])] = i;
+ alphaIndexnucleotide[toupper (alphaSymbolnucleotide[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemorynucBlock3.write()[0] = 1.0;
+ dp.StateMemorynucBlock3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock3Secondary = dp2.StateMemorynucBlock3.read();
+ iTempProb[2] = CurStateMemorynucBlock3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != iPos1) {
+ dp.StateMemorynucBlock2.clear(iPos1);
+ }
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock2To = dp.StateMemorynucBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock2Secondary = dp2.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock2To[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2To[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock2To[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[0];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2To[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock2To[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[2];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2To[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[0];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2To[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
+ CurStateMemorynucBlock2To[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucBlock2To[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[0];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucBlock2To[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemorynucBlock2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
+ CurStateMemorynucBlock1Secondary = dp2.StateMemorynucBlock1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemorynucBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ iTempProb[0] = CurStateMemorynucBlock1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat Backward(NucleotideAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemorynucBlock2To;
+ const bfloat *CurStateMemorynucBlock2From;
+ const bfloat *CurStateMemorynucBlock3From;
+ bfloat *CurStateMemorynucBlock1To;
+ const bfloat *CurStateMemorynucBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideAlignDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemorynucBlock3.write()[0] = 1.0;
+ dp.StateMemorynucBlock3.written();
+ iPrevSlowCoord = -1;
+ for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
+ for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ }
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock2To = dp.StateMemorynucBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock2To[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ CurStateMemorynucBlock2To[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock2To[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ CurStateMemorynucBlock2To[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock2To[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ CurStateMemorynucBlock2To[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ CurStateMemorynucBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ }
+ iEmission[0] = 1.0;
+ if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
+ CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
+ CurStateMemorynucBlock2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ CurStateMemorynucBlock2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ CurStateMemorynucBlock2To[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ }
+ dp.StateMemorynucBlock2.written();
+ }
+ if ((iPos0+0<=0)&&(iPos1+0<=0)) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
+ }
+ dp.StateMemorynucBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ iTempProb[0] = CurStateMemorynucBlock1From[0];
+ }
+ }
+ *ppOutTable = new NucleotideAlignDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+const string _NucleotideAlignWithBandingstateId[] = {"start","insert1","match","delete1","end"};
+const string _NucleotideAlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
+const string _NucleotideAlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
+const string _NucleotideAlignWithBandingtransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
+const string _NucleotideAlignWithBandingtransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
+const string _NucleotideAlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
+const string _NucleotideAlignWithBandingtransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
+const string _NucleotideAlignWithBandingoutputId[] = {"sequence1","sequence2"};
+const string _NucleotideAlignWithBandingempty = "";
+const int _NucleotideAlignWithBandingstateNum = 5;
+const int _NucleotideAlignWithBandingemitNum = 4;
+const int _NucleotideAlignWithBandingtransNum = 13;
+const int _NucleotideAlignWithBandingoutputNum = 2;
+
+
+
+
+bfloat ForwardBanding(NucleotideAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemorynucBlock2withbandingTo;
+ const bfloat *CurStateMemorynucBlock1From;
+ const bfloat *CurStateMemorynucBlock2withbandingFrom;
+ bfloat *CurStateMemorynucBlock3To;
+ const bfloat *CurStateMemorynucBlock3From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideAlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemorynucBlock1.write()[0] = 1.0;
+ dp.StateMemorynucBlock1.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.forwardIterator();
+ bool bLastSlowCoordInited = false;
+ int iLastSlowCoord = -1;
+ do {
+ if (bLastSlowCoordInited) {
+ if (iLastSlowCoord > position[1]) {
+ cout << "WARNING: Banding (forward): Slowest coordinate should be nondecreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ } else {
+ bLastSlowCoordInited = true;
+ }
+ iLastSlowCoord = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+-1>=0)) {
+ iSymbol[0] = iSequence2[position[1]+-1];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+-1>=0)) {
+ iSymbol[1] = iSequence1[position[0]+-1];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock2withbandingTo = dp.StateMemorynucBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+0<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ CurStateMemorynucBlock2withbandingTo[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
+ }
+ if ((position[1]+-1>=0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
+ CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ CurStateMemorynucBlock2withbandingTo[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
+ }
+ if ((position[0]+-1>=0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ CurStateMemorynucBlock2withbandingTo[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
+ }
+ if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
+ CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ }
+ dp.StateMemorynucBlock2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextForward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ CurStateMemorynucBlock3To = dp.StateMemorynucBlock3.write();
+ iEmission[0] = 1.0;
+ if (1) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock3To[0] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ CurStateMemorynucBlock3To[0] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ CurStateMemorynucBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ }
+ dp.StateMemorynucBlock3.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
+ iTempProb[0] = CurStateMemorynucBlock3From[0];
+ }
+ }
+ *ppOutTable = new NucleotideAlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBaumWelchBanding(NucleotideAlignWithBandingBaumWelch& bw,NucleotideAlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ const bfloat *CurStateMemorynucBlock3Secondary;
+ bfloat iTransition[13];
+ bfloat *CurStateMemorynucBlock2withbandingTo;
+ const bfloat *CurStateMemorynucBlock2withbandingSecondary;
+ const bfloat *CurStateMemorynucBlock2withbandingFrom;
+ unsigned char alphaSymbolnucleotide[4] = {'A', 'C', 'G', 'T'};
+ unsigned char alphaIndexnucleotide[256];
+ const bfloat *CurStateMemorynucBlock3From;
+ bfloat *CurStateMemorynucBlock1To;
+ const bfloat *CurStateMemorynucBlock1Secondary;
+ const bfloat *CurStateMemorynucBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[3];
+ NucleotideAlignWithBandingFoldedDPTable dp(iLen1,2);
+ NucleotideAlignWithBandingDPTable dp2(*pInTable);
+ // make sure tables don't get deleted
+ dp2.isInCharge = false;
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ for (int i=0; i<256; i++) {
+ alphaIndexnucleotide[i]=0;
+ }
+
+// for (int i=0; i<4; i++) {
+// alphaIndexnucleotide[alphaSymbolnucleotide[i]]=i;
+// }
+ for (int i=0; i<4; i++) {
+ alphaIndexnucleotide[tolower (alphaSymbolnucleotide[i])] = i;
+ alphaIndexnucleotide[toupper (alphaSymbolnucleotide[i])] = i;
+ }
+ // treat lower and upper-case characters as equivalent during Baum-Welch
+ // -- RKB
+
+ dp.StateMemorynucBlock3.write()[0] = 1.0;
+ dp.StateMemorynucBlock3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock3Secondary = dp2.StateMemorynucBlock3.read();
+ iTempProb[2] = CurStateMemorynucBlock3Secondary[0];
+ bw.scaleCounts(iTempProb[2]);
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (iPrevSlowCoord != -1 && iPrevSlowCoord != position[1]) {
+ dp.StateMemorynucBlock2withbanding.clear(position[1]);
+ }
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock2withbandingTo = dp.StateMemorynucBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucBlock2withbandingSecondary = dp2.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucBlock2withbandingTo[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[11] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2withbandingTo[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[5] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[4] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2withbandingTo[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[8] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[10] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[3] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ CurStateMemorynucBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[7] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
+ CurStateMemorynucBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[2];
+ bw.transitionBaumWelchCount00[12] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
+ bw.transitionBaumWelchCount00[6] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ CurStateMemorynucBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[0];
+ bw.transitionBaumWelchCount00[9] += iTempProb[1];
+ bw.emissionBaumWelchCount00[0] += iTempProb[1];
+ }
+ dp.StateMemorynucBlock2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
+ CurStateMemorynucBlock1Secondary = dp2.StateMemorynucBlock1.read();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[2] += iTempProb[1];
+ bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[1] += iTempProb[1];
+ bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
+ bw.transitionBaumWelchCount00[0] += iTempProb[1];
+ bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
+ }
+ dp.StateMemorynucBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ bw.scaleCounts(1.0 / iTempProb[2]);
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ iTempProb[0] = CurStateMemorynucBlock1From[0];
+ }
+ }
+ return iTempProb[0];
+};
+
+
+
+
+
+bfloat BackwardBanding(NucleotideAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
+ bfloat iTransition[13];
+ bfloat *CurStateMemorynucBlock2withbandingTo;
+ const bfloat *CurStateMemorynucBlock2withbandingFrom;
+ const bfloat *CurStateMemorynucBlock3From;
+ bfloat *CurStateMemorynucBlock1To;
+ const bfloat *CurStateMemorynucBlock1From;
+ int iPrevSlowCoord;
+ int iLen1 = iSequence1.size(); // The sequence lengths are not passed as parameters, but are
+ int iLen2 = iSequence2.size(); // computed from the vector<char> itself
+
+ // indexing for emission probs
+ unsigned char iTranslate[256];
+ for (int i=0; i<256; i++) {
+ iTranslate[i]= 0;
+ }
+ iTranslate[(unsigned)'A'] = 0; // It is important that this is in alphabetical order, to
+ iTranslate[(unsigned)'a'] = 0; // make the indices correspond to those used for Baum-Welch
+ iTranslate[(unsigned)'C'] = 1;
+ iTranslate[(unsigned)'c'] = 1;
+ iTranslate[(unsigned)'G'] = 2;
+ iTranslate[(unsigned)'g'] = 2;
+ iTranslate[(unsigned)'T'] = 3;
+ iTranslate[(unsigned)'t'] = 3;
+ MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
+ int iSymbol[2];
+ if (false && iSymbol[0] == iSymbol[0]) {} // avoid 'unused variable' warnings
+ bfloat iEmission[1];
+ /* temporary storage for ordinary reals */
+ register double iTempResult[1];
+ /* temporary storage for extended-exponent reals */
+ register bfloat iTempProb[1];
+ NucleotideAlignWithBandingDPTable dp(iLen1,iLen2);
+ iTransition[0] = iT[0][1];
+
+ iTransition[1] = iT[0][2];
+
+ iTransition[2] = iT[0][3];
+
+ iTransition[3] = iT[1][1];
+
+ iTransition[4] = iT[1][2];
+
+ iTransition[5] = iT[1][3];
+
+ iTransition[6] = iT[1][6];
+
+ iTransition[7] = iT[2][1];
+
+ iTransition[8] = iT[2][2];
+
+ iTransition[9] = iT[2][6];
+
+ iTransition[10] = iT[3][1];
+
+ iTransition[11] = iT[3][3];
+
+ iTransition[12] = iT[3][6];
+ dp.StateMemorynucBlock3.write()[0] = 1.0;
+ dp.StateMemorynucBlock3.written();
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=iLen2+0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=iLen1+0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ }
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ Banding<2>::Position& position = bandingInstance.backwardIterator();
+ int iCheckSlowCoordTraversal = -1;
+ do {
+ if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
+ cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing. Perhaps forgot to specify speed of output coordinates?" << endl;
+ }
+ iCheckSlowCoordTraversal = position[1];
+ if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
+ if (1) {
+ if ((position[1]+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[position[1]+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((position[0]+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[position[0]+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock2withbandingTo = dp.StateMemorynucBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[1]+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucBlock2withbandingTo[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ CurStateMemorynucBlock2withbandingTo[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
+ CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ CurStateMemorynucBlock2withbandingTo[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
+ CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ }
+ iEmission[0] = 1.0;
+ if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
+ CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
+ CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
+ }
+ dp.StateMemorynucBlock2withbanding.written();
+ }
+ iPrevSlowCoord = position[1];
+ }
+ else {
+ bandingInstance.warning();
+
+ }
+ } while (bandingInstance.hasNextBackward());
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ if (1) {
+ if ((iPos1+0<=iLen2+-1)) {
+ iSymbol[0] = iSequence2[iPos1+0];
+ }
+ else {
+ iSymbol[0] = 'A' /* dummy value */;
+
+ }
+ if ((iPos0+0<=iLen1+-1)) {
+ iSymbol[1] = iSequence1[iPos0+0];
+ }
+ else {
+ iSymbol[1] = 'A' /* dummy value */;
+
+ }
+ CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
+ }
+ iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
+ CurStateMemorynucBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
+ }
+ iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
+ iEmission[0] = iTempResult[0];
+ if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
+ CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
+ CurStateMemorynucBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
+ }
+ dp.StateMemorynucBlock1.written();
+ }
+ iPrevSlowCoord = iPos1;
+ }
+ }
+ iPrevSlowCoord = -1;
+ {
+ int iPos1=0;
+ if (iPos1==iPos1) {} // avoid 'unused variable' warnings
+ {
+ int iPos0=0;
+ if (iPos0==iPos0) {} // avoid 'unused variable' warnings
+ CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
+ iTempProb[0] = CurStateMemorynucBlock1From[0];
+ }
+ }
+ *ppOutTable = new NucleotideAlignWithBandingDPTable(dp);
+ // make sure tables don't get deleted
+ dp.isInCharge = false;
+ return iTempProb[0];
+};
+
+
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/nucleotidedp.h b/src/fsa/nucleotidedp.h
new file mode 100644
index 0000000..628b35f
--- /dev/null
+++ b/src/fsa/nucleotidedp.h
@@ -0,0 +1,315 @@
+/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
+/* Generated from file nucleotide.xml (author: Robert K. Bradley ) on Tue Dec 23 01:04:16 CST 2008 */
+
+/*
+This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
+Copyright (C) 2006 by Gerton Lunter, Oxford University.
+
+HMMoC and works based on it are 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 2 of the License, or (at your option) any later version.
+
+HMMOC 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 HMMoC; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _nucleotidedp_h_
+#define _nucleotidedp_h_
+
+
+#include "dptables.h"
+#include "algebras.h"
+#include <string>
+
+#include <map>
+
+using std::map;
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesnucBlock2;
+typedef States<bfloat,1> StatesnucBlock1;
+typedef States<bfloat,1> StatesnucBlock3;
+
+class NucleotideAlignDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesnucBlock2,2> StateMemorynucBlock2;
+ DPTable<StatesnucBlock1,0> StateMemorynucBlock1;
+ DPTable<StatesnucBlock3,0> StateMemorynucBlock3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideAlignDPTable(int iLen1,int iLen2);
+ ~NucleotideAlignDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat NucleotideAlignReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double NucleotideAlignShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesnucBlock2;
+typedef States<bfloat,1> StatesnucBlock3;
+typedef States<bfloat,1> StatesnucBlock1;
+
+class NucleotideAlignFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesnucBlock2,2> StateMemorynucBlock2;
+ DPTable<StatesnucBlock3,0> StateMemorynucBlock3;
+ DPTable<StatesnucBlock1,0> StateMemorynucBlock1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideAlignFoldedDPTable(int iLen1,int iLen2);
+ ~NucleotideAlignFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class NucleotideAlignBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ NucleotideAlignBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[13];
+ static int transitionIdentifier00[13];
+ static const int transitionDimension00 = 13;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[4][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[4][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[4][4][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[13];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesnucBlock2withbanding;
+typedef States<bfloat,1> StatesnucBlock1;
+typedef States<bfloat,1> StatesnucBlock3;
+
+class NucleotideAlignWithBandingDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ DPTable<StatesnucBlock2withbanding,2> StateMemorynucBlock2withbanding;
+ DPTable<StatesnucBlock1,0> StateMemorynucBlock1;
+ DPTable<StatesnucBlock3,0> StateMemorynucBlock3;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideAlignWithBandingDPTable(int iLen1,int iLen2);
+ ~NucleotideAlignWithBandingDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+// give a name to the real type used for this HMM
+typedef bfloat NucleotideAlignWithBandingReal;
+// define type for a 'short' real -- usually double, but can be logspace for efficiency
+typedef double NucleotideAlignWithBandingShortReal;
+
+
+
+// Here go the state memory clique typedefs:
+typedef States<bfloat,3> StatesnucBlock2withbanding;
+typedef States<bfloat,1> StatesnucBlock3;
+typedef States<bfloat,1> StatesnucBlock1;
+
+class NucleotideAlignWithBandingFoldedDPTable {
+ public:
+ // If true, this class' destructor will delete the DP arrays
+ bool isInCharge;
+ // Pointers to arrays containing ids of states and transitions
+ const string* const stateId;
+ const string* const emissionId;
+ const string* const transitionId;
+ const string* const transitionFrom;
+ const string* const transitionTo;
+ const string* const transitionProb;
+ const string* const transitionEmit;
+ const string* const outputId;
+ // The actual DP tables, and total sequence lengths (which determine size of DP arrays) follow:
+ int iLen1;
+ int iLen2;
+ FoldedTable<DPTable,StatesnucBlock2withbanding,2> StateMemorynucBlock2withbanding;
+ DPTable<StatesnucBlock3,0> StateMemorynucBlock3;
+ DPTable<StatesnucBlock1,0> StateMemorynucBlock1;
+ // Member functions:
+ public:
+ // Default copy constructor is used; user has to set isInCharge appropriately afterwards!
+ NucleotideAlignWithBandingFoldedDPTable(int iLen1,int iLen2);
+ ~NucleotideAlignWithBandingFoldedDPTable();
+ // returns probability from DP table, given position and int or string state identifier
+ bfloat getProb(int iState ,int ,int ) const;
+ bfloat getProb(const string sState ,int ,int ) const;
+ // converts string identifier (for state, transition or emission) into integer id
+ static int getId(const string& sState);
+ static const string& getTransitionId(int id);
+ static const string& getEmissionId(int id);
+ static const string& getStateId(int id);
+ static const string& getOutputId(int id);
+ static void _cleanup() { getId("_cleanup_"); }
+};
+
+
+
+class NucleotideAlignWithBandingBaumWelch {
+ public:
+ // Default copy constructor is used.
+ // Void constructor:
+ NucleotideAlignWithBandingBaumWelch() { resetCounts(); }
+ // Not calling resetCounts() across calls allows to aggregate results over multiple datasets
+ void resetCounts();
+ void scaleCounts(bfloat scale);
+ // Translate an identifier (string or integer) to the index into their corresponding Baum-Welch counter array (below)
+ // Which array is used for any particular emission/transition depends on its order signature - see documentation for details
+ int transitionIndex(int intId) const { return atransitionIdx[intId]; }
+ int transitionIndex(string strId) const;
+ int emissionIndex(int intId) const { return aemissionIdx[intId]; }
+ int emissionIndex(string strId) const;
+ // Now follow, in triplets (one for each order signature):
+ // Transition or emission counters;
+ // Array of identifiers; and
+ // Dimension of array (number of counters).
+ bfloat transitionBaumWelchCount00[13];
+ static int transitionIdentifier00[13];
+ static const int transitionDimension00 = 13;
+ bfloat emissionBaumWelchCount00[1];
+ static int emissionIdentifier00[1];
+ static const int emissionDimension00 = 1;
+ bfloat emissionBaumWelchCount01[4][1];
+ static int emissionIdentifier01[1];
+ static const int emissionDimension01 = 1;
+ bfloat emissionBaumWelchCount10[4][1];
+ static int emissionIdentifier10[1];
+ static const int emissionDimension10 = 1;
+ bfloat emissionBaumWelchCount11[4][4][1];
+ static int emissionIdentifier11[1];
+ static const int emissionDimension11 = 1;
+ private:
+ static int atransitionIdx[13];
+ static int aemissionIdx[4];
+ static map<const string,int> mId;
+};
+
+
+
+bfloat Forward(NucleotideAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat BackwardBaumWelch(NucleotideAlignBaumWelch& bw,NucleotideAlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat Backward(NucleotideAlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT);
+
+bfloat ForwardBanding(NucleotideAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBaumWelchBanding(NucleotideAlignWithBandingBaumWelch& bw,NucleotideAlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+bfloat BackwardBanding(NucleotideAlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth);
+
+#endif // _nucleotidedp_h_
+
+/* --- end of HMMoC-generated file --- */
diff --git a/src/fsa/sequence_pair_selector.cc b/src/fsa/sequence_pair_selector.cc
new file mode 100644
index 0000000..da4f03a
--- /dev/null
+++ b/src/fsa/sequence_pair_selector.cc
@@ -0,0 +1,360 @@
+
+/**
+ * \file sequence_pair_selector.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <queue>
+
+#include "util/logfile.h"
+#include "fsa/sequence_pair_selector.h"
+
+using namespace fsa;
+
+Sequence_pair_selector::Sequence_pair_selector (const Sequence_database& seq_db,
+ const Alphabet& alphabet,
+ const size_t k)
+: __seq_db (seq_db),
+ __k (k),
+ __similarity_matrix (Sequence_similarity_matrix (seq_db,
+ alphabet,
+ k)),
+ __added (std::vector<std::vector<bool> > (seq_db.size(), std::vector<bool> (seq_db.size(), false))),
+ __num_selected (0)
+{
+
+ // log
+ CTAG(9,FSA) << "Computed k-mer similarities (k = " << __k << ") between input sequences." << endl;
+
+ // log similarities if requested
+ if (CTAGGING(-1,KMER)) {
+ CL << "Sequence similarity matrix (k = " << __k << "):" << endl;
+ __similarity_matrix.write (CL);
+ }
+
+}
+
+void Sequence_pair_selector::choose_minimum_spanning_tree (const size_t num_mst,
+ const bool compute_maximum_spanning_tree /* = false */) {
+
+ // iteratively build disjoint minimum spanning trees
+ size_t mst_added = 0;
+ while (mst_added++ < num_mst) {
+
+ // assemble the edge set
+ MST_Kruskal::Edge_set edges;
+ edges.reserve (__seq_db.size() * __seq_db.size());
+ for (size_t i = 0; i < __seq_db.size(); ++i)
+ for (size_t j = i + 1; j < __seq_db.size(); ++j) {
+
+ // don't store previously-added edges
+ if (__added[i][j])
+ continue;
+
+ // convert the k-mer similarity to a weight
+ // (k-mer similarities necessarily fall in the interval [0, 1])
+ double weight;
+
+ // if we're computing a maximum spanning tree,
+ // then store the weight as a similarity,
+ // so that my minimum spanning tree code will
+ // choose edges with the lowest similarity and thereby
+ // build a maximum spanning tree
+ if (compute_maximum_spanning_tree)
+ weight = __similarity_matrix.get_similarity (i, j);
+
+ // else we're computing a minimum spanning tree,
+ // so convert the k-mer similarity to a k-mer distance
+ else
+ weight = 1.0 - __similarity_matrix.get_similarity (i, j);
+
+ // store
+ edges.push_back (MST_Kruskal::Edge (i, j, weight));
+
+ }
+
+ // compute the MST
+ MST_Kruskal::Edge_set mst = MST_Kruskal::compute_mst (edges, __seq_db.size(),
+ false); // die_on_failure = false
+
+ // if no MST exists, then break (we're done)
+ if (!mst.size())
+ break;
+
+ // log MST if requested
+ if (CTAGGING(-1,KMER)) {
+
+ // compute the total k-mer similarity, summed over branches of the tree
+ double total_similarity = 0;
+ for (MST_Kruskal::Edge_set::const_iterator edge = mst.begin(); edge != mst.end(); ++edge)
+ total_similarity += __similarity_matrix.get_similarity (edge->u, edge->v);
+
+ // display
+ if (compute_maximum_spanning_tree)
+ CL << "Maximum spanning tree on sequences (total k-mer similarity = " << total_similarity << "):" << endl;
+ else
+ CL << "Minimum spanning tree on sequences (total k-mer similarity = " << total_similarity << "):" << endl;
+ for (MST_Kruskal::Edge_set::const_iterator edge = mst.begin(); edge != mst.end(); ++edge)
+ CL << __seq_db.get_seq (edge->u).name << " -- " << __seq_db.get_seq (edge->v).name << " => " << __similarity_matrix.get_similarity (edge->u, edge->v) << endl;
+
+ }
+
+ // store the MST
+ for (MST_Kruskal::Edge_set::const_iterator edge = mst.begin(); edge != mst.end(); ++edge) {
+
+ const size_t u = edge->u;
+ const size_t v = edge->v;
+
+ // sanity check
+ assert (u < v);
+ __added[u][v] = true;
+ ++__num_selected;
+
+ }
+
+ }
+
+}
+
+void Sequence_pair_selector::choose_maximum_spanning_tree (const size_t num_mst) {
+
+ choose_minimum_spanning_tree (num_mst,
+ true); // compute_maximum_spanning_tree = true
+
+}
+
+void Sequence_pair_selector::choose_minimum_spanning_palm_tree (const size_t num_mst) {
+
+ // check sane
+ if (num_mst > __seq_db.size())
+ THROWEXPR ("Cannot compute more minimum spanning palm trees than there are sequences.");
+
+ // keep track of which sequences we've used as centers of palm trees
+ // (so that we don't repeat ourselves)
+ std::vector<bool> chosen_centers (__seq_db.size(), false);
+
+ // iteratively build minimum spanning palm trees
+ size_t mst_added = 0;
+ while (mst_added++ < num_mst) {
+
+ // find the sequence at the center of the minimum spanning palm tree
+ size_t best_center = 0;
+ double best_similarity = -1;
+ for (size_t i = 0; i < __seq_db.size(); ++i) {
+
+ // avoid repeats
+ if (chosen_centers[i])
+ continue;
+
+ // calculate the total similarity (summed over all branches)
+ // associated with a palm tree whose center is sequence i
+ double tree_similarity = 0;
+ for (size_t j = 0; j < __seq_db.size(); ++j) {
+
+ if (i == j)
+ continue;
+
+ tree_similarity += __similarity_matrix.get_similarity (i, j);
+
+ }
+
+ // is this a new best center for the palm tree?
+ if (best_similarity < tree_similarity) {
+ best_similarity = tree_similarity;
+ best_center = i;
+ }
+
+ }
+
+ // confirm that we did indeed find a valid MST
+ if (best_similarity < 0)
+ THROWEXPR ("Unable to compute a valid minimum spanning palm tree.");
+
+ // log if requested
+ if (CTAGGING(-1,KMER))
+ CL << "Minimum spanning palm tree on sequences is centered on sequence '" << __seq_db.get_seq (best_center).name << "' (total k-mer similarity = " << best_similarity << ")." << endl;
+
+ // store the MST
+ for (size_t j = 0; j < __seq_db.size(); ++j) {
+
+ if (best_center == j)
+ continue;
+
+ // keep track of how many new sequence pairs we're selecting here
+ // (avoid over-counting previously-selected ones)
+ if (!__added[best_center][j] && !__added[j][best_center])
+ ++__num_selected;
+
+ // maintain i < j for consistency
+ if (best_center < j)
+ __added[best_center][j] = true;
+ else
+ __added[j][best_center] = true;
+
+ }
+
+ // record the center so that we don't repeat ourselves
+ chosen_centers[best_center] = true;
+
+ }
+
+}
+
+void Sequence_pair_selector::choose_palm_tree (const std::string& centerseq) {
+
+ // check sane
+ if (!__seq_db.exists_seq (centerseq))
+ THROWEXPR ("Requested center sequence of palm tree does not exist: '" << centerseq << "'.");
+
+ const size_t center = __seq_db.get_seq_index (centerseq);
+
+ // store the MST
+ for (size_t j = 0; j < __seq_db.size(); ++j) {
+
+ if (center == j)
+ continue;
+
+ // keep track of how many new sequence pairs we're selecting here
+ // (avoid over-counting previously-selected ones)
+ if (!__added[center][j] && !__added[j][center])
+ ++__num_selected;
+
+ // maintain i < j for consistency
+ if (center < j)
+ __added[center][j] = true;
+ else
+ __added[j][center] = true;
+
+ }
+
+}
+
+void Sequence_pair_selector::choose_kmer_similarity (const size_t degree) {
+
+ // keep track of how many sequence pairs we've stored
+ size_t num_added = 0;
+
+ // now add sequence pairs based on their k-mer similarity until
+ // we've hit the requested number degree per sequence
+ for (size_t i = 0; i < __seq_db.size(); ++i) {
+
+ // assemble a heap of edges, ordered by descending k-mer similarity
+ // (STL priority_queue order such that the first element is the greatest,
+ // according to the designated strict weak ordering)
+ std::priority_queue<std::pair<double, size_t>, std::vector<std::pair<double, size_t> >, Util::Duple_less<double, size_t> > weighted_edges;
+ for (size_t j = i + 1; j < __seq_db.size(); ++j) {
+ if (!__added[i][j])
+ weighted_edges.push (std::make_pair (__similarity_matrix.get_similarity (i, j), j));
+ }
+
+ // what's the current degree of sequence i?
+ size_t degree_i = 0;
+ for (size_t j = 0; j < __seq_db.size(); ++j) {
+ if (__added[i][j] || __added[j][i])
+ ++degree_i;
+ }
+
+ // now add edges one by one until we reach the requested degree
+ // (or run out of edges)
+ while (!weighted_edges.empty()) {
+
+ // have we reached the requested degree for sequence i?
+ if (degree_i >= degree)
+ break;
+
+ // get the lowest-weight edge
+ const std::pair<double, size_t> weighted_edge = weighted_edges.top();
+ weighted_edges.pop();
+ const size_t j = weighted_edge.second;
+
+ // store it
+ assert (!__added[i][j]);
+ __added[i][j] = true;
+ ++degree_i;
+ ++__num_selected;
+ ++num_added;
+
+ }
+
+ }
+
+ // log
+ if (CTAGGING(-1,KMER) && degree > 1)
+ CL << "Stored " << num_added << " sequence pairs to reach the requested degree = " << degree << "." << endl;
+
+}
+
+void Sequence_pair_selector::choose_random (size_t num) {
+
+ // make sure that it's possible to store the desired number of sequence pairs without duplicates
+ if ((__num_selected + num) > (__seq_db.size() * (__seq_db.size() - 1) / 2))
+ num = (__seq_db.size() * (__seq_db.size() - 1) / 2) - __num_selected;
+
+ // then randomly add more until we hit num_alignment_pairs
+ size_t num_added = 0;
+ while (num_added < num) {
+
+ // randomly choose a sequence pair
+ size_t i = static_cast<size_t> (std::floor (Util::rand (__seq_db.size() - 1)));
+ size_t j = static_cast<size_t> (std::floor (Util::rand (__seq_db.size() - 1)));
+
+ // check sane
+ assert (i < __seq_db.size());
+ assert (j < __seq_db.size());
+
+ // skip identities
+ if (i == j)
+ continue;
+
+ // require that i < j for consistency
+ if (i > j)
+ std::swap (i, j);
+ assert (i < j);
+
+ // skip duplicates
+ if (__added[i][j])
+ continue;
+
+ // store
+ __added[i][j] = true;
+ ++num_added;
+ ++__num_selected;
+
+ }
+ assert (num_added == num);
+
+ // log
+ CTAG(8,FSA) << "Stored " << num_added << " randomly-chosen sequence pairs." << endl;
+
+}
+
+void Sequence_pair_selector::choose_all() {
+
+ for (size_t i = 0; i < __added.size(); ++i) {
+ for (size_t j = i + 1; j < __added.size(); ++j)
+ __added[i][j] = true;
+ }
+
+}
+
+Sequence_pairs Sequence_pair_selector::get_chosen_sequence_pairs() const {
+
+ Sequence_pairs sequence_pairs;
+ for (size_t i = 0; i < __added.size(); ++i) {
+ for (size_t j = i + 1; j < __added.size(); ++j)
+ if (__added[i][j])
+ sequence_pairs.push_back (Sequence_pair (i, j));
+ }
+
+ return sequence_pairs;
+
+}
+
+double Sequence_pair_selector::erdos_renyi_p_cutoff (const size_t nodes) {
+
+ const double epsilon = 0.1;
+ return ((1 + epsilon) * std::log (static_cast<double> (nodes)) / static_cast<double> (nodes));
+
+}
+
diff --git a/src/fsa/sequence_pair_selector.h b/src/fsa/sequence_pair_selector.h
new file mode 100644
index 0000000..07c8e72
--- /dev/null
+++ b/src/fsa/sequence_pair_selector.h
@@ -0,0 +1,122 @@
+
+/**
+ * \file sequence_pair_selector.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef FSA_SEQUENCE_PAIR_SELECTOR_INCLUDED
+#define FSA_SEQUENCE_PAIR_SELECTOR_INCLUDED
+
+#include "math/mst.h"
+#include "seq/sequence.h"
+#include "seq/similarity_matrix.h"
+
+namespace fsa {
+
+ typedef std::pair<size_t, size_t> Sequence_pair; ///< a sequence pair (i, j)
+ typedef std::vector<Sequence_pair> Sequence_pairs; ///< a vector of sequence pairs
+
+ /**
+ * \brief Select sequence pairs for pairwise comparisons.
+ */
+ struct Sequence_pair_selector {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ * \param seq_db sequence data
+ * \param alphabet alphabet which sequences are defined over
+ * \param k word length to use when computing k-mer similarities
+ */
+ Sequence_pair_selector (const Sequence_database& seq_db,
+ const Alphabet& alphabet,
+ const size_t k);
+
+ /**
+ * \brief Choose sequence pairs based on their inclusion in minimum spanning trees.
+ *
+ * Iteratively constructs disjoint minimum spanning trees.
+ * \param num_mst number of disjoint MSTs to construct
+ * \param compute_maximum_spanning_tree compute the maximum, rather than minimum, spanning tree
+ */
+ void choose_minimum_spanning_tree (const size_t num_mst,
+ const bool compute_maximum_spanning_tree = false);
+
+ /**
+ * \brief Choose sequence pairs based on their inclusion in maximum spanning trees.
+ *
+ * Iteratively constructs disjoint maximum spanning trees.
+ * \param num_mst number of disjoint MSTs to construct
+ * \see choose_minimum_spanning_tree
+ */
+ void choose_maximum_spanning_tree (const size_t num_mst);
+
+ /**
+ * \brief Choose sequence pairs based on their inclusion in the minimum palm spanning tree.
+ *
+ * Iteratively construct minimum palm spanning trees with distinct centers.
+ * \param num_palm_mst number of palm MSTs to construct
+ */
+ void choose_minimum_spanning_palm_tree (const size_t num_palm_mst);
+
+ /**
+ * \brief Choose sequence pairs which form a palm tree with the specified sequence at the center.
+ *
+ * \param seq sequence which is the center of the palm tree
+ *
+ */
+ void choose_palm_tree (const std::string& centerseq);
+
+ /**
+ * \brief Choose sequence pairs based on their k-mer similarity.
+ *
+ * \param degree every sequence must be included in degree sequence pairs
+ */
+ void choose_kmer_similarity (const size_t degree);
+
+ /**
+ * \brief Choose sequence pairs randomly.
+ *
+ * \param num number of sequence pairs to add randomly
+ */
+ void choose_random (size_t num);
+
+ /**
+ * \brief Choose all sequence pairs.
+ */
+ void choose_all();
+
+ /**
+ * \brief Count the number of selected sequence pairs.
+ */
+ size_t num_selected() const { return __num_selected; }
+
+ /**
+ * \brief Get a list of sequence pairs which we have selected.
+ */
+ Sequence_pairs get_chosen_sequence_pairs() const;
+
+ /**
+ * \brief Erdos-Renyi threshold probability.
+ *
+ * Probability above which an Erdos-Renyi random graph will almost surely be connected.
+ * \param nodes number of nodes in graph
+ */
+ static double erdos_renyi_p_cutoff (const size_t nodes);
+
+ private:
+
+ const Sequence_database& __seq_db; ///< sequence data
+ const size_t __k; ///< k-mer word length
+
+ Sequence_similarity_matrix __similarity_matrix; ///< k-mer similarity matrix
+ std::vector<std::vector<bool> >__added; ///< __added[i][j] == true iff sequence pair (i, j) or (j, i) is chosen
+ size_t __num_selected; ///< number of sequence pairs selected
+
+ };
+
+}
+
+#endif /* FSA_SEQUENCE_PAIR_SELECTOR_INCLUDED */
diff --git a/src/main/Makefile.am b/src/main/Makefile.am
new file mode 100644
index 0000000..f43ec1f
--- /dev/null
+++ b/src/main/Makefile.am
@@ -0,0 +1,55 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+# AM_CXXFLAGS = -finline-limit=10000 --param inline-unit-growth=70
+# Commented out b/c was causing bugs on some older compilers.
+# --RKB & CD 4/14/09
+
+LDADD = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a
+
+if HAVE_CONDOR
+ AM_CPPFLAGS += -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+
+ AM_LDFLAGS = -static -L$(top_builddir)/MW/lib
+ LDADD += \
+ -lMW \
+ -lMWRMComm \
+ -lMWutil \
+ -lNWS \
+ -lMWsocketmaster \
+ -lpthread
+endif
+
+bin_PROGRAMS = \
+ fsa \
+ gapcleaner \
+ isect_mercator_alignment_gff \
+ map_coords \
+ map_gff_coords \
+ percentid \
+ prot2codon \
+ slice_fasta \
+ slice_fasta_gff \
+ slice_mercator_alignment \
+ translate
+
+fsa_SOURCES = main.cc
+gapcleaner_SOURCES = gapcleaner.cc
+isect_mercator_alignment_gff_SOURCES = isect_mercator_alignment_gff.cc
+map_coords_SOURCES = map_coords.cc
+map_gff_coords_SOURCES = map_gff_coords.cc
+percentid_SOURCES = percentid.cc
+prot2codon_SOURCES = prot2codon.cc
+slice_fasta_SOURCES = slice_fasta.cc
+slice_fasta_gff_SOURCES = slice_fasta_gff.cc
+slice_mercator_alignment_SOURCES = slice_mercator_alignment.cc
+translate_SOURCES = translate.cc
+
+noinst_HEADERS =
diff --git a/src/main/Makefile.in b/src/main/Makefile.in
new file mode 100644
index 0000000..14c3044
--- /dev/null
+++ b/src/main/Makefile.in
@@ -0,0 +1,806 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ at HAVE_CONDOR_TRUE@am__append_1 = -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+ at HAVE_CONDOR_TRUE@am__append_2 = \
+ at HAVE_CONDOR_TRUE@ -lMW \
+ at HAVE_CONDOR_TRUE@ -lMWRMComm \
+ at HAVE_CONDOR_TRUE@ -lMWutil \
+ at HAVE_CONDOR_TRUE@ -lNWS \
+ at HAVE_CONDOR_TRUE@ -lMWsocketmaster \
+ at HAVE_CONDOR_TRUE@ -lpthread
+
+bin_PROGRAMS = fsa$(EXEEXT) gapcleaner$(EXEEXT) \
+ isect_mercator_alignment_gff$(EXEEXT) map_coords$(EXEEXT) \
+ map_gff_coords$(EXEEXT) percentid$(EXEEXT) prot2codon$(EXEEXT) \
+ slice_fasta$(EXEEXT) slice_fasta_gff$(EXEEXT) \
+ slice_mercator_alignment$(EXEEXT) translate$(EXEEXT)
+subdir = src/main
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_fsa_OBJECTS = main.$(OBJEXT)
+fsa_OBJECTS = $(am_fsa_OBJECTS)
+fsa_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+fsa_DEPENDENCIES = $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_gapcleaner_OBJECTS = gapcleaner.$(OBJEXT)
+gapcleaner_OBJECTS = $(am_gapcleaner_OBJECTS)
+gapcleaner_LDADD = $(LDADD)
+gapcleaner_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_isect_mercator_alignment_gff_OBJECTS = \
+ isect_mercator_alignment_gff.$(OBJEXT)
+isect_mercator_alignment_gff_OBJECTS = \
+ $(am_isect_mercator_alignment_gff_OBJECTS)
+isect_mercator_alignment_gff_LDADD = $(LDADD)
+isect_mercator_alignment_gff_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_map_coords_OBJECTS = map_coords.$(OBJEXT)
+map_coords_OBJECTS = $(am_map_coords_OBJECTS)
+map_coords_LDADD = $(LDADD)
+map_coords_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_map_gff_coords_OBJECTS = map_gff_coords.$(OBJEXT)
+map_gff_coords_OBJECTS = $(am_map_gff_coords_OBJECTS)
+map_gff_coords_LDADD = $(LDADD)
+map_gff_coords_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_percentid_OBJECTS = percentid.$(OBJEXT)
+percentid_OBJECTS = $(am_percentid_OBJECTS)
+percentid_LDADD = $(LDADD)
+percentid_DEPENDENCIES = $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_prot2codon_OBJECTS = prot2codon.$(OBJEXT)
+prot2codon_OBJECTS = $(am_prot2codon_OBJECTS)
+prot2codon_LDADD = $(LDADD)
+prot2codon_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_slice_fasta_OBJECTS = slice_fasta.$(OBJEXT)
+slice_fasta_OBJECTS = $(am_slice_fasta_OBJECTS)
+slice_fasta_LDADD = $(LDADD)
+slice_fasta_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_slice_fasta_gff_OBJECTS = slice_fasta_gff.$(OBJEXT)
+slice_fasta_gff_OBJECTS = $(am_slice_fasta_gff_OBJECTS)
+slice_fasta_gff_LDADD = $(LDADD)
+slice_fasta_gff_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_slice_mercator_alignment_OBJECTS = \
+ slice_mercator_alignment.$(OBJEXT)
+slice_mercator_alignment_OBJECTS = \
+ $(am_slice_mercator_alignment_OBJECTS)
+slice_mercator_alignment_LDADD = $(LDADD)
+slice_mercator_alignment_DEPENDENCIES = \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+am_translate_OBJECTS = translate.$(OBJEXT)
+translate_OBJECTS = $(am_translate_OBJECTS)
+translate_LDADD = $(LDADD)
+translate_DEPENDENCIES = $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__DEPENDENCIES_1)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(fsa_SOURCES) $(gapcleaner_SOURCES) \
+ $(isect_mercator_alignment_gff_SOURCES) $(map_coords_SOURCES) \
+ $(map_gff_coords_SOURCES) $(percentid_SOURCES) \
+ $(prot2codon_SOURCES) $(slice_fasta_SOURCES) \
+ $(slice_fasta_gff_SOURCES) $(slice_mercator_alignment_SOURCES) \
+ $(translate_SOURCES)
+DIST_SOURCES = $(fsa_SOURCES) $(gapcleaner_SOURCES) \
+ $(isect_mercator_alignment_gff_SOURCES) $(map_coords_SOURCES) \
+ $(map_gff_coords_SOURCES) $(percentid_SOURCES) \
+ $(prot2codon_SOURCES) $(slice_fasta_SOURCES) \
+ $(slice_fasta_gff_SOURCES) $(slice_mercator_alignment_SOURCES) \
+ $(translate_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src $(am__append_1)
+
+# AM_CXXFLAGS = -finline-limit=10000 --param inline-unit-growth=70
+# Commented out b/c was causing bugs on some older compilers.
+# --RKB & CD 4/14/09
+LDADD = $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/fsa/libfsa.a \
+ $(top_builddir)/src/annealing/libannealing.a \
+ $(top_builddir)/src/manager/libmanager.a \
+ $(top_builddir)/src/seq/libseq.a \
+ $(top_builddir)/src/util/libutil.a \
+ $(top_builddir)/src/math/libmath.a $(am__append_2)
+ at HAVE_CONDOR_TRUE@AM_LDFLAGS = -static -L$(top_builddir)/MW/lib
+fsa_SOURCES = main.cc
+gapcleaner_SOURCES = gapcleaner.cc
+isect_mercator_alignment_gff_SOURCES = isect_mercator_alignment_gff.cc
+map_coords_SOURCES = map_coords.cc
+map_gff_coords_SOURCES = map_gff_coords.cc
+percentid_SOURCES = percentid.cc
+prot2codon_SOURCES = prot2codon.cc
+slice_fasta_SOURCES = slice_fasta.cc
+slice_fasta_gff_SOURCES = slice_fasta_gff.cc
+slice_mercator_alignment_SOURCES = slice_mercator_alignment.cc
+translate_SOURCES = translate.cc
+noinst_HEADERS =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/main/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/main/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+fsa$(EXEEXT): $(fsa_OBJECTS) $(fsa_DEPENDENCIES) $(EXTRA_fsa_DEPENDENCIES)
+ @rm -f fsa$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fsa_OBJECTS) $(fsa_LDADD) $(LIBS)
+
+gapcleaner$(EXEEXT): $(gapcleaner_OBJECTS) $(gapcleaner_DEPENDENCIES) $(EXTRA_gapcleaner_DEPENDENCIES)
+ @rm -f gapcleaner$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(gapcleaner_OBJECTS) $(gapcleaner_LDADD) $(LIBS)
+
+isect_mercator_alignment_gff$(EXEEXT): $(isect_mercator_alignment_gff_OBJECTS) $(isect_mercator_alignment_gff_DEPENDENCIES) $(EXTRA_isect_mercator_alignment_gff_DEPENDENCIES)
+ @rm -f isect_mercator_alignment_gff$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(isect_mercator_alignment_gff_OBJECTS) $(isect_mercator_alignment_gff_LDADD) $(LIBS)
+
+map_coords$(EXEEXT): $(map_coords_OBJECTS) $(map_coords_DEPENDENCIES) $(EXTRA_map_coords_DEPENDENCIES)
+ @rm -f map_coords$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(map_coords_OBJECTS) $(map_coords_LDADD) $(LIBS)
+
+map_gff_coords$(EXEEXT): $(map_gff_coords_OBJECTS) $(map_gff_coords_DEPENDENCIES) $(EXTRA_map_gff_coords_DEPENDENCIES)
+ @rm -f map_gff_coords$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(map_gff_coords_OBJECTS) $(map_gff_coords_LDADD) $(LIBS)
+
+percentid$(EXEEXT): $(percentid_OBJECTS) $(percentid_DEPENDENCIES) $(EXTRA_percentid_DEPENDENCIES)
+ @rm -f percentid$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(percentid_OBJECTS) $(percentid_LDADD) $(LIBS)
+
+prot2codon$(EXEEXT): $(prot2codon_OBJECTS) $(prot2codon_DEPENDENCIES) $(EXTRA_prot2codon_DEPENDENCIES)
+ @rm -f prot2codon$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(prot2codon_OBJECTS) $(prot2codon_LDADD) $(LIBS)
+
+slice_fasta$(EXEEXT): $(slice_fasta_OBJECTS) $(slice_fasta_DEPENDENCIES) $(EXTRA_slice_fasta_DEPENDENCIES)
+ @rm -f slice_fasta$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(slice_fasta_OBJECTS) $(slice_fasta_LDADD) $(LIBS)
+
+slice_fasta_gff$(EXEEXT): $(slice_fasta_gff_OBJECTS) $(slice_fasta_gff_DEPENDENCIES) $(EXTRA_slice_fasta_gff_DEPENDENCIES)
+ @rm -f slice_fasta_gff$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(slice_fasta_gff_OBJECTS) $(slice_fasta_gff_LDADD) $(LIBS)
+
+slice_mercator_alignment$(EXEEXT): $(slice_mercator_alignment_OBJECTS) $(slice_mercator_alignment_DEPENDENCIES) $(EXTRA_slice_mercator_alignment_DEPENDENCIES)
+ @rm -f slice_mercator_alignment$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(slice_mercator_alignment_OBJECTS) $(slice_mercator_alignment_LDADD) $(LIBS)
+
+translate$(EXEEXT): $(translate_OBJECTS) $(translate_DEPENDENCIES) $(EXTRA_translate_DEPENDENCIES)
+ @rm -f translate$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(translate_OBJECTS) $(translate_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gapcleaner.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isect_mercator_alignment_gff.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/main.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_coords.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/map_gff_coords.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/percentid.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/prot2codon.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/slice_fasta.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/slice_fasta_gff.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/slice_mercator_alignment.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/translate.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \
+ distclean distclean-compile distclean-generic distclean-tags \
+ distdir dvi dvi-am html html-am info info-am install \
+ install-am install-binPROGRAMS install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am \
+ uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/main/gapcleaner.cc b/src/main/gapcleaner.cc
new file mode 100644
index 0000000..e4ec691
--- /dev/null
+++ b/src/main/gapcleaner.cc
@@ -0,0 +1,116 @@
+
+/**
+ * \file gapcleaner.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "annealing/alignment_DAG.h"
+
+using namespace fsa;
+
+static std::string program_name = "gapcleaner";
+
+// short options letters
+const char* const short_options = "vh";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " <multi-FASTA or Stockholm alignment>" << endl
+ << endl
+ << "Find the most-parsimonious ordering of indels." << endl
+ << "Finds the minimal chain decomposition of the POSET of the alignment;" << endl
+ << "this corresponds to minimizing the number of gap-openings across the sequences." << endl
+ << endl
+ << "Input protein alignment must be in multi-FASTA or Stockholm format." << endl
+ << endl;
+}
+
+
+int main (int argc, char** argv) {
+
+ std::string alignfilename;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 1 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ alignfilename = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+ // now do stuff!
+ Sequence_database seq_db;
+ Stockholm stockholm (seq_db);
+
+ bool is_mfa = false;
+ if (Alignment::detect_mfa (alignfilename))
+ is_mfa = true;
+ if (is_mfa)
+ stockholm.read_mfa (alignfilename);
+ else
+ stockholm.read_stockholm (alignfilename);
+
+ // perform greedy DFS decomposition
+ Alignment_DAG dag (seq_db, stockholm);
+ dag.dfs_topological_sort();
+
+ // show results
+ if (is_mfa)
+ dag.get_stockholm().write_mfa (cout);
+ else
+ dag.get_stockholm().write_stockholm (cout);
+
+ return 0;
+}
diff --git a/src/main/isect_mercator_alignment_gff.cc b/src/main/isect_mercator_alignment_gff.cc
new file mode 100644
index 0000000..151cb0f
--- /dev/null
+++ b/src/main/isect_mercator_alignment_gff.cc
@@ -0,0 +1,244 @@
+
+/**
+ * \file isect_mercator_alignment_gff.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+#include <fstream>
+
+#include "config.h"
+#include "seq/gff.h"
+#include "seq/alignment.h"
+#include "seq/mercator.h"
+
+using namespace fsa;
+
+static std::string program_name = "isect_mercator_alignment_gff";
+
+static std::string type = "";
+
+static std::string datadir = ".";
+static std::string mapdir = ".";
+static std::string aligndir = ".";
+static bool stockholm = false;
+static bool lazy = false;
+static bool truncate_ok = false;
+
+static bool verbose = false;
+
+// short options letters
+const char* const short_options = "hvt:D:M:A:LUse";
+
+// long options
+static struct option long_options[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+
+ {"type", required_argument, NULL, 't'},
+
+ {"data", required_argument, NULL, 'D'},
+ {"map", required_argument, NULL, 'M'},
+ {"align", required_argument, NULL, 'A'},
+ {"lazy", no_argument, NULL, 'L'},
+ {"truncate", no_argument, NULL, 'U'},
+
+ {"stockholm", no_argument, NULL, 's'},
+
+ {"verbose", no_argument, NULL, 'e'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " [options] <genome> <GFF file>" << endl
+ << endl
+ << "Extracts subalignments from a Mercator multiple alignment for the features in the GFF file." << endl
+ << endl
+ << "Options:" << endl
+ << " -h, --help show this message" << endl
+ << " -v, --version show version information" << endl
+ << endl
+ << " -t, --type <string> only look at features of particular type" << endl
+ << endl
+ << " -D, --data <directory> path to map, genome and alignment files" << endl
+ << " -M, --map <directory> path to map and genome files" << endl
+ << " -A, --align <directory> path to alignment files" << endl
+ << " -L, --lazy warn, rather than die, if the subalignment can't be obtained" << endl
+ << " -U, --truncate truncate unmappable sequence (rather than skipping) and show truncated subalignment" << endl
+ << endl
+ << " -s, --stockholm use and display Stockholm-format alignments with conservation statistics (default is multi-FASTA)" << endl
+ << endl
+ << " -e, --verbose report progress" << endl
+ << endl
+ << "PLEASE NOTE: While this program is reasonably fast if the GFF is properly" << endl
+ << "ordered by chromosome and the start and end coordinates of features, it" << endl
+ << "will be *very slow* if the GFF is not sorted."
+ << endl
+ << "Assumes that the \"seqid\" or \"name\" field (the first field) of the GFF entries" << endl
+ << "holds the chromosome name." << endl
+ << endl
+ << "Note that the GFF specification defines coordinates to be 1-based" << endl
+ << "and fully-closed, therefore representing the interval [start, end]." << endl
+ << "Conformance to this specification is assumed internally." << endl
+ << endl
+ << "If requested, unmappable sequence will be truncated to the mappable portion;" << endl
+ << "note that the truncation will favor the beginning of the requested sequence." << endl
+ << endl
+ << "If a GFF feature is on the - strand, then the corresponding" << endl
+ << "subalignment will be reverse-complemented."
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string genome;
+ std::string gfffile;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 't': // type
+ type = std::string (optarg);
+ break;
+
+ case 'D': // data directory
+ datadir = std::string (optarg);
+ break;
+
+ case 'M': // map directory
+ mapdir = std::string (optarg);
+ break;
+
+ case 'A': // align directory
+ aligndir = std::string (optarg);
+ break;
+
+ case 'L': // lazy
+ lazy = true;
+ break;
+
+ case 'U': // truncate
+ truncate_ok = true;
+ break;
+
+ case 's': // stockholm
+ stockholm = true;
+ break;
+
+ case 'e': // verbose
+ verbose = true;
+ break;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 2 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ genome = std::string (argv[optind++]);
+ gfffile = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+
+ // now do stuff!
+
+ // read GFF file
+ GFF_database gff_db;
+ gff_db.from_file (gfffile,
+ true); // strip_leading_chr
+
+ // create Mercator map
+ Mercator_alignment mercator_alignment (mapdir != "." ? mapdir : datadir, aligndir != "." ? aligndir : datadir);
+
+ // initialize persistent sequence & alignment information for current bin
+ Sequence_database seq_db_bin;
+ Stockholm stockholm_bin (seq_db_bin);
+ unsigned bin = 0; // initialize to dummy 0 value
+
+ // turn off sync with stdio to try to increase speed of input/output to standard streams
+ std::ios::sync_with_stdio (false);
+
+ // iterate through GFF
+ for (std::vector<GFF>::const_iterator gff = gff_db.begin(); gff != gff_db.end(); ++gff) {
+
+ // if requested, only look at features of a particular type
+ if (type.length() && type != gff->type)
+ continue;
+
+ // hold subalignment sequence information
+ Sequence_database seq_db_subalign;
+
+ // take slice
+ Stockholm* slice = mercator_alignment.slice (seq_db_subalign,
+ bin,
+ stockholm_bin,
+ genome, gff->seqid,
+ gff->strand,
+ gff->start - 1, gff->end - 1, // convert to 0-based coordinates
+ lazy, truncate_ok,
+ stockholm, // annotate with homology information if stockholm
+ verbose);
+
+ // skip empty subalignments
+ // (indicating that no mapping was found)
+ if (slice->columns() == 0)
+ continue;
+
+ // annotate entire alignment with #=GF GFF line
+ slice->add_gf_annot (Stockholm::gff_annotation, gff->to_string());
+
+ // display
+ if (stockholm) {
+ slice->annotate_with_statistics();
+ slice->write_stockholm (cout);
+ }
+ else
+ slice->write_mfa (cout);
+
+ // clean up
+ delete slice;
+
+ }
+
+ return 0;
+
+}
diff --git a/src/main/main.cc b/src/main/main.cc
new file mode 100644
index 0000000..3d06ea4
--- /dev/null
+++ b/src/main/main.cc
@@ -0,0 +1,59 @@
+
+/**
+ * \file main.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley and Jaeyoung Do.
+ */
+
+#include "fsa/fsa.h"
+
+using namespace fsa;
+
+/**
+ * \brief Check whether this appears to be a worker instance.
+ *
+ * Examines command-line arguments and checks whether they conform
+ * to the expected format for worker instances.
+ */
+bool is_mw_worker_format (int argc, char** argv);
+
+/**
+ * \brief Create & run an FSA object from command-line arguments
+ */
+int main (int argc, char** argv) {
+
+ if (is_mw_worker_format (argc, argv)) {
+ Manager manager;
+ return manager.mw_worker_run (argc, argv);
+ }
+ else {
+ FSA fsa (argc, argv);
+ return fsa.run();
+ }
+}
+
+/**
+ * \brief Simple method to check whether we seem to be running as a MW_worker.
+ */
+bool is_mw_worker_format(int argc, char** argv) {
+
+ if (argc == 5) {
+ bool chk_arg2 = (atoi(argv[2]) != 0 ) ? true : false; // 2nd parameter must be an integer value
+ bool chk_arg3 = (atoi(argv[3]) != 0 ) ? true : false; // 3rd parameter must be an integer value
+
+ int dot_cnt = 0;
+ char tmp_argv[512],*dot_pch;
+
+ strcpy(tmp_argv, argv[4]);
+ dot_pch = strtok (tmp_argv, ".");
+
+ while (dot_pch != NULL) { // check whether 4th parameter is a valid IPv4
+ ++dot_cnt;
+ dot_pch = strtok(NULL, ".");
+ }
+
+ if (chk_arg2 && chk_arg3 && dot_cnt == 4)
+ return true;
+ }
+ return false;
+}
diff --git a/src/main/map_coords.cc b/src/main/map_coords.cc
new file mode 100644
index 0000000..5e1b894
--- /dev/null
+++ b/src/main/map_coords.cc
@@ -0,0 +1,205 @@
+
+/**
+ * \file map_coords.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/alignment.h"
+#include "seq/mercator.h"
+
+using namespace fsa;
+
+static std::string program_name = "map_coords";
+
+static std::string datadir = ".";
+static std::string mapdir = ".";
+static std::string aligndir = ".";
+static bool lazy = false;
+static bool truncate_ok = false;
+
+// short options letters
+const char* const short_options = "vhD:M:A:LU";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ {"data", required_argument, NULL, 'D'},
+ {"map", required_argument, NULL, 'M'},
+ {"align", required_argument, NULL, 'A'},
+ {"lazy", no_argument, NULL, 'L'},
+ {"truncate", no_argument, NULL, 'U'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " [options] <source genome> <chromosome> <start> <end> <strand> <target genome>" << endl
+ << endl
+ << "Map coordinates from one genome to another using a Mercator multiple alignment." << endl
+ << endl
+ << "Options:" << endl
+ << " -h, --help show this message" << endl
+ << endl
+ << " -D, --data <directory> path to map, genome and alignment files" << endl
+ << " -M, --map <directory> path to map and genome files" << endl
+ << " -A, --align <directory> path to alignment files" << endl
+ << " -L, --lazy warn, rather than die, if the subalignment can't be obtained" << endl
+ << " -U, --truncate truncate unmappable sequence (rather than skipping) and show truncated subalignment" << endl
+ << endl
+ << "Assumes that coordinates are 1-based and fully-closed," << endl
+ << "therefore representing the interval [start, end]." << endl
+ << endl
+ << "If requested, unmappable sequence will be truncated to the mappable portion;" << endl
+ << "note that the truncation will favor the beginning of the requested sequence." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string genome_source;
+ std::string chromosome_source;
+ unsigned start_source, end_source;
+ char strand_source;
+ std::string genome_target;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case 'D': // data directory
+ datadir = std::string (optarg);
+ break;
+
+ case 'M': // map directory
+ mapdir = std::string (optarg);
+ break;
+
+ case 'A': // align directory
+ aligndir = std::string (optarg);
+ break;
+
+ case 'L': // lazy
+ lazy = true;
+ break;
+
+ case 'U': // truncate
+ truncate_ok = true;
+ break;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 6 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ genome_source = std::string (argv[optind++]);
+ chromosome_source = std::string (argv[optind++]);
+ start_source = static_cast<size_t> (atoi (argv[optind++]));
+ end_source = static_cast<size_t> (atoi (argv[optind++]));
+ strand_source = argv[optind++][0];
+ genome_target = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+
+ // now do stuff!
+
+ // create Mercator map
+ Mercator_alignment mercator_alignment (mapdir != "." ? mapdir : datadir, aligndir != "." ? aligndir : datadir);
+
+ // initialize persistent sequence & alignment information for current bin
+ Sequence_database seq_db_bin;
+ Stockholm stockholm_bin (seq_db_bin);
+ unsigned bin = 0; // initialize to dummy 0 value
+
+ // use the alignment to find the homologous interval
+ Genomic_interval region_target = mercator_alignment.find_homologous_interval (bin,
+ stockholm_bin,
+ genome_source, chromosome_source,
+ start_source - 1, end_source - 1, // convert to 0-based coordinates
+ genome_target,
+ lazy, truncate_ok);
+
+
+ // check that it was mapped successfully
+ // (Mercator_alignment::find_homologous_interval returns an empty value
+ // if it wasn't or if homologous subsequence is empty)
+ // NB no need to enforce lazy here, b/c find_homologous_interval does this for us
+ if (region_target.genome == "") {
+ cerr << "WARNING: No homologous sequence found (all gaps)." << endl;
+ return 0;
+ }
+
+ // get the Mercator_interval for the source
+ const size_t idx_source = mercator_alignment.find_mercator_interval (genome_source, chromosome_source,
+ start_source - 1, end_source - 1, // convert to 0-based coordinates
+ !truncate_ok);
+ assert (idx_source < mercator_alignment.size());
+ const Mercator_interval& interval_source = mercator_alignment.get_interval (idx_source);
+
+ // use the source interval to determine whether the source feature was
+ // reverse-complemented w.r.t. the strand in the Mercator_interval
+ // if it was, then the target feature will also be reverse-complemented
+ // w.r.t. the strand in the Mercator_interval
+ const bool is_rc = (interval_source.strand != strand_source);
+
+ std::string chromosome_target = region_target.chromosome;
+ size_t start_target = region_target.start + 1; // convert back to 1-based coordinates
+ size_t end_target = region_target.end + 1;
+ char strand_target;
+ if (strand_source == GFF::unknown_strand) // if the source feature had no annotated strand, then do the same for the target feature
+ strand_target = GFF::unknown_strand;
+ else { // otherwise set the target strand appropriately using the homology mapping implied by the alignment
+ strand_target = region_target.strand;
+ if (is_rc)
+ Sequence::complement_strand (strand_target);
+ }
+
+ cout << genome_target << '\t' << chromosome_target << '\t'
+ << start_target << '\t' << end_target << '\t'
+ << strand_target << endl;
+
+ return 0;
+
+}
diff --git a/src/main/map_gff_coords.cc b/src/main/map_gff_coords.cc
new file mode 100644
index 0000000..f936204
--- /dev/null
+++ b/src/main/map_gff_coords.cc
@@ -0,0 +1,204 @@
+
+/**
+ * \file map_gff_coords.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/gff.h"
+#include "seq/alignment.h"
+#include "seq/mercator.h"
+
+using namespace fsa;
+
+static std::string program_name = "map_gff_coords";
+
+static std::string type = "";
+
+static std::string datadir = ".";
+static std::string mapdir = ".";
+static std::string aligndir = ".";
+static bool lazy = false;
+static bool truncate_ok = false;
+static bool force_entry = false;
+
+static bool verbose = false;
+
+// short options letters
+const char* const short_options = "vht:D:M:A:LUf:e";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ {"type", required_argument, NULL, 't'},
+
+ {"data", required_argument, NULL, 'D'},
+ {"map", required_argument, NULL, 'M'},
+ {"align", required_argument, NULL, 'A'},
+ {"lazy", no_argument, NULL, 'L'},
+ {"truncate", no_argument, NULL, 'U'},
+
+ {"force-entry", no_argument, NULL, 'f'},
+
+ {"verbose", no_argument, NULL, 'e'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " [options] <source genome> <source GFF file> <target genome>" << endl
+ << endl
+ << "Map coordinates of GFF features from one genome to another using a Mercator multiple alignment." << endl
+ << endl
+ << "Options:" << endl
+ << " -h, --help show this message" << endl
+ << endl
+ << " -t, --type <string> only look at features of particular type" << endl
+ << endl
+ << " -D, --data <directory> path to map, genome and alignment files" << endl
+ << " -M, --map <directory> path to map and genome files" << endl
+ << " -A, --align <directory> path to alignment files" << endl
+ << " -L, --lazy warn, rather than die, if the subalignment can't be obtained" << endl
+ << " -U, --truncate truncate unmappable sequence (rather than skipping) and show truncated subalignment" << endl
+ << endl
+ << " -f, --force-entry if a feature can't be mapped, then add an empty entry to the GFF file (rather than skipping it entirely); implies --lazy" << endl
+ << endl
+ << " -e, --verbose report progress" << endl
+ << endl
+ << "PLEASE NOTE: While this program is reasonably fast if the GFF is properly" << endl
+ << "ordered by chromosome and the start and end coordinates of features, it" << endl
+ << "will be *very slow* if the GFF is not sorted."
+ << endl
+ << "Assumes that the \"seqid\" or \"name\" field (the first field) of the GFF entries" << endl
+ << "holds the chromosome name." << endl
+ << endl
+ << "Note that the GFF specification defines coordinates to be 1-based" << endl
+ << "and fully-closed, therefore representing the interval [start, end]." << endl
+ << "Conformance to this specification is assumed internally." << endl
+ << endl
+ << "If requested, unmappable sequence will be truncated to the mappable portion;" << endl
+ << "note that the truncation will favor the beginning of the requested sequence." << endl
+ << endl
+ << "If a GFF feature is on the + strand for the source genome but" << endl
+ << "the corresponding homologous region in the target genome is on the - strand," << endl
+ << "then the mapped GFF feature will be reported as on the - strand." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string genome_source;
+ std::string gfffile;
+ std::string genome_target;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case 't': // type
+ type = std::string (optarg);
+ break;
+
+ case 'D': // data directory
+ datadir = std::string (optarg);
+ break;
+
+ case 'M': // map directory
+ mapdir = std::string (optarg);
+ break;
+
+ case 'A': // align directory
+ aligndir = std::string (optarg);
+ break;
+
+ case 'L': // lazy
+ lazy = true;
+ break;
+
+ case 'U': // truncate
+ truncate_ok = true;
+ break;
+
+ case 'f': // force-entry
+ force_entry = true;
+ lazy = true;
+ break;
+
+ case 'e': // verbose
+ verbose = true;
+ break;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 3 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ genome_source = std::string (argv[optind++]);
+ gfffile = std::string (argv[optind++]);
+ genome_target = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+
+ // now do stuff!
+
+ // read GFF file
+ GFF_database gff_db_from;
+ gff_db_from.from_file (gfffile);
+
+ // create Mercator map
+ Mercator_alignment mercator_alignment (mapdir != "." ? mapdir : datadir, aligndir != "." ? aligndir : datadir);
+
+ // map the GFF!
+ GFF_database gff_db_to = mercator_alignment.map_gff_database (genome_source, genome_target,
+ gff_db_from,
+ lazy, truncate_ok,
+ verbose,
+ force_entry);
+
+ gff_db_to.write (cout);
+
+ return 0;
+
+}
diff --git a/src/main/percentid.cc b/src/main/percentid.cc
new file mode 100644
index 0000000..14e10a5
--- /dev/null
+++ b/src/main/percentid.cc
@@ -0,0 +1,108 @@
+
+/**
+ * \file percentid.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+using namespace fsa;
+
+static std::string program_name = "percentid";
+
+// short options letters
+const char* const short_options = "vh";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " <multi-FASTA or Stockholm alignment>" << endl
+ << endl
+ << "Calculate the percentage identity of the passed alignment." << endl
+ << endl
+ << "Input protein alignment must be in multi-FASTA or Stockholm format." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string alignfilename;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 1 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ alignfilename = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+ // now do stuff!
+
+ // read in alignment
+ Sequence_database seq_db;
+ Stockholm stockholm (seq_db);
+ bool is_mfa = false;
+ if (Alignment::detect_mfa (alignfilename))
+ is_mfa = true;
+ if (is_mfa)
+ stockholm.read_mfa (alignfilename);
+ else
+ stockholm.read_stockholm (alignfilename);
+
+ cout << stockholm.percent_id() << endl;
+
+ return 0;
+
+}
diff --git a/src/main/prot2codon.cc b/src/main/prot2codon.cc
new file mode 100644
index 0000000..8387d90
--- /dev/null
+++ b/src/main/prot2codon.cc
@@ -0,0 +1,133 @@
+
+/**
+ * \file prot2codon.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+using namespace fsa;
+
+static std::string program_name = "prot2codon";
+
+// short options letters
+const char* const short_options = "vh";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " <multi-FASTA or Stockholm alignment> <FASTA file>" << endl
+ << endl
+ << "Find the codon alignment corresponding to the given protein alignment." << endl
+ << endl
+ << "Input protein alignment must be in multi-FASTA or Stockholm format." << endl
+ << "Input nucleotide sequences must be in FASTA format." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string alignfilename;
+ std::string seqfilename;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 2 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ alignfilename = std::string (argv[optind++]);
+ seqfilename = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+ // now do stuff!
+
+ // read in protein alignment
+ Sequence_database seq_db_aa;
+ Stockholm stockholm_aa (seq_db_aa);
+ bool is_mfa = false;
+ if (Alignment::detect_mfa (alignfilename))
+ is_mfa = true;
+ if (is_mfa)
+ stockholm_aa.read_mfa (alignfilename);
+ else
+ stockholm_aa.read_stockholm (alignfilename);
+
+ // check correct alphabet
+ Protein_alphabet prot = Protein_alphabet();
+ if (!seq_db_aa.matches_alphabet (prot, 0.75)) { // use loose threshold for calling it protein
+ cerr << "ERROR: Input alignment doesn't seem to be protein sequence; I'm bailing." << endl;
+ return 1;
+ }
+
+ // read in nucleotide fasta file
+ if (!Sequence::detect_fasta (seqfilename)) {
+ cerr << "ERROR: Input nucleotide sequences must be in FASTA format.";
+ return 1;
+ }
+ Sequence_database seq_db_codon;
+ seq_db_codon.read_fasta (seqfilename, Alignment::is_gap_char,
+ false, // strip_leading_chr
+ true); // verbose
+
+ // translate sequences & display
+ Stockholm stockholm_codon = stockholm_aa.get_codon_from_aa_alignment (seq_db_codon);
+ if (is_mfa)
+ stockholm_codon.write_mfa (cout);
+ else
+ stockholm_codon.write_stockholm (cout);
+
+ return 0;
+
+}
diff --git a/src/main/slice_fasta.cc b/src/main/slice_fasta.cc
new file mode 100644
index 0000000..d497cdd
--- /dev/null
+++ b/src/main/slice_fasta.cc
@@ -0,0 +1,170 @@
+
+/**
+ * \file slice_fasta.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+using namespace fsa;
+
+static std::string program_name = "slice_fasta";
+
+// short options letters
+const char* const short_options = "vh";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " <FASTA file> <sequence name> <start> <end> <strand>" << endl
+ << endl
+ << "Slice a subsequence from an input FASTA file." << endl
+ << "Assumes 1-based, fully-closed coordinates." << endl
+ << "If <strand> is omitted, then the + strand is assumed." << endl
+ << "If the - strand is requested, then the subsequence is pulled out and then reverse-complemented." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string filename;
+ std::string seqname;
+ unsigned start;
+ unsigned end;
+ char strand = '+';
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if ((optind + 4 != argc) && (optind + 5 != argc)) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ filename = std::string (argv[optind++]);
+ seqname = std::string (argv[optind++]);
+ Util::strip_leading_chr (seqname);
+ start = static_cast<unsigned> (atoi (argv[optind++]));
+ end = static_cast<unsigned> (atoi (argv[optind++]));
+ // optionally get strand
+ if (optind + 1 == argc)
+ strand = argv[optind++][0];
+
+ // check that arguments are sane
+ if (strand != '+' && strand != '-') {
+ print_usage (cerr);
+ return 1;
+ }
+
+ // check that coordinates are sane
+ if (end < start) {
+ cerr << "ERROR: Please enter valid coordinates." << endl;
+ return 1;
+ }
+ if (start == 0 || end == 0) {
+ cerr << "ERROR: Please enter valid coordinates (remember that they are 1-based)." << endl;
+ return 1;
+ }
+
+ assert (optind == argc);
+
+ // now do stuff!
+ Sequence_database seq_db;
+ if (!Sequence::detect_fasta (filename)) {
+ cerr << "ERROR: Input nucleotide sequences must be in FASTA format.";
+ return 1;
+ }
+ seq_db.read_fasta (filename, Alignment::is_gap_char,
+ true, // strip_leading_chr
+ true); // verbose
+
+ // get requested subsequence
+ if (!seq_db.exists_seq (seqname)) {
+ cerr << "ERROR: No sequence named '" << seqname << "'." << endl
+ << "Available sequences are:" << endl
+ << Util::join (seq_db.get_sequence_list(), "\t") << endl;
+ return 1;
+ }
+ const Sequence& sequence = seq_db.get_seq (seqname);
+
+ // convert to 0-based coordinates
+ --start;
+ --end;
+
+ // check coordinates sane
+ if (start >= sequence.length()) {
+ cerr << "ERROR: Requested coordinates are out of bounds." << endl;
+ exit (1);
+ }
+
+ // take subsequence
+ Sequence* subseq = sequence.subsequence (start, end);
+
+ // reverse-complement if relevant
+ const DNA_alphabet dna_alphabet;
+ if (strand == '-') {
+ if (seq_db.matches_alphabet (dna_alphabet))
+ subseq->revcomp (dna_alphabet);
+ else {
+ cerr << "ERROR: Sequences in FASTA file don't match DNA alphabet, so I can't take the reverse-complement." << endl;
+ return 1;
+ }
+ }
+
+ // display
+ subseq->write_fasta (cout);
+
+ // clean up
+ delete subseq;
+
+ return 0;
+
+}
diff --git a/src/main/slice_fasta_gff.cc b/src/main/slice_fasta_gff.cc
new file mode 100644
index 0000000..e1d48c2
--- /dev/null
+++ b/src/main/slice_fasta_gff.cc
@@ -0,0 +1,173 @@
+
+/**
+ * \file slice_fasta.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/gff.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+using namespace fsa;
+
+static std::string program_name = "slice_fasta";
+
+static std::string type = "";
+
+// short options letters
+const char* const short_options = "vht:";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ {"type", required_argument, NULL, 't'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " [options] <FASTA file> <GFF file>" << endl
+ << endl
+ << "Options:" << endl
+ << " -t, --type <string> only look at features of particular type" << endl
+ << endl
+ << "Slice subsequences from an input FASTA file." << endl
+ << "Assumes 1-based, fully-closed coordinates." << endl
+ << "If no strand information is available, then the + strand is assumed." << endl
+ << "If the - strand is requested, then the subsequence is pulled out and then reverse-complemented." << endl
+ << endl
+ << "Assumes a DNA alphabet." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string filename;
+ std::string gff_filename;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 't': // type
+ type = std::string (optarg);
+ break;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 2 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ filename = std::string (argv[optind++]);
+ gff_filename = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+ // read in sequence
+ Sequence_database seq_db;
+ if (!Sequence::detect_fasta (filename)) {
+ cerr << "ERROR: Input nucleotide sequences must be in FASTA format.";
+ return 1;
+ }
+ seq_db.read_fasta (filename, Alignment::is_gap_char,
+ true, // strip_leading_chr
+ true); // verbose
+
+ // read GFF file
+ GFF_database gff_db;
+ gff_db.from_file (gff_filename,
+ true); // strip_leading_chr
+
+ // initialize alphabet for reverse-complementing
+ const DNA_alphabet dna_alphabet;
+
+ // iterate through GFF
+ for (std::vector<GFF>::const_iterator gff = gff_db.begin(); gff != gff_db.end(); ++gff) {
+
+ // if requested, only look at features of a particular type
+ if (type.length() && type != gff->type)
+ continue;
+
+ // confirm that we have sequence data for this chromosome
+ if (!seq_db.exists_seq (gff->seqid)) {
+ cerr << "WARNING: No sequence data found for requested chromosome '" << gff->seqid << "'." << endl;
+ continue;
+ }
+
+ // get sequence data
+ const Sequence& sequence = seq_db.get_seq (gff->seqid);
+
+ // convert to 0-based coordinates
+ const size_t start = gff->start - 1;
+ const size_t end = gff->end - 1;
+
+ // check coordinates sane
+ if (gff->start - 1 >= sequence.length()) {
+ cerr << "ERROR: Requested coordinates are out of bounds:" << endl
+ << *gff << endl;
+ exit (1);
+ }
+
+ // take subsequence
+ Sequence* subseq = sequence.subsequence (start, end);
+
+ // replace chromosome name with GFF entry
+ subseq->name = gff->to_string();
+
+ // reverse-complement if relevant
+ if (gff->strand == '-')
+ subseq->revcomp (dna_alphabet);
+
+ // display
+ subseq->write_fasta (cout);
+
+ // clean up
+ delete subseq;
+
+ }
+
+ return 0;
+
+}
diff --git a/src/main/slice_mercator_alignment.cc b/src/main/slice_mercator_alignment.cc
new file mode 100644
index 0000000..f220af8
--- /dev/null
+++ b/src/main/slice_mercator_alignment.cc
@@ -0,0 +1,227 @@
+
+/**
+ * \file slice_mercator_alignment.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+#include <fstream>
+
+#include "config.h"
+#include "seq/alignment.h"
+#include "seq/mercator.h"
+
+using namespace fsa;
+
+static std::string program_name = "slice_mercator_alignment";
+
+static std::string datadir = ".";
+static std::string mapdir = ".";
+static std::string aligndir = ".";
+static bool stockholm = false;
+static bool lazy = false;
+static bool truncate_ok = false;
+static bool zerobased = false;
+static bool halfopen = false;
+
+// short options letters
+const char* const short_options = "vhD:M:A:LUs0o";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ {"data", required_argument, NULL, 'D'},
+ {"map", required_argument, NULL, 'M'},
+ {"align", required_argument, NULL, 'A'},
+ {"lazy", no_argument, NULL, 'L'},
+ {"truncate", no_argument, NULL, 'U'},
+
+ {"stockholm", no_argument, NULL, 's'},
+
+ {"zerobased", no_argument, NULL, '0'},
+ {"halfopen", no_argument, NULL, 'o'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " [options] <genome> <chromosome> <start> <end> <strand>" << endl
+ << endl
+ << "Extracts the corresponding subalignment from a Mercator multiple alignment." << endl
+ << endl
+ << "Options:" << endl
+ << " -h, --help show this message" << endl
+ << endl
+ << " -D, --data <directory> path to map, genome and alignment files" << endl
+ << " -M, --map <directory> path to map and genome files" << endl
+ << " -A, --align <directory> path to alignment files" << endl
+ << " -L, --lazy warn, rather than die, if the subalignment can't be obtained" << endl
+ << " -U, --truncate truncate unmappable sequence (rather than skipping) and show truncated subalignment" << endl
+ << endl
+ << " -s, --stockholm use and display Stockholm-format alignments with conservation statistics (default is multi-FASTA)" << endl
+ << endl
+ << " -0, --zerobased coordinates are 0-based (default is 1-based)" << endl
+ << " -o, --halfopen end coordinate is open, i.e., [start, end)" << endl
+ << endl
+ << "Assumes that coordinates are 1-based and fully-closed," << endl
+ << "therefore representing the interval [start, end]." << endl
+ << endl
+ << "If requested, unmappable sequence will be truncated to the mappable portion;" << endl
+ << "note that the truncation will favor the beginning of the requested sequence." << endl
+ << endl
+ << "If the requested sequence is on the - strand, then the corresponding" << endl
+ << "subalignment will be reverse-complemented." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string genome;
+ std::string chromosome;
+ unsigned start;
+ unsigned end;
+ char strand;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case 'D': // data directory
+ datadir = std::string (optarg);
+ break;
+
+ case 'M': // map directory
+ mapdir = std::string (optarg);
+ break;
+
+ case 'A': // align directory
+ aligndir = std::string (optarg);
+ break;
+
+ case 'L': // lazy
+ lazy = true;
+ break;
+
+ case 'U': // truncate
+ truncate_ok = true;
+ break;
+
+ case 's': // stockholm
+ stockholm = true;
+ break;
+
+ case '0': // zerobased
+ zerobased = true;
+ break;
+
+ case 'o': // halfopen
+ halfopen = true;
+ break;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // get the rest of the command-line arguments
+ if (optind + 5 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ genome = std::string (argv[optind++]);
+ chromosome = std::string (argv[optind++]);
+ start = static_cast<unsigned> (atoi (argv[optind++]));
+ end = static_cast<unsigned> (atoi (argv[optind++]));
+ strand = argv[optind++][0];
+
+ // check that arguments are sane
+ if (strand != '+' && strand != '-') {
+ print_usage (cerr);
+ return 1;
+ }
+
+ // check that coordinates are sane
+ if (end < start) {
+ cerr << "ERROR: Please enter valid coordinates." << endl;
+ return 1;
+ }
+ if (!zerobased && start == 0) {
+ cerr << "ERROR:Please enter a valid start coordinate (remember that they are 1-based by default)." << endl;
+ return 1;
+ }
+
+ assert (optind == argc);
+
+
+ // now do stuff!
+ Sequence_database seq_db;
+
+ // map coordinates to make them 0-based and fully-closed
+ if (!zerobased) {
+ --start; --end;
+ }
+ if (halfopen) {
+ --end;
+ }
+
+ // turn off sync with stdio to try to increase speed of input/output to standard streams
+ std::ios::sync_with_stdio (false);
+
+ // take alignment slice
+ Mercator_alignment mercator_alignment (mapdir != "." ? mapdir : datadir, aligndir != "." ? aligndir : datadir);
+ Sequence_database seq_db_subalign;
+ Stockholm* slice = mercator_alignment.slice (seq_db_subalign,
+ genome, chromosome,
+ strand,
+ start, end,
+ lazy, truncate_ok,
+ stockholm); // annotate with homology information if stockholm
+
+ // display
+ if (stockholm) {
+ slice->annotate_with_statistics();
+ slice->write_stockholm (cout);
+ }
+ else
+ slice->write_mfa (cout);
+
+ // clean up
+ delete slice;
+
+ return 0;
+
+}
diff --git a/src/main/translate.cc b/src/main/translate.cc
new file mode 100644
index 0000000..b7803be
--- /dev/null
+++ b/src/main/translate.cc
@@ -0,0 +1,107 @@
+
+/**
+ * \file translate.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+#include "seq/sequence.h"
+#include "seq/alignment.h"
+
+using namespace fsa;
+
+static std::string program_name = "translate";
+
+// short options letters
+const char* const short_options = "vh";
+
+// long options
+static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+
+ /* required NULL termination of array */
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version (std::ostream& o) {
+ o << program_name << " from " << PACKAGE_STRING << endl;
+}
+
+static void print_usage (std::ostream& o) {
+ print_version (o);
+ o << endl
+ << "Usage: " << program_name << " <FASTA file>" << endl
+ << endl
+ << "Translate input nucleotide sequences into protein sequence." << endl
+ << endl
+ << "Input nucleotide sequences must be in FASTA format." << endl
+ << "Uses the first reading frame and drops incomplete codons at ends of sequences." << endl
+ << endl;
+}
+
+int main (int argc, char** argv) {
+
+ std::string filename;
+
+ // parse options
+ int c;
+ int option_index = 0; // getopt_long stores option index here
+ while (1) {
+
+ // get next option
+ c = getopt_long (argc, argv, short_options,
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+
+ case 'v': // version message
+ print_version (cout);
+ return 0;
+
+ case 'h': // help message
+ print_usage (cout);
+ return 0;
+
+ case '?': // invalid option
+ print_usage (cerr);
+ return 1;
+
+ default: // unexpected
+ abort();
+
+ }
+ }
+
+ // stuff
+ if (optind + 1 != argc) {
+ print_usage (cerr);
+ return 1;
+ }
+
+ filename = std::string (argv[optind++]);
+
+ assert (optind == argc);
+
+ // now do stuff!
+ Sequence_database seq_db;
+ if (!Sequence::detect_fasta (filename)) {
+ cerr << "ERROR: Input nucleotide sequences must be in FASTA format.";
+ return 1;
+ }
+ seq_db.read_fasta (filename, Alignment::is_gap_char,
+ false, // strip_leading_chr
+ true); // verbose
+
+ // translate sequences & display
+ seq_db.translate().write_fasta (cout);
+
+ return 0;
+
+}
diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am
new file mode 100644
index 0000000..44cae56
--- /dev/null
+++ b/src/manager/Makefile.am
@@ -0,0 +1,49 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src -Wno-deprecated
+
+noinst_LIBRARIES = libmanager.a
+
+libmanager_a_SOURCES = \
+ manager.cc \
+ mw_adapter.cc \
+ db_adapter.cc \
+ db_misc.cc
+
+noinst_HEADERS = \
+ manager.h \
+ mw_adapter.h \
+ db_adapter.h \
+ db_misc.h
+
+if HAVE_CONDOR
+
+AM_CPPFLAGS += -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+
+libmanager_a_SOURCES += \
+ mw_master.cc \
+ mw_worker.cc \
+ mw_task.cc \
+ transfer_data.cc
+
+noinst_HEADERS += \
+ mw_master.h \
+ mw_worker.h \
+ mw_task.h
+
+else
+
+if HAVE_POSTGRES
+libmanager_a_SOURCES += \
+ transfer_data.cc
+endif
+
+endif
+
+if HAVE_POSTGRES
+
+libmanager_a_SOURCES += \
+ db_postgres.cc
+
+noinst_HEADERS += \
+ db_postgres.h
+
+endif
diff --git a/src/manager/Makefile.in b/src/manager/Makefile.in
new file mode 100644
index 0000000..486d3bc
--- /dev/null
+++ b/src/manager/Makefile.in
@@ -0,0 +1,585 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+ at HAVE_CONDOR_TRUE@am__append_1 = -I$(top_srcdir)/MW/src -I$(top_srcdir)/MW/src/MWControlTasks -I$(top_srcdir)/MW/src/RMComm -I$(top_srcdir)/MW/src/RMComm/MW-Socket
+ at HAVE_CONDOR_TRUE@am__append_2 = \
+ at HAVE_CONDOR_TRUE@ mw_master.cc \
+ at HAVE_CONDOR_TRUE@ mw_worker.cc \
+ at HAVE_CONDOR_TRUE@ mw_task.cc \
+ at HAVE_CONDOR_TRUE@ transfer_data.cc
+
+ at HAVE_CONDOR_TRUE@am__append_3 = \
+ at HAVE_CONDOR_TRUE@ mw_master.h \
+ at HAVE_CONDOR_TRUE@ mw_worker.h \
+ at HAVE_CONDOR_TRUE@ mw_task.h
+
+ at HAVE_CONDOR_FALSE@@HAVE_POSTGRES_TRUE at am__append_4 = \
+ at HAVE_CONDOR_FALSE@@HAVE_POSTGRES_TRUE@ transfer_data.cc
+
+ at HAVE_POSTGRES_TRUE@am__append_5 = \
+ at HAVE_POSTGRES_TRUE@ db_postgres.cc
+
+ at HAVE_POSTGRES_TRUE@am__append_6 = \
+ at HAVE_POSTGRES_TRUE@ db_postgres.h
+
+subdir = src/manager
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(am__noinst_HEADERS_DIST)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_ at AM_V@)
+am__v_AR_ = $(am__v_AR_ at AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libmanager_a_AR = $(AR) $(ARFLAGS)
+libmanager_a_LIBADD =
+am__libmanager_a_SOURCES_DIST = manager.cc mw_adapter.cc db_adapter.cc \
+ db_misc.cc mw_master.cc mw_worker.cc mw_task.cc \
+ transfer_data.cc db_postgres.cc
+ at HAVE_CONDOR_TRUE@am__objects_1 = mw_master.$(OBJEXT) \
+ at HAVE_CONDOR_TRUE@ mw_worker.$(OBJEXT) mw_task.$(OBJEXT) \
+ at HAVE_CONDOR_TRUE@ transfer_data.$(OBJEXT)
+ at HAVE_CONDOR_FALSE@@HAVE_POSTGRES_TRUE at am__objects_2 = transfer_data.$(OBJEXT)
+ at HAVE_POSTGRES_TRUE@am__objects_3 = db_postgres.$(OBJEXT)
+am_libmanager_a_OBJECTS = manager.$(OBJEXT) mw_adapter.$(OBJEXT) \
+ db_adapter.$(OBJEXT) db_misc.$(OBJEXT) $(am__objects_1) \
+ $(am__objects_2) $(am__objects_3)
+libmanager_a_OBJECTS = $(am_libmanager_a_OBJECTS)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(libmanager_a_SOURCES)
+DIST_SOURCES = $(am__libmanager_a_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__noinst_HEADERS_DIST = manager.h mw_adapter.h db_adapter.h \
+ db_misc.h mw_master.h mw_worker.h mw_task.h db_postgres.h
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src -Wno-deprecated $(am__append_1)
+noinst_LIBRARIES = libmanager.a
+libmanager_a_SOURCES = manager.cc mw_adapter.cc db_adapter.cc \
+ db_misc.cc $(am__append_2) $(am__append_4) $(am__append_5)
+noinst_HEADERS = manager.h mw_adapter.h db_adapter.h db_misc.h \
+ $(am__append_3) $(am__append_6)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/manager/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/manager/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libmanager.a: $(libmanager_a_OBJECTS) $(libmanager_a_DEPENDENCIES) $(EXTRA_libmanager_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libmanager.a
+ $(AM_V_AR)$(libmanager_a_AR) libmanager.a $(libmanager_a_OBJECTS) $(libmanager_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libmanager.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/db_adapter.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/db_misc.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/db_postgres.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/manager.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mw_adapter.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mw_master.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mw_task.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mw_worker.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/transfer_data.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/manager/db_adapter.cc b/src/manager/db_adapter.cc
new file mode 100644
index 0000000..e76bc3e
--- /dev/null
+++ b/src/manager/db_adapter.cc
@@ -0,0 +1,263 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include "manager/db_adapter.h"
+
+using namespace fsa;
+
+DB_adapter::DB_adapter() {
+#ifdef HAVE_POSTGRES
+ m_seqs_schema_id = DB_NOT_AVAILABLE;
+ m_params_table_id = DB_NOT_AVAILABLE;
+
+ m_db_connection = NULL;
+#endif
+}
+
+DB_adapter::~DB_adapter() {
+ // disconnect the connection
+ disconnect_db();
+}
+
+void DB_adapter::disconnect_db () {
+#ifdef HAVE_POSTGERS
+ if (!m_db_connection) {
+ // if there's previous connection garbage, delete it and create new one
+ m_db_connection->disconnect_db();
+ delete m_db_connection;
+ }
+
+ // set various ids as "UNDETERMINED" ids
+ m_seqs_schema_id = DB_NOT_AVAILABLE;
+ m_params_table_id = DB_NOT_AVAILABLE;
+ m_db_connection = NULL;
+
+#endif
+
+}
+
+bool DB_adapter::connect_db (const char *db_hostname, const char *db_hostaddr, const char* db_name,
+ const int db_port, const char *db_user, const char *db_password) {
+#ifndef HAVE_POSTGRES
+ return DB_BAD;
+#else
+ m_db_connection = new DB_postgres();
+
+ // can we establish a connection to the database server?
+ bool is_db_available = m_db_connection->connect_db(db_hostname, db_hostaddr, db_name, db_port, db_user, db_password);
+
+ if ( !is_db_available) {
+ // in the case that the database we are willing to connect is not running (or does not response)
+ delete m_db_connection;
+ m_db_connection = NULL;
+ }
+
+ return is_db_available;
+#endif
+}
+
+bool DB_adapter::set_up_ids (const int seqs_schema_id, const int params_table_id, const int worker_id) {
+#ifndef HAVE_POSTGRES
+ return DB_BAD;
+#else
+ // set sequence schema id
+ m_db_connection->set_seqs_schema_id (seqs_schema_id);
+
+ // set parameter table id
+ m_db_connection->set_params_table_id (params_table_id);
+
+ // set worker id
+ m_db_connection->set_worker_id (worker_id);
+
+ m_seqs_schema_id = seqs_schema_id;
+ m_params_table_id = params_table_id;
+
+ return DB_OK;
+#endif
+}
+
+bool DB_adapter::init_database(const Sequence_database &seq_db_internal, const DB_opts &db_opts) {
+
+#ifndef HAVE_POSTGRES
+ return DB_BAD;
+#else
+ if ( is_data_available() ) {
+ // in the case of the input sequences that has been previously considered
+ m_db_connection->update_fsa_table ();
+ m_db_connection->update_params_table (db_opts.num_parallelized_jobs);
+ }
+ else {
+ // if the input sequences are available - but possibly there's no relevant parameters
+ if ( is_seqs_available() )
+ m_db_connection->update_fsa_table ();
+ else {
+ std::string whole_seqs = "";
+ float seqs_avr_length = 0.0;
+ uint32_t hash_key = 0;
+ int num_seqs = seq_db_internal.size();
+
+ // generate a hash key based on the input sequences
+ for (int i=0; i<num_seqs; i++) {
+ whole_seqs += seq_db_internal.get_seq (i).seq;
+ seqs_avr_length += (float) seq_db_internal.get_seq (i).length();
+ }
+ seqs_avr_length /= (float) num_seqs;
+ seqs_avr_length = (int) seqs_avr_length;
+ hash_key = Hash_functions::hsieh_hash(whole_seqs.c_str());
+
+ // create fsa main table "public.fsa_root"
+ m_db_connection->create_fsa_table ();
+
+ // add a row to the fsa main table for the input sequences
+ m_db_connection->insert_fsa_schema (hash_key, num_seqs, seqs_avr_length);
+
+ // set the id
+ m_seqs_schema_id = m_db_connection->get_seqs_schema_id (hash_key, num_seqs, seqs_avr_length);
+
+ if (m_seqs_schema_id != DB_NOT_AVAILABLE)
+ m_db_connection->set_seqs_schema_id (m_seqs_schema_id);
+
+ // create a new schema for the input sequences with the hash key
+ m_db_connection->create_seqs_schema ();
+
+ // create a parameter table in the schema
+ m_db_connection->create_params_table ();
+
+ // create seqs table - for information of the input sequences
+ m_db_connection->create_seqs_table ();
+
+ // insert input sequences into the seqs table
+ m_db_connection->insert_seqs_table (seq_db_internal);
+ }
+
+ // insert parameter info. into the parameter table
+ m_db_connection->insert_params_table (db_opts);
+
+ // set the parameter id
+ m_params_table_id = m_db_connection->get_params_table_id (db_opts);
+ if (m_params_table_id != DB_NOT_AVAILABLE)
+ m_db_connection->set_params_table_id (m_params_table_id);
+ }
+
+ for (int i=0; i<db_opts.num_parallelized_jobs; i++) {
+
+ // create sparse matrix tables to store pairwise posterior probabilities
+ if ( m_db_connection->create_sparse_matrix_table (i) == DB_BAD ) {
+ m_db_connection->delete_sparse_matrix_table (i);
+ m_db_connection->drop_sparse_matrix_table_index (i);
+ }
+
+ // create num cells tables
+ // num cells table : how many entries are in each sequence pair
+ // Note that seq1 = 0 and seq2 = 0 indicates the number of edges
+ if ( m_db_connection->create_num_cells_table (i) == DB_BAD )
+ m_db_connection->delete_num_cells_table (i);
+
+ // create heap tables to store candidate edges of the null alignment
+ if ( m_db_connection->create_heap_table(i) == DB_BAD ) {
+ m_db_connection->delete_heap_table (i);
+ }
+
+ // create merged heap table
+ // merged heap table: when doing the sequence annealing, the merged heap table acts like the priority queue
+ if ( m_db_connection->create_merged_heap_table() == DB_BAD ) {
+ m_db_connection->delete_merged_heap_table();
+ m_db_connection->drop_merged_heap_table_index ();
+ }
+ }
+
+ return DB_OK;
+#endif
+
+}
+
+bool DB_adapter::look_up_data (const Sequence_database &seq_db_internal, const DB_opts &db_opts) {
+#ifndef HAVE_POSTGRES
+ return DB_BAD;
+#else
+ // to look up data, the database must be running
+ if (!is_db_running())
+ return DB_NO;
+
+ std::string whole_seqs = "";
+ float seqs_avr_length = 0.0;
+ uint32_t hash_key = 0;
+
+ // generate the hash key based on input sequences
+
+ for (int i=0; i<seq_db_internal.size(); i++) {
+ whole_seqs += seq_db_internal.get_seq (i).seq;
+ seqs_avr_length += (float) seq_db_internal.get_seq (i).length();
+ }
+
+ seqs_avr_length /= (float) seq_db_internal.size();
+ seqs_avr_length = (int) seqs_avr_length;
+
+ hash_key = Hash_functions::hsieh_hash(whole_seqs.c_str());
+
+ // set the sequence table id and the parameter id as looking up the appropriate data based
+ // on the input sequences (which can be referenced by seq_db_internal) and the options
+ // (which can be gotten from db_opts) that have been used when running fsa.
+
+ if ( (m_seqs_schema_id = m_db_connection->get_seqs_schema_id (hash_key, seq_db_internal.size(), seqs_avr_length) )
+ != DB_NOT_AVAILABLE) {
+ m_db_connection->set_seqs_schema_id (m_seqs_schema_id);
+
+ if ( (m_params_table_id = m_db_connection->get_params_table_id (db_opts) )
+ != DB_NOT_AVAILABLE)
+ m_db_connection->set_params_table_id (m_params_table_id);
+ }
+
+ // see if there are tables for input sequences and input parameters of the sequences.
+ if ( m_seqs_schema_id != DB_NOT_AVAILABLE && m_params_table_id != DB_NOT_AVAILABLE)
+ return DB_OK;
+ else
+ return DB_BAD;
+#endif
+
+}
+
+#ifdef HAVE_POSTGRES
+/// get the connection
+DB_postgres* DB_adapter::get_connection () {
+ return m_db_connection;
+}
+
+/// is the database server is running?
+bool DB_adapter::is_db_running ()
+{
+ if ( m_db_connection )
+ return DB_YES;
+ else
+ return DB_NO;
+}
+
+/// data is available only if there're tables related to input sequences and parameters of the input sequences.
+bool DB_adapter::is_data_available ()
+{
+ if ( is_seqs_available () && is_params_available () )
+ return DB_YES;
+ else
+ return DB_NO;
+}
+
+/// is seqs available?
+bool DB_adapter::is_seqs_available ()
+{
+ if ( m_seqs_schema_id != DB_NOT_AVAILABLE )
+ return DB_YES;
+ else
+ return DB_NO;
+}
+
+/// is parameters available?
+bool DB_adapter::is_params_available ()
+{
+ if (m_params_table_id != DB_NOT_AVAILABLE )
+ return DB_YES;
+ else
+ return DB_NO;
+}
+#endif
diff --git a/src/manager/db_adapter.h b/src/manager/db_adapter.h
new file mode 100644
index 0000000..8c8aee3
--- /dev/null
+++ b/src/manager/db_adapter.h
@@ -0,0 +1,108 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef DB_ADAPTER_INCLUDED
+#define DB_ADAPTER_INCLUDED
+
+#include "seq/sequence.h"
+#include "util/hash_fcn.h"
+#include "manager/db_misc.h"
+#ifdef HAVE_POSTGRES
+#include "manager/db_postgres.h"
+#endif
+
+namespace fsa {
+
+ /// Class DB_adapter
+ /*
+ * This is a bridge class between the Manager class and Database classes.
+ * The purpose of this class is to support many different databases.
+ * Note that currently only PostgresSQL is supported.
+ *
+ * The organization of db tables and schemas
+ *
+ * fsa_root +- schema_1 ------+-- sequence_info // for input sequences
+ * +- schema_2 +-- parameter_info // for parameters of the input sequences
+ * +- ... +-- h1_0, h1_1, ... // heap tables for candidate edges
+ * +-- ncells1_0, ncells1_1, ... // num cells tables
+ * +-- s1_0, s1_1, ... // sparse matrix tables for pairwise posterior probabilities
+ *
+ * Note 1) schema_x (i.e., x is the sequence schema id) matches the unique set of sequences
+ * Note 2) hy_z, ncellsy_z, sy_z: y is the unique parameter table id, and 0 <= z <= # of workers that have been used
+ * when generating the data
+ */
+
+ class DB_adapter
+ {
+ public:
+ /// Constructor
+ DB_adapter();
+
+ /// Distructor
+ ~DB_adapter();
+
+ /// attempt to establish a connection to the given database host
+ /*
+ * With given information, try to make a connection to database server.
+ * Note that to establish a connection, at least db_hostname (or db_hostaddr) and db_name
+ * must be provided.
+ */
+ bool connect_db (const char *db_hostname, const char* db_hostaddr, const char *db_name,
+ const int db_port, const char *db_user, const char *db_password);
+
+ /// disconnect the connection
+ void disconnect_db ();
+
+ /// look up data to be used when the sequence annealing.
+ /*
+ * seq_db_internal contains information about the input sequence strings.
+ * db_opts contains the options that have been used when running fsa
+ */
+ bool look_up_data (const Sequence_database &seq_db_internal, const DB_opts &db_opts);
+
+ /// initialize the database
+ /*
+ * If necessary, create tables and schemas, and insert tuples to the tables.
+ */
+ bool init_database(const Sequence_database &seq_db_internal, const DB_opts &db_opts);
+
+ /// set up various ids
+ /*
+ * <seqs_schema_id, params_table_id> is the unique pair of ids denoting
+ * specific sequences with the set of options that has been used when
+ * the data was generated.
+ */
+ bool set_up_ids (const int seqs_schema_id, const int params_table_id, const int worker_id);
+
+#ifdef HAVE_POSTGRES
+
+ private:
+ int m_seqs_schema_id; /// sequence schema id
+ int m_params_table_id; /// parameter table id
+ DB_postgres* m_db_connection; /// db connection object
+
+ public:
+
+ /// get the db connection
+ DB_postgres* get_connection ();
+
+ /// true if the database server is running
+ bool is_db_running ();
+
+ /// is data available? true if (is_seqs_available() && is_params_available())
+ bool is_data_available ();
+
+ /// is input sequences available?
+ bool is_seqs_available ();
+
+ /// does the data in database correspond with the input parameters?
+ bool is_params_available ();
+#endif
+
+ };
+
+}
+
+#endif
diff --git a/src/manager/db_misc.cc b/src/manager/db_misc.cc
new file mode 100644
index 0000000..0cd64cd
--- /dev/null
+++ b/src/manager/db_misc.cc
@@ -0,0 +1,36 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include "manager/db_misc.h"
+#include "fsa/fsa.h"
+
+using namespace fsa;
+
+void DB_opts::copy_opts (const FSA *from) {
+
+ // copy all options
+
+ fsa = from;
+
+ num_refinement_steps = from->num_refinement_steps;
+ anchored = from->anchored;
+
+ learn_emit_all = from->learn_emit_all;
+ learn_gap = from->learn_gap;
+ regularize = from->regularize;
+ num_parallelized_jobs = from->num_parallelized_jobs;
+ num_alignment_pairs = from->num_alignment_pairs;
+
+ db_hostname = from->db_hostname;
+ db_hostaddr = from->db_hostaddr;
+ db_name = from->db_name;
+ db_port = from->db_port;
+ db_user = from->db_user;
+ db_password = from->db_password;
+ db_max_ram = from->db_max_ram;
+
+ write_db = from->write_db;
+}
+
diff --git a/src/manager/db_misc.h b/src/manager/db_misc.h
new file mode 100644
index 0000000..dba250f
--- /dev/null
+++ b/src/manager/db_misc.h
@@ -0,0 +1,162 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef DB_MISC_INCLUDED
+#define DB_MISC_INCLUDED
+
+#include <string>
+#include "util/sstring.h"
+
+#define BUFFER_RATIO 0.9
+#define MAX_MEM_BUFFER_SIZE 1024*1024*10 // MAX SOCKET SIZE = 10MB
+#define MAX_DB_BUFFER_SIZE 1024*1024*20 // MAX DB SIZE = 1GB
+#define MAX_DB_ENTRY_LENGTH 100
+
+#define DB_FSA_SUFIX "fsa"
+#define DB_FSA_TABLE_PREFIX "root"
+
+#define DB_SEQUENCE_INFO "sequence_info"
+#define DB_SPARSE_MATRIX_INFO "sparse_matrix_info"
+#define DB_HEAP_INFO "heap_info"
+#define DB_PARAMETER_INFO "parameter_info"
+
+#define DB_SPARSE_MATRIX_SUFIX "s"
+#define DB_HEAP_SUFIX "h"
+#define DB_MERGED_HEAP_SUFIX "heap"
+#define DB_NUM_CELLS_SUFIX "ncells"
+
+#define DB_MEMORY_RATIO 1
+#define DEFAULT_DB_BUFFERSIZE ULONG_MAX
+
+namespace fsa {
+
+ struct FSA;
+
+ /// Three types of response
+ typedef enum {
+ DB_NOT_AVAILABLE = -1,
+ DB_OK = 1,
+ DB_BAD = 0
+ } DB_Response_Type;
+
+ /// Yes or No type returns
+ typedef enum {
+ DB_YES = 1,
+ DB_NO = 0
+ } DB_Yes_No_Type;
+
+ /// the structure of num cells buffer
+ /*
+ * the sparse matrix of the sequence pair (seq1, seq2)
+ * requires size data cells.
+ */
+ typedef struct Num_Cells_Buffer {
+ int seq1;
+ int seq2;
+ int size;
+ } Num_Cells_Buffer;
+
+ /// the structure of sparse matrix buffer
+ typedef struct Sparse_Matrix_Buffer {
+ int pos1;
+ int pos2;
+ float prob;
+ } Sparse_Matrix_Buffer;
+
+ /// the structure of heap buffer
+ typedef struct Heap_Buffer {
+ int seq1;
+ int pos1;
+ int seq2;
+ int pos2;
+ double weight;
+ float delta;
+ } Heap_Buffer;
+
+ /// the structure of MEM_Buffer
+ /* this is used when workers send the data including pairwise posterior probabilities and
+ * candidate edges to the master directly.
+ */
+ typedef struct MEM_Buffer {
+ Sparse_Matrix_Buffer *sparse_matrix;
+ Num_Cells_Buffer *num_cells;
+ Heap_Buffer *heap;
+ } MEM_Buffer;
+
+ /// the structure of DB_Buffer
+ /*
+ * this is used when workers put the data into the database
+ */
+ typedef struct DB_Buffer {
+ sstring sparse_matrix;
+ sstring num_cells;
+ sstring heap;
+ } DB_Buffer;
+
+ /// type define pairs
+ typedef std::pair <int, Sparse_Matrix_Buffer *> Sparse_pair;
+ typedef std::pair <int, Num_Cells_Buffer *> Cells_pair;
+ typedef std::pair <int, Heap_Buffer *> Heap_pair;
+
+ /// type define vectors
+ typedef std::vector <Sparse_pair> Sparse_vector;
+ typedef std::vector <Cells_pair> Cells_vector;
+ typedef std::vector <Heap_pair> Heap_vector;
+
+ /// the structure of MEM_Buffers
+ typedef struct MEM_Buffers {
+ Sparse_vector sparse_matrix_buffers;
+ Cells_vector num_cells_buffers;
+ Heap_vector heap_buffers;
+ } MEM_Buffers;
+
+
+ /// class DB_opts
+ /*
+ * The main purpose of this class is to store states of options that have been used when running FSA
+ */
+ struct DB_opts {
+
+ const FSA *fsa;
+
+ // alignment speedup options
+ int num_alignment_pairs; /// total number of all (n choose 2) pairs to consider during alignment inference
+
+ // sequence annealing options
+ int num_refinement_steps; /// number of iterative refinement steps
+
+ // anchoring options
+ bool anchored; /// use anchor annealing
+
+ // parameter estimation options
+ bool learn_gap; /// learn indel parameters
+ bool regularize; /// regularize learned parameters with Dirichlet distribution specified by model
+ bool learn_emit_all; /// learn emit parameters over all sequences
+
+ // parallelization options
+ int num_parallelized_jobs; /// num of jobs to be simutaneously run
+
+ // database connection options
+ sstring db_hostname; /// database server host name
+ sstring db_hostaddr; /// database server host IP address
+ sstring db_name; /// database name
+ int db_port; /// database server port
+ sstring db_user; /// database user name
+ sstring db_password; /// database password
+ int db_max_ram; /// database maximum ram
+
+ // output options
+ bool write_db; /// write post. prob. matrices and cand. edges to database
+
+ /// constructor
+ DB_opts() {}
+
+ /// Copy all parameters.
+ void copy_opts (const FSA *from);
+ };
+
+}
+
+#endif
diff --git a/src/manager/db_postgres.cc b/src/manager/db_postgres.cc
new file mode 100644
index 0000000..7420872
--- /dev/null
+++ b/src/manager/db_postgres.cc
@@ -0,0 +1,1011 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include <string.h>
+
+#include "manager/db_postgres.h"
+#include "annealing/alignment_DAG.h"
+
+
+using namespace fsa;
+
+/// connect_db
+bool DB_postgres::connect_db (const char *hostname, const char *hostaddr, const char* dbname,
+ const int port, const char *user, const char *password) {
+
+ char conninfo[DB_MAX_QUERY_LENGTH];
+ memset( conninfo, 0, sizeof(conninfo) );
+
+ // set conninfo string
+ if ( strlen(hostname) > 0 )
+ sprintf( conninfo, "host = '%s'", hostname );
+ if ( strlen(hostaddr) > 0 )
+ sprintf( conninfo, "%s hostaddr = '%s'", conninfo, hostaddr );
+ if ( strlen(dbname) > 0 )
+ sprintf( conninfo, "%s dbname = '%s'", conninfo, dbname);
+ if ( port > 0 )
+ sprintf( conninfo, "%s port = %d", conninfo, port);
+ if ( strlen(user) > 0 )
+ sprintf( conninfo, "%s user = '%s'", conninfo, user);
+ if ( strlen(password) > 0 )
+ sprintf( conninfo, "%s password = '%s'", conninfo, password);
+
+ // make a connection to the database
+ m_conn = PQconnectdb(conninfo);
+
+ // check to see that the backend connection was successfully made
+ if ( PQstatus(m_conn) != CONNECTION_OK ) {
+ CTAG(5,DB) << "Connection to database '" << PQdb(m_conn) << "' failed." << endl;
+ CTAG(3,DB) << PQerrorMessage(m_conn) << endl;
+ PQfinish(m_conn);
+
+ return DB_BAD;
+ }
+
+ CTAG(9,DB) << "Connection to database '" << PQdb(m_conn) << "' succeeded." << endl;
+
+ return DB_OK;
+}
+
+
+int DB_postgres::get_seqs_schema_id () {
+ return m_seqs_schema_id;
+}
+
+int DB_postgres::get_params_table_id () {
+ return m_params_table_id;
+}
+
+int DB_postgres::get_seqs_schema_id (const uint32_t hash_key, const int num_seqs, const float avg_length) {
+ //TODO: what happen if nTuples>1
+
+ int num_tuples, seqs_schema_id;
+
+ // make a query
+ sprintf(m_query, "SELECT id FROM %s WHERE hash = %u AND num_seqs = %d AND avg_length = %f",
+ m_fsa_table.c_str(), hash_key, num_seqs, avg_length);
+
+ // execute the query
+ if (execute_query() == DB_BAD)
+ return DB_NOT_AVAILABLE;
+
+ // get the number of tuples
+ num_tuples = PQntuples(m_res);
+
+ // error check
+ if (num_tuples == 0) {
+ PQclear (m_res);
+ return DB_NOT_AVAILABLE;
+ }
+
+ // get the sequence schema id
+ seqs_schema_id = atoi (PQgetvalue (m_res, 0, 0));
+
+ PQclear(m_res);
+
+ return seqs_schema_id;
+}
+
+
+int DB_postgres::get_params_table_id (const DB_opts &db_opts) {
+
+ int num_tuples, params_table_id;
+
+ // make a query
+ sprintf(m_query, "SELECT id, num_jobs FROM %s WHERE learn_gap = %s AND learn_emit_all = %s AND regularize = %s AND anchored = %s AND num_refinement_steps = %d",
+ m_params_table.c_str(), (db_opts.learn_gap)? "true" : "false", (db_opts.learn_emit_all)? "true" : "false",
+ (db_opts.regularize)? "true" : "false", (db_opts.anchored)? "true" : "false", db_opts.num_refinement_steps);
+
+ // execute the query
+ if (execute_query() == DB_BAD)
+ return DB_NOT_AVAILABLE;
+
+ // get the number of tuples
+ num_tuples = PQntuples(m_res);
+
+ // error check
+ if ( num_tuples == 0 ) {
+ PQclear(m_res);
+ return DB_NOT_AVAILABLE;
+ }
+
+ // get the parameter table id and the number of workers that have been used when generating the data
+ params_table_id = atoi (PQgetvalue (m_res, 0, 0));
+ m_num_jobs = atoi (PQgetvalue (m_res, 0, 1));
+
+ PQclear(m_res);
+
+ return params_table_id;
+}
+
+int DB_postgres::get_num_jobs () {
+ return m_num_jobs;
+}
+
+bool DB_postgres::update_fsa_table() {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "UPDATE %s SET last_modified = CURRENT_TIMESTAMP WHERE id = %d",
+ m_fsa_table.c_str(), m_seqs_schema_id);
+
+ // execute the query
+ if (res = execute_query())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_fsa_table () {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s (id SERIAL, hash BIGINT, num_seqs INT, avg_length INT, first_generated TIMESTAMP with time zone, last_modified TIMESTAMP with time zone)",
+ m_fsa_table.c_str());
+
+ // execute the query
+ if (res = execute_query())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::copy_to_merged_heap_table (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "INSERT INTO %s (seq1, pos1, seq2, pos2, weight, delta ) SELECT * FROM %s_%d",
+ m_merged_heap_table.c_str(), m_heap_table.c_str(), id);
+
+ // exeucte the query
+ if ( res = execute_query () )
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_merged_heap_table_index () {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE INDEX %s_%s_idx ON %s (weight DESC, seq1, seq2, pos1, pos2)",
+ m_seqs_schema.c_str(), m_merged_heap_prefix.c_str(), m_merged_heap_table.c_str());
+
+ // execute the query
+ res = execute_query();
+
+ if (res)
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::insert_fsa_schema (const uint32_t &hash_key, const int &num_seqs, const float &avg_length) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "INSERT INTO %s (hash, num_seqs, avg_length, first_generated, last_modified) VALUES (%u, %d, %f, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)",
+ m_fsa_table.c_str(), hash_key, num_seqs, avg_length);
+
+ // execute the query
+ if (res = execute_query())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_seqs_schema() {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE SCHEMA %s", m_seqs_schema.c_str());
+
+ // execute the query
+ if (res = execute_query())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_params_table() {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s (id SERIAL, learn_gap BOOLEAN, learn_emit_all BOOLEAN, regularize BOOLEAN, anchored BOOLEAN, num_refinement_steps INT, first_generated TIMESTAMP with time zone, last_modified TIMESTAMP with time zone, num_jobs INT)",
+ m_params_table.c_str());
+
+ // execute the query
+ if (res = execute_query())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_seqs_table() {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s (id SERIAL, sequence TEXT, length INT, hash BIGINT)",
+ m_seqs_table.c_str());
+
+ // execute the query
+ if (res = execute_query())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::insert_seqs_table(const Sequence_database &seq_db_internal) {
+
+ sstring seqs_buffer;
+ sstring table_name;
+
+ seqs_buffer.clear();
+ table_name.clear();
+
+ table_name = m_seqs_table.c_str();
+ table_name += " (sequence, length, hash)";
+
+ // make a buffer to contain input sequence strings
+ for (int i = 0; i < seq_db_internal.size(); i++) {
+ seqs_buffer.append(seq_db_internal.get_seq (i).seq);
+ sprintf(m_exec, "\t%d\t%lu\n", seq_db_internal.get_seq (i).length(), Hash_functions::hsieh_hash (seq_db_internal.get_seq (i).seq.c_str()));
+ seqs_buffer.append(m_exec);
+ }
+
+ // put the input sequence strings into the database
+ return copy_stdin (table_name.c_str(), seqs_buffer.c_str());
+}
+
+bool DB_postgres::get_merged_heap (const int size, const int offset, double &min_edge_weight,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps, std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges, bool &last) {
+
+ // make a query
+ sprintf(m_query,"SELECT seq1, pos1, seq2, pos2, weight, delta FROM %s ORDER BY WEIGHT DESC LIMIT %d OFFSET %d",
+ m_merged_heap_table.c_str(), size, offset * size);
+
+ // execute the query
+ if (!execute_query())
+ return DB_BAD;
+
+ int num_tuples, seq1, pos1, seq2, pos2;
+ double weight;
+ float delta;
+ Edge *edge = NULL;
+
+ // get the number of tuples
+ num_tuples = PQntuples(m_res);
+
+ // if the number of result tuples is less than size, then
+ // it means that the reult is the last set of tuples
+ if (num_tuples < size)
+ last = true;
+
+ // error check
+ if (num_tuples == 0) {
+ PQclear (m_res);
+ return DB_BAD;
+ }
+
+ // put edges into the priority queue
+ for (int i = 0; i < num_tuples; i++) {
+ seq1 = atoi (PQgetvalue (m_res, i, 0));
+ pos1 = atoi (PQgetvalue (m_res, i, 1));
+ seq2 = atoi (PQgetvalue (m_res, i, 2));
+ pos2 = atoi (PQgetvalue (m_res, i, 3));
+ weight = atof (PQgetvalue (m_res, i, 4));
+ delta = atof (PQgetvalue (m_res, i, 5));
+
+ // min_edge_weight == 0.0: initial condition
+ // find the smallest weight
+ if (min_edge_weight == 0.0 || min_edge_weight > weight)
+ min_edge_weight = weight;
+
+ // create a new edge and push it into the queue
+ edge = new Edge(seq_pos_col_maps[seq1][pos1], seq_pos_col_maps[seq2][pos2],
+ std::pair<int, int> (seq1, pos1), std::pair<int, int> (seq2, pos2), weight, delta, 2);
+ edges.push(edge);
+ }
+
+ PQclear(m_res);
+
+ return DB_OK;
+}
+
+int DB_postgres::get_heaps (const int worker_id, double &min_edge_weight, std::vector<Seq_pos_col_map> &seq_pos_col_maps,
+ std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges) {
+
+ sstring table_name;
+ std::stringstream sstream;
+
+ table_name.clear();
+ sstream << worker_id;
+
+ // set the table name
+ table_name = m_heap_table.c_str();
+ table_name += "_";
+ table_name += sstream.str();
+
+ // move tuples in database tables to the standard output
+ if ( copy_stdout (table_name.c_str()) != DB_OK)
+ return DB_BAD;
+
+ char *buf;
+ int seq1, seq2, pos1, pos2;
+ double weight;
+ float delta;
+ Edge *edge = NULL;
+
+ // put edges into the priority queue
+ if (PQgetCopyData(m_conn, &buf, 0) != -1) {
+ do {
+ char *pch;
+ pch = strtok(buf, "\t"); seq1 = atoi(pch);
+ pch = strtok(NULL, "\t"); pos1 = atoi(pch);
+ pch = strtok(NULL, "\t"); seq2 = atoi(pch);
+ pch = strtok(NULL, "\t"); pos2 = atoi(pch);
+ pch = strtok(NULL, "\t"); weight = atof(pch);
+ pch = strtok(NULL, "\t"); delta = atof(pch);
+
+ // deallocated the memory
+ PQfreemem(buf);
+
+ // find the smallest weight
+ if ( min_edge_weight > weight)
+ min_edge_weight = weight;
+
+ // create a new edge and push it into the queue
+ edge = new Edge(seq_pos_col_maps[seq1][pos1], seq_pos_col_maps[seq2][pos2],
+ std::pair<int, int> (seq1, pos1), std::pair<int, int> (seq2, pos2), weight, delta, 2);
+ edges.push(edge);
+
+ } while ( (PQgetCopyData(m_conn, &buf, 0)) != -1);
+ } else
+ return DB_NOT_AVAILABLE;
+
+ return DB_OK;
+}
+
+int DB_postgres::get_sparse_matrices (const int worker_id, const Sequence_database &seq_db_internal,
+ const std::vector<std::vector<int> > &num_cells, std::vector<std::vector<SparseMatrix*> > &sparse_matrices) {
+
+ sstring table_name;
+ std::stringstream sstream;
+
+ table_name.clear();
+ sstream << worker_id;
+
+ // set the table name
+ table_name = m_sparse_matrix_table.c_str();
+ table_name += "_";
+ table_name += sstream.str();
+
+ // move tuples in database tables to the standard output
+ if ( copy_stdout (table_name.c_str()) != DB_OK)
+ return DB_BAD;
+
+ char *buf;
+ int seq1, seq2, pos1, pos2, offset = 0;
+ int ex_seq1 = -1, ex_seq2 = -1;
+ float prob;
+
+ int cnt = 0;
+
+ // put edges into the priority queue
+ if ( (PQgetCopyData (m_conn, &buf, 0 )) != -1) {
+
+ do {
+ ++cnt;
+ char *pch;
+ pch = strtok(buf, "\t"); seq1 = atoi(pch);
+ pch = strtok(NULL, "\t"); pos1 = atoi(pch);
+ pch = strtok(NULL, "\t"); seq2 = atoi(pch);
+ pch = strtok(NULL, "\t"); pos2 = atoi(pch);
+ pch = strtok(NULL, "\t"); prob = atof(pch);
+
+ // deallocated the memory
+ PQfreemem(buf);
+
+ if ( sparse_matrices[seq1][seq2] == NULL ) {
+
+ // once the sparse matrix of the sequence pair (ex_seq1, ex_seq2) has been constructed,
+ // create a new sparse matrix of sequence pair (ex_seq2, ex_seq1)
+
+ if (ex_seq1 != -1 && ex_seq2 != -1)
+ sparse_matrices[ex_seq2][ex_seq1] = sparse_matrices[ex_seq1][ex_seq2]->ComputeTranspose();
+
+ offset = 0;
+
+ int seq1Length = seq_db_internal.get_seq (seq1).length();
+ int seq2Length = seq_db_internal.get_seq (seq2).length();
+
+ ex_seq1 = seq1;
+ ex_seq2 = seq2;
+
+ // create the sparse matrix for the sequence pair (seq1, seq2)
+ sparse_matrices[seq1][seq2] = new SparseMatrix (seq1, seq2,
+ seq1Length, seq2Length,
+ num_cells[seq1][seq2] - seq1Length - seq2Length);
+ }
+
+ // insert a pairwise posterior probabitlity into the sparse matrix
+ sparse_matrices[seq1][seq2]->add_probability (pos1, pos2, prob, offset);
+
+ if (pos1 != 0 && pos2 != 0 )
+ offset++;
+
+ } while ( (PQgetCopyData(m_conn, &buf, 0)) != -1);
+
+ }
+ else
+ return DB_NOT_AVAILABLE;
+
+ // compute the transpose for the last sequence pair
+ sparse_matrices[ex_seq2][ex_seq1] = sparse_matrices[ex_seq1][ex_seq2]->ComputeTranspose();
+
+ return DB_OK;
+}
+
+bool DB_postgres::get_sparse_matrix (const int worker_id, const int seq1, const int seq2,
+ const int seq1Length, const int seq2Length,
+ std::vector<std::vector<SparseMatrix*> > &sparse_matrices) {
+
+ // make a query
+ sprintf(m_query,"SELECT pos1, pos2, prob FROM %s_%d where seq1 = %d and seq2 = %d order by pos1, pos2",
+ m_sparse_matrix_table.c_str(), worker_id, seq1, seq2);
+
+ // execute the query
+ if (!execute_query())
+ return DB_BAD;
+
+ int num_tuples, pos1, pos2, offset = 0;
+ float prob;
+
+ // get the number of tuples
+ num_tuples = PQntuples(m_res);
+
+ if (num_tuples == 0) {
+ PQclear (m_res);
+ return DB_BAD;
+ }
+
+ // create the sparse matrix for the sequence pair (seq1, seq2)
+ sparse_matrices[seq1][seq2] = new SparseMatrix (seq1, seq2,
+ seq1Length, seq2Length,
+ num_tuples - seq1Length - seq2Length);
+
+ for (int i = 0; i < num_tuples; i++) {
+ pos1 = atoi (PQgetvalue (m_res, i, 0));
+ pos2 = atoi (PQgetvalue (m_res, i, 1));
+ prob = atof (PQgetvalue (m_res, i, 2));
+
+ // insert a pairwise posterior probability to the sparse matrix
+ sparse_matrices[seq1][seq2]->add_probability (pos1, pos2, prob, offset);
+
+ if (pos1 != 0 && pos2 != 0)
+ offset++;
+ }
+
+ PQclear (m_res);
+
+ return DB_OK;
+}
+
+int DB_postgres::get_list_of_available_pairs (const int worker_id, std::vector<std::vector<int> > &available_sparse_matrices,
+ const Sequence_database *seq_db_internal, double &avg_sparse_matrix_size, int &num_pairs, int &orig_edges_size) {
+
+ sstring table_name;
+ std::stringstream sstream;
+
+ table_name.clear();
+ sstream << worker_id;
+
+ // set the table name
+ table_name = m_num_cells_table.c_str();
+ table_name += "_";
+ table_name += sstream.str();
+
+ // move tuples in the database tables to the standard output
+ if ( copy_stdout (table_name.c_str()) != DB_OK)
+ return DB_BAD;
+
+ char *buf;
+ int seq1, seq2, nCells;
+
+ double avg_size = 0.0;
+ int cnt_pairs = 0;
+
+ if (PQgetCopyData(m_conn, &buf, 0)!= -1) {
+ do {
+ char *pch;
+ pch = strtok(buf, "\t"); seq1 = atoi(pch);
+ pch = strtok(NULL, "\t"); seq2 = atoi(pch);
+ pch = strtok(NULL, "\t"); nCells = atoi(pch);
+
+ // deallocate the memory
+ PQfreemem(buf);
+
+ int seq1Length = seq_db_internal->get_seq (seq1).length();
+ int seq2Length = seq_db_internal->get_seq (seq2).length();
+
+ if (seq1 == 0 && seq2 == 0 )
+ orig_edges_size += nCells;
+ else {
+ cnt_pairs++;
+
+ // flag the availability of the sparse matrix (seq1, seq2) on by setting the worker id
+ // which has generated the sparse matrix
+ available_sparse_matrices[seq1][seq2] = worker_id;
+ avg_size += sizeof (int) * (seq1Length + 1) + sizeof (int) * (seq1Length + 1) +
+ sizeof(float) * (seq1Length + seq2Length + 2) + (sizeof (int) + sizeof(float)) * nCells;
+ }
+ } while ( (PQgetCopyData(m_conn, &buf, 0)) != -1);
+ } else
+ return DB_NOT_AVAILABLE;
+
+ // compute the average sparse matrix size
+ avg_sparse_matrix_size = ((avg_sparse_matrix_size * (double) num_pairs ) + avg_size) / ((double) (num_pairs + cnt_pairs));
+
+ // compute the sum of available sequence pairs
+ num_pairs += cnt_pairs;
+
+ return DB_OK;
+}
+
+int DB_postgres::get_num_cells (const int worker_id, std::vector<std::vector<int> > &num_cells) {
+
+ sstring table_name;
+ std::stringstream sstream;
+
+ table_name.clear();
+ sstream << worker_id;
+
+ // set the table name
+ table_name = m_num_cells_table.c_str();
+ table_name += "_";
+ table_name += sstream.str();
+
+ // move the tuples in the database tables to the standard output
+ if ( copy_stdout (table_name.c_str()) != DB_OK)
+ return DB_BAD;
+
+ char *buf;
+ int seq1, seq2, nCells;
+
+ if (PQgetCopyData(m_conn, &buf, 0)!= -1) {
+ do {
+ char *pch;
+ pch = strtok(buf, "\t"); seq1 = atoi(pch);
+ pch = strtok(NULL, "\t"); seq2 = atoi(pch);
+ pch = strtok(NULL, "\t"); nCells = atoi(pch);
+
+ // deallocate the memory
+ PQfreemem(buf);
+
+ // set the number of data cells that are used for the sparse matrix (seq1, seq2)
+ num_cells[seq1][seq2] += nCells;
+
+ } while ( (PQgetCopyData(m_conn, &buf, 0)) != -1);
+ } else
+ return DB_NOT_AVAILABLE;
+
+ return DB_OK;
+}
+
+bool DB_postgres::copy_stdout (const char *table_name) {
+
+ // make a query
+ sprintf(m_query, "COPY %s TO STDOUT", table_name);
+
+ // execute the query
+ execute_query();
+
+ PQclear(m_res);
+
+ return DB_OK;
+}
+
+bool DB_postgres::copy_stdin (const char *table_name, const char* copy_string) {
+
+ // make a query
+ sprintf(m_query, "COPY %s FROM STDIN", table_name);
+
+ // execute the query
+ execute_query();
+
+ PQclear(m_res);
+
+ PQputCopyData(m_conn, copy_string, strlen(copy_string));
+
+ PQputCopyEnd(m_conn, NULL);
+
+ m_res = PQgetResult(m_conn);
+
+ // error check
+ if (PQresultStatus(m_res) != PGRES_COPY_IN && PQresultStatus(m_res) != PGRES_COMMAND_OK) {
+ PQclear(m_res);
+ return DB_BAD;
+ }
+
+ PQclear(m_res);
+ return DB_OK;
+}
+
+bool DB_postgres::insert_params_table (const DB_opts &db_opts) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "INSERT INTO %s (learn_gap, learn_emit_all, regularize, anchored, num_refinement_steps, first_generated, last_modified, num_jobs) VALUES (%s, %s, %s, %s, %d, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, %d)",
+ m_params_table.c_str(), (db_opts.learn_gap)? "true" : "false",
+ (db_opts.learn_emit_all)? "true" : "false",
+ (db_opts.regularize)? "true" : "false",
+ (db_opts.anchored)? "true" : "false", db_opts.num_refinement_steps,
+ db_opts.num_parallelized_jobs);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_num_cells_table (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s_%d (seq1 INT, seq2 INT, num_cells INT)",
+ m_num_cells_table.c_str(), id);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_sparse_matrix_table (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s_%d (seq1 INT, pos1 INT, seq2 INT, pos2 INT, prob FLOAT)",
+ m_sparse_matrix_table.c_str(), id);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::delete_num_cells_table(const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "TRUNCATE %s_%d", m_num_cells_table.c_str(), id);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::delete_sparse_matrix_table(const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "TRUNCATE %s_%d", m_sparse_matrix_table.c_str(), id);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::update_params_table (const int num_parallelized_jobs) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "UPDATE %s SET last_modified = CURRENT_TIMESTAMP, num_jobs = %d WHERE id = %d",
+ m_params_table.c_str(), num_parallelized_jobs, m_params_table_id);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear(m_res);
+
+ // set the number of jobs (Note that this is equivalent to the nubmer of workers)
+ m_num_jobs = num_parallelized_jobs;
+
+ return res;
+}
+
+bool DB_postgres::drop_sparse_matrix_table_index (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "DROP INDEX %s.%s_%s_%d_idx",
+ m_seqs_schema.c_str(), m_seqs_schema.c_str(), m_sparse_matrix_prefix.c_str(), id);
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear (m_res);
+
+ return res;
+}
+
+bool DB_postgres::drop_merged_heap_table_index () {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "DROP INDEX %s.%s_%s_idx",
+ m_seqs_schema.c_str(), m_seqs_schema.c_str(), m_merged_heap_prefix.c_str());
+
+ // execute the query
+ if (res = execute_query ())
+ PQclear (m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_heap_table (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s_%d (seq1 INT, pos1 INT, seq2 INT, pos2 INT, weight DOUBLE PRECISION, delta FLOAT )",
+ m_heap_table.c_str(), id);
+
+ // execute the query
+ if ( res = execute_query () )
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::create_merged_heap_table () {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE TABLE %s (seq1 INT, pos1 INT, seq2 INT, pos2 INT, weight DOUBLE PRECISION, delta FLOAT ) ",
+ m_merged_heap_table.c_str());
+
+ // execute the query
+ if ( res = execute_query () )
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::delete_merged_heap_table () {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "TRUNCATE %s",
+ m_merged_heap_table.c_str());
+
+ // execute the query
+ if (res = execute_query() )
+ PQclear(m_res);
+
+ return res;
+}
+
+bool DB_postgres::delete_heap_table (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "TRUNCATE %s_%d",
+ m_heap_table.c_str(),id);
+
+ // execute the query
+ if (res = execute_query() )
+ PQclear(m_res);
+
+ return res;
+}
+
+void DB_postgres::flush_merged_heap_buffer(const char* string)
+{
+ // move the contents in the buffer (i.e., char* string) to the database table
+ if (strlen (string) > 0 )
+ copy_stdin (m_merged_heap_table.c_str(), string);
+}
+
+void DB_postgres::flush_sparse_matrix_buffer(const char* string)
+{
+ // move the contents in the buffer (i.e., char* string) to the database table
+ if (strlen (string) > 0)
+ copy_stdin (m_sparse_matrix_table.c_str(), string);
+}
+
+void DB_postgres::flush_num_cells_buffer(const char* string)
+{
+ // move the contents in the buffer (i.e., char* string) to the database table
+ if (strlen(string) > 0)
+ copy_stdin (m_num_cells_table.c_str(), string);
+}
+
+void DB_postgres::flush_heap_buffer(const char *string)
+{
+ // move the contents in the buffer (i.e., char* string) to the database table
+ if (strlen (string) > 0 ) {
+ copy_stdin (m_heap_table.c_str(), string);
+ }
+}
+
+void DB_postgres::set_worker_id (const int worker_id) {
+
+ // append the worker id to the heap table name, the sparse matrix table name,
+ // and the num cells table name
+ std::stringstream sstream;
+ sstream << worker_id;
+
+ m_heap_table += "_" + sstream.str();
+ m_sparse_matrix_table += "_" + sstream.str();
+ m_num_cells_table += "_" + sstream.str();
+}
+
+void DB_postgres::set_seqs_schema_id (const int seqs_schema_id) {
+
+ // make the sequence schema name, the sequence table name, the sparse matrix info table name,
+ // the heap info table name, and the parameter table name
+ m_seqs_schema_id = seqs_schema_id;
+ std::stringstream sstream;
+ sstream << m_seqs_schema_id;
+
+ m_seqs_schema.clear();
+ m_seqs_schema = DB_FSA_SUFIX;
+ m_seqs_schema += "_";
+ m_seqs_schema += sstream.str();
+
+ m_seqs_table.clear();
+ m_seqs_table = m_seqs_schema;
+ m_seqs_table += ".";
+ m_seqs_table += DB_SEQUENCE_INFO;
+
+ m_sparse_matrix_info.clear();
+ m_sparse_matrix_info = m_seqs_schema;
+ m_sparse_matrix_info += ".";
+ m_sparse_matrix_info += DB_SPARSE_MATRIX_INFO;
+
+ m_heap_info.clear();
+ m_heap_info = m_seqs_schema;
+ m_heap_info += ".";
+ m_heap_info += DB_HEAP_INFO;
+
+ m_params_table.clear();
+ m_params_table = m_seqs_schema;
+ m_params_table += ".";
+ m_params_table += DB_PARAMETER_INFO;
+}
+
+void DB_postgres::set_params_table_id (const int params_table_id) {
+
+ // make the heap_table name, the merged_heap_table name, the sparse_matrix_table name,
+ // and the num cells table name
+ m_params_table_id = params_table_id;
+ std::stringstream sstream;
+ sstream << m_params_table_id;
+
+ m_heap_prefix.clear();
+ m_heap_prefix = DB_HEAP_SUFIX;
+ m_heap_prefix += sstream.str();
+
+ m_heap_table.clear();
+ m_heap_table = m_seqs_schema;
+ m_heap_table += ".";
+ m_heap_table += m_heap_prefix;
+
+ m_merged_heap_prefix.clear();
+ m_merged_heap_prefix = DB_MERGED_HEAP_SUFIX;
+ m_merged_heap_prefix += sstream.str();
+
+ m_merged_heap_table.clear();
+ m_merged_heap_table = m_seqs_schema;
+ m_merged_heap_table += ".";
+ m_merged_heap_table += m_merged_heap_prefix;
+
+ m_sparse_matrix_prefix.clear();
+ m_sparse_matrix_prefix = DB_SPARSE_MATRIX_SUFIX;
+ m_sparse_matrix_prefix += sstream.str();
+
+ m_sparse_matrix_table.clear();
+ m_sparse_matrix_table = m_seqs_schema;
+ m_sparse_matrix_table += ".";
+ m_sparse_matrix_table += m_sparse_matrix_prefix;
+
+ m_num_cells_table.clear();
+ m_num_cells_table = m_seqs_schema;
+ m_num_cells_table += ".";
+ m_num_cells_table += DB_NUM_CELLS_SUFIX;
+ m_num_cells_table += sstream.str();
+}
+
+bool DB_postgres::execute_query() {
+
+ // execute the query
+ m_res = PQexec(m_conn, m_query);
+
+ // error check
+ if (PQresultStatus(m_res) != PGRES_COMMAND_OK && PQresultStatus(m_res) != PGRES_TUPLES_OK
+ && PQresultStatus(m_res) != PGRES_COPY_IN && PQresultStatus(m_res) != PGRES_COPY_OUT) {
+
+ PQclear(m_res);
+ m_res = NULL;
+ return DB_BAD;
+ }
+
+ return DB_OK;
+}
+
+DB_postgres::DB_postgres() {
+ m_conn = NULL;
+
+ // make the fsa_table name, which is the main table name
+ m_fsa_table.clear();
+ m_fsa_table = DB_FSA_SUFIX;
+ m_fsa_table += "_";
+ m_fsa_table += DB_FSA_TABLE_PREFIX;
+}
+
+DB_postgres::~DB_postgres() {}
+
+void DB_postgres::disconnect_db() {
+ PQfinish(m_conn);
+}
+
+bool DB_postgres::create_sparse_matrix_table_index (const int id) {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "CREATE INDEX %s_%s_%d_idx ON %s_%d (seq1, seq2, pos1, pos2)",
+ m_seqs_schema.c_str(), m_sparse_matrix_prefix.c_str(), id, m_sparse_matrix_table.c_str(), id);
+
+ // execute the query
+ res = execute_query();
+
+ if (res)
+ PQclear(m_res);
+
+ return res;
+}
+
+int DB_postgres::get_merged_heap_size() {
+
+ bool res;
+
+ // make a query
+ sprintf(m_query, "SELECT COUNT(weight) FROM %s",
+ m_merged_heap_table.c_str());
+
+ // execute the query
+ res = execute_query();
+
+ if (res)
+ PQclear(m_res);
+
+ return res;
+}
diff --git a/src/manager/db_postgres.h b/src/manager/db_postgres.h
new file mode 100644
index 0000000..fe8fb78
--- /dev/null
+++ b/src/manager/db_postgres.h
@@ -0,0 +1,301 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef DB_POSTGRES_INCLUDED
+#define DB_POSTGRES_INCLUDED
+
+#include <queue>
+#include <string>
+
+#include "libpq-fe.h"
+#include "manager/db_misc.h"
+
+#include "seq/sequence.h"
+#include "util/hash_fcn.h"
+#include "annealing/SparseMatrix.h"
+
+namespace fsa {
+
+ class Edge;
+ class Column;
+ class smaller_weight;
+
+ /// Map a position in a sequence to the containing Column*.
+ typedef std::vector<Column*> Seq_pos_col_map;
+
+ /// Maximum length of queries
+#define DB_MAX_QUERY_LENGTH 1000
+
+ /// DB_postgres class
+ /*
+ * This class contains database methods depending on PostgreSQL.
+ * This class has developed based on PostgreSQL 8.3.1
+ *
+ * For more information about PostgreSQL,
+ * please visit http://www.postgresql.org
+ *
+ * For more information about database tables, schemas, ids, etc,
+ * please see db_adapter.h
+ */
+
+ class DB_postgres
+ {
+ public:
+ /// Constructor
+ DB_postgres();
+
+ /// Destructor
+ ~DB_postgres();
+
+ /// Attempt to establish a connection to the given database host
+ /*
+ * With given information, try to make a connection to database server.
+ * Note that to establish a connection, at least db_hostname (or db_hostaddr) and db_name
+ * must be provided.
+ */
+ bool connect_db (const char *hostname, const char *hostaddr, const char* dbname,
+ const int port, const char *user, const char *password);
+
+ /// Disconnect from the database
+ void disconnect_db();
+
+ /// Get methods
+
+ /// Return sequence schema id
+ /*
+ * Looking up the database with a combination of hash_key (that has been generated by using
+ * input sequences), the number of the input sequences, and the average length of the sequences.
+ */
+ int get_seqs_schema_id (const uint32_t hash_key, const int num_seqs, const float avg_length);
+
+ /// Return sequence schema id
+ /*
+ * Just return the sequence schema id. This method is called only from the WORKER instance.
+ */
+ int get_seqs_schema_id ();
+
+ /// Return parameter table id
+ /*
+ * Looking up the database with a combination of options that has been inputed when running FSA.
+ * If no options are used, then select conditions are filled with default options.
+ */
+ int get_params_table_id (const DB_opts &db_opts);
+
+ /// Return parameter table id
+ /*
+ * Just return the parameter table id. This method is called only from the WORKER instance.
+ */
+ int get_params_table_id ();
+
+ /// Return the number of jobs
+ /*
+ * Return the number of workers that have been used to generate the data.
+ */
+ int get_num_jobs ();
+
+ /// Create sparse matrices
+ /*
+ * Construct all sparse matrices with pairwise posterior probabilties in the database.
+ */
+ int get_sparse_matrices (const int worker_id, const Sequence_database &seq_db_internal,
+ const std::vector<std::vector<int> > &num_cells, std::vector<std::vector<SparseMatrix*> > &sparse_matrices);
+
+ /// Create a sparse matrix
+ /*
+ * Construct a sparse matrix of the sequence pair (seq1, seq2)
+ */
+ bool get_sparse_matrix (const int worker_id, const int seq1, const int seq2,
+ const int seq1Length, const int seq2Length, std::vector<std::vector<SparseMatrix*> > &sparse_matrices);
+
+ /// Get a number of cells that is constituted for each sparse matrix
+ /*
+ * A num_cells table contains the number of data cells that are used to construct each sparse matrix.
+ */
+ int get_num_cells (const int worker_id, std::vector<std::vector<int> > &num_cells);
+
+ /// Get the list of available pairs
+ /*
+ * If there's N input sequences, total N*(N-1)/2 pairs are considered for the annealing. However, it does
+ * not always heppen (ex, --fast option). Therefore, we need to determine which sequence pairs would be
+ * considered for the sequence annealing.
+ */
+ int get_list_of_available_pairs (const int worker_id, std::vector<std::vector<int> > &available_sparse_matrices,
+ const Sequence_database *seq_db_internal, double &avg_sparse_matrix_size, int &num_pairs, int &orig_edges_size);
+
+ /// Get all candidate edges of the null alignment
+ /*
+ * Construct the initial priority queue with candidate edges of the null alignment.
+ */
+ int get_heaps (const int worker_id, double &min_edge_weight, std::vector<Seq_pos_col_map> &seq_pos_col_maps,
+ std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges);
+
+ /// Get some of candidate edges of the null alignment
+ /*
+ * When there's a restriction on the memory size that can be consumed, instead of getting all candidate edges
+ * at once, it is needed to get some candidate edges. The number of candidate edges that are gotten at once is
+ * size.
+ */
+ bool get_merged_heap (const int size, const int offset, double &min_edge_weight,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps, std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges, bool &last);
+
+ /// Return the size of merged heap.
+ int get_merged_heap_size();
+
+ /// Put pairwise posterior probabilities into the database.
+ void flush_sparse_matrix_buffer(const char *string);
+
+ /// Put numbers of data cells of sparse matrices into the database.
+ void flush_num_cells_buffer(const char *string);
+
+ /// Put candidate edges of the null alignment into the database.
+ void flush_heap_buffer(const char *string);
+
+ /// Put re-weighted edges into the database.
+ void flush_merged_heap_buffer(const char* string);
+
+ /// Insert-related methods
+
+ /// Insert a tuple into the fsa_main table for a schema related to the input sequences.
+ bool insert_fsa_schema (const uint32_t &hash_key, const int &num_seqs, const float &avg_length);
+
+ /// Insert tuples into the sequence table, with each tuple matching to the each input sequence.
+ bool insert_seqs_table (const Sequence_database &seq_db_internal);
+
+ /// Insert a tuple into the parameter table for the options that have been used when generating the data.
+ bool insert_params_table (const DB_opts &db_opts);
+
+
+ /// Set methods
+
+ /// Set sequence schema id.
+ void set_seqs_schema_id (const int seqs_schema_id);
+
+ /// Set parameter table id.
+ void set_params_table_id (const int params_table_id);
+
+ /// Set worker id.
+ void set_worker_id (const int worker_id);
+
+ /// Update methods
+
+ /// Update the tuple that has already been in the main_fsa table.
+ bool update_fsa_table ();
+
+ /// Update the tuple that has already been in the parameter table.
+ bool update_params_table (const int num_parallelized_jobs);
+
+
+ /// Create methods
+
+ /// Create fsa_table which is the main table.
+ bool create_fsa_table ();
+
+ /// Create a sequence schema which is related to a set of input sequences.
+ bool create_seqs_schema ();
+
+ /// Create the parameter table which belongs to a sequence schema.
+ bool create_params_table();
+
+ /// Create a sequence table.
+ bool create_seqs_table();
+
+ /// Create a sparse matrix table with given id.
+ bool create_sparse_matrix_table (const int id);
+
+ /// Create an index on the sparse matrix table_id.
+ bool create_sparse_matrix_table_index (const int id);
+
+ /// Create a num_cells table.
+ bool create_num_cells_table (const int id);
+
+ /// Create a heap table.
+ bool create_heap_table (const int id);
+
+ /// Create the merged_heap_table.
+ bool create_merged_heap_table ();
+
+ /// Create an index on the merged heap table.
+ bool create_merged_heap_table_index ();
+
+
+ /// Delete methods
+
+ /// Delete tuples in the sparse matrix table.
+ bool delete_sparse_matrix_table (const int id);
+
+ /// Delete tuples in the num_cells table.
+ bool delete_num_cells_table (const int id);
+
+ /// Delete tuples in the heap table.
+ bool delete_heap_table (const int id);
+
+ /// Delete tuples in the merged heap table.
+ bool delete_merged_heap_table ();
+
+
+ /// Drop methods
+
+ /// Drop the sparse matrix table index
+ bool drop_sparse_matrix_table_index (const int id);
+
+ /// Drop the merged heap table index
+ bool drop_merged_heap_table_index ();
+
+
+ /// Execute_query
+ /*
+ * Execute the query in m_query
+ */
+ bool execute_query ();
+
+ /// move contents in the buffer (copy_string) to the database tables
+ /*
+ * NOTE: it is PostgreSQL specific methods. It is much much faster than just "INSERT" query
+ */
+ bool copy_stdin (const char *table_name, const char* copy_string);
+
+ /// move contents in the database tables to the standard output
+ /*
+ * NOTE: it is PostgreSQL specific methods. It is much much faster than just "SELECT" query
+ */
+ bool copy_stdout (const char *table_name);
+
+ /// Copy heap tables to the merged heap table
+ /*
+ * The merged heap table is used only when the db-maxram option is used.
+ */
+ bool copy_to_merged_heap_table (const int id);
+
+ private:
+ PGconn *m_conn; // the class to access PostgreSQL database
+ PGresult *m_res; // the class to represent the query result tuples
+ char m_query[DB_MAX_QUERY_LENGTH]; // common buffer for queries
+ char m_exec[DB_MAX_QUERY_LENGTH]; // common buffer for execution commands
+
+ int m_seqs_schema_id; // seqeunce schema id
+ int m_params_table_id; // parameter table id
+ int m_num_jobs; // the number of jobs (workers)
+
+ sstring m_seqs_schema; // sequence schema name
+ sstring m_params_table; // parameter table name
+ sstring m_seqs_table; // sequence table name
+
+ sstring m_sparse_matrix_info; // sparse matrix info
+ sstring m_heap_info; // heap info
+
+ sstring m_fsa_table; // fsa table name
+ sstring m_heap_table; // heap table name
+ sstring m_merged_heap_table; // merged heap table name
+ sstring m_sparse_matrix_table; // sparse matrix table name
+ sstring m_num_cells_table; // num cells table name
+
+ sstring m_sparse_matrix_prefix; // sparse matrix prefix
+ sstring m_heap_prefix; // heap prefix
+ sstring m_merged_heap_prefix; // merged heap prefix
+ };
+
+}
+
+#endif
diff --git a/src/manager/manager.cc b/src/manager/manager.cc
new file mode 100644
index 0000000..8dc0025
--- /dev/null
+++ b/src/manager/manager.cc
@@ -0,0 +1,772 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include "manager/manager.h"
+#include "annealing/alignment_DAG.h"
+#include "fsa/fsa.h"
+
+using namespace fsa;
+
+
+#ifdef HAVE_POSTGRES
+extern void init_single_worker(const FSA *fsa, DB_adapter *db_adapter, Params ¶ms_seed, Params &pseudocounts);
+extern void build_multiple_alignment();
+extern void build_anchored_multiple_alignment();
+#endif
+
+Manager::Manager() {
+ m_seq_db_internal = NULL;
+ m_db_opts = NULL;
+
+#ifdef HAVE_POSTGRES
+ m_num_cells = NULL;
+ m_available_sparse_matrices = NULL;
+ m_sparse_matrix_scheduler = NULL;
+#endif
+
+}
+
+Manager::Manager(const Sequence_database &seq_db_internal, DB_opts &db_opts) {
+
+ m_seq_db_internal = &seq_db_internal;
+ m_db_opts = &db_opts;
+
+#ifdef HAVE_POSTGRES
+ bool is_db_running, is_db_available;
+
+ // make a connection to the database
+ is_db_running = m_db_adapter.connect_db(m_db_opts->db_hostname.c_str(), m_db_opts->db_hostaddr.c_str(),
+ m_db_opts->db_name.c_str(), m_db_opts->db_port, m_db_opts->db_user.c_str(), m_db_opts->db_password.c_str());
+
+ if (!is_db_running && m_db_opts->write_db)
+ THROWEXPR ("ERROR: We can not access database server. exit");
+
+ // try to find data of input sequences
+ is_db_available = m_db_adapter.look_up_data (seq_db_internal, db_opts);
+
+ if (is_db_running && !m_db_opts->write_db && !is_db_available)
+ CL << "WARNING: there's no relevent data of the input sequences in the database." << endl;
+
+ // initialize variables
+ SPARSE_MATRIX_MAX_SIZE = 0;
+ HEAP_WINDOW_SIZE = 0;
+
+ m_db_merged_heap_buffer.clear();
+
+ m_num_inserted_edges = 0;
+ m_min_edge_weight = 0;
+ m_merged_heap_offset = 0;
+ m_num_cells = NULL;
+ m_available_sparse_matrices = NULL;
+ m_sparse_matrix_scheduler = NULL;
+
+ m_last_edge_chunk = (m_db_opts->db_max_ram > 0)? false : true;
+#endif
+
+}
+
+Manager::~Manager() {
+#ifdef HAVE_POSTGRES
+ if (m_num_cells)
+ delete m_num_cells;
+
+ if (m_available_sparse_matrices)
+ delete m_available_sparse_matrices;
+
+ if (m_sparse_matrix_scheduler)
+ delete m_sparse_matrix_scheduler;
+#endif
+}
+
+bool Manager::check_available_sparse_matrices () {
+
+#ifdef HAVE_POSTGRES
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ if (db_connection) {
+
+ int num_jobs = db_connection->get_num_jobs ();
+ int num_seqs = m_seq_db_internal->size();
+
+ if (num_jobs > 0) {
+ int seq_pair_position = 1;
+ int num_seq_pairs = num_seqs * (num_seqs - 1 ) / 2;
+ int num_of_pairs = num_seq_pairs / num_jobs;
+ int num_remains = num_seq_pairs % num_jobs;
+
+ for (int i=0; i<num_jobs; i++) {
+ m_sparse_matrix_ref.push_back (seq_pair_position);
+ int length = (i < num_remains) ? num_of_pairs + 1 : num_of_pairs;
+ seq_pair_position += length;
+ }
+ }
+
+ CTAG(4,MANAGER) << "Checking available sparse matrices." << endl;
+ m_available_sparse_matrices = new std::vector<std::vector<int> > (num_seqs, std::vector<int> (num_seqs, -1));
+
+ std::vector<int> added_workers;
+
+ avg_sparse_matrix_size = 0.0;
+ int num_pairs = 0;
+
+ for (int i = 0; i < num_jobs; i++)
+ added_workers.push_back (i);
+
+ while (!added_workers.empty()) {
+ int id = added_workers.front();
+ if (db_connection->get_list_of_available_pairs (id, *m_available_sparse_matrices, m_seq_db_internal, avg_sparse_matrix_size, num_pairs, m_orig_edges_size))
+ added_workers.erase (added_workers.begin());
+ }
+
+
+ if (m_db_opts && m_db_opts->db_max_ram > 0) {
+ m_sparse_matrix_scheduler = new std::queue <Sparse_matrix_entry> ();
+ m_cnt_sparse_matrices = 0;
+
+ // by the default, we assign 90% of total memory for the sparse matirces and the 10% of it to the priority queue
+ SPARSE_MATRIX_MAX_SIZE = (int)(0.90 * m_db_opts->db_max_ram * 1024 * 1024) / (sizeof (SparseMatrix) + (int) avg_sparse_matrix_size);
+ HEAP_WINDOW_SIZE = (int)(0.10 * m_db_opts->db_max_ram * 1024 * 1024 ) / sizeof (Edge);
+
+ if (HEAP_WINDOW_SIZE > m_orig_edges_size) {
+ // in this case, we can assign more memory for the sparse matrices
+ HEAP_WINDOW_SIZE = m_orig_edges_size;
+ SPARSE_MATRIX_MAX_SIZE = (int)(m_db_opts->db_max_ram * 1024 * 1024 - sizeof(Edge) * m_orig_edges_size) / (sizeof (SparseMatrix) + (int) avg_sparse_matrix_size);
+ }
+ }
+ }
+
+ return true;
+#endif
+
+ return false;
+}
+
+
+#ifdef HAVE_POSTGRES
+bool Manager::update_size (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges) {
+ if (!m_db_opts)
+ return false;
+
+ SPARSE_MATRIX_MAX_SIZE = (int)(m_db_opts->db_max_ram * 1024 * 1024 - sizeof(Edge) * edges.size()) / (sizeof (SparseMatrix) + (int) avg_sparse_matrix_size);
+
+ return true;
+}
+#endif
+
+bool Manager::get_num_cells () {
+
+#ifdef HAVE_POSTGRES
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ if (db_connection) {
+
+ int num_jobs = db_connection->get_num_jobs ();
+ int num_seqs = m_seq_db_internal->size();
+
+ if (num_jobs > 0) {
+ int seq_pair_position = 1;
+ int num_seq_pairs = num_seqs * (num_seqs - 1 ) / 2;
+ int num_of_pairs = num_seq_pairs / num_jobs;
+ int num_remains = num_seq_pairs % num_jobs;
+
+ for (int i=0; i<num_jobs; i++) {
+ m_sparse_matrix_ref.push_back (seq_pair_position);
+ int length = (i < num_remains) ? num_of_pairs + 1 : num_of_pairs;
+ seq_pair_position += length;
+ }
+ }
+
+ CTAG(4,MANAGER) << "Getting the number of cells of each sparse matrix." << endl;
+ m_num_cells = new std::vector<std::vector<int> > (num_seqs, std::vector<int> (num_seqs, 0));
+
+ std::vector<int> added_workers;
+
+ for (int i = 0; i < num_jobs; i++)
+ added_workers.push_back (i);
+
+ while (!added_workers.empty()) {
+ int id = added_workers.front();
+ if (db_connection->get_num_cells (id, *m_num_cells) == DB_OK)
+ added_workers.erase (added_workers.begin());
+ }
+
+
+ m_orig_edges_size = (*m_num_cells)[0][0]; /// [0][0] => heap size
+ }
+ return true;
+#endif
+
+ return false;
+}
+
+bool Manager::is_edges_available () {
+#ifdef HAVE_CONDOR
+ if (!(m_mem_buffers.heap_buffers).empty()) {
+ return true;
+ }
+#endif
+
+#ifdef HAVE_POSTGRES
+ if (m_db_adapter.is_data_available()) {
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool Manager::is_sparse_matrices_available () {
+#ifdef HAVE_CONDOR
+ if (!(m_mem_buffers.sparse_matrix_buffers).empty()) {
+ return true;
+ }
+#endif
+#ifdef HAVE_POSTGRES
+ if (m_db_adapter.is_data_available()) {
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+bool Manager::is_sparse_matrix_available (const int i, const int j) {
+
+
+#ifdef HAVE_POSTGRES
+ if ( (m_num_cells && ((*m_num_cells)[i][j] > 0 || (*m_num_cells)[j][i]>0)) ||
+ (m_available_sparse_matrices && ((*m_available_sparse_matrices)[i][j] > -1|| (*m_available_sparse_matrices)[j][i] > -1)) )
+ return true;
+#endif
+ return false;
+
+}
+
+#ifdef HAVE_POSTGRES
+int Manager::look_up_sparse_matrix_table_id (const int i, const int j) {
+
+ // binary search
+ int num_seqs = m_seq_db_internal->size();
+ int input_seq_position = (int) (i * (2 * num_seqs - i - 1) / 2) + (j - i);
+
+ int first = 0;
+ int last = m_sparse_matrix_ref.size() - 1;
+
+ //binary search
+ while (first <= last) {
+ int mid = (first + last) / 2; //compute mid point
+
+ if ( m_sparse_matrix_ref[mid] <= input_seq_position ) {
+ if (((mid == m_sparse_matrix_ref.size()-1)) || (input_seq_position < m_sparse_matrix_ref[mid+1]))
+ return mid;
+ else
+ first = mid + 1;
+ }
+
+ if ( input_seq_position < m_sparse_matrix_ref[mid] ) {
+
+ if (mid == 0 || (m_sparse_matrix_ref[mid-1] <= input_seq_position))
+ return mid-1;
+ else
+ last = mid - 1;
+ }
+ }
+
+ return -1;
+}
+#endif
+
+bool Manager::get_sparse_matrix (std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const int i, const int j) {
+
+#ifdef HAVE_POSTGRES
+ // get a sparse matrix from the database
+ if ( !is_sparse_matrix_available (i, j) )
+ return false;
+
+ if (sparse_matrices[i][j] != NULL)
+ return true;
+
+ assert (sparse_matrices[i][j] == NULL);
+
+ // see if transpose is possible
+ if (sparse_matrices[j][i]) {
+ sparse_matrices[i][j] = sparse_matrices[j][i]->ComputeTranspose();
+
+ //check
+ if (m_cnt_sparse_matrices > SPARSE_MATRIX_MAX_SIZE) {
+ SparseMatrix **sparse_matrix_ptr = m_sparse_matrix_scheduler->front();
+ m_sparse_matrix_scheduler->pop();
+ delete (*sparse_matrix_ptr);
+ (*sparse_matrix_ptr) = NULL;
+ m_cnt_sparse_matrices--;
+ }
+
+ if (m_sparse_matrix_scheduler->size() < MAX_SPARSE_MATRIX_COUNT) {
+ m_sparse_matrix_scheduler->push (&sparse_matrices[i][j]);
+ m_cnt_sparse_matrices++;
+ } else
+ m_cnt_sparse_matrices++;
+
+ return true;
+ }
+
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ if (!db_connection)
+ return false;
+
+ int seq1 = (i<j)? i : j;
+ int seq2 = (i<j)? j : i;
+
+ int seq1Length = m_seq_db_internal->get_seq (seq1).length();
+ int seq2Length = m_seq_db_internal->get_seq (seq2).length();
+
+ /*get the table for (seq1, seq2) from the database */
+ int id = (*m_available_sparse_matrices)[i][j];
+ if (id == -1)
+ return false;
+
+ bool res = db_connection->get_sparse_matrix (id, seq1, seq2, seq1Length, seq2Length, sparse_matrices);
+
+ assert (sparse_matrices[i][j]);
+
+ //check
+ if (m_cnt_sparse_matrices > SPARSE_MATRIX_MAX_SIZE) {
+ SparseMatrix **sparse_matrix_ptr = m_sparse_matrix_scheduler->front();
+ m_sparse_matrix_scheduler->pop();
+ delete (*sparse_matrix_ptr);
+ (*sparse_matrix_ptr) = NULL;
+ m_cnt_sparse_matrices--;
+ }
+
+ if (m_sparse_matrix_scheduler->size() < MAX_SPARSE_MATRIX_COUNT) {
+ m_sparse_matrix_scheduler->push (&sparse_matrices[i][j]);
+ m_cnt_sparse_matrices++;
+ } else
+ m_cnt_sparse_matrices++;
+
+ if (res && sparse_matrices[i][j] == NULL) {
+ sparse_matrices[i][j] = sparse_matrices[j][i]->ComputeTranspose();
+
+ //check
+ if (m_cnt_sparse_matrices > SPARSE_MATRIX_MAX_SIZE) {
+ SparseMatrix **sparse_matrix_ptr = m_sparse_matrix_scheduler->front();
+ m_sparse_matrix_scheduler->pop();
+ delete (*sparse_matrix_ptr);
+ (*sparse_matrix_ptr) = NULL;
+ m_cnt_sparse_matrices--;
+ }
+
+ if (m_sparse_matrix_scheduler->size() < MAX_SPARSE_MATRIX_COUNT) {
+ m_sparse_matrix_scheduler->push (&sparse_matrices[i][j]);
+ m_cnt_sparse_matrices++;
+ } else
+ m_cnt_sparse_matrices++;
+ }
+
+ assert (sparse_matrices[i][j]);
+
+ return res;
+#else
+ return false;
+#endif
+}
+
+bool Manager::get_all_sparse_matrices (std::vector<std::vector<SparseMatrix*> >& sparse_matrices) {
+
+#ifdef HAVE_CONDOR
+ // get pairwise posterior probabilties from the database
+ Cells_vector &num_cells_buffers = m_mem_buffers.num_cells_buffers;
+ Sparse_vector &sparse_matrix_buffers = m_mem_buffers.sparse_matrix_buffers;
+
+ if (!num_cells_buffers.empty()) {
+
+ Num_Cells_Buffer *num_cells_buffer = NULL;
+ Sparse_Matrix_Buffer *sparse_matrix_buffer = NULL;
+ int size = 0;
+
+ while (!num_cells_buffers.empty()) {
+ Cells_pair &cells_pair = num_cells_buffers.front();
+ Sparse_pair &sparse_pair = sparse_matrix_buffers.front();
+
+ size = cells_pair.first;
+
+ Num_Cells_Buffer *num_cells_buffer = cells_pair.second;
+ Sparse_Matrix_Buffer *sparse_matrix_buffer = sparse_pair.second;
+
+ int pre_len = 0;
+ int len = 0;
+
+ // create a sparse matrix and the trasposed one
+ for (int cnt = 0; cnt < size; cnt++) {
+ int i = num_cells_buffer[cnt].seq1;
+ int j = num_cells_buffer[cnt].seq2;
+
+ len = num_cells_buffer[cnt].size;
+
+ int seq1Length = m_seq_db_internal->get_seq (i).length();
+ int seq2Length = m_seq_db_internal->get_seq (j).length();
+
+ sparse_matrices[i][j] = new SparseMatrix (i, j,
+ seq1Length, seq2Length,
+ pre_len, len, sparse_matrix_buffer);
+ sparse_matrices[j][i] = sparse_matrices[i][j]->ComputeTranspose();
+
+ pre_len += len;
+ }
+
+ assert (pre_len == sparse_pair.first);
+ if (num_cells_buffer)
+ free (num_cells_buffer); // prevent memory leak
+
+ if (sparse_matrix_buffer)
+ free (sparse_matrix_buffer);
+ num_cells_buffers.erase (num_cells_buffers.begin()); //erase
+ sparse_matrix_buffers.erase (sparse_matrix_buffers.begin());
+ }
+ assert (m_mem_buffers.num_cells_buffers.size() == 0);
+ assert (m_mem_buffers.sparse_matrix_buffers.size() == 0);
+
+ return true;
+ }
+
+#endif
+
+#ifdef HAVE_POSTGRES
+ // get pairwise posterior probabilities from the workers
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ if (!db_connection)
+ return false;
+
+ int num_seqs = m_seq_db_internal->size();
+
+ // get the nubmer of jobs
+ int num_jobs = db_connection->get_num_jobs ();
+
+ if ( num_jobs == 0 )
+ return false;
+
+ std::vector<int> added_workers;
+
+ for (int i = 0; i < num_jobs; i++)
+ added_workers.push_back (i);
+
+ while (!added_workers.empty()) {
+ int id = added_workers.front();
+ if (db_connection->get_sparse_matrices (id, *m_seq_db_internal, *m_num_cells, sparse_matrices) == DB_OK)
+ added_workers.erase (added_workers.begin());
+ }
+
+ return true;
+#endif
+ return false;
+}
+
+
+bool Manager::get_all_edges (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps) {
+
+#ifdef HAVE_CONDOR
+ // get all edges from the workers
+ Heap_vector &heap_buffers = m_mem_buffers.heap_buffers;
+
+ if (!heap_buffers.empty()) {
+
+ while (!heap_buffers.empty()) {
+ Heap_pair &heap_pair = heap_buffers.front();
+
+ int size = heap_pair.first;
+ Heap_Buffer *heap_buffer = heap_pair.second;
+
+ // create a new edge and push it into the priority queue
+ for (int i = 0; i < size; i++) {
+ Edge *edge = new Edge(seq_pos_col_maps[heap_buffer[i].seq1][heap_buffer[i].pos1],
+ seq_pos_col_maps[heap_buffer[i].seq2][heap_buffer[i].pos2],
+ std::pair<int, int> (heap_buffer[i].seq1, heap_buffer[i].pos1),
+ std::pair<int, int> (heap_buffer[i].seq2, heap_buffer[i].pos2),
+ heap_buffer[i].weight, heap_buffer[i].delta, 2);
+
+ edges.push(edge);
+
+ }
+ if (heap_buffer)
+ free (heap_buffer); // prevent memory leak
+ heap_buffers.erase (heap_buffers.begin()); //erase
+
+ }
+ return true;
+ }
+#endif
+
+#ifdef HAVE_POSTGRES
+ // get all edges from the database
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ if (!db_connection)
+ return false;
+
+ int num_seqs = m_seq_db_internal->size();
+
+ // get the number of jobs ( = workers)
+ int num_jobs = db_connection->get_num_jobs ();
+
+ if ( num_jobs == 0 )
+ return false;
+
+ std::vector<int> added_workers;
+
+ for (int i = 0; i < num_jobs; i++)
+ added_workers.push_back (i);
+
+ while (!added_workers.empty()) {
+ int id = added_workers.front();
+ if (db_connection->get_heaps (id, m_min_edge_weight, seq_pos_col_maps, edges) == DB_OK)
+ added_workers.erase (added_workers.begin());
+ }
+
+ return true;
+#endif
+
+ return false;
+}
+
+
+bool Manager::mw_master_run (int argc, char** argv, const Params ¶ms_seed, const Params &pseudocounts) {
+
+#ifdef HAVE_CONDOR
+ if (m_db_opts && m_db_opts->write_db) {
+
+ int seqs_schema_id = 0;
+ int params_table_id = 0;
+
+#ifdef HAVE_POSTGRES
+ if ( !m_db_adapter.init_database (*m_seq_db_internal, *m_db_opts) )
+ THROWEXPR ("ERROR: We can not initialize database server. exit");
+
+ // set the sequence schema id and the parameter table id
+ seqs_schema_id = (m_db_adapter.get_connection())->get_seqs_schema_id ();
+ params_table_id = (m_db_adapter.get_connection())->get_params_table_id ();
+#endif
+
+ }
+ // if it is not the database mode , just send dummy values for seqs_schema_id and params_table_id
+ m_mw_adapter.master_run (argc, argv, params_seed, pseudocounts, m_mem_buffers,
+ m_seq_db_internal->size(), m_db_opts->num_alignment_pairs, m_db_opts->num_parallelized_jobs,
+ seqs_schema_id, params_table_id);
+
+#ifdef HAVE_POSTGRES
+ m_db_adapter.look_up_data(*m_seq_db_internal, *m_db_opts);
+#endif //endif for HAVE_POSTGRES
+ return true;
+
+#else
+ // else for HAVE_CONDOR
+ return false;
+#endif
+}
+
+bool Manager::mw_worker_run(int argc, char** argv) {
+ // run the worker instance
+
+#ifdef HAVE_CONDOR
+ return m_mw_adapter.worker_run (argc, argv, m_db_adapter);
+#else
+
+ return false;
+#endif
+
+}
+
+bool Manager::mw_single_worker_run (Params ¶ms_seed, Params &pseudocounts) {
+
+#ifdef HAVE_POSTGRES
+
+ assert(m_db_opts);
+
+ m_db_opts->num_parallelized_jobs = 1;
+
+ if ( !m_db_adapter.init_database (*m_seq_db_internal, *m_db_opts) )
+ THROWEXPR ("ERROR: We can not initialize database server. exit");
+
+ init_single_worker(m_db_opts->fsa, &m_db_adapter, params_seed, pseudocounts);
+ if (m_db_opts->anchored)
+ build_anchored_multiple_alignment ();
+ else
+ build_multiple_alignment ();
+
+ m_db_adapter.look_up_data(*m_seq_db_internal, *m_db_opts);
+
+ return true;
+#else
+ return false;
+#endif
+
+}
+
+void Manager::push_edge(std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges, Edge *edge) {
+
+#ifdef HAVE_POSTGRES
+ edges.push(edge);
+ return;
+
+ if ( edge->weight >= m_min_edge_weight)
+ edges.push (edge);
+ else {
+
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ Seq_pos_map::const_iterator seq_pos_source= edge->source->get_seq_pos_map().begin();
+ Seq_pos_map::const_iterator seq_pos_dest = edge->dest->get_seq_pos_map().begin();
+
+ // put the edge into the buffer
+ char entry[MAX_DB_ENTRY_LENGTH];
+ sprintf(entry,"%d\t%d\t%d\t%d\t%lf\t%f\n",
+ seq_pos_source->first, seq_pos_source->second, seq_pos_dest->first, seq_pos_dest->second, edge->weight, edge->delta);
+
+ m_db_merged_heap_buffer.append (entry);
+
+ // increase the number of inserted re-weighted edges by one
+ ++m_num_inserted_edges;
+
+ delete edge;
+ }
+#else
+
+ edges.push (edge);
+#endif
+
+}
+
+
+bool Manager::get_next_edges (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps) {
+
+#ifdef HAVE_POSTGRES
+ // that is, this method is called only when the --db-maxram option is used
+ if (m_db_opts && m_db_opts->db_max_ram == 0)
+ return false;
+
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+
+ if (!db_connection)
+ return false;
+
+ // before getting the next edges, put re-weighted edges in the merged_heap_buffer to
+ // the merged heap table
+ db_connection->flush_merged_heap_buffer ( m_db_merged_heap_buffer.c_str());
+ m_db_merged_heap_buffer.clear();
+
+ // get the next edges
+ if ( (db_connection->get_merged_heap (HEAP_WINDOW_SIZE, m_merged_heap_offset, m_min_edge_weight,
+ seq_pos_col_maps, edges, m_last_edge_chunk)) == DB_BAD)
+ return false;
+ ++m_merged_heap_offset;
+
+ return true;
+#else
+
+ return false;
+#endif
+
+}
+
+
+int Manager::get_edges_size(std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges) {
+
+#ifdef HAVE_POSTGRES
+ if ( is_edges_available ())
+ // the merged heap table is needed to be considered
+ return (edges.size() + m_orig_edges_size - (m_merged_heap_offset * HEAP_WINDOW_SIZE) + m_num_inserted_edges);
+ else
+ return edges.size();
+#else
+
+ return edges.size();
+#endif
+
+}
+
+
+void Manager::get_sparse_matrices (std::vector<std::vector<SparseMatrix*> >& sparse_matrices) {
+
+#ifdef HAVE_POSTGRES
+ if (m_db_opts && m_db_opts->db_max_ram > 0) {
+
+ DB_postgres *db_connection = m_db_adapter.get_connection ();
+ int num_jobs = db_connection->get_num_jobs ();
+
+ // create an index on each table.
+ for (int i=0;i<num_jobs;i++)
+ db_connection->create_sparse_matrix_table_index(i);
+
+ // drop merged heap table index
+ // it is much faster to insert tuples into a table that does not have an index
+ // than the one having an index
+ db_connection->drop_merged_heap_table_index();
+ db_connection->delete_merged_heap_table();
+
+ // copy to merged heap
+ for (int i=0; i<num_jobs;i++) {
+ db_connection->copy_to_merged_heap_table (i);
+ }
+
+ // create merged_heap index
+ db_connection->create_merged_heap_table_index();
+
+ //m_orig_edges_size = db_connection->get_merged_heap_size();
+ CTAG(1,MANAGER) << "Original edge size : " << m_orig_edges_size << endl;
+
+ check_available_sparse_matrices();
+ } else
+#endif
+ {
+
+ // in the case of database || parallelization
+ get_num_cells ();
+ get_all_sparse_matrices (sparse_matrices);
+ }
+
+}
+
+void Manager::get_edges (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps) {
+
+#ifdef HAVE_POSTGRES
+ if (m_db_opts && m_db_opts->db_max_ram > 0) {
+ get_next_edges (edges, seq_pos_col_maps);
+ } else
+#endif
+ {
+ // in the case of database || parallelization
+ get_all_edges (edges, seq_pos_col_maps);
+ }
+
+}
+
+Edge* Manager::get_next_top_edge (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps) {
+
+ Edge *edge = edges.top();
+
+#ifdef HAVE_POSTGRES
+ if (m_db_opts && m_db_opts->db_max_ram > 0) {
+ // if --db-maxram option is used
+ if (m_last_edge_chunk== true ) {
+ update_size(edges);
+ }
+
+ if (m_last_edge_chunk == false && edge->weight < m_min_edge_weight || edges.size() == 1) {
+ // in the case of getting next edges
+ get_next_edges (edges, seq_pos_col_maps);
+ edge = edges.top();
+ }
+ }
+#endif
+
+ edges.pop();
+
+ return edge;
+
+}
diff --git a/src/manager/manager.h b/src/manager/manager.h
new file mode 100644
index 0000000..96fe70b
--- /dev/null
+++ b/src/manager/manager.h
@@ -0,0 +1,217 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef MANAGER_INCLUDED
+#define MANAGER_INCLUDED
+#include <queue>
+#include <float.h>
+
+#include "seq/sequence.h"
+#include "annealing/SparseMatrix.h"
+#include "manager/db_adapter.h"
+#include "manager/mw_adapter.h"
+
+#define MAX_SPARSE_MATRIX_COUNT 10
+
+#ifdef HAVE_POSTGRES
+#include "manager/db_postgres.h"
+#endif
+
+namespace fsa {
+
+ class Edge;
+ class Column;
+ class smaller_weight;
+
+ /// Point a cell (which is SparseMatrix*) in a SparseMatrix
+ typedef SparseMatrix** Sparse_matrix_entry;
+
+ /// Map a position in a sequence to the containing Column*.
+ typedef std::vector<Column*> Seq_pos_col_map;
+
+ // Class Manager
+ /*
+ * This class is needed to glue the fsa class together with some classes for the parallelization and the database
+ */
+ class Manager {
+
+ public:
+
+ /// Constructor
+ Manager();
+
+ /// Constructor
+ /*
+ * Detects whether the database is running, and we can get the appropriate data from the database
+ */
+ Manager (const Sequence_database& seq_db_internal, DB_opts &db_opts);
+
+ /// Destructor
+ ~Manager();
+
+
+ /// Get methods
+
+ /// Get a sparse matrix from the database
+ /*
+ * Create a new sparse matrix for the sequence pair (i,j)
+ */
+ bool get_sparse_matrix(std::vector<std::vector<SparseMatrix*> >& sparse_matrices, const int i, const int j);
+
+ /// Get numbers of data cells that are required for the sparse matrices
+ bool get_num_cells ();
+
+ /// Create all sparse matrices.
+ /*
+ * If the database mode is being used, pairwise posterior probabilities are gotten from the database.
+ * If the parallizaition mode is being used, the data are transfered from the workers
+ */
+ bool get_all_sparse_matrices (std::vector<std::vector<SparseMatrix*> >& sparse_matrices);
+
+
+ /// Construct the priority queue with the candidate edges of the null alignment
+ /*
+ * If the database mode is being used, candidate edges are gotten from the database.
+ * If the parallizaition mode is being used, the data are transfered from the workers
+ */
+ bool get_all_edges (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps);
+
+ /// Get the size of edges
+ /*
+ * In the case that the --db-maxram option is used:
+ * The priority queue, edges, contains only some portion of the total edges so that
+ * the number of tuples in the merged heap table is needed to be considered.
+ * Otherwise, just return the size of the priority queue
+ */
+ int get_edges_size(std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges);
+
+ /// Get edges
+ /*
+ * In the case that the --db-maxram option is used:
+ * instead of getting all candidate edges of the null alignment at once, some portion of
+ * candidate edges are gotten from the merged heap table.
+ * Otherwise, get all candidate edges at once from either the database or the workers
+ */
+ void get_edges (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps);
+
+ /// Get some of candidate edges from the database
+ bool get_next_edges (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps);
+
+ /// Get sparse matrices
+ /*
+ * In the case that the --db-maxram option is used:
+ * Create the merged heap table and copy all tuples in the heap tables into the merged heap table.
+ * Note that sparse matrix is gotten from the database on-the-fly during the sequence annealing
+ */
+ void get_sparse_matrices (std::vector<std::vector<SparseMatrix*> >& sparse_matrices);
+
+ /// Get the top element in the priority queue
+ /*
+ * In the case that the --db-maxram option is used:
+ * once next some edges have been gotten from the database, return the top element in the priority queue.
+ * Otherwise, just return the top element in the priority queue
+ */
+ Edge* get_next_top_edge (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges,
+ std::vector<Seq_pos_col_map> &seq_pos_col_maps);
+
+ /// Push edge
+ /*
+ * In the case that the --db-maxram option is used:
+ * If the recomputed weight of the edge is greater than the m_min_edge_weight, the smallest
+ * edge weight among edge weights in the priority queue, push it into the priority queue.
+ * Otherwise, put this edge into the merged heap table. This is because if the recomputed
+ * weight is less than the m_min_edge_weight, there might be an edge whose initial weight is
+ * greater then the edge.
+ *
+ * In the case that the --db-maxram option is NOT used:
+ * push it into the priority queue
+ */
+ void push_edge(std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges, Edge *edge);
+
+ /// Is the appropriate data in the database?
+ bool is_data_available ();
+
+ /// Can we use the sparse matrix of the sequence pair (i,j)?
+ bool is_sparse_matrix_available (const int i, const int j);
+
+ /// Are sparse matrices avialable?
+ bool is_sparse_matrices_available ();
+
+ /// Are edges available?
+ bool is_edges_available ();
+
+ /// Get the list of available sparse matrices
+ bool check_available_sparse_matrices ();
+
+ /// run the master instance
+ bool mw_master_run (int argc, char** argv, const Params ¶ms_seed, const Params &pseudocounts);
+
+ /// run the worker instance
+ bool mw_worker_run(int argc, char** argv);
+
+ bool mw_single_worker_run (Params ¶ms_seed, Params &pseudocounts);
+
+ private:
+
+ const Sequence_database *m_seq_db_internal; // hold all input sequence data (FSA's internal format)
+ DB_opts *m_db_opts; // hold all options that have been used when running FSA
+
+ DB_adapter m_db_adapter; // database adapter class
+ MW_adapter m_mw_adapter; // master-worker adapter class
+
+#ifdef HAVE_POSTGRES
+ public:
+
+ /// Find the worker id that has generated the sparse matrix of the sequence pair (i,j)
+ int look_up_sparse_matrix_table_id (const int i, const int j);
+
+ /// Re-set the maximum number of sparse matrices to be stored in the memory
+ /*
+ * Note that this method is called when the --db-maxram option is used
+ */
+ bool update_size (std::priority_queue<Edge*, std::vector<Edge*>, smaller_weight> &edges);
+
+ private:
+
+ bool m_last_edge_chunk; // is this the last chunk of edges?
+
+ int m_num_inserted_edges; // the number of inserted re-weighted edges to the merged heap table duing the sequence anenaling
+ int m_merged_heap_offset; // merged heap offet to be used to get some portion of edges
+ double m_min_edge_weight; // the smallest edge weight among edges in the priority queue
+
+ std::vector<std::vector<int> > *m_num_cells; // 2-dim vector to keep numbers of data cells
+ std::vector<std::vector<int> > *m_available_sparse_matrices; // 2-dim vector for the available sparse matrices:
+ // The entry [i][j] stores the worker id that has generated the sparse matrix[i][j]
+
+ std::queue <Sparse_matrix_entry> *m_sparse_matrix_scheduler; // queue to keep the maximum number of sparse matrices that are on memory
+ int m_cnt_sparse_matrices; // how many sparse matrices are on the memory?
+
+ std::vector<int> m_sparse_matrix_ref; // 1-dim vector to be used in look_up_sparse_matrix_table_id method
+
+ int m_orig_edges_size; // the number of candidate edges of the null alignment
+
+ int HEAP_WINDOW_SIZE; // how many edges can we hold at a time?
+ int SPARSE_MATRIX_MAX_SIZE; // how many sparse matrices can we hold at a time?
+
+ sstring m_db_merged_heap_buffer; // the merged_heap_buffer
+
+ double avg_sparse_matrix_size; // the average sparse matrix size
+#endif
+
+#ifdef HAVE_CONDOR
+ private:
+ MEM_Buffers m_mem_buffers; // MEM buffers
+#endif
+
+ };
+
+}
+
+#endif
+
+
diff --git a/src/manager/mw_adapter.cc b/src/manager/mw_adapter.cc
new file mode 100644
index 0000000..f7d0be7
--- /dev/null
+++ b/src/manager/mw_adapter.cc
@@ -0,0 +1,31 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+#include "manager/mw_adapter.h"
+
+using namespace fsa;
+
+int MW_adapter::worker_run(int argc, char** argv, DB_adapter &db_adapter) {
+#ifdef HAVE_CONDOR
+ MWWorker::RMC = new MWSocketRC ( FALSE, 0 );
+ MWTask::RMC = MWWorker::RMC;
+ MWDriver::RMC = NULL;
+
+ MW_worker mw_worker (db_adapter);
+ mw_worker.go (argc, argv); //start worker
+#endif
+ return 0;
+}
+
+int MW_adapter::master_run(int argc, char** argv, const Params ¶ms_seed, const Params &pseudocounts, MEM_Buffers &mem_buffers,
+ const int num_seqs, const int num_seqs_pairs, const int num_jobs,
+ const int seqs_schema_id, const int params_table_id) {
+#ifdef HAVE_CONDOR
+ MW_master mw_master (params_seed, pseudocounts, mem_buffers, num_seqs, num_seqs_pairs, num_jobs, seqs_schema_id, params_table_id);
+ mw_master.go (argc, argv); //start master
+#endif
+ return 0;
+}
+
+
diff --git a/src/manager/mw_adapter.h b/src/manager/mw_adapter.h
new file mode 100644
index 0000000..ad1d7f4
--- /dev/null
+++ b/src/manager/mw_adapter.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef MW_ADAPTER_INCLUDED
+#define MW_ADAPTER_INCLUDED
+
+#include "seq/sequence.h"
+
+#include "manager/db_misc.h"
+#include "manager/db_adapter.h"
+
+#ifdef HAVE_CONDOR
+#include "MW.h"
+#include "MWSocketRC.h"
+#include "MWDriver.h"
+
+#include "manager/mw_master.h"
+#include "manager/mw_worker.h"
+#endif
+
+namespace fsa {
+
+ struct Params;
+
+ /// MW_adapter class
+ /*
+ * This class manages all stuffs related to the Master-Worker framework
+ */
+ class MW_adapter {
+ private:
+
+ public:
+ /// constructor
+ MW_adapter() {}
+
+ /// destructor
+ ~MW_adapter() {}
+
+ /// run the worker instance
+ int worker_run(int argc, char** argv, DB_adapter &db_adapter);
+
+ /// run the master instance
+ int master_run(int argc, char** argv,
+ const Params ¶ms_seed, const Params &pseudocounts, MEM_Buffers &mem_buffers,
+ const int num_seqs, const int num_seqs_pairs, const int num_jobs,
+ const int seqs_schema_id, const int params_table_id);
+
+ };
+
+}
+
+#endif
diff --git a/src/manager/mw_master.cc b/src/manager/mw_master.cc
new file mode 100644
index 0000000..4d4214f
--- /dev/null
+++ b/src/manager/mw_master.cc
@@ -0,0 +1,530 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+// TODO int meanlen = (int) floor (seq_db.mean_length());
+
+#include <arpa/inet.h>
+#include <pthread.h>
+
+#include "manager/mw_master.h"
+#include "manager/db_adapter.h"
+#include "fsa/fsa.h"
+
+using namespace fsa;
+
+static pthread_mutex_t worker_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+typedef struct ThreadData {
+ MW_task* m_task;
+ MW_master* m_driver;
+} ThreadData;
+
+MW_master::MW_master(const Params ¶ms_seed, const Params &pseudocounts, MEM_Buffers &mem_buffers,
+ const int num_seqs, const int num_seqs_pairs, const int num_jobs,
+ const int seqs_schema_id, const int params_table_id) {
+
+ set_MWprintf_level (1);
+
+ m_num_parallelized_jobs = num_jobs;
+ m_params_seed = ¶ms_seed;
+ m_pseudocounts = &pseudocounts;
+ m_num_seqs = num_seqs;
+ m_num_seq_pairs = num_seqs_pairs;
+
+ m_seqs_schema_id = seqs_schema_id;
+ m_params_table_id = params_table_id;
+
+ m_mem_buffers = &mem_buffers;
+}
+
+
+static void *__do_raw_unpack(void *ptr)
+{
+ ThreadData* tdata = (ThreadData*)ptr;
+ MW_task* t = tdata->m_task;
+ MW_master* driver = tdata->m_driver;
+
+ int worker_id = t->worker->get_id1();
+ free(tdata);
+
+ double wall_time = 0.0;
+ double cpu_time = 0.0;
+ bool ret = driver->do_raw_unpack(t, wall_time, cpu_time);
+
+ // Now we have finished reading data from socket
+ // So we transfer the control over the socket to main process
+ t->RMC->thread_stop(worker_id);
+
+ if( !ret ) {
+ fprintf(stderr, "do_raw_unpack failed from worker(id=%d,name=%s)\n",
+ worker_id, t->worker->machine_name());
+ fprintf(stderr, "Creating a new task for this failed task\n");
+ fflush(stderr);
+ // Fail
+ //in case of error, need to put this task into job queue again..
+
+ // Create a new Task
+ MW_task *new_task = new MW_task;
+ assert(new_task);
+
+ new_task->m_worker_id = t->m_worker_id;
+ new_task->m_prev_length_sum = t->m_prev_length_sum;
+ new_task->m_length = t->m_length;
+ new_task->m_start_seq_i = t->m_start_seq_i;
+ new_task->m_start_seq_j = t->m_start_seq_j;
+
+ driver->getGlobalLock();
+
+ // Delete old one
+ MWWorkerID* w = t->worker;
+ wall_time = 0.0;
+ cpu_time = 0.0;
+ t->completedTask(wall_time, cpu_time);
+ delete t;
+
+ // Add new one
+ driver->AddTask((MWTask*)new_task);
+
+ driver->getGlobalUnLock();
+ }else {
+ // success
+ driver->getGlobalLock();
+ MWWorkerID* w = t->worker;
+ t->completedTask(wall_time, cpu_time);
+ delete t;
+ driver->getGlobalUnLock();
+ }
+
+ driver->decreasePendingNum();
+ return NULL;
+}
+
+/// get_userinfo
+MWReturn MW_master::get_userinfo(int argc, char **argv)
+{
+
+ char arch[10];
+ char requirements[100];
+
+ char *exec_ptr = NULL;
+
+ m_argc = argc;
+ m_argv = argv;
+
+ /* exec classes */
+ RMC->set_num_exec_classes(1);
+ /* arch classes */
+ RMC->set_num_arch_classes(1);
+ /* set architecture and linux type */
+
+ if (get_proc_cpuinfo(arch)) {
+ sprintf(requirements,"((Arch==\"%s\") && (Opsys==\"LINUX\"))",arch);
+ RMC->set_arch_class_attributes (0, requirements);
+ }
+ else
+ RMC->set_arch_class_attributes (0, "((Arch==\"INTEL\") && (Opsys==\"LINUX\"))"); // default setting
+
+ /* we have only one executable - fsa */
+ RMC->set_num_executables(1);
+
+ RMC->add_executable(0, 0, (((exec_ptr = strchr(argv[0], '/')) != NULL)? (exec_ptr + 1) : argv[0]), "");
+
+ /* checkpoint requirement */
+ set_checkpoint_frequency(0);
+
+ /* Set the number of jobs */
+
+ RMC->set_target_num_workers(m_num_parallelized_jobs);
+ RMC->set_worker_increment(m_num_parallelized_jobs);
+
+ m_num_of_pairs = m_num_seq_pairs / m_num_parallelized_jobs;
+ m_num_remains = m_num_seq_pairs % m_num_parallelized_jobs;
+
+ return OK;
+}
+
+/// setup (generate and push) the first batch of tasks in the beginning
+MWReturn MW_master::setup_initial_tasks(int *n_init , MWTask ***init_tasks)
+{
+ // Create initial tasks
+ *n_init = m_num_parallelized_jobs;
+ *init_tasks = new MWTask* [m_num_parallelized_jobs];
+
+ CTAG(9, MW) << "Creating " << m_num_parallelized_jobs << " job(s)." << endl;
+
+ // Starting pair of sequence
+ int seq_i = 0;
+ int seq_j = 1;
+ int i = 0;
+ int prev_length_sum = 0;
+
+ for (i = 0; i < m_num_parallelized_jobs; i++) {
+
+ MW_task *new_task = new MW_task;
+
+ int prev_length = (i == 0) ? 0 : (((i - 1) < m_num_remains) ? (1 + m_num_of_pairs) : (m_num_of_pairs));
+
+ int length = (i < m_num_remains) ? m_num_of_pairs + 1 : m_num_of_pairs;
+ prev_length_sum += prev_length;
+
+ compute_next_starting_pair(seq_i, seq_j, prev_length, m_num_seqs);
+
+ new_task->m_worker_id = i;
+ new_task->m_prev_length_sum = prev_length_sum;
+ new_task->m_length = length;
+ new_task->m_start_seq_i = seq_i;
+ new_task->m_start_seq_j = seq_j;
+
+ (*init_tasks)[i] = new_task;
+ }
+
+ return OK;
+}
+
+void MW_master::pack_params(const Params ¶ms) {
+
+ // bandwidth
+ RMC->pack(&(params.bandwidth), 1,1);
+
+ // is_indel2
+ char is_indel2 = (params.is_indel2) ? 1 : 0;
+ RMC->pack(&is_indel2, 1,1);
+
+ // gap_open1
+ RMC->pack(&(params.gap_open1), 1,1);
+
+ // gap_open2
+ RMC->pack(&(params.gap_open2), 1,1);
+
+ // gap_extend1
+ RMC->pack(&(params.gap_extend1), 1,1);
+
+ // gap extend2
+ RMC->pack(&(params.gap_extend2), 1,1);
+
+ // to_end
+ RMC->pack(&(params.to_end), 1,1);
+
+ // time
+ RMC->pack(&(params.time), 1,1);
+
+ // alphabet_string
+ RMC->pack(params.alphabet_string.c_str());
+
+ // single_dist: size
+ int size = (int) params.single_dist.size();
+ RMC->pack(&size, 1,1);
+
+ // single_dist: values
+ for (int i=0;i<(int) params.single_dist.size();i++)
+ RMC->pack(&(params.single_dist[i]), 1,1);
+
+ // pair_dist: size(n) -> n by n array
+ size = (int) params.pair_dist.size();
+ RMC->pack(&size, 1,1);
+
+ // pair_dist: values
+ for (int i=0;i<(int) params.pair_dist.size();i++)
+ for (int j=0;j<(int) params.pair_dist.size();j++)
+ RMC->pack(&(params.pair_dist[i][j]), 1,1);
+
+ // transition_matrix: column size
+ size = (int) params.transition_matrix.size();
+ RMC->pack(&size, 1,1);
+
+ for (int i=0;i<(int) params.transition_matrix.size();i++)
+ for (int j=0;j<(int) params.transition_matrix[i].size();j++)
+ RMC->pack(&(params.transition_matrix[i][j]), 1,1);
+}
+
+/// The first batch of data for a newly spawned worker, e.g. init data
+MWReturn MW_master::pack_worker_init_data() {
+
+ int argc=0;
+ char argv[100][512];
+
+ // Send arguments without the arugment having information of the number of jobs
+ for (int i=0; i<m_argc; i++) {
+ if (strstr(m_argv[i], "--parallelize") != NULL)
+ ++i;
+ else {
+ strcpy(argv[argc], m_argv[i]);
+ ++argc;
+ }
+ }
+
+ strcpy(argv[argc++], "--noannealing");
+
+
+ // Send the total number of arguments
+ RMC->pack(&argc,1,1);
+
+ for (int i=0; i<argc; i++)
+ RMC->pack(argv[i]);
+
+ // Send the schema id of DB
+ RMC->pack(&m_seqs_schema_id, 1,1);
+
+ // Send the data id of DB
+ RMC->pack(&m_params_table_id, 1,1);
+
+ pack_params (*m_params_seed);
+ pack_params (*m_pseudocounts);
+
+ return OK;
+}
+
+static bool raw_unpack(MWRMComm* _RMC, int worker_id, char* buf, int len)
+{
+ static int cnt = 0;
+ cnt++;
+
+ int got = _RMC->raw_unpack(worker_id, buf, len);
+ if( got != len ) {
+ fprintf(stderr, "raw_unpack[%d] failed to read the size of data.\n", cnt);
+ fprintf(stderr, "need to read(%d) but got(%d)\n", len, got);
+ fflush(stderr);
+ return false;
+ }
+ return true;
+}
+
+bool MW_master::do_raw_unpack(MW_task *tf, double& wall_time, double& cpu_time)
+{
+ int tmpSize = 0;
+ int hostSize = 0;
+
+ int worker_id = tf->worker->get_id1();
+ MWRMComm* _RMC = tf->RMC;
+
+ Sparse_Matrix_Buffer *sparse_matrix_buffer = NULL;
+ Num_Cells_Buffer *num_cells_buffer = NULL;
+ Heap_Buffer *heap_buffer = NULL;
+
+ int what_data = 0;
+ int num_edges = 0;
+ int num_probs = 0;
+ int num_logs = 0;
+
+ MEM_Buffers mem_buffers;
+
+ do {
+ if (!raw_unpack( _RMC, worker_id, (char*)&what_data, sizeof(int)))
+ return false;
+
+ if ( what_data == 1 ) {
+
+ if (!raw_unpack( _RMC, worker_id, (char*)&num_logs, sizeof(int))) {
+ return false;
+ }
+
+ num_cells_buffer = (Num_Cells_Buffer *) malloc (sizeof (Num_Cells_Buffer) * num_logs);
+ assert(num_cells_buffer);
+
+
+ if (!raw_unpack( _RMC, worker_id, (char*) num_cells_buffer, num_logs * sizeof(Num_Cells_Buffer))) {
+ return false;
+ }
+
+ if (!raw_unpack( _RMC, worker_id, (char*)&num_probs, sizeof(int))) {
+ return false;
+ }
+
+ sparse_matrix_buffer = (Sparse_Matrix_Buffer *) malloc (sizeof (Sparse_Matrix_Buffer) * num_probs);
+ assert(sparse_matrix_buffer);
+
+ if (!raw_unpack( _RMC, worker_id, (char*) sparse_matrix_buffer, num_probs * sizeof(Sparse_Matrix_Buffer))) {
+ return false;
+ }
+
+ mem_buffers.num_cells_buffers.push_back (Cells_pair (num_logs, num_cells_buffer) );
+
+ mem_buffers.sparse_matrix_buffers.push_back (Sparse_pair (num_probs, sparse_matrix_buffer) );
+
+
+ }
+ else if ( what_data == 2) {
+
+ if (!raw_unpack( _RMC, worker_id, (char*)&num_edges, sizeof(int))) {
+ return false;
+ }
+
+ heap_buffer = (Heap_Buffer *) malloc (sizeof (Heap_Buffer) * num_edges);
+ assert(heap_buffer);
+
+ if (!raw_unpack( _RMC, worker_id, (char*) heap_buffer, num_edges * sizeof(Heap_Buffer))) {
+ return false;
+ }
+
+ mem_buffers.heap_buffers.push_back (Heap_pair (num_edges, heap_buffer) );
+ }
+
+ } while ( what_data > 0 );
+
+ // We finished to read all data
+ // Now, we need to read two doubles
+ wall_time = 0.0;
+ cpu_time = 0.0;
+ if (!raw_unpack( _RMC, worker_id, (char*)&wall_time, sizeof(double))) {
+ return false;
+ }
+ if (!raw_unpack( _RMC, worker_id, (char*)&cpu_time, sizeof(double))) {
+ return false;
+ }
+
+ pthread_mutex_lock(&worker_thread_mutex);
+
+ for (int i = 0; i < mem_buffers.num_cells_buffers.size(); i++) {
+ m_mem_buffers->num_cells_buffers.push_back (mem_buffers.num_cells_buffers[i]);
+ }
+
+ for (int i = 0; i < mem_buffers.sparse_matrix_buffers.size(); i++) {
+ m_mem_buffers->sparse_matrix_buffers.push_back (mem_buffers.sparse_matrix_buffers[i]);
+ }
+
+ for (int i = 0; i < mem_buffers.heap_buffers.size(); i++) {
+ m_mem_buffers->heap_buffers.push_back (mem_buffers.heap_buffers[i]);
+ }
+
+ pthread_mutex_unlock(&worker_thread_mutex);
+
+
+ return true;
+}
+
+/// Implement application behavior to process a just completed task */
+MWReturn MW_master::act_on_completed_task( MWTask *t ) {
+ MW_task *tf = dynamic_cast<MW_task *>(t);
+
+ if( !tf->m_raw_flag ) {
+ return OK;
+ }
+
+ /// It means that we need to call raw_unpack
+ int worker_id = tf->worker->get_id1();
+
+ // Set the timeout of Main process select/poll to 1 sec
+ tf->RMC->setPollTimeOut(5);
+
+ // This will indicate
+ // "this socket will be taken over by new thread"
+ // "So main thread MUST do nothing on it"
+ tf->RMC->thread_start(worker_id);
+
+ // Create pthread
+ increasePendingNum();
+
+ ThreadData* tdata = (ThreadData*)malloc(sizeof(ThreadData));
+ assert(tdata);
+
+ tdata->m_task = tf;
+ tdata->m_driver = this;
+
+ pthread_t thread;
+ if( pthread_create(&thread, NULL, __do_raw_unpack, (void *)tdata) != 0 ) {
+ fprintf(stderr, "Failed to create a new thread\n");
+ free(tdata);
+
+ tf->RMC->thread_stop(worker_id);
+
+ decreasePendingNum();
+
+ double wall_time = 0.0;
+ double cpu_time = 0.0;
+ if( do_raw_unpack(tf, wall_time, cpu_time) == false ) {
+ fprintf(stderr, "do_raw_unpack failed from worker(id=%d,name=%s)\n",
+ worker_id, tf->worker->machine_name());
+ return ABORT;
+ }
+ }else {
+ // Detach this thread
+ pthread_detach(thread);
+ }
+
+ return PENDING;
+}
+
+
+/// printresults
+void MW_master::printresults() {
+
+ assert(getPendingNum() == 0 );
+
+}
+
+/// Write app-specific master checkpoint info
+void MW_master::write_master_state( FILE *fp ) {
+ // Nothing to be written
+}
+
+/// Read app-specific master checkpoint info
+void MW_master::read_master_state( FILE *fp ) {
+ // Nothing to be read
+}
+
+/// Return a new application task object
+MWTask* MW_master::gimme_a_task() {
+ return new MW_task;
+}
+
+/// Return a new driver object
+MWDriver* gimme_the_master() {
+ return NULL;
+}
+
+void
+MW_master::AddTask( MWTask* t)
+{
+ addTask(t);
+}
+
+/// compute_next_starting_pair
+void MW_master::compute_next_starting_pair(int& seq_i, int& seq_j, int length, int total_seq_num) {
+
+ int tmp_length = length;
+
+ // Compute the next sequence pair
+ while( tmp_length > 0 ) {
+ if( (seq_j + tmp_length) < total_seq_num ) {
+ seq_j += tmp_length;
+ break;
+ } else {
+ tmp_length -= total_seq_num - seq_j;
+ seq_j = ++seq_i + 1;
+ }
+ }
+}
+
+/// get_proc_cpuinfo
+bool MW_master::get_proc_cpuinfo(char *arch) {
+ char path[64];
+ FILE *fp;
+ char line_input[1024];
+
+ memset(path, 0, sizeof(path));
+ strcpy(path, "/proc/cpuinfo");
+
+ if ((fp = fopen(path, "r")) != NULL ) {
+ while (!feof(fp)) {
+ fgets ( line_input, 1024, fp);
+ if (strstr ( line_input, "flags" ) != NULL && strstr(line_input, " lm ") != NULL) {
+ strcpy(arch,"X86_64");
+ fclose ( fp );
+ return true;
+ }
+ }
+ }
+ else {
+ fclose (fp);
+ return false;
+ }
+
+ strcpy(arch,"INTEL");
+ fclose (fp);
+ return true;
+
+}
+
+
diff --git a/src/manager/mw_master.h b/src/manager/mw_master.h
new file mode 100644
index 0000000..2117061
--- /dev/null
+++ b/src/manager/mw_master.h
@@ -0,0 +1,93 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef MW_MASTER_INCLUDED
+#define MW_MASTER_INCLUDED
+
+#include "MWDriver.h"
+#include "seq/sequence.h"
+#include "manager/mw_task.h"
+#include "manager/db_misc.h"
+
+#ifdef HAVE_POSTGRES
+#include "manager/db_postgres.h"
+#endif
+
+namespace fsa {
+
+ class Params;
+ class DB_opts;
+
+ /// Application Driver subclass derived from MWDriver
+ class MW_master : public MWDriver
+ {
+ public:
+
+ /// constructor
+ MW_master();
+
+ /// constructor
+ MW_master(const Params ¶ms_seed, const Params &pseudocounts, MEM_Buffers &mem_buffers,
+ const int num_seqs, const int num_seqs_pairs, const int num_jobs,
+ const int seqs_schema_id, const int params_table_id);
+
+
+ /// Get the info from the user. Don't forget to get the worker_executable!
+ MWReturn get_userinfo(int argc, char **argv);
+
+ /// Set up an array of tasks here
+ MWReturn setup_initial_tasks( int *, MWTask *** );
+
+ /// What to do when a task finishes
+ MWReturn act_on_completed_task( MWTask * );
+
+ /// Put things in the send buffer here that go to a worker
+ MWReturn pack_worker_init_data( void );
+
+ /// Print the results
+ void printresults();
+
+ /// Write out the state of the master to a file.
+ void write_master_state( FILE *fp );
+
+ /// Read in the state from a file.
+ void read_master_state( FILE *fp );
+
+ /// Just return a newly constructed application task
+ MWTask* gimme_a_task();
+
+ /// Compute next candidate starting pair
+ void compute_next_starting_pair(int& seq_i, int& seq_j, int length, int total_seq_num);
+
+ /// Get cpuinfo
+ bool get_proc_cpuinfo(char *arch);
+
+ bool do_raw_unpack (MW_task *tf, double&, double& );
+
+ void pack_params(const Params ¶ms);
+
+ void AddTask( MWTask* t);
+
+ private:
+
+ int m_num_parallelized_jobs;
+ int m_num_seq_pairs;
+ int m_num_of_pairs;
+ int m_num_remains;
+ int m_num_seqs;
+ int m_seqs_schema_id;
+ int m_params_table_id;
+
+ const Params *m_params_seed;
+ const Params *m_pseudocounts;
+ int m_argc;
+ char** m_argv;
+
+ MEM_Buffers *m_mem_buffers;
+ };
+
+}
+
+#endif
diff --git a/src/manager/mw_task.cc b/src/manager/mw_task.cc
new file mode 100644
index 0000000..6f0375b
--- /dev/null
+++ b/src/manager/mw_task.cc
@@ -0,0 +1,62 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include "manager/mw_task.h"
+
+using namespace fsa;
+
+/// this funtion is called inside pack_results
+extern void transfer_data(MW_task *);
+
+MW_task::MW_task() {
+ m_raw_flag = 0;
+}
+
+MW_task::~MW_task() {}
+
+void MW_task::printself( int level ) {
+ // do nothing
+}
+
+void MW_task::pack_work( void ) {
+
+ RMC->pack(&m_worker_id,1,1); // the number of sequence pairs
+ RMC->pack(&m_prev_length_sum,1,1);
+ RMC->pack(&m_length,1,1); // the number of sequence pairs
+ RMC->pack(&m_start_seq_i,1,1); // the first sequence of the starting sequence pair
+ RMC->pack(&m_start_seq_j,1,1); // the secnod sequence of the starting sequence pair
+}
+
+void MW_task::unpack_work( void ) {
+ RMC->unpack(&m_worker_id,1,1); // the number of sequence pairs
+ RMC->unpack(&m_prev_length_sum,1,1);
+ RMC->unpack(&m_length,1,1); // the number of sequence pairs
+ RMC->unpack(&m_start_seq_i,1,1); // the first sequence of the starting sequence pair
+ RMC->unpack(&m_start_seq_j,1,1); // the second sequence of the starting sequence pair
+
+}
+
+void MW_task::pack_results( void ) {
+ RMC->pack(&m_raw_flag, 1, 1);
+
+ if (m_raw_flag) {
+ RMC->pre_send(RESULTS);
+ }
+
+ transfer_data(this);
+}
+
+void MW_task::unpack_results( void ) {
+ m_raw_flag = 0;
+ RMC->unpack(&m_raw_flag, 1, 1);
+}
+
+void MW_task::write_ckpt_info( FILE *fp ) {
+ // Nothing in this app, will lose data if it crashes.
+}
+
+void MW_task::read_ckpt_info( FILE *fp ) {
+ // Nothing to be read since nothing is written
+}
diff --git a/src/manager/mw_task.h b/src/manager/mw_task.h
new file mode 100644
index 0000000..7e2e7bd
--- /dev/null
+++ b/src/manager/mw_task.h
@@ -0,0 +1,63 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef MW_TASK_INCLUDED
+#define MW_TASK_INCLUDED
+
+#include "MWTask.h"
+
+namespace fsa {
+
+ /// MW_task class
+ /*
+ * The master and the workers communicate by passing this class
+ */
+ class MW_task : public MWTask
+ {
+ public:
+ /// constructor
+ MW_task();
+
+ /// Destructor
+ ~MW_task();
+
+
+ /// App is required to implement the following functions.
+
+ /// The driver packs the input data via RMC, the data which will be sent to a worker.
+ void pack_work( void );
+
+ /// The worker unpacks input data via RMC, need to allocate space for data
+ void unpack_work( void );
+
+ /// The worker packs result data via RMC, the result will be sent back to driver
+ void pack_results( void );
+
+ /// The driver unpacks result data via RMC
+ void unpack_results( void );
+
+ /// The following functions have default implementation.
+
+ /// Print the task to stdout
+ void printself( int level = 70 );
+
+ /// write checkpoint info per task, for each task haven't been finished
+ void write_ckpt_info( FILE *fp );
+
+ /// read checkpoint info, in the order written into the file
+ void read_ckpt_info( FILE *fp );
+
+ int m_start_seq_i;
+ int m_start_seq_j;
+ int m_prev_length_sum;
+ int m_length;
+ int m_worker_id;
+
+ int m_raw_flag;
+ };
+
+}
+
+#endif
diff --git a/src/manager/mw_worker.cc b/src/manager/mw_worker.cc
new file mode 100644
index 0000000..89fe720
--- /dev/null
+++ b/src/manager/mw_worker.cc
@@ -0,0 +1,232 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "manager/mw_worker.h"
+#include "fsa/fsa.h"
+
+using namespace fsa;
+
+extern FSA *m_fsa;
+extern DB_adapter *m_db_adapter;
+extern Params m_params_seed;
+extern Params m_pseudocounts;
+extern MEM_Buffer m_mem_buffer;
+extern DB_Buffer m_db_buffer;
+extern bool final_buffer;
+extern bool send_thread_waiting;
+
+
+
+MW_worker::MW_worker() {}
+
+MW_worker::MW_worker(DB_adapter &db_adapter)
+{
+ // how much info you wants the driver to print
+ set_MWprintf_level( 1 );
+
+ m_db_adapter = &db_adapter;
+
+ workingTask = new MW_task;
+
+ m_mem_buffer.sparse_matrix = NULL;
+ m_mem_buffer.num_cells = NULL;
+ m_mem_buffer.heap = NULL;
+}
+
+MW_worker::~MW_worker() {
+ for (int i=0; i<m_argc; i++)
+ free (m_argv[i]);
+ free (m_argv);
+
+ if (workingTask)
+ delete workingTask;
+}
+
+double MW_worker::benchmark( MWTask *t ) {
+ // As we don't have benchmark, we do nothing
+ return (double)3.14;
+}
+
+void MW_worker::unpack_params (Params ¶ms) {
+ // bandwidth
+ RMC->unpack(&(params.bandwidth), 1,1);
+
+ // is_indel2
+ char is_indel2;
+ RMC->unpack(&is_indel2, 1, 1);
+ params.is_indel2 = (is_indel2 == 1) ? true : false;
+
+ // gap_open1
+ RMC->unpack(&(params.gap_open1), 1,1);
+
+ // gap_open2
+ RMC->unpack(&(params.gap_open2), 1,1);
+
+ // gap_extend1
+ RMC->unpack(&(params.gap_extend1), 1,1);
+
+ // gap extend2
+ RMC->unpack(&(params.gap_extend2), 1,1);
+
+ // to_end
+ RMC->unpack(&(params.to_end), 1,1);
+
+ // time
+ RMC->unpack(&(params.time), 1,1);
+
+ // alphabet_string
+ char *temp_char = (char *) malloc (1024 * sizeof (char) );
+ RMC->unpack(temp_char);
+ params.alphabet_string = temp_char;
+ free (temp_char);
+
+ // single_dist: size
+ int size;
+ RMC->unpack(&size, 1,1);
+ params.single_dist.resize(size);
+
+ // single_dist: values
+ for (int i=0;i<size;i++)
+ RMC->unpack(&(params.single_dist[i]), 1,1);
+
+ // pair_dist: size(n) -> n by n array
+ RMC->unpack(&size, 1,1);
+ params.pair_dist.resize(size);
+
+ // pair_dist: values
+ for (int i=0;i<size;i++) {
+ params.pair_dist[i].resize(size);
+ for (int j=0;j<size;j++)
+ RMC->unpack(&(params.pair_dist[i][j]), 1,1);
+ }
+
+ // transaction_matrix: column size
+ RMC->unpack(&size, 1,1);
+ params.transition_matrix.resize(size);
+
+ for (int i=0;i<size;i++) {
+ params.transition_matrix[i].resize(size);
+ for (int j=0;j<size;j++)
+ RMC->unpack(&(params.transition_matrix[i][j]), 1,1);
+ }
+}
+
+/// unpack the init data from the driver
+MWReturn MW_worker::unpack_init_data( void ) {
+
+ // Read the total number of arguments
+ RMC->unpack(&m_argc,1,1);
+
+ // Read arguments
+ m_argv = (char**) malloc(m_argc * sizeof(char*));
+
+ for (int i = 0; i < m_argc; i++) {
+ m_argv[i] = (char *) malloc (512 * sizeof(char));
+ RMC->unpack(m_argv[i]);
+ }
+
+ // Read schema id of DB
+ RMC->unpack(&m_seqs_schema_id, 1,1);
+
+ // Read data id of DB
+ RMC->unpack(&m_params_table_id, 1,1);
+
+ unpack_params (m_params_seed);
+ unpack_params (m_pseudocounts);
+
+ return OK;
+}
+
+void MW_worker::init_transfer(const int worker_id, int &raw_flag) {
+
+ final_buffer = false;
+ send_thread_waiting = false;
+
+ if (m_fsa->write_db) {
+ bool is_db_running = false;
+ m_db_buffer.sparse_matrix.clear();
+ m_db_buffer.num_cells.clear();
+ m_db_buffer.heap.clear();
+
+ // connect DB
+ is_db_running = m_db_adapter->connect_db(m_fsa->db_hostname.c_str(), m_fsa->db_hostaddr.c_str(), m_fsa->db_name.c_str(),
+ m_fsa->db_port, m_fsa->db_user.c_str(), m_fsa->db_password.c_str());
+
+ if (!is_db_running)
+ THROWEXPR ("ERROR: We can not access database server.");
+
+ m_db_adapter->set_up_ids (m_seqs_schema_id, m_params_table_id, worker_id);
+
+ raw_flag = 0;
+
+ }
+ else {
+ if (!m_mem_buffer.sparse_matrix)
+ m_mem_buffer.sparse_matrix = (Sparse_Matrix_Buffer*) malloc (
+ sizeof (Sparse_Matrix_Buffer) * ((int) (MAX_DB_BUFFER_SIZE / sizeof (Sparse_Matrix_Buffer))));
+
+
+ if (!m_mem_buffer.num_cells)
+ m_mem_buffer.num_cells = (Num_Cells_Buffer *) malloc (
+ sizeof (Num_Cells_Buffer) * ((int) (MAX_DB_BUFFER_SIZE / sizeof (Num_Cells_Buffer))));
+
+ if (!m_mem_buffer.heap)
+ m_mem_buffer.heap = (Heap_Buffer *) malloc (
+ sizeof (Heap_Buffer) * ((int) (MAX_DB_BUFFER_SIZE / sizeof (Heap_Buffer))));
+
+ raw_flag = 1;
+
+ }
+}
+
+/// Execute each task
+void MW_worker::execute_task( MWTask *t ) {
+
+ MW_task *tf = dynamic_cast<MW_task *>(t);
+ int num_seq_pairs = tf->m_length;
+ int prev_seq_pairs_sum = tf->m_prev_length_sum;
+ std::pair <int,int> start_seq_pair (tf->m_start_seq_i, tf->m_start_seq_j);
+
+ // create fsa
+ m_fsa = new FSA (m_argc, m_argv);
+
+ // create buffers and init
+ m_fsa->init_for_mw_worker (start_seq_pair, prev_seq_pairs_sum, num_seq_pairs);
+
+ try
+ {
+ // It's important that we input the data /before/ parsing the command-line
+ // This allows us to set preset values for DNA, RNA and proteins and then let
+ // them be overriden by the command-line
+ m_fsa->init_opts();
+ m_fsa->input_data();
+ m_fsa->set_up_defaults();
+ m_fsa->parse_opts();
+ m_fsa->assemble_sequence_data();
+ m_fsa->choose_seq_pairs();
+
+ init_transfer(tf->m_worker_id, tf->m_raw_flag);
+ }
+ catch (const Dart_exception& e)
+ {
+ CLOGERR << e.what();
+ exit(1);
+ }
+
+}
+
+MWTask* MW_worker::gimme_a_task() {
+ return new MW_task;
+}
+
+// Just return a newly created application worker object
+MWWorker* gimme_a_worker () {
+ return new MW_worker;
+}
+
diff --git a/src/manager/mw_worker.h b/src/manager/mw_worker.h
new file mode 100644
index 0000000..5187bd8
--- /dev/null
+++ b/src/manager/mw_worker.h
@@ -0,0 +1,63 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#ifndef MW_WORKER_INCLUDED
+#define MW_WORKER_INCLUDED
+
+#include "MWWorker.h"
+
+#include "manager/db_adapter.h"
+#include "manager/mw_task.h"
+
+namespace fsa {
+
+ class Params;
+
+ class MW_worker : public MWWorker
+ {
+ public:
+
+ /// constructor
+ MW_worker();
+
+ /// constructor
+ MW_worker(DB_adapter &db_adapter);
+
+ /// destructor
+ ~MW_worker();
+
+ /// Benchmarking
+ double benchmark( MWTask *t );
+
+ /// return a task
+ MWTask* gimme_a_task();
+
+ /// unpack init data
+ MWReturn unpack_init_data( void );
+
+ /// unpack parameters
+ void unpack_params(Params ¶ms);
+
+ /// do the real work for each task
+ void execute_task( MWTask * );
+
+ void init_transfer(const int worker_id, int &raw_flag);
+
+ private:
+
+ int m_seqs_schema_id;
+ int m_params_table_id;
+
+ // command arguments
+ int m_argc;
+ char **m_argv;
+
+
+
+ };
+
+}
+
+#endif
diff --git a/src/manager/transfer_data.cc b/src/manager/transfer_data.cc
new file mode 100644
index 0000000..f9fd41b
--- /dev/null
+++ b/src/manager/transfer_data.cc
@@ -0,0 +1,634 @@
+/*
+ * This file is part of FSA, a sequence alignment algorithm.
+ * Source code in this file was written by Jaeyoung Do.
+ */
+
+#include "fsa/fsa.h"
+#include <errno.h>
+
+#if defined(HAVE_CONDOR)
+#include "MW.h"
+#include "MWSystem.h"
+#endif
+
+#define END_DATA 0
+#define SPARSE_DATA 1
+#define HEAP_DATA 2
+
+using namespace fsa;
+
+FSA *m_fsa = NULL;
+DB_adapter *m_db_adapter = NULL;
+
+Params m_params_seed;
+Params m_pseudocounts;
+
+MEM_Buffer m_mem_buffer;
+DB_Buffer m_db_buffer;
+
+static int num_probs = 0;
+static int num_logs = 0;
+static int num_edges = 0;
+
+typedef struct MEM_Container {
+ int what_data;
+
+ int size1;
+ char* buffer1;
+ int size2;
+ char* buffer2;
+
+} MEM_Container;
+
+static std::queue<MEM_Container*> buffer_queue;
+
+bool final_buffer = false;
+bool send_thread_waiting = false;
+
+static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
+
+static double wall_time = 0.0;
+static double cpu_time = 0.0;
+
+void compute_data (SparseMatrix *ijMatrix, int i, int j);
+
+void insert_posterior_probability (int seq1, int pos1, int seq2, int pos2, float prob);
+void insert_num_cells (int seq1, int seq2, int size);
+void insert_edge (int seq1, int pos1, int seq2, int pos2, double weight, float delta);
+
+void flush_on_the_fly (bool force);
+
+void build_multiple_alignment();
+void build_anchored_multiple_alignment();
+
+static void enqueue_buffer(MEM_Container* buffer, bool final);
+static MEM_Container* dequeue_buffer(void);
+
+#if defined(HAVE_POSTGRES)
+void init_single_worker(const FSA *fsa, DB_adapter *db_adapter, Params ¶ms_seed, Params &pseudocounts);
+#endif
+
+#if defined(HAVE_CONDOR)
+static void* send_thread(void *ptr);
+static bool do_raw_pack (MWRMComm* RMC, MEM_Container *mem_container);
+static bool raw_pack(MWRMComm* _RMC, char* buf, int len);
+void transfer_data(MW_task *t);
+#endif
+
+
+void insert_posterior_probability (int seq1, int pos1, int seq2, int pos2, float prob) {
+
+ if (m_fsa->write_db) {
+ char entry[MAX_DB_ENTRY_LENGTH];
+ sprintf(entry,"%d\t%d\t%d\t%d\t%lf\n", seq1, pos1, seq2, pos2, prob);
+ m_db_buffer.sparse_matrix.append (entry);
+ }
+ else {
+ m_mem_buffer.sparse_matrix[num_probs].pos1 = pos1;
+ m_mem_buffer.sparse_matrix[num_probs].pos2 = pos2;
+ m_mem_buffer.sparse_matrix[num_probs].prob = prob;
+ }
+
+ num_probs++;
+}
+
+void insert_num_cells (int seq1, int seq2, int size) {
+
+
+ if (m_fsa->write_db) {
+ char entry[MAX_DB_ENTRY_LENGTH];
+ sprintf(entry,"%d\t%d\t%d\n", seq1, seq2, size);
+ m_db_buffer.num_cells.append (entry);
+ }
+ else {
+ if (seq1 == 0 && seq2 == 0 )
+ return;
+
+ m_mem_buffer.num_cells[num_logs].seq1 = seq1;
+ m_mem_buffer.num_cells[num_logs].seq2 = seq2;
+ m_mem_buffer.num_cells[num_logs].size = size;
+ }
+
+ num_logs++;
+}
+
+void insert_edge (int seq1, int pos1, int seq2, int pos2, double weight, float delta) {
+
+
+ if (m_fsa->write_db) {
+ char entry[MAX_DB_ENTRY_LENGTH];
+ sprintf(entry,"%d\t%d\t%d\t%d\t%lf\t%f\n", seq1, pos1, seq2, pos2, weight, delta);
+ m_db_buffer.heap.append (entry);
+ }
+ else {
+
+ m_mem_buffer.heap[num_edges].seq1 = seq1;
+ m_mem_buffer.heap[num_edges].pos1 = pos1;
+ m_mem_buffer.heap[num_edges].seq2 = seq2;
+ m_mem_buffer.heap[num_edges].pos2 = pos2;
+ m_mem_buffer.heap[num_edges].weight = weight;
+ m_mem_buffer.heap[num_edges].delta = delta;
+ }
+
+ num_edges++;
+}
+
+
+void compute_data (SparseMatrix *ijMatrix, int i, int j)
+{
+ if (ijMatrix == 0)
+ return;
+
+ int xlen = m_fsa->seq_db.get_seq (i).length();
+ int ylen = m_fsa->seq_db.get_seq (j).length();
+
+ int pre_num_probs = num_probs;
+
+ for (int jj = 0; jj < ylen; jj++)
+ insert_posterior_probability (i, 0, j, jj+1, ijMatrix->get_gap_prob (1, jj+1));
+
+ // for all entries in the SparseMatrix, calculate the corresponding weight
+ // and store the edge
+ for (int ii = 0; ii < xlen; ii++) { // note 0-based indexing for sequences
+ float p_gap_ii = ijMatrix->get_gap_prob (0, ii + 1);
+
+ insert_posterior_probability (i, ii+1, j, 0, p_gap_ii);
+
+ for (std::vector<Matrix_entry>::iterator rowPtr = ijMatrix->GetRowPtr (ii + 1),
+ rowEnd = rowPtr + ijMatrix->GetRowSize (ii + 1); rowPtr != rowEnd; rowPtr++) {
+ int jj = rowPtr->first - 1; // convert from SparseMatrix's 1-based coords to the 0-based coords which we use here
+
+ insert_posterior_probability (i, ii+1, j, jj+1, ijMatrix->get_match_prob(ii+1, jj+1));
+
+ float p_match = rowPtr->second;
+ if (!p_match)
+ continue;
+
+ float p_gap = p_gap_ii + ijMatrix->get_gap_prob (1, jj + 1);
+ float weight = m_fsa->use_tgf ? (2 * p_match / p_gap) : (2 * p_match - m_fsa->gap_factor * p_gap);
+ float delta = 2 * p_match - p_gap;
+
+ float edge_weight_threshold = 0; //TODO it should be the same with in fsa
+
+ // if the edge already scores too low to ever be accepted, then skip it
+ if ((weight < edge_weight_threshold) || (m_fsa->use_tgf && weight < m_fsa->gap_factor))
+ continue;
+
+ insert_edge (i, ii, j, jj, weight, delta);
+ }
+ }
+
+ insert_num_cells (i, j, (num_probs - pre_num_probs));
+}
+
+void build_anchored_multiple_alignment() {
+
+ // read in weights for sequence pairs if information present
+ if (m_fsa->tree_weights_file != "")
+ m_fsa->tree_weights.from_file (m_fsa->seq_db, m_fsa->tree_weights_file);
+
+ // get resolved anchors for the sequence pairs which we're going use for alignment
+ Anchor_resolver anchor_resolver (m_fsa->seq_db, m_fsa->seq_db_internal, m_fsa->alignment_seq_pairs);
+
+ // add Mercator constraints if present
+ if (m_fsa->mercator_constraint_file != "")
+ anchor_resolver.add_mercator_constraints (m_fsa->mercator_constraint_file);
+
+ // now actually get resolved anchors
+ std::vector<Anchors > resolved_anchors_list = anchor_resolver.get_resolved_anchors (m_fsa->tree_weights,
+ m_fsa->anchor_minlen, m_fsa->anchor_max_join_length, m_fsa->use_translated,
+ m_fsa->exonerate, m_fsa->exonerate_minscore, m_fsa->softmasked,
+ m_fsa->hardmasked,
+ m_fsa->num_refinement_steps,
+ m_fsa->output_for_gui, m_fsa->gui_prefix);
+
+ // loop through sequence database
+ for (size_t cnt = 0; cnt < m_fsa->alignment_seq_pairs.size(); ++cnt) {
+
+ // initialize all the sequence data
+ int i = m_fsa->alignment_seq_pairs[cnt].first;
+ int j = m_fsa->alignment_seq_pairs[cnt].second;
+
+ // initialize all the sequence data
+ const Sequence& xseq = m_fsa->seq_db_internal.get_seq (i);
+ const Sequence& yseq = m_fsa->seq_db_internal.get_seq (j);
+
+ Post_probs post_probs = m_fsa->perform_anchored_pairwise_inference (m_params_seed, xseq, yseq,
+ m_pseudocounts,
+ resolved_anchors_list[cnt]);
+
+ // we need the original sequences in case we've been hardmasking
+ const Sequence& xseq_orig = (m_fsa->seq_db).get_seq (i);
+ const Sequence& yseq_orig = (m_fsa->seq_db).get_seq (j);
+
+ // if hardmasking, map coords back to original sequence
+ if (m_fsa->hardmasked) {
+ for (Post_probs::iterator p = post_probs.begin(); p != post_probs.end(); ++p) {
+ (*p).x = xseq_orig.map_stripped_to_orig ((*p).x);
+ (*p).y = yseq_orig.map_stripped_to_orig ((*p).y);
+ }
+ }
+
+ SparseMatrix *ijMatrix = new SparseMatrix (i, j,
+ xseq_orig.length(), yseq_orig.length(),
+ post_probs);
+
+ compute_data (ijMatrix, i, j);
+
+ flush_on_the_fly (false);
+
+ delete ijMatrix;
+
+ } // end loop over seq_db_internal
+
+ insert_num_cells (0, 0, num_edges);
+
+ flush_on_the_fly (true);
+
+}
+
+
+void build_multiple_alignment() {
+
+ // read in weights for sequence pairs if information present
+ if (m_fsa->tree_weights_file != "")
+ m_fsa->tree_weights.from_file (m_fsa->seq_db, m_fsa->tree_weights_file);
+
+ bool left_match = false; // do not require homology beyond sequence boundaries
+ bool right_match = false;
+
+ // loop through sequence database
+ for (size_t cnt = 0; cnt < m_fsa->alignment_seq_pairs.size(); ++cnt) {
+
+ // initialize all the sequence data
+ int i = m_fsa->alignment_seq_pairs[cnt].first;
+ int j = m_fsa->alignment_seq_pairs[cnt].second;
+
+ // initialize all the sequence data
+ const Sequence& xseq = m_fsa->seq_db_internal.get_seq (i);
+ const Sequence& yseq = m_fsa->seq_db_internal.get_seq (j);
+
+ Params params_seed;
+ params_seed.copy_all (m_params_seed);
+
+ Post_probs post_probs = m_fsa->perform_pairwise_inference (params_seed, xseq, yseq,
+ left_match, right_match, m_fsa->ragged_ends, m_pseudocounts);
+
+ // we need the original sequences in case we've been hardmasking
+ const Sequence& xseq_orig = (m_fsa->seq_db).get_seq (i);
+ const Sequence& yseq_orig = (m_fsa->seq_db).get_seq (j);
+
+ // if hardmasking, map coords back to original sequence
+ if (m_fsa->hardmasked) {
+ for (Post_probs::iterator p = post_probs.begin(); p != post_probs.end(); ++p) {
+ (*p).x = xseq_orig.map_stripped_to_orig ((*p).x);
+ (*p).y = yseq_orig.map_stripped_to_orig ((*p).y);
+ }
+ }
+
+ SparseMatrix *ijMatrix = new SparseMatrix (i, j,
+ xseq_orig.length(), yseq_orig.length(),
+ post_probs);
+
+ compute_data(ijMatrix, i, j);
+
+ delete ijMatrix;
+
+ flush_on_the_fly (false);
+ }
+
+ insert_num_cells (0, 0, num_edges);
+
+ flush_on_the_fly (true);
+
+}
+
+void flush_on_the_fly (bool force) {
+ if (m_fsa->write_db) {
+ if ( force || ( (m_db_buffer.sparse_matrix.size() + m_db_buffer.num_cells.size() + m_db_buffer.heap.size() ) > (BUFFER_RATIO * MAX_DB_BUFFER_SIZE))) {
+#if defined(HAVE_POSTGRES)
+ (m_db_adapter->get_connection())->flush_sparse_matrix_buffer (m_db_buffer.sparse_matrix.c_str());
+ m_db_buffer.sparse_matrix.clear();
+
+ (m_db_adapter->get_connection())->flush_num_cells_buffer (m_db_buffer.num_cells.c_str());
+ m_db_buffer.num_cells.clear();
+
+ (m_db_adapter->get_connection())->flush_heap_buffer (m_db_buffer.heap.c_str());
+ m_db_buffer.heap.clear();
+#endif
+ }
+
+ } else {
+
+ if ( force || (num_probs * sizeof (Sparse_Matrix_Buffer) > (BUFFER_RATIO * MAX_MEM_BUFFER_SIZE))) {
+ MEM_Container *mem_container = (MEM_Container*) malloc ( sizeof (MEM_Container) );
+ assert (mem_container);
+
+ mem_container->what_data = SPARSE_DATA;
+
+ mem_container->size1 = num_logs * sizeof (Num_Cells_Buffer);
+ mem_container->buffer1 = (char*) m_mem_buffer.num_cells;
+
+ mem_container->size2 = num_probs * sizeof (Sparse_Matrix_Buffer);
+ mem_container->buffer2 = (char*) m_mem_buffer.sparse_matrix;
+
+ enqueue_buffer(mem_container, false);
+
+ if (!force) {
+
+ m_mem_buffer.num_cells = (Num_Cells_Buffer *) malloc (
+ sizeof (Num_Cells_Buffer) * ((int) (MAX_DB_BUFFER_SIZE / sizeof (Num_Cells_Buffer))));
+ assert(m_mem_buffer.num_cells);
+
+ m_mem_buffer.sparse_matrix = (Sparse_Matrix_Buffer*) malloc (
+ sizeof (Sparse_Matrix_Buffer) * ((int) (MAX_DB_BUFFER_SIZE / sizeof (Sparse_Matrix_Buffer))));
+ assert(m_mem_buffer.sparse_matrix);
+ } else {
+ m_mem_buffer.num_cells = NULL;
+ m_mem_buffer.sparse_matrix = NULL;
+ }
+
+ num_probs = 0;
+ num_logs = 0;
+ }
+
+ if ( force || (num_edges * sizeof (Heap_Buffer) > (BUFFER_RATIO * MAX_MEM_BUFFER_SIZE))) {
+
+ MEM_Container *mem_container = (MEM_Container*) malloc ( sizeof (MEM_Container) );
+ assert (mem_container);
+
+ mem_container->what_data = HEAP_DATA;
+
+ mem_container->size1 = num_edges * sizeof (Heap_Buffer);
+ mem_container->buffer1 = (char*) m_mem_buffer.heap;
+
+ mem_container->size2 = 0;
+ mem_container->buffer2 = NULL;
+
+ enqueue_buffer(mem_container, false);
+
+ if (!force) {
+ m_mem_buffer.heap = (Heap_Buffer *) malloc (
+ sizeof (Heap_Buffer) * ((int) (MAX_DB_BUFFER_SIZE / sizeof (Heap_Buffer))));
+ assert(m_mem_buffer.heap);
+ }
+ else
+ m_mem_buffer.heap = NULL;
+
+ num_edges = 0;
+ }
+
+ if ( force ) {
+ // send last signal
+ MEM_Container *mem_container = (MEM_Container*) malloc ( sizeof (MEM_Container) );
+ assert (mem_container);
+
+ mem_container->what_data = END_DATA;
+ mem_container->size1 = 0;
+ mem_container->buffer1 = NULL;
+
+ mem_container->size2 = 0;
+ mem_container->buffer2 = NULL;
+
+ enqueue_buffer(mem_container, true);
+ }
+ }
+}
+
+
+
+static void enqueue_buffer(MEM_Container* buffer, bool final)
+{
+ if( !buffer ) {
+ return;
+ }
+
+ pthread_mutex_lock(&queue_lock);
+
+ buffer_queue.push(buffer);
+ if( final ) {
+ final_buffer = true;
+ }
+
+ if( send_thread_waiting ) {
+ pthread_cond_signal(&queue_cond);
+ }
+
+ pthread_mutex_unlock(&queue_lock);
+
+}
+
+static MEM_Container* dequeue_buffer (void) {
+
+ MEM_Container *mem_container;
+
+ if (buffer_queue.empty() )
+ mem_container = NULL;
+ else {
+ mem_container = buffer_queue.front();
+ buffer_queue.pop();
+ }
+
+ return mem_container;
+}
+
+#if defined(HAVE_CONDOR)
+
+static void* send_thread(void *ptr)
+{
+
+ MWTask* t = (MWTask*)ptr;
+
+ while(1) {
+ MEM_Container* mem_container = NULL;
+ bool done = false;
+
+ pthread_mutex_lock(&queue_lock);
+ while( (mem_container = dequeue_buffer()) == NULL ) {
+
+ if( final_buffer ) {
+ break;
+ }else {
+ send_thread_waiting = true;
+ pthread_cond_wait(&queue_cond, &queue_lock);
+ send_thread_waiting = false;
+ }
+ }
+
+ if(buffer_queue.empty()) {
+ done = final_buffer;
+ }
+
+ pthread_mutex_unlock(&queue_lock);
+
+ if( mem_container ) {
+ if(!do_raw_pack (t->RMC, mem_container) ) {
+ fprintf(stderr, "Failed to send data\n");
+ exit(1);
+ }
+
+ if (mem_container->buffer1) {
+ free (mem_container->buffer1);
+ }
+
+ if (mem_container->buffer2) {
+ free (mem_container->buffer2);
+ }
+
+
+ free(mem_container);
+ }
+
+ if( done ) {
+ // Now, we have sent all data
+ // Here, we will send two extra double for stats
+ wall_time += MWSystem::gettimeofday();
+ cpu_time += MWSystem::getcputime();
+ if (!raw_pack (t->RMC, (char*)&wall_time, sizeof(double))) {
+ fprintf(stderr, "Failed to send stats data\n");
+ exit(1);
+ }
+ if (!raw_pack (t->RMC, (char*)&cpu_time, sizeof(double))) {
+ fprintf(stderr, "Failed to send stats data\n");
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static bool raw_pack(MWRMComm* _RMC, char* buf, int len)
+{
+ static int cnt = 0;
+
+ cnt++;
+ int ret = _RMC->raw_pack(buf, len);
+ if( ret != len ) {
+ fprintf(stderr, "raw_pack(%d) failed to write the size of data.\n", cnt);
+ fprintf(stderr, "need to send (%d), but ret = %d\n", len, ret);
+ if( ret < 0 ) {
+ fprintf(stderr, "errno=%d, string=%s\n", errno, strerror(errno));
+ fflush(stderr);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+static bool do_raw_pack (MWRMComm* RMC, MEM_Container *mem_container)
+{
+ int network_int = mem_container->what_data;
+ if (!raw_pack (RMC, (char*) &network_int, sizeof (int)))
+ return false;
+
+ switch (mem_container->what_data) {
+ case SPARSE_DATA :
+ {
+ network_int = ((int) (mem_container->size1 / sizeof(Num_Cells_Buffer)));
+
+ if (!raw_pack (RMC, (char*) &network_int, sizeof (int)))
+ return false;
+
+ if (!raw_pack (RMC, (char*) mem_container->buffer1, mem_container->size1))
+ return false;
+
+ network_int = ((int) mem_container->size2 / sizeof(Sparse_Matrix_Buffer));
+
+ if (!raw_pack (RMC, (char*) &network_int, sizeof (int)))
+ return false;
+
+ if (!raw_pack (RMC, (char*) mem_container->buffer2, mem_container->size2))
+ return false;
+
+ break;
+ }
+ case HEAP_DATA :
+ {
+ network_int = ((int) mem_container->size1 / sizeof (Heap_Buffer));
+ if (!raw_pack (RMC, (char*) &network_int, sizeof(int))) {
+ return false;
+ }
+
+ if (!raw_pack (RMC, (char*) mem_container->buffer1, mem_container->size1)) {
+ return false;
+ }
+
+ break;
+ }
+ default :
+ break;
+ }
+
+ return true;
+}
+
+void transfer_data(MW_task *t)
+{
+
+ // Record times for stats
+ // Set our stopwatch
+ wall_time -= MWSystem::gettimeofday();
+ cpu_time -= MWSystem::getcputime();
+
+ pthread_t thread;
+ if( t->m_raw_flag ) {
+ // we need to create a new thread
+ if( pthread_create(&thread, NULL, send_thread, (void *)t ) != 0 ) {
+ fprintf(stderr, "Failed to create a new thread\n");
+ exit(1);
+ }
+ }
+
+ if (m_fsa->anchored)
+ build_anchored_multiple_alignment ();
+ else
+ build_multiple_alignment ();
+
+ delete m_fsa;
+
+ if( t->m_raw_flag ) {
+ // Now, we have to wait for send_thread to be finished.
+ void *ptr;
+ int ret = pthread_join(thread, &ptr);
+ if( ret != 0 ) {
+ fprintf(stderr, "pthread_join error %d\n", ret);
+ exit(1);
+ }
+
+ }
+}
+
+#endif
+
+#if defined(HAVE_POSTGRES)
+void init_single_worker(const FSA *fsa, DB_adapter *db_adapter, Params ¶ms_seed, Params &pseudocounts) {
+ m_fsa = const_cast<FSA *> (fsa);
+ m_db_adapter = db_adapter;
+
+ m_params_seed.copy_all (params_seed);
+ m_pseudocounts.copy_all (pseudocounts);
+
+ int seqs_schema_id = 0;
+ int params_table_id = 0;
+
+ final_buffer = false;
+ send_thread_waiting = false;
+
+ bool is_db_running = false;
+
+ m_db_buffer.sparse_matrix.clear();
+ m_db_buffer.num_cells.clear();
+ m_db_buffer.heap.clear();
+
+ // set the sequence schema id and the parameter table id
+ seqs_schema_id = (m_db_adapter->get_connection())->get_seqs_schema_id ();
+ params_table_id = (m_db_adapter->get_connection())->get_params_table_id ();
+
+ m_db_adapter->set_up_ids (seqs_schema_id, params_table_id, 0);
+}
+#endif
+
diff --git a/src/math/Makefile.am b/src/math/Makefile.am
new file mode 100644
index 0000000..498159b
--- /dev/null
+++ b/src/math/Makefile.am
@@ -0,0 +1,10 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+noinst_LIBRARIES = libmath.a
+libmath_a_SOURCES = \
+ mathematics.cc \
+ mst.cc
+
+noinst_HEADERS = \
+ mathematics.h \
+ mst.h
diff --git a/src/math/Makefile.in b/src/math/Makefile.in
new file mode 100644
index 0000000..f3a3983
--- /dev/null
+++ b/src/math/Makefile.in
@@ -0,0 +1,549 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/math
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_ at AM_V@)
+am__v_AR_ = $(am__v_AR_ at AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libmath_a_AR = $(AR) $(ARFLAGS)
+libmath_a_LIBADD =
+am_libmath_a_OBJECTS = mathematics.$(OBJEXT) mst.$(OBJEXT)
+libmath_a_OBJECTS = $(am_libmath_a_OBJECTS)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(libmath_a_SOURCES)
+DIST_SOURCES = $(libmath_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+noinst_LIBRARIES = libmath.a
+libmath_a_SOURCES = \
+ mathematics.cc \
+ mst.cc
+
+noinst_HEADERS = \
+ mathematics.h \
+ mst.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/math/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/math/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libmath.a: $(libmath_a_OBJECTS) $(libmath_a_DEPENDENCIES) $(EXTRA_libmath_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libmath.a
+ $(AM_V_AR)$(libmath_a_AR) libmath.a $(libmath_a_OBJECTS) $(libmath_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libmath.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mathematics.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mst.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/math/mathematics.cc b/src/math/mathematics.cc
new file mode 100644
index 0000000..dc13fd6
--- /dev/null
+++ b/src/math/mathematics.cc
@@ -0,0 +1,36 @@
+
+/**
+ * \file mathematics.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include "math/mathematics.h"
+
+using namespace fsa;
+
+const double Mathematics::double_tiny = 0.001;
+const double Mathematics::double_very_tiny = 0.000001;
+
+unsigned Mathematics::factorial (unsigned x) {
+
+ unsigned f = 1;
+
+ while (x > 0) {
+ f *= x--;
+ }
+
+ return f;
+}
+
+double Mathematics::log_factorial (unsigned x) {
+
+ double logf = 0;
+
+ while (x > 1) {
+ logf += std::log (static_cast<double> (x--));
+ }
+
+ return logf;
+}
+
diff --git a/src/math/mathematics.h b/src/math/mathematics.h
new file mode 100644
index 0000000..ac52479
--- /dev/null
+++ b/src/math/mathematics.h
@@ -0,0 +1,195 @@
+
+/**
+ * \file mathematics.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef MATH_MATHEMATICS_INCLUDED
+#define MATH_MATHEMATICS_INCLUDED
+
+#include <cmath>
+#include <utility>
+#include <vector>
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+#include "config.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include "util/misc.h"
+
+namespace fsa {
+
+ struct Mathematics {
+
+ public:
+
+ /**
+ * \brief Is a number a power of 2?
+ */
+ static bool is_power_of_2 (const uintmax_t num);
+
+ /**
+ * \brief Calculates power of 2.
+ */
+ static uintmax_t power_of_2 (const unsigned n);
+
+ /**
+ * \brief Calculates power of k^n, where both k and n are integers.
+ */
+ static uintmax_t power_of_integer (const unsigned k, const unsigned n);
+
+ /**
+ * \brief Calculate factorial x!.
+ */
+ static unsigned factorial (unsigned x);
+
+ /**
+ * \brief Calculate log-factorial log (x!).
+ */
+ static double log_factorial (unsigned x);
+
+ /**
+ * \brief Compute the average value.
+ */
+ template<typename T>
+ static double mean (const std::vector<T>& values);
+
+ /**
+ * \brief Compute the median value.
+ * \param is_sorted true if the data are already sorted low-to-high
+ */
+ template<typename T>
+ static T median (std::vector<T>& values,
+ const bool is_sorted = false);
+
+ /**
+ * \brief Compute the value at a particular percentile (in [0, 1]).
+ * \param is_sorted true if the data are already sorted low-to-high
+ */
+ template<typename T>
+ static T percentile_value (std::vector<T>& values, const float percentile,
+ const bool is_sorted = false);
+
+ /**
+ * \brief Return original value if inside range, or bound if outside.
+ */
+ template<typename N>
+ static N bounded_value (N n, N min_bound, N max_bound) {
+ return n < min_bound
+ ? min_bound
+ : (n > max_bound ? max_bound : n);
+ }
+
+ /**
+ * \brief Function object to compute the normalized difference function (x - y) / (x + y).
+ */
+ template<typename T>
+ struct normalized_difference {
+ double operator() (const T x, const T y) const {
+ return (x - y) / (x + y);
+ }
+ };
+
+
+
+ static const double double_tiny; ///< small double value
+ static const double double_very_tiny; ///< very small double value
+
+ };
+
+ inline bool Mathematics::is_power_of_2 (const uintmax_t num) {
+ return (num & (num - 1)) == 0;
+ }
+
+ inline uintmax_t Mathematics::power_of_2 (const unsigned n) {
+#ifndef NDEBUG
+ if (std::pow (static_cast<double> (2), static_cast<int> (n)) > std::numeric_limits<uintmax_t>::max()) {
+ cerr << "ERROR: Overflow of uintmax_t type: attempting to calculate 2^" << n << endl;
+ exit (1);
+ }
+#endif
+ return static_cast<uintmax_t> (1) << n;
+ }
+
+ inline uintmax_t Mathematics::power_of_integer (const unsigned k, const unsigned n) {
+#ifndef NDEBUG
+ if (std::pow (static_cast<double> (k), static_cast<int> (n)) > std::numeric_limits<uintmax_t>::max()) {
+ cerr << "ERROR: Overflow of uintmax_t type: attempting to calculate " << k << "^" << n << endl;
+ exit (1);
+ }
+#endif
+ uintmax_t sum = 1;
+ for (size_t i = 0; i < n; ++i)
+ sum *= k;
+ return sum;
+ }
+
+ template<typename T>
+ double Mathematics::mean (const std::vector<T>& values) {
+
+ if (!values.size()) {
+ cerr << "ERROR: Tried to take the mean of an empty vector." << endl;
+ exit (1);
+ }
+
+ double total = 0.0;
+ for (typename std::vector<T>::const_iterator value = values.begin(); value != values.end(); ++value)
+ total += *value;
+
+ return (total / values.size());
+
+ }
+
+ template<typename T>
+ T Mathematics::median (std::vector<T>& values,
+ const bool is_sorted /* = false */) {
+
+ return percentile_value (values, 0.5,
+ is_sorted);
+
+ }
+
+ template<typename T>
+ T Mathematics::percentile_value (std::vector<T>& values, const float percentile,
+ const bool is_sorted /* = false */) {
+
+ // check sane
+ if (percentile < 0.0 || percentile > 1.0) {
+ cerr << "ERROR: A percentile of " << percentile << " is not meaningful." << endl;
+ exit (1);
+ }
+
+ if (!values.size()) {
+ cerr << "ERROR: Tried to find a percentile within an empty vector." << endl;
+ exit (1);
+ }
+
+ // sort values if necessary
+ if (!is_sorted)
+ std::sort (values.begin(), values.end());
+
+ // pull out the index into the vector for the appropriate percentile
+ size_t index = static_cast<size_t> (std::floor (values.size() * percentile));
+
+ // catch the case of percentile_value = 1
+ if (index == values.size())
+ index = values.size() - 1;
+ else if (index > values.size()) {
+ cerr << "ERROR: Array index indicated by percentile value overflows the vector indices!" << endl
+ << "index = " << index << "; array size = " << values.size() << endl;
+ exit (1);
+ }
+
+ // take array slice to get appropriate percentile
+ return values[index];
+
+ }
+
+}
+
+#endif /* MATH_MATHEMATICS_INCLUDED */
diff --git a/src/math/mst.cc b/src/math/mst.cc
new file mode 100644
index 0000000..78133e5
--- /dev/null
+++ b/src/math/mst.cc
@@ -0,0 +1,101 @@
+
+/**
+ * \file mst.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include "math/mst.h"
+
+using namespace fsa;
+
+Disjoint_set::Disjoint_set (const size_t n) {
+
+ __elements.reserve (n);
+ for (size_t e = 0; e < n; ++e)
+ __elements.push_back (Element (e, 0)); // parent = e, rank = 0
+
+}
+
+Disjoint_set::Index Disjoint_set::find_dj (const Disjoint_set::Index e) {
+
+ Element& element = get_element (e);
+ if (element.parent == e)
+ return e;
+ else {
+ element.parent = find_dj (element.parent);
+ return element.parent;
+ }
+
+}
+
+void Disjoint_set::union_dj (const Disjoint_set::Index e1, const Disjoint_set::Index e2) {
+
+ Disjoint_set::Index root1index = find_dj (e1);
+ Element& root1 = get_element (root1index);
+ Disjoint_set::Index root2index = find_dj (e2);
+ Element& root2 = get_element (root2index);
+
+ if (root1.rank > root2.rank)
+ root2.parent = root1index;
+ else if (root1.rank < root2.rank)
+ root1.parent = root2index;
+ // unless e1 and e2 are already in the same set, merge them
+ else if (root1 != root2) {
+ root2.parent = root1index;
+ root1.rank = root1.rank + 1;
+ }
+
+}
+
+MST_Kruskal::Edge_set MST_Kruskal::compute_mst (MST_Kruskal::Edge_set& edges, const size_t N,
+ const bool die_on_failure /* = true */) {
+
+ MST_Kruskal::Edge_set mst;
+ mst.reserve (N);
+
+ // initialize forest:
+ // each vertex is a tree
+ Disjoint_set dj (N);
+
+ // sort edges, ordered by increasing weight
+ std::sort (edges.begin(), edges.end());
+
+ // loop over edges, lowest weight first
+ for (MST_Kruskal::Edge_set::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
+
+ // get vertices connected by this edge
+ const size_t u = edge->u;
+ const size_t v = edge->v;
+
+ // check that the vertices are labeled as 0, ..., (N - 1)
+ assert ((u < N) && (v < N));
+
+ // if connecting u and v does not form a cycle
+ // (if the trees containing them are distinct),
+ // then do so
+ if (dj.find_dj (u) != dj.find_dj (v)) {
+ mst.push_back (*edge);
+ dj.union_dj (u, v);
+ }
+
+ // have we assembled a MST?
+ if (mst.size() == N - 1)
+ break;
+
+ }
+
+ // confirm that we've created a spanning tree
+ // (i.e., that the graph was complete to begin with)
+ if (mst.size() != N - 1) {
+ if (die_on_failure) {
+ cerr << "ERROR: Unable to compute a minimal spanning tree. Was the graph complete to begin with?" << endl;
+ exit (1);
+ } else
+ return MST_Kruskal::Edge_set();
+ }
+
+ return mst;
+
+}
+
diff --git a/src/math/mst.h b/src/math/mst.h
new file mode 100644
index 0000000..5736f5f
--- /dev/null
+++ b/src/math/mst.h
@@ -0,0 +1,166 @@
+
+/**
+ * \file mst.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef MATH_MST_INCLUDED
+#define MATH_MST_INCLUDED
+
+#include "util/misc.h"
+#include "math/mathematics.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a disjoint set with UNION-FIND capabilities.
+ *
+ * Representation is a disjoint set forest, where each set is represented
+ * by a tree and each node in the tree (element in the set) holds a reference
+ * to the root of the tree, the representative element of the set.
+ * This is essentially an implementation of the wikipedia description:
+ * http://en.wikipedia.org/wiki/Disjoint-set_data_structure
+ */
+ struct Disjoint_set {
+
+ public:
+
+ typedef size_t Index;
+
+ /**
+ * \brief Constructor.
+ *
+ * Create a disjoint set with the specified number of elements;
+ * each element is in its own set.
+ * Implicitly implements the make_set operation.
+ */
+ Disjoint_set (const size_t n);
+
+ /**
+ * \brief Find the set containing the element e.
+ *
+ * Can also be used to determine whether two elements are in the same set.
+ * Implements the path compression heuristic.
+ * \param e index of element
+ * \return index of the representative of the set
+ */
+ Index find_dj (const Index e);
+
+ /**
+ * \brief Merge the sets containing two elements into a single set.
+ *
+ * Implements the union by rank heuristic.
+ * Awkward name is because "union" is reserved by C++.
+ * \param e1 index of element in set 1 to be merged
+ * \param e2 index of element in set 2 to be merged
+ */
+ void union_dj (const Index e1, const Index e2);
+
+ private:
+
+ /**
+ * \brief Represent a single element in the disjoint set.
+ */
+ struct Element {
+
+ Element (const Index parent, const size_t rank)
+ : parent (parent), rank (rank)
+ { }
+
+ Index parent;
+ size_t rank;
+
+ /**
+ * \brief Equality iff parents are identical.
+ * \see find_dj
+ */
+ bool operator== (const Element& e) const {
+ return parent == e.parent;
+ }
+
+ bool operator!= (const Element& e) const {
+ return !(*this == e);
+ }
+
+ };
+
+ /**
+ * \brief Get an element by its index.
+ */
+ Element& get_element (const Index e) {
+ assert (e < __elements.size());
+ return __elements[e];
+ }
+
+ std::vector<Element> __elements; ///< elements in the disjoint set
+
+ };
+
+ /**
+ * \brief Perform's Kruskal's algorithm for finding the minimum spanning tree of a graph.
+ */
+ struct MST_Kruskal {
+
+ public:
+
+ /**
+ * \brief Represent a weighted, undirected edge.
+ */
+ struct Edge {
+
+ /**
+ * \brief Constructor.
+ */
+ Edge (const unsigned short u, const unsigned short v,
+ const float weight)
+ : u (u), v (v), weight (weight)
+ { }
+
+ unsigned short u;
+ unsigned short v;
+ float weight;
+
+ /**
+ * \brief Comparison operator.
+ */
+ bool operator< (const Edge& e) const {
+ return (weight < e.weight);
+ }
+
+ /**
+ * \brief Comparison operator.
+ */
+ bool operator> (const Edge& e) const {
+ return (weight > e.weight);
+ }
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Edge& edge) {
+ o << edge.u << " -- " << edge.v << " => " << edge.weight;
+ return o;
+ }
+
+ };
+
+ typedef std::vector<Edge> Edge_set; ///< a set of edges
+
+ /**
+ * \brief Find the minimum spanning tree on the given set of edges.
+ *
+ * The vertices in edges MUST be numbered as 0,...,(N - 1)!
+ * \param edges list of edges of graph
+ * \param N number of nodes in the graph
+ * \param die_on_failure die if the graph is not complete (a MST does not exist)
+ * \return the edges composing the MST (empty if no MST found)
+ */
+ static Edge_set compute_mst (Edge_set& edges, const size_t N,
+ const bool die_on_failure = true);
+
+ };
+
+}
+
+#endif /* MATH_MST_INCLUDED */
diff --git a/src/seq/Makefile.am b/src/seq/Makefile.am
new file mode 100644
index 0000000..f100263
--- /dev/null
+++ b/src/seq/Makefile.am
@@ -0,0 +1,22 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+LDADD = \
+ $(top_builddir)/src/util/libutil.a
+
+noinst_LIBRARIES = libseq.a
+libseq_a_SOURCES = \
+ alphabet.cc \
+ alignment.cc \
+ gff.cc \
+ mercator.cc \
+ sequence.cc \
+ similarity_matrix.cc
+
+noinst_HEADERS = \
+ alphabet.h \
+ alignment.h \
+ gff.h \
+ interval.h \
+ mercator.h \
+ sequence.h \
+ similarity_matrix.h
diff --git a/src/seq/Makefile.in b/src/seq/Makefile.in
new file mode 100644
index 0000000..8420c0e
--- /dev/null
+++ b/src/seq/Makefile.in
@@ -0,0 +1,567 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/seq
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_ at AM_V@)
+am__v_AR_ = $(am__v_AR_ at AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libseq_a_AR = $(AR) $(ARFLAGS)
+libseq_a_LIBADD =
+am_libseq_a_OBJECTS = alphabet.$(OBJEXT) alignment.$(OBJEXT) \
+ gff.$(OBJEXT) mercator.$(OBJEXT) sequence.$(OBJEXT) \
+ similarity_matrix.$(OBJEXT)
+libseq_a_OBJECTS = $(am_libseq_a_OBJECTS)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(libseq_a_SOURCES)
+DIST_SOURCES = $(libseq_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+LDADD = \
+ $(top_builddir)/src/util/libutil.a
+
+noinst_LIBRARIES = libseq.a
+libseq_a_SOURCES = \
+ alphabet.cc \
+ alignment.cc \
+ gff.cc \
+ mercator.cc \
+ sequence.cc \
+ similarity_matrix.cc
+
+noinst_HEADERS = \
+ alphabet.h \
+ alignment.h \
+ gff.h \
+ interval.h \
+ mercator.h \
+ sequence.h \
+ similarity_matrix.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/seq/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/seq/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libseq.a: $(libseq_a_OBJECTS) $(libseq_a_DEPENDENCIES) $(EXTRA_libseq_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libseq.a
+ $(AM_V_AR)$(libseq_a_AR) libseq.a $(libseq_a_OBJECTS) $(libseq_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libseq.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/alignment.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/alphabet.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gff.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mercator.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sequence.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/similarity_matrix.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/seq/alignment.cc b/src/seq/alignment.cc
new file mode 100644
index 0000000..f30c050
--- /dev/null
+++ b/src/seq/alignment.cc
@@ -0,0 +1,1154 @@
+
+/**
+ * \file alignment.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <numeric>
+#include <functional>
+#include <algorithm>
+
+#include "util/regexp.h"
+#include "seq/alignment.h"
+
+using namespace fsa;
+
+// NB: Who knows why, but I get linker errors when these definitions
+// are in the header file. It works fine when they're not. Very strange!
+
+const char Alignment::gap_char = '-';
+
+const std::string Stockholm::gff_annotation = "GFF";
+const std::string Stockholm::percent_id_annotation = "Percent_id";
+const std::string Stockholm::gap_fraction_annotation = "Gap_fraction";
+
+const std::string Stockholm::format_identifier = "STOCKHOLM";
+const std::string Stockholm::version_identifier = "1.0";
+const std::string Stockholm::alignment_header = "# " + Stockholm::format_identifier + ' ' + Stockholm::version_identifier;
+const std::string Stockholm::alignment_separator = "//";
+
+const std::string Stockholm::file_annotation = "#=GF";
+const std::string Stockholm::column_annotation = "#=GC";
+const std::string Stockholm::sequence_annotation = "#=GS";
+const std::string Stockholm::sequence_column_annotation = "#=GR";
+
+const char Stockholm::annotation_wildcard_char = '.';
+
+
+
+Alignment_row::Alignment_row (Row_path* row_path)
+ : __row_path (row_path) {
+
+ // calculate the total sequence length
+ __seqlength = static_cast<size_t> (accumulate (__row_path->begin(), __row_path->end(), 0));
+
+ build_coordinate_indices();
+
+}
+
+Alignment_row::Alignment_row (const Alignment_row& parent) {
+
+ // deep copy
+ __seq_to_align_coords_map = parent.__seq_to_align_coords_map;
+ __align_to_seq_coords_map = parent.__align_to_seq_coords_map;
+ __row_path = new Row_path (*parent.__row_path);
+ __seqlength = parent.__seqlength;
+
+}
+
+Alignment_row& Alignment_row::operator= (const Alignment_row& parent) {
+
+ // check for self-assignment
+ if (this == &parent)
+ return *this;
+
+ // clear old memory
+ delete __row_path;
+
+ // deep copy
+ __seq_to_align_coords_map = parent.__seq_to_align_coords_map;
+ __align_to_seq_coords_map = parent.__align_to_seq_coords_map;
+ __row_path = new Row_path (*parent.__row_path);
+ __seqlength = parent.__seqlength;
+
+ return *this;
+
+}
+
+Alignment_row::~Alignment_row() {
+
+ delete __row_path;
+
+}
+
+void Alignment_row::build_coordinate_indices() {
+
+ __seq_to_align_coords_map.clear();
+ __align_to_seq_coords_map.clear();
+
+ // build map from sequence to alignment coordinates, as well as
+ // map from alignment to sequence coordinates
+ // if an alignment position is gapped, then store the sequence
+ // position corresponding to the next ungapped alignment position
+ // note that this means that if the alignment ends with a run of gaps,
+ // then the gapped alignment positions will be mapped to __seqlength,
+ // so this end case must be explicitly checked for
+ __seq_to_align_coords_map.reserve (__seqlength);
+ __align_to_seq_coords_map.reserve (__row_path->size());
+ size_t seqpos = 0; // this always holds the "next" sequence position
+ for (size_t alignpos = 0; alignpos < __row_path->size(); ++alignpos) {
+
+ if (is_gapped (alignpos)) {
+ // do nothing for __seq_to_align_coords_map
+ // record previous sequence position for __align_to_seq_coords_map
+ __align_to_seq_coords_map.push_back (seqpos);
+ }
+
+ else {
+ // record for __seq_to_align_coords_map
+ __seq_to_align_coords_map.push_back (alignpos);
+ // records for __align_to_seq_coords_map
+ __align_to_seq_coords_map.push_back (seqpos);
+ ++seqpos;
+ }
+
+ }
+ assert (__seq_to_align_coords_map.size() == __seqlength);
+ assert (__align_to_seq_coords_map.size() == __row_path->size());
+ assert (seqpos == __seqlength); // sanity check
+
+}
+
+Alignment_row* Alignment_row::subalignment (const unsigned start, const unsigned end) const {
+
+ assert (!__seqlength || (end < length()));
+
+ Row_path* row_path = NULL;
+ if (end < start)
+ row_path = new Row_path();
+ else
+ row_path = new Row_path (__row_path->begin() + start, __row_path->begin() + end + 1);
+
+ return new Alignment_row (row_path);
+
+}
+
+Alignment_row::Row_path* Alignment_row::subalignment_row_path (const unsigned start, const unsigned end) const {
+
+ assert (!__seqlength || (end < length()));
+ if (end < start)
+ return new Row_path();
+ return new Row_path (__row_path->begin() + start, __row_path->begin() + end + 1);
+
+}
+
+void Alignment_row::reverse() {
+
+ // reverse the alignment
+ std::reverse (__row_path->begin(), __row_path->end());
+
+ // and then re-build coordinate indices (it is NOT sufficient to merely reverse these!)
+ build_coordinate_indices();
+
+}
+
+Alignment::Alignment (Sequence_database& seq_db)
+ : seq_db (&seq_db) {
+
+}
+
+Alignment::Alignment (const Alignment& parent) {
+
+ // perform deep copy
+ seq_db = parent.seq_db;
+ for (std::vector<Alignment_row*>::const_iterator row = parent.__rows.begin(); row != parent.__rows.end(); ++row) {
+ Alignment_row* a = new Alignment_row (**row);
+ __rows.push_back (a);
+ }
+ __row_index = parent.__row_index;
+
+}
+
+Alignment& Alignment::Alignment::operator= (const Alignment& parent) {
+
+ // check for self-assignment
+ if (this == &parent)
+ return *this;
+
+ // perform deep copy
+ seq_db = parent.seq_db;
+ for (std::vector<Alignment_row*>::const_iterator row = parent.__rows.begin(); row != parent.__rows.end(); ++row) {
+ Alignment_row* a = new Alignment_row (**row);
+ __rows.push_back (a);
+ }
+ __row_index = parent.__row_index;
+
+ return *this;
+
+}
+
+Alignment::~Alignment() {
+
+ for (std::vector<Alignment_row*>::iterator row = __rows.begin(); row != __rows.end(); ++row)
+ delete *row;
+
+}
+
+bool Alignment::detect_mfa (const std::string& filename) {
+
+ return Sequence::detect_fasta (filename);
+
+}
+
+void Alignment::read_mfa (const std::string& filename, const bool strict /* = true */,
+ const bool verbose /* = true */) {
+
+ clear();
+
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ if (verbose)
+ cerr << "Reading multi-FASTA alignment '" << filename << "'...";
+
+ Regexp re_name ("^[ \t]*" + Sequence::fasta_seq_start + "([^ \t]*)[ \t]*(.*)");
+
+ std::string line;
+
+ std::vector<std::string> gapped_seqs_names;
+ std::vector<std::string> gapped_seqs;
+ std::vector<std::string> gapped_seqs_info;
+
+ bool in_seq_body = false;
+ size_t curr_idx = 0; // dummy value to prevent compiler warnings
+ while (!filestream.eof()) {
+
+ getline (filestream, line);
+
+ // are we at a name line?
+ if (re_name.Match (line.c_str())) {
+ if (re_name.SubStrings() < 1) { continue; }
+ // store name
+ const std::string name = re_name[1];
+ curr_idx = gapped_seqs_names.size();
+ gapped_seqs_names.push_back (name);
+ // store info following name, if present
+ std::string info;
+ if (re_name.SubStrings() >= 2)
+ info = re_name[2];
+ gapped_seqs_info.push_back (info);
+ // store empty row
+ gapped_seqs.push_back ("");
+ in_seq_body = true;
+ }
+ // if not, then we must be reading sequence data
+ else if (in_seq_body) {
+ // if this is the first line of data for this sequence
+ if (gapped_seqs.size() < gapped_seqs_names.size())
+ gapped_seqs.push_back (line);
+ else
+ gapped_seqs[curr_idx] += line;
+ }
+
+ }
+ filestream.close();
+
+ // assert sane
+ if (gapped_seqs.size() != gapped_seqs_names.size()) {
+ cerr << "ERROR: Sequence names and data don't match up. Is your MFA file improperly formatted?" << endl;
+ exit (1);
+ }
+ assert (gapped_seqs_names.size() == gapped_seqs_info.size());
+
+ // now store
+ for (size_t r = 0; r < gapped_seqs.size(); ++r) {
+
+ const std::string& name = gapped_seqs_names[r];
+ std::string& gapped_seq = gapped_seqs[r];
+ std::string& info = gapped_seqs_info[r];
+
+ // strip out whitespace
+ std::string::iterator last_pos = std::remove_if (gapped_seq.begin(), gapped_seq.end(),
+ isspace);
+ gapped_seq.erase (last_pos, gapped_seq.end());
+
+ // remove newline from info, if present
+ Util::chomp (info);
+
+ // create ungapped sequence
+ std::string ungapped_seq;
+ ungapped_seq.resize (gapped_seq.length());
+ last_pos = std::remove_copy_if (gapped_seq.begin(), gapped_seq.end(),
+ ungapped_seq.begin(),
+ Alignment::is_gap_char);
+ ungapped_seq.erase (last_pos, ungapped_seq.end()); // erase unnecessary positions
+
+ // create alignment path
+ Alignment_row::Row_path* row_path = new Alignment_row::Row_path (gapped_seq.length()); // allocate space
+ std::transform (gapped_seq.begin(), gapped_seq.end(),
+ row_path->begin(),
+ std::not1 (std::ptr_fun (Alignment::is_gap_char)));
+
+ // now store row
+ Sequence* sequence = new Sequence (name, ungapped_seq, info);
+ add_row (sequence,
+ row_path);
+ }
+
+ if (strict)
+ assert_flush();
+
+ if (verbose)
+ cerr << "done." << endl;
+
+}
+
+const Alignment_row& Alignment::get_row (const std::string& name) const {
+
+#ifndef NDEBUG
+ if (!exists_row (name)) {
+ cerr << "ERROR: No row named '" << name << "'." << endl;
+ write_mfa (cerr, false);
+ }
+#endif
+ assert (exists_row (name));
+
+ return *__rows[__row_index.find (name)->second];
+
+}
+
+double Alignment::percent_id() const {
+
+ return percent_id (0, columns() - 1);
+
+}
+
+double Alignment::percent_id (const unsigned start, const unsigned end) const {
+
+ assert (start <= end);
+ assert (end < columns());
+
+ double id = 0.; // sum of per-column percent IDs
+ size_t cols = 0; // number of columns used in calculation
+
+ for (size_t c = start; c <= end; ++c) {
+
+ // count the (maximal) fraction of identical characters in the column
+ std::map<char, size_t> char_count;
+ size_t colsize = 0; // # of non-gap characters in column
+ for (size_t r = 0; r < rows(); ++r) {
+ if (!is_gapped (r, c)) {
+ ++char_count[static_cast<char> (tolower (get_char (r, c)))];
+ ++colsize;
+ }
+ }
+
+ // only count columns with > 1 non-gap character
+ if (colsize < 2)
+ continue;
+
+ // find the most common character
+ std::map<char, size_t>::const_iterator max = std::max_element (char_count.begin(), char_count.end(),
+ Util::Map_value_less<std::map<char, size_t> >());
+ // if no character appears more than once,
+ // then percent id = 0
+ if (max->second > 1)
+ id += static_cast<double> (max->second) / colsize;
+
+ // increment columns counter
+ ++cols;
+
+ }
+
+ if (cols == 0)
+ return 0;
+
+ return (id / cols);
+
+}
+
+double Alignment::gap_fraction() const {
+
+ return gap_fraction (0, columns() - 1);
+
+}
+
+double Alignment::gap_fraction (const unsigned start, const unsigned end) const {
+
+ assert (start <= end);
+ assert (end < columns());
+
+ if (columns() == 0 || rows() == 0)
+ return 0;
+
+ size_t gaps = 0;
+
+ for (size_t c = start; c <= end; ++c) {
+ for (size_t r = 0; r < rows(); ++r) {
+ if (is_gapped (r, c))
+ ++gaps;
+ }
+ }
+
+ return (static_cast<double> (gaps) / ((end - start + 1) * rows()));
+
+}
+
+const Sequence Alignment::get_gapped_row (const std::string& name) const {
+
+ assert (exists_row (name));
+
+ return get_gapped_row (__row_index.find (name)->second);
+
+}
+
+const Sequence Alignment::get_gapped_row (const size_t r) const {
+
+ assert (r < rows());
+
+ return get_row (r).get_gapped_seq (seq_db->get_seq (r), Alignment::gap_char);
+
+}
+
+std::vector<std::string> Alignment::get_row_names() const {
+
+ std::vector<std::string> names (rows());
+ for (size_t r = 0; r < rows(); ++r)
+ names[r] = get_row_name (r);
+
+ return names;
+
+}
+
+void Alignment::add_row (Sequence* sequence,
+ Alignment_row::Row_path* row_path) {
+
+#ifndef NDEBUG
+ // check that sequence length matches (implied) alignment sequence length
+ if (sequence->seq.length() != static_cast<size_t> (accumulate (row_path->begin(), row_path->end(), 0))) {
+ cerr << "ERROR: Sequence length mismatch for " << sequence->name << "." << endl
+ << "Sequence: " << sequence->seq << endl
+ << "Alignment_row::Row_path: " << Util::join (*row_path, "") << endl;
+ exit (1);
+ }
+#endif
+ assert (sequence->seq.length() == static_cast<size_t> (accumulate (row_path->begin(), row_path->end(), 0)));
+
+ // store in Sequence_database
+ if (!seq_db->exists_seq (sequence->name))
+ seq_db->add_seq (sequence);
+ // now store alignment information
+ __rows.push_back (new Alignment_row (row_path));
+ // only create a new entry in __row_index if there isn't one already
+ if (!exists_row (sequence->name))
+ __row_index.insert (make_pair (sequence->name, __rows.size() - 1));
+
+#ifndef NDEBUG
+ // check that the sequence indices for the rows in *this
+ // and sequences in the Sequence_database& are still in sync
+ // after this operation
+ if (get_row_index (sequence->name) != seq_db->get_seq_index (sequence->name)) {
+ cerr << "ERROR: Sequence indices are out of sync between the Alignment (index = " << get_row_index (sequence->name) << ") and corresponding Sequence_database& (index = " << seq_db->get_seq_index (sequence->name) << ") after storing '" << sequence->name << "'." << endl;
+ exit (1);
+ }
+#endif
+
+}
+
+void Alignment::add_row (Sequence* sequence,
+ Alignment_row* alignment_row) {
+
+#ifndef NDEBUG
+ // check that sequence length matches alignment sequence length
+ if (sequence->seq.length() != alignment_row->seqlength()) {
+ cerr << "ERROR: Sequence length mismatch for " << sequence->name << "." << endl
+ << "Sequence: " << sequence->seq << endl
+ << "Alignment_row::Row_path: " << *alignment_row << endl;
+ }
+#endif
+ assert (sequence->seq.length() == alignment_row->seqlength());
+
+ // store in Sequence_database
+ if (!seq_db->exists_seq (sequence->name))
+ seq_db->add_seq (sequence);
+ // now store alignment information
+ __rows.push_back (alignment_row);
+ // only create a new entry in __row_index if there isn't one already
+ if (!exists_row (sequence->name))
+ __row_index.insert (make_pair (sequence->name, __rows.size() - 1));
+
+#ifndef NDEBUG
+ // check that the sequence indices for the rows in *this
+ // and sequences in the Sequence_database& are still in sync
+ // after this operation
+ if (get_row_index (sequence->name) != seq_db->get_seq_index (sequence->name)) {
+ cerr << "ERROR: Sequence indices are out of sync between the Alignment (index = " << get_row_index (sequence->name) << ") and corresponding Sequence_database& (index = " << seq_db->get_seq_index (sequence->name) << ") after storing '" << sequence->name << "'." << endl;
+ exit (1);
+ }
+#endif
+
+}
+
+void Alignment::set_row (const std::string& name,
+ Alignment_row::Row_path* row_path) {
+
+ // confirm that such a sequence already exists in the Sequence_database
+ if (!seq_db->exists_seq (name)) {
+ cerr << "ERROR: No sequence 'name' found in the stored Sequence_database." << endl;
+ exit (1);
+ }
+
+#ifndef NDEBUG
+ const Sequence& sequence = seq_db->get_seq (name);
+ // check that sequence length matches (implied) alignment sequence length
+ if (sequence.seq.length() != static_cast<size_t> (accumulate (row_path->begin(), row_path->end(), 0))) {
+ cerr << "ERROR: Sequence length mismatch for " << sequence.name << "." << endl
+ << "Sequence: " << sequence.seq << endl
+ << "Alignment_row::Row_path: " << Util::join (*row_path, "") << endl;
+ exit (1);
+ }
+ assert (sequence.seq.length() == static_cast<size_t> (accumulate (row_path->begin(), row_path->end(), 0)));
+#endif
+
+ // store alignment information
+
+ // only create a new entry in __row_index if there isn't one already
+ if (!exists_row (name)) {
+ __rows.push_back (new Alignment_row (row_path));
+ __row_index.insert (make_pair (name, __rows.size() - 1));
+ } else {
+ __rows[get_row_index (name)] = new Alignment_row (row_path);
+ }
+
+#ifndef NDEBUG
+ // check that the sequence indices for the rows in *this
+ // and sequences in the Sequence_database& are still in sync
+ // after this operation
+ if (get_row_index (name) != seq_db->get_seq_index (name)) {
+ cerr << "ERROR: Sequence indices are out of sync between the Alignment (index = " << get_row_index (name) << ") and corresponding Sequence_database& (index = " << seq_db->get_seq_index (name) << ") after storing '" << name << "'." << endl;
+ exit (1);
+ }
+#endif
+
+}
+
+void Alignment::clear() {
+
+ seq_db->clear();
+
+ for (std::vector<Alignment_row*>::iterator row = __rows.begin(); row != __rows.end(); ++row)
+ delete *row;
+ __rows.clear();
+
+ __row_index.clear();
+
+}
+
+Sequence Alignment_row::get_gapped_seq (const Sequence& ungapped, const char gap_char) const {
+
+#ifndef NDEBUG
+ // check lengths ok
+ if (ungapped.length() != static_cast<size_t> (accumulate (__row_path->begin(), __row_path->end(), 0))) {
+ cerr << "ERROR: Sequence length mismatch for " << ungapped.name << "." << endl
+ << "Sequence: " << ungapped.seq << endl
+ << "Alignment_row::Row_path: " << *this << endl;
+ }
+#endif
+ assert (ungapped.length() == static_cast<size_t> (accumulate (__row_path->begin(), __row_path->end(), 0)));
+
+ std::string gapped (__row_path->size(), gap_char);
+ size_t pos = 0; // sequence position
+ for (size_t col = 0; col < gapped.length(); ++col) { // column (alignment position)
+ if (!is_gapped (col))
+ gapped[col] = ungapped.seq[pos++];
+ }
+
+ return Sequence (ungapped.name, gapped, ungapped.info);
+
+}
+
+void Alignment::assert_flush() const {
+
+#ifndef NDEBUG
+
+ for (std::vector<Alignment_row*>::const_iterator row = __rows.begin(); row != __rows.end(); ++row) {
+ if (columns() != (*row)->length()) {
+ write_mfa (cerr, false);
+ cerr << "ERROR: Alignment not flush." << endl;
+ exit (1);
+ }
+ }
+
+#endif
+
+}
+
+void Alignment::write_mfa (std::ostream& o, const bool strict /* = true */) const {
+
+ if (strict)
+ assert_flush();
+
+ // align to left
+ o.setf (std::ios_base::left);
+
+ for (size_t r = 0; r < rows(); ++r) {
+
+ const Sequence& sequence = get_gapped_row (r);
+ o << Sequence::fasta_seq_start << sequence.name
+ << (sequence.info.length() ? (' ' + sequence.info) : "") << endl
+ << sequence.seq << endl;
+ }
+
+}
+
+Stockholm::Stockholm (Sequence_database& seq_db)
+ : Alignment (seq_db) {
+
+}
+
+void Stockholm::read_stockholm (const std::string& filename, const bool strict /* = true */,
+ const bool verbose /* = true */) {
+
+ clear();
+
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ if (verbose)
+ cerr << "Reading Stockholm alignment '" << filename << "'...";
+
+ Regexp re_stock ("^[ \t]*#[ \t]*" + format_identifier + "[ \t]*" + version_identifier + "[ \t]*$"); // format & version identifiers
+ Regexp re_sep ("^[ \t]*" + alignment_separator + "[ \t]*$"); // alignment separator lines, "//"
+ Regexp re_gf ("^[ \t]*" + file_annotation + "[ \t]+([^ \t]+)[ \t]+(.*)$"); // #=GF lines
+ Regexp re_gc ("^[ \t]*" + column_annotation + "[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]*$"); // #=GC lines
+ Regexp re_gs ("^[ \t]*" + sequence_annotation + "[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+(.*)$"); // #=GS lines
+ Regexp re_gr ("^[ \t]*" + sequence_column_annotation + "[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]*$"); // #=GR lines
+ Regexp re_row ("^[ \t]*([^ \t#]+)[ \t]+([^ \t]*)[ \t]*$"); // alignment row data
+ Regexp re_nonwhite ("[^ \t]"); // whitespace
+
+ // first store gapped sequences in database,
+ // then parse them later to initialize the alignment
+
+ // hold raw (gapped) sequence data read in from file
+ std::vector<std::string> gapped_seqs;
+ std::vector<std::string> gapped_seqs_names;
+
+ std::string line;
+ while (!filestream.eof()) {
+
+ getline (filestream, line);
+ Util::chomp (line);
+
+ // ignore format-version identifiers
+ if (re_stock.Match (line.c_str()))
+ continue;
+
+ // break if we encounter an alignment separator
+ else if (re_sep.Match (line.c_str()))
+ break;
+
+ // #=GF
+ else if (re_gf.Match (line.c_str()) && re_gf.SubStrings() == 2) {
+ const std::string& gf_key = re_gf[1];
+ const std::string& gf_data = re_gf[2];
+ __gf_annot.push_back (std::make_pair (gf_key, gf_data));
+ __gf_index[gf_key].insert (__gf_annot.size() - 1);
+ }
+
+ // #=GC
+ else if (re_gc.Match (line.c_str()) && re_gc.SubStrings() == 2)
+ __gc_annot[re_gc[1]].append (re_gc[2]);
+
+ // #=GS
+ else if (re_gs.Match (line.c_str()) && re_gs.SubStrings() == 3)
+ __gs_annot[re_gs[1]][re_gs[2]] = re_gs[3];
+
+ // #=GR
+ else if (re_gr.Match (line.c_str()) && re_gr.SubStrings() == 3)
+ __gr_annot[re_gr[1]][re_gr[2]].append (re_gr[3]);
+
+ // row data
+ else if (re_row.Match (line.c_str()) && re_row.SubStrings() == 2) {
+
+ const std::string name = re_row[1];
+ const std::string gapped_seq = re_row[2];
+
+ // is it the first time that we've seen this sequence?
+ if (!exists_row (name)) {
+
+ gapped_seqs_names.push_back (name);
+ __row_index.insert (std::make_pair (name, __row_index.size()));
+ gapped_seqs.push_back (gapped_seq);
+
+ if (__gs_annot.find (name) == __gs_annot.end())
+ __gs_annot[name] = Annotation();
+
+ if (__gr_annot.find (name) == __gr_annot.end())
+ __gr_annot[name] = Annotation();
+
+ }
+ // if not, then just append sequence data
+ else {
+ gapped_seqs[__row_index.find (name)->second] += gapped_seq;
+ }
+
+ }
+
+ else if (line.size() && re_nonwhite.Match (line.c_str())) {
+ cerr << "WARNING: couldn't parse the following alignment line:" << endl << line << endl;
+ continue;
+ }
+
+ }
+ filestream.close();
+
+ // now parse this gapped sequence data into an alignment
+ for (size_t r = 0; r < gapped_seqs.size(); ++r) {
+
+ const std::string& name = gapped_seqs_names[r];
+ const std::string& gapped_seq = gapped_seqs[r];
+
+ // create ungapped sequence
+ std::string ungapped_seq;
+ ungapped_seq.resize (gapped_seq.length());
+ std::string::iterator last_pos = remove_copy_if (gapped_seq.begin(), gapped_seq.end(),
+ ungapped_seq.begin(),
+ Alignment::is_gap_char);
+ ungapped_seq.erase (last_pos, ungapped_seq.end()); // erase unnecessary positions
+
+ // create alignment path
+ Alignment_row::Row_path* row_path = new Alignment_row::Row_path (gapped_seq.length()); // allocate space
+ transform (gapped_seq.begin(), gapped_seq.end(),
+ row_path->begin(),
+ std::not1 (std::ptr_fun (Alignment::is_gap_char)));
+
+ // now store row
+ Sequence* sequence = new Sequence (name, ungapped_seq);
+ add_row (sequence,
+ row_path);
+
+ }
+
+ if (strict)
+ assert_all_flush();
+
+ if (verbose)
+ cerr << "done." << endl;
+
+}
+
+void Stockholm::write_stockholm (std::ostream& o, const bool strict /* = true */) const {
+
+ if (strict)
+ assert_all_flush();
+
+ o << alignment_header << endl;
+
+ // align to left
+ o.setf (std::ios_base::left);
+
+ // get the field width for the key columns
+ // max_name_width takes into account sequence names, GF/GS/GC/GR annotations,
+ // and GS annotations for internal nodes...
+ // scroll down to see where it gets its final value
+ size_t max_name_width = 0;
+ for (size_t r = 0; r < rows(); r++) {
+ // sequence names
+ const std::string& name = get_row_name (r);
+ max_name_width = std::max (max_name_width, name.length());
+ // 6 chars for "#=GS name "
+ const Row_annotation::const_iterator gs_annot_row = __gs_annot.find (name);
+ if (gs_annot_row != __gs_annot.end()) {
+ for (Annotation::const_iterator gs = gs_annot_row->second.begin();gs != gs_annot_row->second.end(); ++gs)
+ max_name_width = std::max (max_name_width, gs->first.size() + name.length() + 6);
+ }
+ // 6 chars for "#=GR name "
+ const Row_annotation::const_iterator gr_annot_row = __gr_annot.find (name);
+ if (gr_annot_row != __gr_annot.end()) {
+ for (Annotation::const_iterator gr = gr_annot_row->second.begin();gr != gr_annot_row->second.end(); ++gr)
+ max_name_width = std::max (max_name_width, gr->first.size() + name.length() + 6);
+ }
+ }
+ // 5 chars for "#=GF "
+ for (std::vector<std::pair<std::string, std::string> >::const_iterator gf = __gf_annot.begin(); gf != __gf_annot.end(); ++gf)
+ max_name_width = std::max (max_name_width, gf->first.length() + 5);
+ // 5 chars for "#=GC "
+ for (Annotation::const_iterator gc = __gc_annot.begin();gc != __gc_annot.end(); ++gc)
+ max_name_width = std::max (max_name_width, gc->first.size() + 5);
+
+ // #=GF lines
+ for (std::vector<std::pair<std::string, std::string> >::const_iterator gf = __gf_annot.begin(); gf != __gf_annot.end(); ++gf) {
+ std::string key = file_annotation + ' ' + gf->first;
+ o.width (max_name_width + 1);
+ o << key << gf->second << endl;
+ }
+
+ // #=GS lines
+ for (size_t r = 0; r < rows(); ++r) {
+ const std::string& name = get_row_name (r);
+ const Row_annotation::const_iterator gs_annot_row = __gs_annot.find (name);
+ if (gs_annot_row != __gs_annot.end()) {
+ for (Annotation::const_iterator gs = gs_annot_row->second.begin(); gs != gs_annot_row->second.end(); ++gs) {
+ std::string key = sequence_annotation + ' ' + name + ' ' + gs->first;
+ o.width (max_name_width + 1);
+ o << key << gs->second << endl;
+ }
+ }
+
+ }
+
+ // main body of alignment
+ for (size_t r = 0; r < rows(); r++) {
+ const std::string& name = get_row_name (r);
+
+ // sequence data
+ o.width (max_name_width + 1);
+ const Sequence& sequence = get_gapped_row (r);
+ o << sequence.name
+ << sequence.seq << endl;
+
+ // #=GR lines
+ const Row_annotation::const_iterator gr_annot_row = __gr_annot.find (name);
+ if (gr_annot_row != __gr_annot.end()) {
+ for (Annotation::const_iterator gr = gr_annot_row->second.begin(); gr != gr_annot_row->second.end(); ++gr) {
+ std::string key = sequence_column_annotation + ' ' + name + ' ' + gr->first;
+ o.width (max_name_width + 1);
+ o << key << gr->second << endl;
+ }
+ }
+
+ }
+
+ // #=GC lines
+ for (Annotation::const_iterator gc = __gc_annot.begin(); gc != __gc_annot.end(); ++gc) {
+ std::string key;
+ key = column_annotation + ' ' + gc->first;
+ o.width (max_name_width + 1);
+ o << key << gc->second << endl;
+ }
+
+ o << alignment_separator << endl;
+
+}
+
+void Stockholm::read_stockholm_or_mfa (const std::string& filename, const bool strict /* = true */,
+ const bool verbose /* = true */) {
+
+ if (!detect_mfa (filename))
+ read_stockholm (filename, strict,
+ verbose);
+ else
+ read_mfa (filename, strict,
+ verbose);
+
+}
+
+std::string Stockholm::get_gf_annot (const std::string& key) const {
+
+ std::string s;
+ const std::map<std::string, std::set<size_t> >::const_iterator index = __gf_index.find (key);
+ if (index != __gf_index.end()) {
+ for (std::set<size_t>::const_iterator i = index->second.begin(); i != index->second.end(); ++i)
+ s.append (__gf_annot[*i].second);
+ }
+
+ return s;
+
+}
+
+std::string Stockholm::get_gc_annot (const std::string& key) const {
+
+ std::string s;
+ const Annotation::const_iterator gc_iter = __gc_annot.find (key);
+ if (gc_iter != __gc_annot.end())
+ s = gc_iter->second;
+
+ return s;
+
+}
+
+std::string Stockholm::get_gs_annot (const std::string& seq, const std::string& key) const {
+
+ std::string s;
+ const Row_annotation::const_iterator gs_row_annot = __gs_annot.find (seq);
+ if (gs_row_annot != __gs_annot.end()) {
+ const Annotation::const_iterator gs = gs_row_annot->second.find (key);
+ if (gs != gs_row_annot->second.end())
+ s = gs->second;
+ }
+
+ return s;
+
+}
+
+std::string Stockholm::get_gr_annot (const std::string& seq, const std::string& key) const {
+
+ std::string s;
+ const Row_annotation::const_iterator gr_row_annot = __gr_annot.find (seq);
+ if (gr_row_annot != __gr_annot.end()) {
+ const Annotation::const_iterator gr = gr_row_annot->second.find (key);
+ if (gr != gr_row_annot->second.end())
+ s = gr->second;
+ }
+
+ return s;
+
+}
+
+void Stockholm::clear() {
+
+ this->Alignment::clear();
+ clear_annot();
+
+}
+
+void Stockholm::clear_annot() {
+
+ __gf_annot.clear();
+ __gc_annot.clear();
+ __gs_annot.clear();
+ __gr_annot.clear();
+ __gf_index.clear();
+
+}
+
+void Stockholm::add_gf_annot (const std::string& key, const std::string& value) {
+ __gf_annot.push_back (std::make_pair (key, value));
+ __gf_index[key].insert (__gf_annot.size() - 1);
+}
+
+void Stockholm::set_gc_annot (const std::string& key, const std::string& value) {
+ __gc_annot[key] = value;
+}
+
+void Stockholm::set_gs_annot (const std::string& seq, const std::string& key, const std::string& value) {
+ __gs_annot[seq].insert (std::make_pair (key, value));
+}
+
+
+void Stockholm::set_gr_annot (const std::string& seq, const std::string& key, const std::string& value) {
+ __gr_annot[seq].insert (std::make_pair (key, value));
+}
+
+Stockholm* Stockholm::subalignment (Sequence_database& seq_db_subalign,
+ const unsigned start, const unsigned end) const {
+
+ Stockholm* subalign = new Stockholm (seq_db_subalign);
+ subalign->clear();
+
+ // #=GF lines
+ for (std::vector<std::pair<std::string, std::string> >::const_iterator gf = __gf_annot.begin(); gf != __gf_annot.end(); ++gf)
+ subalign->add_gf_annot (gf->first, gf->second);
+
+ // #=GS lines
+ for (size_t r = 0; r < rows(); ++r) {
+ const std::string& name = get_row_name (r);
+ const Row_annotation::const_iterator gs_annot_row = __gs_annot.find (name);
+ if (gs_annot_row != __gs_annot.end()) {
+ for (Annotation::const_iterator gs = gs_annot_row->second.begin(); gs != gs_annot_row->second.end(); ++gs)
+ subalign->set_gs_annot (name, gs->first, gs->second);
+ }
+ }
+
+ // main body of alignment
+ for (size_t r = 0; r < rows(); ++r) {
+
+ const std::string& name = get_row_name (r);
+ const Alignment_row& row = get_row (r);
+
+ // sequence data
+ const Interval seq_coords = row.map_align_to_seq (start, end);
+ subalign->add_row (seq_db->get_seq (r).subsequence (seq_coords.start, seq_coords.end),
+ row.subalignment_row_path (start, end));
+ // (note that the called functions properly handle the case of the 0-length interval (1, 0)
+ // which map_align_to_seq may return)
+
+ // #=GR lines
+ const Row_annotation::const_iterator gr_annot_row = __gr_annot.find (name);
+ if (gr_annot_row != __gr_annot.end()) {
+ for (Annotation::const_iterator gr = gr_annot_row->second.begin(); gr != gr_annot_row->second.end(); ++gr)
+ subalign->set_gr_annot (name, gr->first, gr->second.substr (start, start < end ? end - start + 1 : 0)); // catch case of the empty alignment
+ }
+
+ }
+
+ // #=GC lines
+ for (Annotation::const_iterator gc = __gc_annot.begin(); gc != __gc_annot.end(); ++gc)
+ subalign->set_gc_annot (gc->first, gc->second.substr (start, start < end ? end - start + 1 : 0));
+
+ return subalign;
+
+}
+
+void Stockholm::assert_all_flush() const {
+
+#ifndef NDEBUG
+
+ assert_flush();
+
+ // now check annotations
+ for (size_t r = 0; r < rows(); ++r) {
+
+ const std::string& name = get_row_name (r);
+
+ // #=GR lines
+ const Row_annotation::const_iterator gr_annot_row = __gr_annot.find (name);
+ if (gr_annot_row != __gr_annot.end()) {
+ for (Annotation::const_iterator gr = gr_annot_row->second.begin(); gr != gr_annot_row->second.end(); ++gr) {
+ if (columns() != gr->second.length()) {
+ write_stockholm (cerr, false);
+ cerr << "ERROR: Alignment annotations not flush." << endl;
+ exit (1);
+ }
+ }
+ }
+
+ }
+
+ // #=GC lines
+ for (Annotation::const_iterator gc = __gc_annot.begin(); gc != __gc_annot.end(); ++gc) {
+ if (columns() != gc->second.length()) {
+ write_stockholm (cerr, false);
+ cerr << "ERROR: Alignment annotations not flush." << endl;
+ exit (1);
+ }
+ }
+
+#endif
+
+}
+
+void Stockholm::revcomp (const Alphabet& alphabet) {
+
+ // revcomp sequences
+ seq_db->revcomp (alphabet);
+
+ // now reverse per-column annotations
+ for (size_t r = 0; r < rows(); ++r) {
+
+ const std::string& name = get_row_name (r);
+
+ // reverse alignment row
+ // note that this method properly re-builds the coordinate indices with Alignment_row::build_coordinate_indices
+ get_row (r).reverse();
+
+ // #=GR lines
+ const Row_annotation::iterator gr_annot_row = __gr_annot.find (name);
+ if (gr_annot_row != __gr_annot.end()) {
+ for (Annotation::iterator gr = gr_annot_row->second.begin(); gr != gr_annot_row->second.end(); ++gr)
+ std::reverse (gr->second.begin(), gr->second.end());
+ }
+
+ }
+
+ // #=GC lines
+ for (Annotation::iterator gc = __gc_annot.begin(); gc != __gc_annot.end(); ++gc)
+ std::reverse (gc->second.begin(), gc->second.end());
+
+}
+
+Stockholm Stockholm::get_codon_from_aa_alignment (Sequence_database& seq_db_codon) const {
+
+ // sanity check on number of seqs
+ assert (this->rows() == seq_db_codon.size());
+
+ // calculate the appropriate number of columns for the codon alignment
+ size_t cols = 3 * this->columns(); // columns in aa alignment
+ for (size_t i = 0; i < seq_db_codon.size(); ++i) {
+ const Sequence& sequence = seq_db_codon.get_seq (i);
+ const unsigned rem = sequence.length() % 3; // add columns for overhanging nt
+ cols += rem;
+ }
+
+ // initialize codon alignment
+ Stockholm stockholm_codon (seq_db_codon);
+
+ // #=GF lines
+ stockholm_codon.__gf_annot = this->__gf_annot;
+ stockholm_codon.__gf_index = this->__gf_index;
+
+ // #=GS lines
+ for (size_t r = 0; r < rows(); ++r) {
+ const std::string& name = get_row_name (r);
+ const Row_annotation::const_iterator gs_annot_row = __gs_annot.find (name);
+ if (gs_annot_row != __gs_annot.end()) {
+ for (Annotation::const_iterator gs = gs_annot_row->second.begin(); gs != gs_annot_row->second.end(); ++gs)
+ stockholm_codon.set_gs_annot (name, gs->first, gs->second);
+ }
+ }
+
+ // store nt alignment
+ unsigned indent = 0;
+ for (size_t i = 0; i < seq_db_codon.size(); ++i) {
+
+ const std::string& name = seq_db_codon.get_seq (i).name;
+
+ // #=GR lines
+ const Row_annotation::const_iterator gr_annot_row = __gr_annot.find (name);
+ if (gr_annot_row != __gr_annot.end()) {
+ for (Annotation::const_iterator gr = gr_annot_row->second.begin(); gr != gr_annot_row->second.end(); ++gr) {
+ std::string gr_codon (cols, Stockholm::annotation_wildcard_char);
+ for (size_t s = 0; s < gr->second.length(); ++s)
+ gr_codon[(3 * s)] = gr_codon[(3 * s) + 1] = gr_codon[(3 * s) + 2] = gr->second[s];
+ stockholm_codon.set_gr_annot (name, gr->first, gr_codon);
+ }
+ }
+
+ // store this row of alignment as vector of booleans
+ const Alignment_row& row_aa = this->get_row (i);
+ Alignment_row::Row_path* row_path_nt = new Alignment_row::Row_path (cols, false);
+ size_t ii;
+ for (ii = 0; ii < row_aa.length(); ++ii) {
+ // if a character (aa) here, mark the corresponding codon as aligned
+ if (!row_aa.is_gapped (ii))
+ (*row_path_nt)[(3 * ii)] = (*row_path_nt)[(3 * ii) + 1] = (*row_path_nt)[(3 * ii) + 2] = true;
+ }
+
+ // store overhangs if necessary as unaligned nt
+ const unsigned len_aa = this->get_row (i).seqlength();
+ const unsigned len_nt = seq_db_codon.get_seq (i).length();
+ if (static_cast<unsigned> (len_nt / 3) != len_aa) { // sanity check on sequence lengths
+ cerr << "ERROR: Sequence lengths in protein and codon space don't agree (even when rounded to the lowest multiple of 3)." << endl;
+ exit (1);
+ }
+
+ if (len_nt > 3 * len_aa) {
+ for (size_t overhang = len_nt - (3 * len_aa); overhang > 0; --overhang)
+ (*row_path_nt)[(3 * ii) + overhang + indent - 1] = true;
+ indent += len_nt - (3 * len_aa);
+ }
+
+ // add the row to the alignment
+ stockholm_codon.set_row (seq_db_codon.get_seq (i).name, row_path_nt);
+
+ }
+
+ // #=GC lines
+ for (Annotation::const_iterator gc = __gc_annot.begin(); gc != __gc_annot.end(); ++gc) {
+ std::string gc_codon (cols, Stockholm::annotation_wildcard_char);
+ for (size_t s = 0; s < gc->second.length(); ++s)
+ gc_codon[(3 * s)] = gc_codon[(3 * s) + 1] = gc_codon[(3 * s) + 2] = gc->second[s];
+ stockholm_codon.set_gc_annot (gc->first, gc_codon);
+ }
+
+ stockholm_codon.assert_all_flush();
+
+ return stockholm_codon;
+
+}
+
+void Stockholm::annotate_with_statistics() {
+
+ add_gf_annot (Stockholm::percent_id_annotation, Util::to_string (percent_id()));
+ add_gf_annot (Stockholm::gap_fraction_annotation, Util::to_string (gap_fraction()));
+
+}
diff --git a/src/seq/alignment.h b/src/seq/alignment.h
new file mode 100644
index 0000000..48075ad
--- /dev/null
+++ b/src/seq/alignment.h
@@ -0,0 +1,729 @@
+
+/**
+ * \file alignment.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ * Parsing of Stockholm-format alignments is based on Ian Holmes's
+ * Stockholm class.
+ */
+
+#ifndef SEQ_ALIGNMENT_INCLUDED
+#define SEQ_ALIGNMENT_INCLUDED
+
+#include <set>
+#include <algorithm>
+
+#include "seq/sequence.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a single row of an alignment.
+ *
+ * All coordinates are 0-based.
+ * Intervals are always fully-closed, [start, end].
+ */
+ struct Alignment_row {
+
+ public:
+
+ /**
+ * \brief Represention of row of alignment.
+ *
+ * True indicates that a character is present at an alignment position;
+ * false otherwise.
+ */
+ typedef std::vector<bool> Row_path;
+
+ /**
+ * \brief Constructor.
+ */
+ Alignment_row (Row_path* path);
+ Alignment_row (const Alignment_row& parent);
+ Alignment_row& operator= (const Alignment_row& parent);
+
+ /**
+ * \brief Destructor.
+ */
+ ~Alignment_row();
+
+ /**
+ * \brief Build mapping between sequence and alignment coordinates.
+ */
+ void build_coordinate_indices();
+
+ /**
+ * \brief Length of alignment row.
+ */
+ inline size_t length() const { return __row_path->size(); }
+
+ /**
+ * \brief Length of ungapped sequence.
+ */
+ inline size_t seqlength() const { return __seqlength; }
+
+ /**
+ * \brief Get gapped sequence corresponding to this row.
+ * \param ungapped ungapped sequence
+ */
+ Sequence get_gapped_seq (const Sequence& ungapped, const char gap_char) const;
+
+ /**
+ * \brief Get (possibly-gapped) character for a column of this row.
+ * \param col column of Alignment_row
+ */
+ inline char get_char (const size_t col,
+ const Sequence& ungapped, const char gap_char) const;
+
+ /**
+ * \brief Extract subalignment.
+ *
+ * \param start start coordinate of alignment row
+ * \param end end coordinate of alignment row
+ */
+ Alignment_row* subalignment (const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Extract Row_path subalignment.
+ *
+ * \param start start coordinate of alignment row
+ * \param end end coordinate of alignment row
+ */
+ Row_path* subalignment_row_path (const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Map a sequence position to the corresponding alignment coordinate.
+ */
+ inline unsigned map_seq_to_align (const unsigned pos) const;
+
+ /**
+ * \brief Map subalignment coordinates to the corresponding sequence interval.
+ *
+ * \param start start coordinate of alignment row
+ * \param end end coordinate of alignment row
+ * \return sequence interval, or (1, 0) if the interval is empty
+ */
+ inline Interval map_align_to_seq (const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Reverse alignment.
+ *
+ * Calls build_coordinate_indices.
+ */
+ void reverse();
+
+ /**
+ * \brief Is an alignment coordinate (column) gapped in this sequence?
+ */
+ inline bool is_gapped (const unsigned col) const {
+ assert (col < __row_path->size());
+ return !(*__row_path)[col];
+ }
+
+ /**
+ * \brief Output operator (write Row_path).
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Alignment_row& row) {
+ o << Util::join (*row.__row_path, "") << endl;
+ return o;
+ }
+
+ private:
+
+ std::vector<size_t> __seq_to_align_coords_map; ///< map sequence to alignment coordinates
+ std::vector<size_t> __align_to_seq_coords_map; ///< map alignment to sequence coordinates (next ungapped position)
+ Row_path* __row_path; ///< alignment path
+ size_t __seqlength; ///< length of ungapped sequence
+
+ };
+
+ /**
+ * \brief Represent a matrix-form global alignment.
+ *
+ * All coordinates are 0-based.
+ * An Alignment holds a reference to the Sequence_database
+ * which contains the actual sequence information.
+ * The reference is non-const because an Alignment
+ * can modify the sequence information (e.g., when it reads
+ * in an alignment).
+ */
+ struct Alignment {
+
+ public:
+
+ static const char gap_char; ///< gap character
+
+ /**
+ * \brief Constructor.
+ * \param seq_db Sequence_database to hold actual sequence information
+ */
+ Alignment (Sequence_database& seq_db);
+ Alignment (const Alignment& parent);
+ Alignment& operator= (const Alignment& parent);
+
+ /**
+ * \brief Detect whether an alignment seems to be in multi-FASTA format.
+ * \see Sequence::detect_fasta
+ */
+ static bool detect_mfa (const std::string& filename);
+
+ /**
+ * \brief Initialize from multi-FASTA alignment.
+ *
+ * Clears all alignment and sequence data.
+ * Populates seq_db as appropriate,
+ * being very careful to maintain ordering of sequences
+ * for consistency when indexing seq_db and __rows.
+ * \param filename alignment filename
+ * \param strict Require that alignment be flush.
+ */
+ void read_mfa (const std::string& filename, const bool strict = true,
+ const bool verbose = true);
+
+ /**
+ * \brief Write in multi-FASTA format.
+ * \param strict Require that alignment be flush.
+ */
+ void write_mfa (std::ostream& o, const bool strict = true) const;
+
+ /**
+ * \brief Assert all alignment rows of equal length.
+ */
+ void assert_flush() const;
+
+ /**
+ * \brief Map a sequence position to the corresponding alignment coordinate.
+ * \param seq sequence name
+ * \see Alignment_row::map_seq_to_align
+ */
+ inline size_t map_seq_to_align (const std::string& seq, const unsigned pos) const {
+ return get_row (seq).map_seq_to_align (pos);
+ }
+
+ /**
+ * \brief Map subalignment coordinates to the corresponding sequence interval.
+ *
+ * Maps to the sequence interval which is strictly contained by
+ * the subalignment.
+ * \param seq sequence name
+ * \param start start coordinate of alignment row
+ * \param end end coordinate of alignment row
+ * \return sequence interval, or (1, 0) if the interval is empty
+ * \see Alignment_row::map_align_to_seq
+ */
+ inline Interval map_align_to_seq (const std::string& seq, const unsigned start, const unsigned end) const {
+ return get_row (seq).map_align_to_seq (start, end);
+ }
+
+ /**
+ * \brief Map an interval in one sequence to the corresponding interval in another.
+ *
+ * Maps to the sequence interval in seq_to which is strictly contained by
+ * the subalignment implied by the sequence interval in seq_from.
+ * \return sequence interval, or (1, 0) if the interval is empty
+ * \see map_seq_to_align
+ * \see map_align_to_seq
+ */
+ inline Interval map_seq_to_seq (const std::string& seq_from, const unsigned start_from, const unsigned end_from,
+ const std::string& seq_to) const;
+
+ /**
+ * \brief Calculate average per-column percentage identity of alignment.
+ *
+ * Reports the average per-column percent id:
+ * sum_columns (# identical characters in column / total # non-gap characters in column) / num_columns
+ * Gaps are ignored in both the numerator and denominator.
+ */
+ double percent_id() const;
+
+ /**
+ * \brief Calculate average per-column percentage identity of subalignment [start, end].
+ *
+ * Reports the average per-column percent id:
+ * sum_columns (# identical characters in column / total # non-gap characters in column) / num_columns
+ * Gaps are ignored in both the numerator and denominator.
+ * \param start start column of subalignment
+ * \param end end column of subalignment
+ */
+ double percent_id (const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Calculate fraction of gaps in the alignment.
+ */
+ double gap_fraction() const;
+
+ /**
+ * \brief Calculate fraction of gaps in the subalignment [start, end].
+ *
+ * \param start start column of subalignment
+ * \param end end column of subalignment
+ */
+ double gap_fraction (const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Get row of alignment.
+ * \param name sequence name
+ */
+ const Alignment_row& get_row (const std::string& name) const;
+
+ /**
+ * \brief Get gapped row of alignment formatted for display.
+ * \param name sequence name
+ */
+ const Sequence get_gapped_row (const std::string& name) const;
+
+ /**
+ * \brief Get gapped row of alignment formatted for display.
+ * \param r index in __rows or seq_db
+ */
+ const Sequence get_gapped_row (const size_t r) const;
+
+ /**
+ * \brief Remove all gaps from the passed string.
+ */
+ static void remove_gaps (std::string& str);
+
+ /**
+ * \brief Get name of row of alignment.
+ * \param r index in __rows or seq_db
+ */
+ const std::string& get_row_name (const size_t r) const {
+ assert (r < __rows.size());
+ return seq_db->get_seq (r).name;
+ }
+
+ /**
+ * \brief Get index of row in alignment.
+ * \param name sequence name
+ */
+ size_t get_row_index (const std::string& name) const {
+ assert (exists_row (name));
+ return __row_index.find (name)->second;
+ }
+
+ /**
+ * \brief Get names of rows in the alignment.
+ *
+ * Row names are ordered as they are indexed in the alignment.
+ */
+ std::vector<std::string> get_row_names() const;
+
+ /**
+ * \brief Add a row to the alignment.
+ *
+ * Helper for reading alignment files from disk.
+ * Generally preferred over the other add_row for efficiency.
+ * Add sequence information to Sequence_database as well
+ * if nothing is present for the sequence name.
+ * Beware: This function may not behave as you expect.
+ * \param sequence sequence for alignment row
+ * \param row_path Alignment_row::row_path for row
+ */
+ void add_row (Sequence* sequence,
+ Alignment_row::Row_path* row_path);
+
+ /**
+ * \brief Add a row to the alignment.
+ *
+ * Helper for reading alignment files from disk.
+ * Add sequence information to Sequence_database as well
+ * if nothing is present for the sequence name.
+ * Beware: This function may not behave as you expect.
+ * \param sequence sequence for alignment row
+ * \param alignment_row Alignment_row for row
+ */
+ void add_row (Sequence* sequence,
+ Alignment_row* alignment_row);
+
+ /**
+ * \brief Set a row in the alignment.
+ *
+ * This function should be used when constructing a new alignment
+ * of sequence data which has already been stored in
+ * the Sequence_database&; if you want to read in an alignment
+ * and sequence data simultaneously (e.g., when reading an alignment
+ * file from disk), then you should use add_row.
+ *
+ * Assumes (and requires) that there is a sequence named 'name'
+ * in the stored Sequence_database; dies if not.
+ * If there is a corresponding row already stored in __rows,
+ * then overwrite it; otherwise store
+ * Note that if improperly used, this function can cause
+ * the sequence indices for the Alignment object and the
+ * stored Sequence_database& object to go out of sync!
+ * Be very careful.
+ * \param name name of seqence for alignment row
+ * \param row_path Alignment_row::row_path for row
+ */
+ void set_row (const std::string& name,
+ Alignment_row::Row_path* row_path);
+
+ /**
+ * \brief Do we have a row for a particular sequence name?
+ * \param name sequence name
+ */
+ bool exists_row (const std::string& name) const {
+ return (__row_index.find (name) != __row_index.end());
+ }
+
+ /**
+ * \brief Clear all alignment and sequence data.
+ *
+ * \see Sequence_database::clear
+ */
+ virtual void clear();
+
+ /**
+ * \brief Number of sequences in alignment.
+ */
+ inline size_t rows() const;
+
+ /**
+ * \brief Number of columns in alignment.
+ */
+ inline size_t columns() const;
+
+ /**
+ * \brief Is a character a gap?
+ *
+ * Gaps can be: gap_char . _
+ */
+ static inline bool is_gap_char (char c) {
+ return (c == gap_char || c == '.' || c == '_');
+ }
+
+ /**
+ * \brief Is a particular (row, column) gapped?
+ * \param row row index for sequence
+ * \param col column of alignment
+ */
+ inline bool is_gapped (const size_t row, const size_t col) const;
+
+ protected:
+
+ /**
+ * \brief Get row of alignment.
+ * \param r index in __rows or seq_db
+ */
+ const Alignment_row& get_row (const size_t r) const {
+ assert (r < __rows.size());
+ return *__rows[r];
+ }
+
+ /**
+ * \brief Get row of alignment.
+ * \param r index in __rows or seq_db
+ */
+ Alignment_row& get_row (const size_t r) {
+ assert (r < __rows.size());
+ return *__rows[r];
+ }
+
+ /**
+ * \brief Get the character at a particular (row, column).
+ * \param row row index for sequence
+ * \param col column of alignment
+ * \see Alignment_row::get_char
+ */
+ char get_char (const size_t row, const size_t col) const;
+
+ /**
+ * \brief Destructor.
+ *
+ * Note that the memory for seq_db is NOT freed,
+ * since we assume that it was allocated elsewhere.
+ */
+ virtual ~Alignment();
+
+ Sequence_database* seq_db; ///< sequences of the alignment
+ std::vector<Alignment_row*> __rows; ///< individual rows of the alignment
+ std::map<std::string, size_t> __row_index; ///< map from row names to position in __rows
+
+ };
+
+ /**
+ * \brief Represent a Stockholm-format alignment.
+ */
+ struct Stockholm : public Alignment {
+
+ /**
+ * \brief Constructor.
+ */
+ Stockholm (Sequence_database& seq_db);
+
+ /**
+ * \brief Initialize from Stockholm alignment.
+ *
+ * Clears all alignment and sequence data.
+ * Populates seq_db as appropriate,
+ * being very careful to maintain ordering of sequences
+ * for consistency when indexing seq_db and __rows.
+ * \param filename alignment filename.
+ * \param strict Require that alignment be flush.
+ * \see Alignment::clear
+ */
+ void read_stockholm (const std::string& filename, const bool strict = true,
+ const bool verbose = true);
+
+ /**
+ * \brief Initialize from Stockholm or multi-FASTA alignment.
+ *
+ * Clears all alignment and sequence data.
+ * \param filename alignment filename.
+ * \param strict Require that alignment be flush.
+ * \see Alignment::clear
+ */
+ void read_stockholm_or_mfa (const std::string& filename, const bool strict = true,
+ const bool verbose = true);
+
+ /**
+ * \brief Write in Stockholm format.
+ * \param strict Require that alignment be flush.
+ */
+ void write_stockholm (std::ostream& o, const bool strict = true) const;
+
+ /**
+ * \brief Extract subalignment.
+ *
+ * \param seq_db_subalign Sequence_database to store sequence information for subalignment
+ * \param start start coordinate of alignment
+ * \param end end coordinate of alignment
+ */
+ Stockholm* subalignment (Sequence_database& seq_db_subalign,
+ const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Get all #=GF lines with a given key.
+ */
+ std::string get_gf_annot (const std::string& key) const;
+
+ /**
+ * \brief Get #=GC line with a given key.
+ */
+ std::string get_gc_annot (const std::string& key) const;
+
+ /**
+ * \brief Get #=GS line for a given sequence with a given key.
+ */
+ std::string get_gs_annot (const std::string& seq, const std::string& key) const;
+
+ /**
+ * \brief Get #=GR line for a given sequence with a given key.
+ */
+ std::string get_gr_annot (const std::string& seq, const std::string& key) const;
+
+ /**
+ * \brief Add a #=GF line.
+ */
+ void add_gf_annot (const std::string& key, const std::string& value);
+
+ /**
+ * \brief Set a #=GC line.
+ */
+ void set_gc_annot (const std::string& key, const std::string& value);
+
+ /**
+ * \brief Set a #=GS line.
+ */
+ void set_gs_annot (const std::string& seq, const std::string& key, const std::string& value);
+
+ /**
+ * \brief Set a #=GR line.
+ */
+ void set_gr_annot (const std::string& seq, const std::string& key, const std::string& value);
+
+ /**
+ * \brief Clear all alignment and sequence data as well as annotations.
+ *
+ * \see Sequence_database::clear
+ */
+ void clear();
+
+ /**
+ * \brief Clear all annotation lines.
+ */
+ void clear_annot();
+
+ /**
+ * \brief Assert all alignment rows and per-column annotations of equal length.
+ */
+ void assert_all_flush() const;
+
+ /**
+ * \brief Reverse-complement alignment and associated sequence data under the passed alphabet.
+ *
+ * Handles annotations, etc. properly.
+ * (This is why it's a method of Stockholm rather than the parent Alignment class.)
+ * \param alphabet Alphabet to reverse-complement under
+ */
+ void revcomp (const Alphabet& alphabet);
+
+ /**
+ * \brief Map amino acid alignment to corresponding codon alignment.
+ *
+ * Assumes that the sequences in seq_db_codon are ordered as in this->seq_db.
+ * Handles annotations, etc. properly (overhangs are annotated as '.').
+ * \param seq_db_codon sequence data in nucleotide space
+ */
+ Stockholm get_codon_from_aa_alignment (Sequence_database& seq_db_codon) const;
+
+ /**
+ * \brief Annotate alignment with alignment statistics.
+ *
+ * Assumes that the (implicit) alphabet is NOT case-sensitive.
+ * \see Alignment::percent_id
+ * \see Alignment::gap_fraction
+ */
+ void annotate_with_statistics();
+
+
+ static const std::string gff_annotation; ///< GFF annotation key
+ static const std::string percent_id_annotation; ///< percent id annotation key
+ static const std::string gap_fraction_annotation; ///< gap fraction annotation key
+
+
+
+ private:
+
+ static const std::string format_identifier;
+ static const std::string version_identifier;
+ static const std::string alignment_header;
+ static const std::string alignment_separator;
+
+ static const std::string file_annotation;
+ static const std::string column_annotation;
+ static const std::string sequence_annotation;
+ static const std::string sequence_column_annotation;
+
+ static const char annotation_wildcard_char; ///< Annotation unknown character
+
+ typedef std::map<std::string, std::string> Annotation; ///< keyed annotations
+ typedef std::map<std::string, Annotation> Row_annotation; ///< Annotation keyed by sequence
+
+ std::vector<std::pair<std::string, std::string> > __gf_annot; ///< sorted list of #=GF annotations
+ Annotation __gc_annot; ///< per-column annotation
+ Row_annotation __gs_annot; ///< per-sequence annotation
+ Row_annotation __gr_annot; ///< per-sequence, per-column annotation
+ std::map<std::string, std::set<size_t> > __gf_index; ///< map from keys to #=GF lines
+
+ };
+
+
+ /****************************************
+ * Function definitions.
+ ****************************************/
+
+ inline unsigned Alignment_row::map_seq_to_align (const unsigned pos) const {
+ assert (pos < __seq_to_align_coords_map.size());
+ return __seq_to_align_coords_map[pos];
+ }
+
+ inline Interval Alignment_row::map_align_to_seq (const unsigned start, const unsigned end) const {
+
+ if (start > end)
+ cerr << "start = " << start << ", end = " << end << endl;
+ assert (start <= end);
+ assert (end < __align_to_seq_coords_map.size());
+
+ const unsigned s = __align_to_seq_coords_map[start]; // next ungapped position
+ unsigned e = __align_to_seq_coords_map[end];
+
+ // check for e == 0
+ if (e == 0) {
+
+ // if e == 0 and sequence is gapped at column end,
+ // then [s, e] must map to a run of gaps at the start of the alignment
+ if (is_gapped (end))
+ return Interval (1, 0);
+
+ // if sequence isn't gapped at column end,
+ // then we must have a situation like this:
+ // 000000123
+ // -----AGGC
+ // s e
+ // where column end corresponds to the first ungapped position in the sequence
+ // very very tricky...
+ else {
+ assert (s == e);
+ assert (e == 0);
+ return Interval (0, 0);
+ }
+
+ }
+
+ // from here on we can safely assume that e > 0
+
+ // check for end being gapped;
+ // if it is, then set e to the previous ungapped position
+ // (this also catches case of e running off the end of the sequence)
+ if (is_gapped (end))
+ --e;
+
+ // catch cases giving empty sequence:
+ // - no sequence data in alignment
+ // - case of e < s (interval must be all gaps)
+ if ((__seqlength == 0) || (e < s))
+ return Interval (1, 0);
+
+ return Interval (s, e);
+ }
+
+ inline void Alignment::remove_gaps (std::string& str) {
+
+ std::string::iterator last_pos = std::remove_if (str.begin(), str.end(),
+ Alignment::is_gap_char);
+ str.erase (last_pos, str.end());
+
+ }
+
+ inline size_t Alignment::rows() const {
+ assert (seq_db->size() == __rows.size());
+ assert (__rows.size() == __row_index.size());
+ return __rows.size();
+ }
+
+ inline size_t Alignment::columns() const {
+ if (__rows.size())
+ return __rows[0]->length();
+ return 0;
+ }
+
+ inline Interval Alignment::map_seq_to_seq (const std::string& seq_from, const unsigned start_from, const unsigned end_from,
+ const std::string& seq_to) const {
+
+ assert (start_from <= end_from);
+
+ const unsigned start_align = map_seq_to_align (seq_from, start_from);
+ const unsigned end_align = map_seq_to_align (seq_from, end_from);
+
+ return map_align_to_seq (seq_to, start_align, end_align);
+
+ }
+
+ inline bool Alignment::is_gapped (const size_t row, const size_t col) const {
+
+ return get_row (row).is_gapped (col);
+
+ }
+
+ inline char Alignment_row::get_char (const size_t col,
+ const Sequence& ungapped, const char gap_char) const {
+
+ assert (col < __align_to_seq_coords_map.size());
+
+ if (is_gapped (col))
+ return gap_char;
+
+ return ungapped.seq[__align_to_seq_coords_map[col]];
+
+ }
+
+ inline char Alignment::get_char (const size_t row, const size_t col) const {
+
+ return get_row (row).get_char (col,
+ seq_db->get_seq (row), Alignment::gap_char);
+ }
+
+}
+
+#endif /* SEQ_ALIGNMENT_INCLUDED */
diff --git a/src/seq/alphabet.cc b/src/seq/alphabet.cc
new file mode 100644
index 0000000..9c22fdf
--- /dev/null
+++ b/src/seq/alphabet.cc
@@ -0,0 +1,193 @@
+
+/**
+ * \file sequence.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <climits>
+#include <algorithm>
+
+#include "seq/alphabet.h"
+
+using namespace fsa;
+
+const std::string DNA_alphabet::DNA_alphabet_name = "DNA";
+const std::string RNA_alphabet::RNA_alphabet_name = "RNA";
+const std::string Protein_alphabet::Protein_alphabet_name = "Protein";
+
+
+
+Alphabet::Alphabet (std::string name, size_t size, bool case_sensitive /* = false */)
+ : __name (name), __size (size), __case_sensitive (case_sensitive) {
+
+}
+
+void Alphabet::init_chars (const std::string& chars, const std::string complement /* = "" */) {
+
+ __has_complement = (complement.length() > 0);
+
+ // check sane
+ assert (__size == chars.length());
+ if (__has_complement) {
+ assert (__size == complement.length());
+ __char_complement_list.resize (__size);
+ }
+
+ // now create the __char_index data structure:
+ // this holds a mapping from (non-degenerate) characters in the alphabet
+ // to their numerical indices in __char_list
+ // for speed, we use a vector rather than a map;
+ // elements are accessed by casting the character to int
+ // if a character isn't in the alphabet then it's given an index of __size;
+ // if it is, then it's given the corresponding index in __char_list
+ // (which is smaller than __size by definition)
+
+ // assign dummy value to all entries in __char_index
+ // (indicating not present in alphabet) of __size
+ // NB: CHAR_MAX is defined in climits
+ __char_index.assign (CHAR_MAX + 1, __size);
+
+ // store the alphabet
+ __char_list.resize (__size);
+ for (size_t i = 0; i < chars.length(); ++i) {
+ char ch = chars[i];
+ if (!__case_sensitive)
+ ch = tolower (ch);
+ __char_list[i] = ch;
+ if (__has_complement)
+ __char_complement_list[i] = complement[i];
+ assert (__char_index.size() > static_cast<size_t> (ch));
+ __char_index[ch] = i;
+ }
+
+}
+
+void Alphabet::add_degen_char (char ch, const std::string& nondegen) {
+
+ // initialize __degen_char_map by storing a
+ // dummy empty vector for all characters
+ // (similar in spirit to how __char_index works; see init_chars)
+ // if this is the first time that this function was called
+ if (!__degen_char_map.size())
+ __degen_char_map.assign (CHAR_MAX + 1, std::vector<char>());
+
+ if (!__case_sensitive)
+ ch = tolower (ch);
+
+ std::vector<char> nondegen_chars (nondegen.length());
+ for (size_t i = 0; i < nondegen.length(); ++i)
+ nondegen_chars[i] = nondegen[i];
+ __degen_char_map[ch] = nondegen_chars;
+
+}
+
+void Alphabet::set_unknown_char (const char ch) {
+
+ __unknown_char = ch;
+
+}
+
+void Alphabet::make_nondegen (std::string& seq) const {
+
+ for (std::string::iterator c = seq.begin(); c != seq.end(); ++c)
+ *c = get_nondegen_char (*c);
+
+}
+
+std::string Alphabet::get_nondegen (const std::string& seq) const {
+
+ std::string seq_nondegen;
+ seq_nondegen.resize (seq.length());
+ for (size_t i = 0; i < seq.length(); ++i)
+ seq_nondegen[i] = get_nondegen_char (seq[i]);
+
+ return seq_nondegen;
+
+}
+
+void Alphabet::revcomp (std::string& seq, bool (*is_gap_char) (char) /* = NULL */) const {
+
+ if (!__has_complement) {
+ cerr << "ERROR: Tried to reverse-complement under an alphabet without a complementary alphabet." << endl;
+ exit (1);
+ }
+
+ // first reverse
+ std::reverse (seq.begin(), seq.end());
+
+ // then complement
+ for (std::string::iterator ch = seq.begin(); ch != seq.end(); ++ch) {
+ // if requested, ignore gap characters
+ if ((is_gap_char != 0) && is_gap_char (*ch))
+ continue;
+ // complement nondegen chars
+ if (is_nondegen_char (*ch)) {
+ if (isupper (*ch))
+ *ch = toupper (__char_complement_list[__char_index[tolower (*ch)]]);
+ else
+ *ch = tolower (__char_complement_list[__char_index[*ch]]);
+ }
+ // and set degen & unknown chars to __unknown_char
+ else {
+ *ch = isupper (*ch) ? toupper (__unknown_char) : __unknown_char;
+ }
+ }
+
+}
+
+std::string Alphabet::revcomp (const std::string& seq, bool (*is_gap_char) (char) /* = NULL */) const {
+
+ std::string seq_revcomp = seq;
+ revcomp (seq_revcomp, is_gap_char);
+ return seq_revcomp;
+
+}
+
+DNA_alphabet::DNA_alphabet()
+ : Alphabet (DNA_alphabet_name, 4, false) {
+
+ init_chars ("acgt", "tgca");
+ set_unknown_char ('n');
+ add_degen_char ('u', "t");
+ add_degen_char ('r', "ag");
+ add_degen_char ('y', "ct");
+ add_degen_char ('m', "ac");
+ add_degen_char ('k', "gt");
+ add_degen_char ('s', "cg");
+ add_degen_char ('w', "at");
+ add_degen_char ('h', "act");
+ add_degen_char ('b', "cgt");
+ add_degen_char ('v', "acg");
+ add_degen_char ('d', "agt");
+
+}
+
+RNA_alphabet::RNA_alphabet()
+ : Alphabet (RNA_alphabet_name, 4, false) {
+
+ init_chars ("acgu", "ugca");
+ set_unknown_char ('n');
+ add_degen_char ('t', "u");
+ add_degen_char ('r', "ag");
+ add_degen_char ('y', "ct");
+ add_degen_char ('m', "ac");
+ add_degen_char ('k', "gt");
+ add_degen_char ('s', "cg");
+ add_degen_char ('w', "at");
+ add_degen_char ('h', "act");
+ add_degen_char ('b', "cgt");
+ add_degen_char ('v', "acg");
+ add_degen_char ('d', "agt");
+
+}
+
+Protein_alphabet::Protein_alphabet()
+ : Alphabet (Protein_alphabet_name, 20, false) {
+
+ init_chars ("acdefghiklmnpqrstvwy");
+ set_unknown_char ('x');
+ add_degen_char ('b', "nd");
+ add_degen_char ('z', "qe");
+
+}
diff --git a/src/seq/alphabet.h b/src/seq/alphabet.h
new file mode 100644
index 0000000..952214a
--- /dev/null
+++ b/src/seq/alphabet.h
@@ -0,0 +1,320 @@
+
+/**
+ * \file alphabet.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ * The alphabet representation code is loosely based on Ian Holmes's
+ * Alphabet class.
+ */
+
+#ifndef SEQ_ALPHABET_INCLUDED
+#define SEQ_ALPHABET_INCLUDED
+
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+#include "util/misc.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a sequence alphabet.
+ */
+ struct Alphabet {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ *
+ * Unless the alphabet is designated as case-sensitive,
+ * alphabet information is stored as lower-case internally.
+ * \param name alphabet name
+ * \param size alphabet size
+ * \param case_sensitive is the alphabet case-sensitive?
+ */
+ Alphabet (std::string name, size_t size, bool case_sensitive = false);
+
+ /**
+ * \brief Get the name of the alphabet.
+ */
+ const std::string& name() const { return __name; }
+
+ /**
+ * \brief Make a sequence nondegenerate.
+ */
+ void make_nondegen (std::string& sequence) const;
+
+ /**
+ * \brief Get nondegenerate sequence.
+ */
+ std::string get_nondegen (const std::string& sequence) const;
+
+ /**
+ * \brief Does the alphabet have a complement defined?
+ */
+ bool has_complement() const { return __has_complement; }
+
+ /**
+ * \brief Reverse-complement sequence under alphabet.
+ *
+ * Degenerate characters are set to __unknown_char after reverse-complementing.
+ * If requested, ignores gap characters as defined by the passed function.
+ * \param seq sequence to be reverse-complemented
+ * \param is_gap_char function pointer defining a gap character
+ */
+ void revcomp (std::string& seq, bool (*is_gap_char) (char) = NULL) const;
+
+ /**
+ * \brief Reverse-complement sequence under alphabet.
+ * \see revcomp
+ */
+ std::string revcomp (const std::string& seq, bool (*is_gap_char) (char) = NULL) const;
+
+ /**
+ * \brief Get alphabet size.
+ */
+ inline size_t size() const { return __size; };
+
+ /**
+ * \brief Is this a non-degenerate character in the alphabet?
+ */
+ inline bool is_nondegen_char (char ch) const;
+
+ /**
+ * \brief Is this a degenerate character in the alphabet?
+ */
+ inline bool is_degen_char (char ch) const;
+
+ /**
+ * \brief Does the alphabet contain a possibly-degenerate character?
+ * \see is_nondegen_char
+ * \see is_degen_char
+ */
+ inline bool contains_char (const char ch) const;
+
+ /**
+ * \brief Is this an unknown character?
+ */
+ inline bool is_unknown_char (const char ch) const;
+
+ /**
+ * \brief Convert a possibly-degenerate character to a non-degenerate character.
+ *
+ * Randomizes unknown characters across the entire alphabet.
+ * Preserves character case.
+ */
+ inline char get_nondegen_char (const char ch) const;
+
+ /**
+ * \brief Get the numerical index for a character.
+ *
+ * If the character is degenerate or unknown,
+ * randomizes the character prior to getting the index.
+ */
+ inline size_t get_char_index (char ch) const;
+
+ /**
+ * \brief Get a character from its numerical index.
+ */
+ inline char get_char_from_index (const size_t index) const;
+
+ protected:
+
+ /**
+ * \brief Initialize characters in alphabet.
+ */
+ void init_chars (const std::string& chars, const std::string complement = "");
+
+ /**
+ * \brief Add a degenerate character to the alphabet.
+ */
+ void add_degen_char (char ch, const std::string& nondegen);
+
+ /**
+ * \brief Set the unknown character for the alphabet.
+ */
+ void set_unknown_char (const char ch);
+
+ private:
+
+ std::string __name; ///< alphabet name
+ size_t __size; ///< alphabet size (# of non-degenerate characters)
+ bool __case_sensitive; ///< is the alphabet case-sensitive?
+ bool __has_complement; ///< does the alphabet have a complement?
+
+ std::vector<char> __char_list; ///< ordered list of characters
+ std::vector<char> __char_complement_list; ///< ordered list of complementary characters
+ std::vector<size_t> __char_index; ///< map from characters (cast to int) to index in __char_list
+ char __unknown_char; ///< character representing unknown character
+ std::vector<std::vector<char> > __degen_char_map; ///< map from degenerate to non-degenerate characters (similar in spirit to __char_index)
+
+ };
+
+ /**
+ * \brief Represent a DNA alphabet.
+ */
+ struct DNA_alphabet : public Alphabet {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ DNA_alphabet();
+
+ /**
+ * \brief Define the hardmasked character (ignores case!).
+ */
+ static bool is_hardmask_char (const char ch) {
+ return toupper (ch) == 'N';
+ }
+
+ /**
+ * \brief Call all lower-case characters softmasked.
+ */
+ static bool is_softmasked (const char ch) {
+ return islower (ch);
+ }
+
+ private:
+
+ static const std::string DNA_alphabet_name; ///< alphabet name
+
+ };
+
+ /**
+ * \brief Represent a RNA alphabet.
+ */
+ struct RNA_alphabet : public Alphabet {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ RNA_alphabet();
+
+ private:
+
+ static const std::string RNA_alphabet_name; ///< alphabet name
+
+ };
+
+ /**
+ * \brief Represent a protein alphabet.
+ *
+ * Characters are in IUPAC alphabetical order, 'acdefghiklmnpqrstvwy'.
+ */
+ struct Protein_alphabet : public Alphabet {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ Protein_alphabet();
+
+ private:
+
+ static const std::string Protein_alphabet_name; ///< alphabet name
+
+ };
+
+ inline bool Alphabet::is_nondegen_char (char ch) const {
+ if (!__case_sensitive)
+ ch = tolower (ch);
+ // test for membership in the alphabet
+ if (__char_index[ch] < __size)
+ return true;
+ return false;
+ }
+
+ inline bool Alphabet::is_degen_char (char ch) const {
+ if (!__case_sensitive)
+ ch = tolower (ch);
+ if (__degen_char_map[ch].size())
+ return true;
+ return false;
+ }
+
+ inline bool Alphabet::contains_char (const char ch) const {
+ return (is_nondegen_char (ch) || is_degen_char (ch));
+ }
+
+ inline bool Alphabet::is_unknown_char (const char ch) const {
+ return ((__case_sensitive ? ch : tolower (ch)) == __unknown_char);
+ }
+
+ inline char Alphabet::get_nondegen_char (const char ch) const {
+
+ // if upper-case
+ if (isupper (ch)) {
+
+ // if nondegenerate
+ if (is_nondegen_char (ch))
+ return ch;
+
+ // else if degenerate
+ else if (is_degen_char (ch)) {
+ const std::vector<char>& nondegen = __degen_char_map[__case_sensitive ? ch : tolower (ch)];
+ return toupper (nondegen[Util::rand (nondegen.size() - 1)]);
+ }
+ // else we don't know anything about it, so treat as unknown
+ else
+ return toupper (__char_list[Util::rand (__size - 1)]);
+
+ }
+
+ // if lower-case
+ else {
+
+ // if nondegenerate
+ if (is_nondegen_char (ch))
+ return ch;
+
+ // else if degenerate
+ else if (is_degen_char (ch)) {
+ const std::vector<char>& nondegen = __degen_char_map[__case_sensitive ? ch : tolower (ch)];
+ return tolower (nondegen[Util::rand (nondegen.size() - 1)]);
+ }
+ // else we don't know anything about it, so treat as unknown
+ else {
+ return tolower (__char_list[Util::rand (__size - 1)]);
+ }
+
+ }
+
+ }
+
+ inline size_t Alphabet::get_char_index (char ch) const {
+
+ if (!__case_sensitive)
+ ch = tolower (ch);
+
+ // if this is a non-degenerate character, then return the index
+ if (__char_index[ch] < __size)
+ return __char_index[ch];
+
+ // else randomize and return the corresponding index
+ else {
+ ch = get_nondegen_char (ch);
+ return __char_index[ch];
+ }
+
+ }
+
+ inline char Alphabet::get_char_from_index (const size_t index) const {
+
+ assert (index < __char_list.size());
+ return __char_list[index];
+
+ }
+
+}
+
+#endif /* SEQ_ALPHABET_INCLUDED */
diff --git a/src/seq/gff.cc b/src/seq/gff.cc
new file mode 100644
index 0000000..aa269af
--- /dev/null
+++ b/src/seq/gff.cc
@@ -0,0 +1,364 @@
+
+/**
+ * \file gff.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <fstream>
+#include <sstream>
+#include <cmath>
+#include <algorithm>
+
+#include "util/regexp.h"
+#include "math/mathematics.h"
+#include "seq/gff.h"
+
+using namespace fsa;
+
+const std::string GFF::comment_char = "#";
+const std::string GFF::undef_char = ".";
+
+const char GFF::unknown_strand = '.';
+
+const std::string GFF::attributes_split_char = ";";
+const std::string GFF::attributes_assign_char = "=";
+const std::string GFF::attributes_list_char = ",";
+
+const std::string GFF::key_id = "ID";
+const std::string GFF::key_name = "Name";
+
+const size_t GFF::default_flanking = 10000;
+
+Regexp GFF::re_key_value = "^([^=]+)=(.*)$";
+
+void GFF::from_string (const std::string& str, const bool strip_leading_chr /* = true */) {
+
+ std::vector<std::string> tokens = Util::split (str, "\t"); // hold tab-separated tokens
+
+ // now parse tokens
+
+ // sanity checks
+ if (tokens.size() != 9) {
+ cerr << "ERROR: Not a GFF-format line: " << str << endl;
+ exit (1);
+ }
+
+ seqid = tokens[0];
+ if (strip_leading_chr)
+ Util::strip_leading_chr (seqid);
+ source = tokens[1];
+ type = tokens[2];
+ set_start (atoi (tokens[3].c_str()));
+ end = static_cast<unsigned> (atoi (tokens[4].c_str()));
+ score = (tokens[5] != "" && tokens[5] != GFF::undef_char) ? atof (tokens[5].c_str()) : -1.;
+ strand = (tokens[6])[0];
+ phase = (tokens[7] != "" && tokens[7] != GFF::undef_char) ? static_cast<unsigned> (atoi (tokens[7].c_str())) : 3;
+
+ parse_attributes_string (tokens[8]);
+
+}
+
+void GFF::set_start (const int s) {
+
+ if (s < 1) {
+ cerr << "WARNING: setting GFF feature start coordinate " << s << " to 1." << endl;
+ start = 1;
+ }
+
+ else {
+ start = static_cast<unsigned> (s);
+ }
+
+}
+
+void GFF::parse_attributes_string (const std::string& str) {
+
+ std::vector<std::string> key_value_pairs = Util::split (str, GFF::attributes_split_char);
+ for (std::vector<std::string>::const_iterator key_value = key_value_pairs.begin(); key_value != key_value_pairs.end(); ++key_value) {
+ if (re_key_value.Match (key_value->c_str())) {
+ std::string key = re_key_value[1];
+ std::vector<std::string> values = Util::split (re_key_value[2], GFF::attributes_list_char);
+ if (values.size())
+ attributes_ordering.push_back (key);
+ for (std::vector<std::string>::const_iterator value = values.begin(); value != values.end(); ++value)
+ attributes_map[key].push_back (*value);
+ }
+ }
+
+}
+
+std::string GFF::get_attributes_string() const {
+
+ std::string s;
+
+ // iterate over keys
+ for (std::vector<std::string>::const_iterator key = attributes_ordering.begin(); key != attributes_ordering.end(); ++key) {
+ std::map<std::string, std::vector<std::string> >::const_iterator key_value = attributes_map.find (*key);
+ // iterate over values
+ if (key_value->second.size())
+ s += *key + GFF::attributes_assign_char;
+ for (std::vector<std::string>::const_iterator value = key_value->second.begin(); value != key_value->second.end(); ++value)
+ s += *value + GFF::attributes_list_char;
+ if (s.length())
+ s.erase (s.end() - 1, s.end()); // strip off final comma
+ s += GFF::attributes_split_char;
+ }
+
+ if (!s.length())
+ s += GFF::undef_char;
+
+ return s;
+
+}
+
+std::string GFF::to_string() const {
+
+ std::stringstream ss;
+
+ ss << (seqid != "" ? seqid : GFF::undef_char) << "\t"
+ << (source != "" ? source : GFF::undef_char) << "\t"
+ << (type != "" ? type : GFF::undef_char) << "\t"
+ << start << "\t" << end << "\t";
+ if (score != -1.) { ss << score; }
+ else { ss << GFF::undef_char; }
+ ss << "\t";
+ ss << strand << "\t";
+ if (phase != 3) { ss << phase; }
+ else { ss << GFF::undef_char; }
+ ss << "\t";
+ ss << get_attributes_string();
+
+ return ss.str();
+
+}
+
+void GFF_database::from_file (const std::string& filename, const bool strip_leading_chr /* = true */) {
+
+ Regexp re_gff ("^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*$");
+
+ // open file
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ cerr << "Reading GFF file '" << filename << "'...";
+
+ // parse file
+ std::string line;
+ while (!filestream.eof()) {
+ getline (filestream, line);
+ Util::chomp (line);
+ // skip lines which don't seem to be in GFF format
+ if (!line.length() || !re_gff.Match (line.c_str()))
+ continue;
+ GFF gff;
+ gff.from_string (line, strip_leading_chr);
+ store_entry (gff);
+ __maxlen = std::max (__maxlen, gff.length());
+ }
+
+ cerr << "done." << endl;
+
+ // clean up
+ filestream.close();
+
+}
+
+void GFF_database::write (std::ostream& o) const {
+
+ for (std::vector<GFF>::const_iterator gff = this->begin(); gff != this->end(); ++gff)
+ o << *gff;
+
+}
+
+void GFF_database::append (const GFF_database& gff_db) {
+
+ for (std::vector<GFF>::const_iterator gff = gff_db.begin(); gff != gff_db.end(); ++gff)
+ this->store_entry (*gff);
+ __maxlen = (gff_db.maxlen() > __maxlen) ? gff_db.maxlen() : __maxlen;
+
+}
+
+void GFF_database::create_unique_ids() {
+
+ if (!size())
+ return;
+
+ size_t width = static_cast<size_t> (log10 (size()));
+ std::string format = "%" + Util::to_string (width) + "d";
+ for (size_t i = 0; i < size(); ++i) {
+ std::string id (width - static_cast<size_t> (log10 (i)), '0'); // hack to format the IDs nicely
+ id += Util::to_string (i);
+ __entries[i].set_id (id);
+ }
+
+}
+
+void GFF_database::sort_entries() {
+
+ std::sort (__entries.begin(), __entries.end(), GFF::GFF_less());
+ __is_sorted = true;
+
+}
+
+GFF GFF_database::find_closest_feature_five_prime (const std::string& chromosome,
+ unsigned start, unsigned end,
+ const size_t flanking /* = default_flanking */) const {
+
+ return find_closest_feature (chromosome,
+ start, end,
+ flanking,
+ true); // use_feature_five_prime
+
+}
+
+GFF GFF_database::find_closest_feature_three_prime (const std::string& chromosome,
+ unsigned start, unsigned end,
+ const size_t flanking /* = default_flanking */) const {
+
+ return find_closest_feature (chromosome,
+ start, end,
+ flanking,
+ false); // use_feature_five_prime
+
+}
+
+GFF GFF_database::find_closest_feature (const std::string& chromosome,
+ unsigned start, unsigned end,
+ const size_t flanking /* = default_flanking */,
+ const bool use_feature_five_prime /* = true */) const {
+
+ const unsigned centroid = start + (end - start + 1) / 2;
+ start = (start < flanking) ? 0 : start - flanking;
+ end += flanking;
+
+ const GFF_database isects = intersect_genomic_interval (chromosome,
+ start, end);
+
+ if (!isects.size())
+ return GFF();
+
+ size_t closest_i = 0;
+ size_t closest_distance = std::numeric_limits<size_t>::max();
+ for (size_t i = 0; i < isects.size(); ++i) {
+ const GFF& gff = isects[i];
+ size_t distance = 0;
+ unsigned gff_boundary; // either the 5' or 3' end of the feature, as specified by use_feature_five_prime (0-based)
+ if (gff.strand == '-')
+ gff_boundary = use_feature_five_prime ? gff.end - 1 : gff.start - 1;
+ else
+ gff_boundary = use_feature_five_prime ? gff.start - 1 : gff.end - 1;
+ distance = std::max (centroid, gff_boundary) - std::min (centroid, gff_boundary);
+ if (distance < closest_distance) {
+ closest_i = i;
+ closest_distance = distance;
+ }
+ }
+
+ return isects[closest_i];
+
+}
+
+GFF_database GFF_database::intersect_genomic_interval (const std::string& chromosome,
+ const unsigned start, const unsigned end) const {
+
+ if (!__is_sorted) {
+ cerr << "ERROR: You must call sort_entries before attepting use this function." << endl;
+ exit (1);
+ }
+
+ GFF_database intersections;
+
+ // check for empty interval or no features
+ if (end < start || !size())
+ return intersections;
+
+ // initialize dummy object for comparison
+ GFF g;
+ g.seqid = chromosome;
+ Util::strip_leading_chr (g.seqid);
+
+ // two intervals 1 and 2 intersect iff
+ // 1.start <= 2.end && 1.end >= 2.start
+ // features in database are 1; query interval is 2
+
+ // check first condition (1.start <= 2.end)
+ g.start = end + 1; // convert to 1-based coordinates
+ g.end = end + 1;
+ std::vector<GFF>::const_iterator gff_upper = std::upper_bound (__entries.begin(),
+ __entries.end(),
+ g,
+ GFF::GFF_less());
+
+ // decrement element to try to get to the upper-bound entry
+ // which (possibly) intersects the query interval
+ if (gff_upper != __entries.begin())
+ --gff_upper;
+
+ // now check that we're on the correct chromosome
+ if (gff_upper->seqid != chromosome)
+ return intersections;
+
+ // check that gff_upper doesn't fall completely to the right of the query interval
+ // if gff_upper is __entries.begin(), then it may!
+ if (gff_upper->start > end)
+ return intersections;
+
+ // now iterate backwards through the sorted entries,
+ // checking the second condition (1.end >= 2.start)
+ // as we go
+ while (gff_upper != __entries.begin() - 1) {
+
+ // if we're no longer on the correct chromosome, then we're done
+ if (gff_upper->seqid != chromosome)
+ break;
+
+ // does it intersect the query interval?
+ if (gff_upper->end >= start)
+ intersections.store_entry (*gff_upper);
+
+ // check whether we're done
+ // (i.e., whether given __maxlen, there cannot be any more features close
+ // enough to the query interval to intersect it)
+ if (gff_upper->start + __maxlen < start)
+ break;
+
+ --gff_upper;
+ }
+
+ // sort nicely
+ intersections.sort_entries();
+
+ return intersections;
+
+}
+
+size_t GFF_database::meanlen() const {
+
+ std::vector<size_t> lengths (size(), 0);
+ for (size_t i = 0; i < size(); ++i)
+ lengths[i] = (*this)[i].length();
+
+ assert (static_cast<size_t> (Mathematics::mean (lengths)) <= maxlen());
+
+ return static_cast<size_t> (Mathematics::mean (lengths));
+
+}
+
+
+size_t GFF_database::medianlen() const {
+
+ std::vector<size_t> lengths (size(), 0);
+ for (size_t i = 0; i < size(); ++i)
+ lengths[i] = (*this)[i].length();
+ std::sort (lengths.begin(), lengths.end());
+
+ assert (Mathematics::median (lengths) <= maxlen());
+
+ return Mathematics::median (lengths);
+
+}
diff --git a/src/seq/gff.h b/src/seq/gff.h
new file mode 100644
index 0000000..b69a484
--- /dev/null
+++ b/src/seq/gff.h
@@ -0,0 +1,531 @@
+
+/**
+ * \file gff.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef SEQ_GFF_INCLUDED
+#define SEQ_GFF_INCLUDED
+
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <vector>
+#include <map>
+
+#include "util/misc.h"
+
+namespace fsa {
+
+ /**
+ * \brief Bare-bones representation of a single GFF entry.
+ *
+ * This class repeatedly assumes that the seqid field holds the
+ * chromosome which the feature is on.
+ * Note that GFF coordinates are always 1-based and fully-closed.
+ * This class stores coordinates for GFF features accordingly
+ * (in contrast to the 0-based indexing used throughout other
+ * parts of this code).
+ * See http://www.sequenceontology.org/gff3.shtml.
+ */
+ struct GFF {
+
+ typedef std::map<std::string, std::vector<std::string>, fsa::Util::String_equal_ci> Attribute_table; ///< (case-insensitive) map of key, value pairs
+
+ public:
+
+ std::string seqid; ///< field 0
+ std::string source; ///< field 1
+ std::string type;
+ unsigned start;
+ unsigned end;
+ float score;
+ char strand;
+ unsigned phase;
+ std::vector<std::string> attributes_ordering; ///< sorted list of keys in attributes field
+ Attribute_table attributes_map; ///< map of key, value pairs
+
+ /**
+ * \brief Default constructor.
+ *
+ * Initializes a feature of length 0 (nonsense coordinates [2, 1]).
+ */
+ GFF()
+ : seqid (""), source (""), type (""),
+ start (2), end (1),
+ score (-1.), strand (GFF::unknown_strand), phase (3)
+ { }
+
+ /**
+ * \brief Constructor.
+ *
+ * Initialize from a (possibly-scored) interval.
+ */
+ GFF (std::string seqid, unsigned start, unsigned end, float score = -1.)
+ : seqid (seqid), source (""), type (""),
+ start (start), end (end),
+ score (score), strand (GFF::unknown_strand), phase (3)
+ { }
+
+ /**
+ * \brief Set start coordinate.
+ *
+ * This deserves an accessor method in order to catch the case of negative start coordinates,
+ * which are unfortunately often found in real annotation files.
+ */
+ void set_start (const int s);
+
+ /**
+ * \brief Length of feature.
+ */
+ inline size_t length() const;
+
+ /**
+ * \brief 5' end of feature.
+ */
+ inline unsigned five_prime_end() const;
+
+ /**
+ * \brief 3' end of feature.
+ */
+ inline unsigned three_prime_end() const;
+
+ /**
+ * \brief Add a (possibly-new) key, value pair to the attributes field.
+ *
+ * If values for the key already exist, then the new value is appended.
+ */
+ template<typename K, typename V>
+ inline void add_value (const K& key, const V& value);
+
+ /**
+ * \brief Set a (possibly-new) key, value pair in the attributes field.
+ *
+ * If values for the key already exist, then all old values are cleared
+ * and replaced with the single new value.
+ */
+ template<typename K, typename V>
+ inline void set_value (const K& key, const V& value);
+
+ /**
+ * \brief Get the values for a key.
+ * \return values, or empty vector if no such key
+ * \see get_value
+ */
+ inline std::vector<std::string> get_values (const std::string& key) const;
+
+ /**
+ * \brief Get the first value for a key.
+ * \return value, or empty string if no such key
+ * \see get_values
+ */
+ inline std::string get_value (const std::string& key) const;
+
+ /**
+ * \brief Set name in attributes field.
+ */
+ inline void set_name (const std::string& name);
+
+ /**
+ * \brief Get name from attributes field.
+ */
+ inline std::string get_name() const;
+
+ /**
+ * \brief Set ID in attributes field.
+ */
+ inline void set_id (const std::string& id);
+
+ /**
+ * \brief Get ID from attributes field.
+ */
+ inline std::string get_id() const;
+
+ /**
+ * \brief Initialize from a GFF-formatted std::string.
+ * \param strip_leading_chr strips the leading 'chr', if present, from the seqid field
+ * possibly holding the chromosome name
+ */
+ void from_string (const std::string& str, const bool strip_leading_chr = true);
+
+ /**
+ * \brief Write to GFF-formatted string.
+ */
+ std::string to_string() const;
+
+ /**
+ * \brief Output operator.
+ *
+ * Prints undef_char for undefined fields.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const GFF& gff) {
+ o << gff.to_string() << endl;
+ return o;
+ }
+
+
+ static const std::string comment_char; ///< comment character
+ static const std::string undef_char; ///< character for undefined fields
+
+ static const char unknown_strand; ///< character for unknown strand
+
+ static const std::string attributes_split_char; ///< split key, value pairs in attributes field
+ static const std::string attributes_assign_char; ///< assign value to key in attributes field
+ static const std::string attributes_list_char; ///< separate values for a single key in attributes field
+
+ static const std::string key_id; ///< GFF key for ID
+ static const std::string key_name; ///< GFF key for Name
+
+ static const size_t default_flanking; ///< \see find_closest_feature
+
+ /**
+ * \brief Function object for binary comparison of GFF objects (sort by seqid, start, end).
+ */
+ struct GFF_less : std::binary_function<GFF, GFF, bool> {
+ public:
+ bool operator() (const GFF& l, const GFF& r) const {
+ if (l.seqid == r.seqid) {
+ if (l.start == r.start)
+ return l.end < r.end;
+ return l.start < r.start;
+ }
+ return l.seqid < r.seqid;
+ }
+ };
+
+
+ protected:
+
+ /**
+ * \brief Get string for the attributes field.
+ */
+ std::string get_attributes_string() const;
+
+ private:
+
+ /**
+ * \brief Set start coordinate.
+ */
+ inline void set_start (const unsigned s);
+
+ /**
+ * \brief Parse attributes string into key, value pairs.
+ */
+ void parse_attributes_string (const std::string& str);
+
+ static Regexp re_key_value; ///< match key, value pairs in attributes field
+
+ };
+
+ /**
+ * \brief Represent a GFF file.
+ */
+ struct GFF_database {
+
+ /**
+ * \brief Constructor.
+ */
+ GFF_database()
+ : __maxlen (0) { }
+
+ /**
+ * \brief Load from a file.
+ * \param strip_leading_chr strips the leading 'chr', if present, from the seqid field
+ * possibly holding the chromosome name
+ */
+ void from_file (const std::string& filename, const bool strip_leading_chr = true);
+
+ /**
+ * \brief Write.
+ */
+ void write (std::ostream& o) const;
+
+ /**
+ * \brief Store an entry.
+ */
+ inline void store_entry (const GFF& gff);
+
+ /**
+ * \brief Append a GFF_database to this one.
+ */
+ void append (const GFF_database& gff_db);
+
+ /**
+ * \brief Set a (possibly-new) key, value pair in the attributes field for every entry.
+ *
+ * If values for the key already exist, then all old values are cleared
+ * and replaced with the single new value.
+ * \see GFF::set_value
+ */
+ template<typename K, typename V>
+ inline void set_value (const K& key, const V& value);
+
+ /**
+ * \brief Create nicely-formatted numerical IDs for all entries.
+ */
+ void create_unique_ids();
+
+ /**
+ * \brief Sort entries in database.
+ *
+ * This must be called in order for intersect_genomic_interval to work properly.
+ */
+ void sort_entries();
+
+ /**
+ * \brief Find the GFF feature whose 5' end is closest to the passed interval.
+ * \see find_closest_feature
+ */
+ GFF find_closest_feature_five_prime
+ (const std::string& chromosome,
+ unsigned start, unsigned end,
+ const size_t flanking = GFF::default_flanking) const;
+
+ /**
+ * \brief Find the GFF feature whose 3' end is closest to the passed interval.
+ * \see find_closest_feature
+ */
+ GFF find_closest_feature_three_prime
+ (const std::string& chromosome,
+ unsigned start, unsigned end,
+ const size_t flanking = GFF::default_flanking) const;
+
+ /**
+ * \brief Find GFF features which intersect the passed interval.
+ *
+ * Assumes that the seqid field holds the chromosome
+ * and that the passed interval coordinates are 0-based
+ * and fully closed. Note the contrast with the 1-based
+ * coordinates used for the GFF features themselves.
+ * Note that the entries MUST be sorted in order for this to function properly.
+ * \see GFF_database::sort_entries
+ */
+ GFF_database intersect_genomic_interval (const std::string& chromosome,
+ const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Maximum length of entry.
+ */
+ size_t maxlen() const { return __maxlen; }
+
+ /**
+ * \brief Average length of entry.
+ */
+ size_t meanlen() const;
+
+ /**
+ * \brief Median length of entry.
+ */
+ size_t medianlen() const;
+
+ /**
+ * \brief Number of entries.
+ */
+ size_t size() const { return __entries.size(); }
+
+ /**
+ * \brief Data access operator.
+ */
+ const GFF& operator[] (const size_t i) const {
+ assert (i < __entries.size());
+ return __entries[i];
+ }
+
+
+ /**
+ * \brief Get iterator to start of __entries.
+ */
+ std::vector<GFF>::iterator begin() {
+ return __entries.begin();
+ }
+
+ /**
+ * \brief Get const_iterator to start of __entries.
+ */
+ std::vector<GFF>::const_iterator begin() const {
+ return __entries.begin();
+ }
+
+ /**
+ * \brief Get iterator to end of __entries.
+ */
+ std::vector<GFF>::iterator end() {
+ return __entries.end();
+ }
+
+ /**
+ * \brief Get const_iterator to end of __entries.
+ */
+ std::vector<GFF>::const_iterator end() const {
+ return __entries.end();
+ }
+
+ private:
+
+ /**
+ * \brief Find the GFF feature whose 3' or 5' end is closest to the passed interval.
+ *
+ * The closest feature is defined as the feature whose 3' or 5' end
+ * (specified by use_feature_five_prime) is closest to the centroid of the passed interval.
+ * \param flanking search for features within this distance of the requested interval
+ * \param use_feature_five_prime look for features whose 5' end is closest to the passed interval (false for 3')
+ * \return closest feature, or empty feature if no feature within flanking distance
+ * \see intersect_genomic_interval
+ */
+ GFF find_closest_feature (const std::string& chromosome,
+ unsigned start, unsigned end,
+ const size_t flanking = GFF::default_flanking,
+ const bool use_feature_five_prime = true) const;
+
+ std::vector<GFF> __entries; ///< individual GFF entries in database
+
+ size_t __maxlen; ///< maximum length of an entry in the database
+ bool __is_sorted; ///< have the entries been sorted?
+
+ };
+
+
+
+ /****************************************
+ * Function definitions.
+ ****************************************/
+
+ inline size_t GFF::length() const {
+ // catch case of 0-length feature
+ if (end < start)
+ return 0;
+ return end - start + 1;
+ }
+
+ inline unsigned GFF::five_prime_end() const {
+ if (strand == '-')
+ return end;
+ return start;
+ }
+
+ inline unsigned GFF::three_prime_end() const {
+ if (strand == '-')
+ return start;
+ return end;
+ }
+
+ inline void GFF::set_start (const unsigned s) {
+ if (s >= 1)
+ start = s;
+ else {
+ cerr << "Setting start coordinate " << s << " to 0." << endl;
+ start = 0;
+ }
+ }
+
+ template<typename K, typename V>
+ inline void GFF::add_value (const K& key, const V& value) {
+
+ // use stringstream to convert key and value to string
+ std::string key_str = Util::to_string (key);
+ std::string value_str = Util::to_string (value);
+
+ // now store
+ // if we already have this key, then append value
+ std::map<std::string, std::vector<std::string> >::iterator value_vector = attributes_map.find (key_str);
+ if (value_vector != attributes_map.end())
+ value_vector->second.push_back (value_str);
+ // else add new key and append value
+ else {
+ attributes_ordering.push_back (key_str);
+ attributes_map[key_str].push_back (value_str);
+ }
+
+ }
+
+ template<typename K, typename V>
+ inline void GFF::set_value (const K& key, const V& value) {
+
+ // use stringstream to convert key and value to string
+ std::string key_str = Util::to_string (key);
+ std::string value_str = Util::to_string (value);
+
+ // now store
+ // if we already have this key, then clear old value and record new value
+ std::map<std::string, std::vector<std::string> >::iterator value_vector = attributes_map.find (key_str);
+ if (value_vector != attributes_map.end()) {
+ value_vector->second.clear();
+ value_vector->second.push_back (value_str);
+ }
+ else {
+ attributes_ordering.push_back (key_str);
+ attributes_map[key_str].push_back (value_str);
+ }
+
+ }
+
+ inline std::vector<std::string> GFF::get_values (const std::string& key) const {
+
+ std::map<std::string, std::vector<std::string> >::const_iterator value_vector = attributes_map.find (key);
+ if (value_vector != attributes_map.end())
+ return value_vector->second;
+ else
+ return std::vector<std::string>();
+
+ }
+
+ inline std::string GFF::get_value (const std::string& key) const {
+
+ std::map<std::string, std::vector<std::string> >::const_iterator value_vector = attributes_map.find (key);
+ if (value_vector != attributes_map.end() && value_vector->second.size())
+ return (value_vector->second)[0];
+ else
+ return "";
+
+ }
+
+ inline void GFF::set_name (const std::string& name) {
+ set_value (key_name, name);
+ }
+
+ inline std::string GFF::get_name() const {
+ const std::vector<std::string> names = get_values (key_name);
+ if (!names.size())
+ return "";
+ else if (names.size() > 1) {
+ cerr << "Warning: More than one name detected in GFF entry!" << endl
+ << *this << endl;
+ }
+
+ return names[0];
+ }
+
+ inline void GFF::set_id (const std::string& id) {
+ set_value (key_id, id);
+ }
+
+ inline std::string GFF::get_id() const {
+ const std::vector<std::string> ids = get_values (key_id);
+ if (!ids.size())
+ return "";
+ else if (ids.size() > 1) {
+ cerr << "Warning: More than one ID detected in GFF entry!" << endl
+ << *this << endl;
+ }
+
+ return ids[0];
+ }
+
+ inline void GFF_database::store_entry (const GFF& gff) {
+
+ __entries.push_back (gff);
+ __maxlen = (gff.end - gff.start + 1 > __maxlen) ? gff.end - gff.start + 1 : __maxlen;
+
+ }
+
+ template<typename K, typename V>
+ inline void GFF_database::set_value (const K& key, const V& value) {
+
+ for (std::vector<GFF>::iterator gff = begin(); gff != end(); ++gff)
+ gff->set_value (key, value);
+ }
+
+}
+
+#endif /* SEQ_GFF_INCLUDED */
diff --git a/src/seq/interval.h b/src/seq/interval.h
new file mode 100644
index 0000000..41d99d3
--- /dev/null
+++ b/src/seq/interval.h
@@ -0,0 +1,130 @@
+
+/**
+ * \file interval.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef SEQ_INTERVAL_INCLUDED
+#define SEQ_INTERVAL_INCLUDED
+
+#include "config.h"
+#include "util/misc.h"
+#include "seq/gff.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a 0-based, fully-closed interval.
+ */
+ struct Interval {
+
+ public:
+
+ Interval()
+ { }
+
+ /**
+ * \brief Constructor.
+ */
+ Interval (const unsigned start, const unsigned end)
+ : start (start), end (end)
+ { }
+
+ unsigned start; ///< start coordinate of interval
+ unsigned end; ///< end coordinate of interval
+
+ /**
+ * \brief Length of interval.
+ */
+ size_t length() const;
+
+ };
+
+ /**
+ * \brief Represent a single genomic interval.
+ *
+ * As with all FSA code unless otherwise noted,
+ * this object is intended to use 0-based, fully-closed coordinates.
+ */
+ struct Genomic_interval : public Interval {
+
+ public:
+
+ Genomic_interval() { }
+
+ /**
+ * \brief Constructor.
+ */
+ Genomic_interval (const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end, const char strand = GFF::unknown_strand)
+ : Interval (start, end),
+ genome (genome), chromosome (chromosome),
+ strand (strand)
+ { }
+
+ std::string genome; ///< genome
+ std::string chromosome; ///< chromosome name
+ char strand; ///< strand
+
+ /**
+ * \brief Write in a Mercator-like format.
+ */
+ std::string to_string() const {
+ std::string str;
+ return str;
+ }
+
+ /**
+ * \brief Convert Genomic_intervals to GFFs.
+ *
+ * Assumes that the coordinates in intervals are 0-based and converts them to 1-based coordinates.
+ */
+ static GFF_database convert_to_gff_db (const std::vector<Genomic_interval>& intervals);
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Genomic_interval& interval) {
+ o << ((interval.genome == "") ? "." : interval.genome) << '\t' << interval.chromosome + '\t'
+ << Util::to_string (interval.start) << '\t' << Util::to_string (interval.end) << '\t'
+ << interval.strand;
+ return o;
+ }
+
+ /**
+ * \brief Compare two Genomic_interval objects based on their starting coordinates.
+ */
+ bool operator< (const Genomic_interval& r) const {
+ if (genome == r.genome) {
+ if (chromosome == r.chromosome)
+ return (start < r.start);
+ return chromosome < r.chromosome;
+ }
+ return genome < r.genome;
+ }
+
+ /**
+ * \brief Function object for binary comparison of Genomic_interval objects.
+ *
+ * \see Genomic_interval::operator<
+ */
+ struct Genomic_interval_less : std::binary_function<Genomic_interval, Genomic_interval, bool> {
+ public:
+ bool operator() (const Genomic_interval& l, const Genomic_interval& r) const {
+ return l < r;
+ }
+ };
+
+ };
+
+ inline size_t Interval::length() const {
+ // catch case of an empty interval
+ if (start > end)
+ return 0;
+ return end - start + 1;
+ }
+
+}
+
+#endif /* SEQ_INTERVAL_INCLUDED */
diff --git a/src/seq/mercator.cc b/src/seq/mercator.cc
new file mode 100644
index 0000000..39889aa
--- /dev/null
+++ b/src/seq/mercator.cc
@@ -0,0 +1,856 @@
+
+/**
+ * \file mercator.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <algorithm>
+#include <numeric>
+
+#include "seq/mercator.h"
+#include "seq/gff.h"
+
+using namespace fsa;
+
+const std::string Mercator_map::mercator_empty_interval = "NA";
+const Alphabet Mercator_alignment::alphabet = DNA_alphabet();
+
+
+GFF_database Genomic_interval::convert_to_gff_db (const std::vector<Genomic_interval>& intervals) {
+
+ GFF_database gff_db;
+ for (std::vector<Genomic_interval>::const_iterator interval = intervals.begin(); interval != intervals.end(); ++interval)
+ gff_db.store_entry (GFF (interval->chromosome, interval->start + 1, interval->end + 1)); // convert to 1-based coordinates
+
+ return gff_db;
+
+}
+
+Mercator_map::Mercator_map (const std::string& map_dir)
+ : __num_bins (0) {
+
+ from_file (map_dir + "/genomes", map_dir + "/map");
+ init_bin_index(); // this MUST only be done after sorting __intervals...
+
+}
+
+void Mercator_map::from_file (const std::string& genomes_filename,
+ const std::string& map_filename) {
+
+ cerr << "Reading Mercator map '" << map_filename << "'...";
+
+ std::ifstream filestream;
+
+ // read genomes file
+ filestream.open (genomes_filename.c_str(), std::ifstream::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << genomes_filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ std::string line;
+ while (!filestream.eof()) {
+ getline (filestream, line);
+
+ std::stringstream ss (line);
+ std::string buffer;
+ std::vector<std::string> tokens; // hold whitespace-separated tokens
+ while (ss >> buffer)
+ tokens.push_back (buffer);
+
+ for (size_t i = 0; i < tokens.size(); ++i) {
+ __genomes.push_back (tokens[i]);
+ __genome_index.insert (std::make_pair (tokens[i], i));
+ }
+
+ }
+ filestream.close();
+
+ // read map file
+ filestream.open (map_filename.c_str(), std::ifstream::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << map_filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ while (!filestream.eof()) {
+ getline (filestream, line);
+ Util::chomp (line);
+ if (!line.length()) { continue; }
+ parse_line (line);
+ }
+ filestream.close();
+
+ // sort entries! otherwise binary search will fail
+ std::sort (__intervals.begin(), __intervals.end(),
+ Genomic_interval::Genomic_interval_less());
+
+ cerr << "done." << endl;
+
+}
+
+void Mercator_map::init_bin_index() {
+
+ // __bin_index[bin][__genome_index[genome]] is the index in __intervals
+ // for a particular (bin, genome) pair
+
+ // initialize stuff
+ // add a dummy entry for the 0th bin (hence bins() + 1)
+ // so that we can index with the actual Mercator bin number
+ // set everything to the nonsense index size() at first
+ __bin_index.assign (bins() + 1, std::vector<size_t> (__genome_index.size(), size()));
+
+ // store indices for each Mercator_interval
+ for (size_t i = 0; i < size(); ++i) {
+ const Mercator_interval& interval = get_interval (i);
+ assert (interval.bin < __bin_index.size());
+ assert (__bin_index[interval.bin].size() > __genome_index[interval.genome]);
+ __bin_index[interval.bin][__genome_index[interval.genome]] = i;
+ }
+
+}
+
+void Mercator_map::parse_line (const std::string& line) {
+
+ std::stringstream ss (line);
+ std::string buffer;
+ std::vector<std::string> tokens; // hold whitespace-separated tokens
+ while (ss >> buffer)
+ tokens.push_back (buffer);
+
+ // sanity checks
+ if (tokens.size() != 4 * __genomes.size() + 1) {
+ cerr << "WARNING: Can't parse line: '" << line << "'; skipping." << endl;
+ return;
+ }
+
+ // extract bin number for this line of the map file
+ const unsigned bin = static_cast<unsigned> (atoi (tokens[0].c_str()));
+
+ // keep track of how many bins there are
+ // (remember that bins use 1-based numbering)
+ if (bin > __num_bins)
+ __num_bins = bin;
+
+ for (size_t i = 1; i < tokens.size(); i += 4) {
+
+ // if this is an empty interval,
+ // meaning that this genome has no orthologous sequence in this bin,
+ // then store nothing for this genome
+ if (tokens[i] == mercator_empty_interval)
+ continue;
+
+ const std::string& genome = __genomes[i / 4];
+ std::string& chromosome = tokens[i];
+ Util::strip_leading_chr (chromosome);
+ const unsigned start = atoi (tokens[i + 1].c_str());
+ const unsigned end = atoi (tokens[i + 2].c_str()) - 1; // (remember that Mercator coordinates are half-open, [start, end); convert to fully-closed here)
+ const char strand = (tokens[i + 3])[0];
+
+ assert (end >= start);
+ // strand sanity checks
+ assert (tokens[i + 3].size() == 1);
+ if (strand != '+' && strand != '-') {
+ cerr << "ERROR: Unrecognized strand " << strand << "." << endl;
+ exit (1);
+ }
+
+ // store interval plus indexing from bin -> interval
+ __intervals.push_back (Mercator_interval (bin,
+ genome, chromosome,
+ start, end, strand));
+
+ }
+
+
+}
+
+std::vector<Mercator_interval> Mercator_map::get_mercator_intervals (const std::string& genome) const {
+
+ std::vector<Mercator_interval> gintervals;
+ for (std::vector<Mercator_interval>::const_iterator interval = __intervals.begin(); interval != __intervals.end(); ++interval) {
+ if (interval->genome == genome)
+ gintervals.push_back (*interval);
+ }
+
+ return gintervals;
+
+}
+
+std::string Mercator_map::get_genomes_string() const {
+
+ return Util::join (__genomes, "\t");
+
+}
+
+size_t Mercator_map::find_mercator_interval (const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end,
+ const bool strict /* = true */) const {
+
+ // initialize dummy object for comparison
+ Mercator_interval m;
+ m.genome = genome;
+ m.chromosome = chromosome;
+ Util::strip_leading_chr (m.chromosome);
+ m.start = start;
+ m.end = end;
+
+ std::vector<Mercator_interval>::const_iterator mercator = std::upper_bound (__intervals.begin(),
+ __intervals.end(),
+ m,
+ Genomic_interval::Genomic_interval_less());
+
+ // decrement element to try to get to the Mercator object
+ // which (possibly) contains data for pos
+ // (if element is at beginning, then we have no complete map for sequence,
+ // but we may have a partial map)
+ if (mercator != __intervals.begin())
+ --mercator;
+
+ // now check that we're on the correct genome & chromosome
+ if (mercator->genome != m.genome || mercator->chromosome != m.chromosome)
+ return __intervals.size();
+
+ bool mapped = false;
+
+ // does the complete interval [start, end] fall outside the found mapping?
+ if (start > mercator->end || end < mercator->start)
+ mapped = false;
+
+ // does the complete interval [start, end] fall into the found mapping?
+ else if (start >= mercator->start && end <= mercator->end)
+ mapped = true;
+
+ // if we don't require complete coverage, then look for partial coverage
+ else if (!strict) {
+ if ((start <= mercator->start && end >= mercator->end)
+ || (start >= mercator->start)
+ || (end <= mercator->end))
+ mapped = true;
+ }
+
+ if (mapped)
+ return mercator - __intervals.begin();
+
+ // else couldn't map successfully
+ return __intervals.size();
+
+}
+
+std::vector<Genomic_interval> Mercator_map::choose_random_intervals (const std::string& genome,
+ const size_t length, const size_t num) const {
+
+ // create lists of all intervals for the requested genome
+ std::vector<double> interval_lengths; // weight intervals for genome according to the sequence contained therein
+ std::vector<size_t> interval_indices; // indices for intervals in *this
+ for (size_t i = 0; i < size(); ++i) {
+ if (get_interval (i).genome == genome) {
+ interval_lengths.push_back (get_interval (i).length());
+ interval_indices.push_back (i);
+ }
+ }
+
+ // now normalize properly to get a probability distribution
+ const double norm = accumulate (interval_lengths.begin(), interval_lengths.end(),
+ 0.);
+ for (size_t i = 0; i < interval_lengths.size(); ++i)
+ interval_lengths[i] /= norm;
+
+ // choose intervals!
+ std::vector<Genomic_interval> random_intervals;
+ while (random_intervals.size() < num) {
+
+ // choose a Mercator_interval according to the length of sequence it has for genome
+ const Mercator_interval& interval = get_interval (interval_indices[Util::choose_from_distribution (interval_lengths)]);
+
+ // choose a point within the Mercator_interval
+ const unsigned centroid = interval.start + Util::rand (interval.length() - 1);
+
+ unsigned random_start = centroid > static_cast<size_t> (length / 2) ? centroid - static_cast<size_t> (length / 2) : 0;
+ if (random_start < interval.start)
+ random_start = interval.start;
+ const unsigned random_end = centroid + static_cast<size_t> (length / 2);
+
+ // use this point as a centroid for a Genomic_interval
+ random_intervals.push_back (Genomic_interval (genome, interval.chromosome,
+ random_start, random_end, interval.strand));
+
+ }
+
+ return random_intervals;
+
+}
+
+Mercator_alignment::Mercator_alignment (const std::string& map_dir,
+ const std::string& alignments_dir)
+ : Mercator_map (map_dir),
+ __alignments_dir (alignments_dir) {
+
+ __suffixes_stockholm.push_back ("stock");
+ __suffixes_stockholm.push_back ("stk");
+ __suffixes_mfa.push_back ("mfa");
+ __suffixes_mfa.push_back ("fasta");
+ __suffixes_mfa.push_back ("fa");
+ __suffixes_mfa.push_back ("fas");
+
+}
+
+void Mercator_alignment::read_bin_alignment (const unsigned bin,
+ Stockholm& stockholm_bin,
+ const bool verbose /* = true */) const {
+
+ std::string filename;
+
+ // look for Stockholm files
+ for (std::vector<std::string>::const_iterator suffix = __suffixes_stockholm.begin(); suffix != __suffixes_stockholm.end(); ++suffix) {
+ filename = __alignments_dir + '/' + Util::to_string (bin) + '.' + *suffix;
+ if (Util::exists_file (filename)) {
+ stockholm_bin.read_stockholm (filename, true, // strict = true
+ verbose);
+ return;
+ }
+ }
+
+ // look for MFA files
+ for (std::vector<std::string>::const_iterator suffix = __suffixes_mfa.begin(); suffix != __suffixes_mfa.end(); ++suffix) {
+ filename = __alignments_dir + '/' + Util::to_string (bin) + '.' + *suffix;
+ if (Util::exists_file (filename)) {
+ stockholm_bin.read_mfa (filename, true, // strict = true
+ verbose);
+ return;
+ }
+ }
+
+ // if we're here, then we didn't locate an alignment file
+ cerr << "ERROR: Couldn't locate alignment file of the form '"
+ << bin << ".{stock,stk,mfa,fasta,fa,fas}' in directory '" << __alignments_dir << "/'." << endl;
+ exit (1);
+
+}
+
+Stockholm* Mercator_alignment::slice
+(Sequence_database& seq_db_subalign,
+ const std::string& genome, const std::string& chromosome,
+ char strand,
+ const unsigned start, const unsigned end,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool annotate_homology_information /* = false */,
+ const bool verbose /* = true */) const {
+
+
+ Sequence_database seq_db_bin;
+ Stockholm stockholm_bin (seq_db_bin);
+ unsigned bin;
+
+ return slice (seq_db_subalign,
+ bin,
+ stockholm_bin,
+ genome, chromosome,
+ strand,
+ start, end,
+ lazy, truncate_ok,
+ annotate_homology_information,
+ verbose);
+
+}
+
+Stockholm* Mercator_alignment::slice
+(Sequence_database& seq_db_subalign,
+ unsigned& bin,
+ Stockholm& stockholm_bin,
+ const std::string& genome, const std::string& chromosome,
+ char strand,
+ const unsigned start, const unsigned end,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool annotate_homology_information /* = false */,
+ const bool verbose /* = true */) const {
+
+ // sanity check on strand
+ if (strand != '+' && strand != '-' && verbose) {
+ cerr << "WARNING: Unknown strand '" << strand << "'; assuming + strand." << endl;
+ strand = '+';
+ }
+
+ // map from genomic to alignment coordinates
+ const Interval align_interval = map_genomic_to_align (genome, chromosome,
+ start, end,
+ bin,
+ stockholm_bin,
+ lazy, truncate_ok,
+ verbose);
+ // catch the case of an empty interval, meaning that no mapping could be found
+ if (align_interval.length() == 0) {
+ seq_db_subalign.clear();
+ return new Stockholm (seq_db_subalign);
+ }
+
+ const unsigned start_align = align_interval.start;
+ const unsigned end_align = align_interval.end;
+
+ // pull out the subalignment
+ Stockholm* subalignment = stockholm_bin.subalignment (seq_db_subalign,
+ start_align, end_align);
+
+ // revcomp if necessary
+ const size_t idx = find_mercator_interval (genome, chromosome,
+ start, end,
+ !truncate_ok); // not strict if truncate_ok
+ const Mercator_interval& interval = get_interval (idx);
+ if (strand != interval.strand)
+ subalignment->revcomp (Mercator_alignment::alphabet);
+
+ // show homology information for all seqs if desired
+ // (i.e., what subsequences are in the subalignment)
+ if (annotate_homology_information) {
+
+ // has the subaligment been reverse-complemented w.r.t. the raw Mercator mapping?
+ const bool was_rc = (strand != interval.strand);
+
+ for (size_t r = 0; r < stockholm_bin.rows(); ++r) {
+
+ const std::string& genome2 = stockholm_bin.get_row_name (r);
+
+ GFF gff;
+
+ // if "source" genome, annotate directly
+ if (genome2 == genome) {
+
+ gff.seqid = chromosome;
+ Util::strip_leading_chr (gff.seqid); // for consistency with rest of sequences
+ gff.start = start + 1; // convert to 1-based coordinates (b/c GFF)
+ gff.end = end + 1;
+ gff.strand = strand;
+
+ }
+
+ // else find the homologous sequence to annotate with
+ else {
+
+ // find homologous interval
+ Genomic_interval interval2 = find_homologous_interval (bin,
+ stockholm_bin,
+ genome, chromosome,
+ start, end,
+ genome2,
+ lazy, truncate_ok,
+ verbose);
+
+ // figure out what strand genome2 is on in the subalignment
+ if (was_rc)
+ Sequence::complement_strand (interval2.strand);
+
+ // annotate
+ gff.seqid = interval2.chromosome;
+ gff.start = interval2.start + 1; // convert to 1-based coordinates (b/c GFF)
+ gff.end = interval2.end + 1;
+ gff.strand = interval2.strand;
+
+ }
+
+ // annotate!
+ subalignment->set_gs_annot (genome2, Stockholm::gff_annotation, gff.to_string());
+
+ }
+
+ }
+
+ return subalignment;
+
+}
+
+
+Genomic_interval Mercator_alignment::find_homologous_interval
+(const std::string& genome_from, const std::string& chromosome_from,
+ const unsigned start_from, const unsigned end_from,
+ const std::string& genome_to,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool verbose /* = true */) const {
+
+ Sequence_database seq_db_bin;
+ Stockholm stockholm_bin (seq_db_bin);
+ unsigned bin;
+
+ return find_homologous_interval (bin,
+ stockholm_bin,
+ genome_from, chromosome_from,
+ start_from, end_from,
+ genome_to,
+ lazy, truncate_ok,
+ verbose);
+
+}
+
+Genomic_interval Mercator_alignment::find_homologous_interval
+(unsigned& bin,
+ Stockholm& stockholm_bin,
+ const std::string& genome_from, const std::string& chromosome_from,
+ const unsigned start_from, const unsigned end_from,
+ const std::string& genome_to,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool verbose /* = true */) const {
+
+ // check that these are valid genomes
+ if (!exists_genome (genome_from)) {
+ cerr << "ERROR: No information for genome '" << genome_from << "'; valid genomes are:" << endl
+ << get_genomes_string() << endl;
+ exit (1);
+ }
+ if (!exists_genome (genome_to)) {
+ cerr << "ERROR: No information for genome '" << genome_to << "'; valid genomes are:" << endl
+ << get_genomes_string() << endl;
+ exit (1);
+ }
+
+ // try to map the interval
+ const size_t idx_from = find_mercator_interval (genome_from, chromosome_from,
+ start_from, end_from,
+ !truncate_ok);
+ if (idx_from == size()) {
+ if (!lazy) {
+ cerr << "ERROR: No mapping exists for: " << genome_from << '\t' << chromosome_from << '\t'
+ << start_from << '\t' << end_from << endl;
+ exit (1);
+ } else {
+ cerr << "WARNING: No mapping exists for: " << genome_from << '\t' << chromosome_from << '\t'
+ << start_from << '\t' << end_from << endl;
+ return Genomic_interval();
+ }
+ }
+ const Mercator_interval& interval_from = get_interval (idx_from);
+ const unsigned this_bin = interval_from.bin;
+
+ // find the bin for genome_map_to
+ Mercator_interval mercator_interval_to = get_interval_by_bin (this_bin, genome_to);
+
+ // now extract the homologous interval using the base-level alignment
+
+ // if this_bin isn't the passed alignment,
+ // then find and open the appropriate bin
+ if (bin != this_bin) {
+ // find & read alignment
+ read_bin_alignment (this_bin, stockholm_bin, verbose);
+ // record current bin
+ bin = this_bin;
+ }
+
+
+ // map the sequence interval using the alignment
+ // (remember to convert coordinates w.r.t. Mercator_interval)
+
+ // first calculate the sequence coordinate offsets w.r.t. the interval_from alignment
+ // the conditionals truncate the requested sequence as appropriate if it's not entirely
+ // contained within the interval_from alignment
+ unsigned start_from_seq, end_from_seq;
+ // if Mercator_interval is on - strand, then need to flip the interval and calculate w.r.t.
+ // the end of the mapped Mercator_interval (because the sequence in the alignment has
+ // been reverse-complemented, so it "begins" at the end of the Mercator_interval)
+ if (interval_from.strand == '-') {
+ start_from_seq = static_cast<int> (interval_from.end - end_from) >= 0
+ ? interval_from.end - end_from
+ : 0;
+ end_from_seq = static_cast<int> (interval_from.end - start_from) >= 0
+ ? interval_from.end - start_from
+ : interval_from.end - interval_from.start;
+ }
+ // if Mercator_interval is on + strand, then just subtract offsets
+ else {
+ start_from_seq = static_cast<int> (start_from - interval_from.start) >= 0
+ ? start_from - interval_from.start
+ : 0;
+ end_from_seq = static_cast<int> (interval_from.end - end_from) >= 0
+ ? end_from - interval_from.start
+ : interval_from.end - interval_from.start;
+ }
+
+ // warn if we've truncated
+ if (static_cast<int> (start_from - interval_from.start) < 0 || static_cast<int> (interval_from.end - end_from) < 0
+ || static_cast<int> (interval_from.end - end_from) < 0 || static_cast<int> (interval_from.end - start_from) < 0)
+ cerr << "WARNING: Truncating alignment slice to mapped sequence: " << genome_from << '\t' << chromosome_from << '\t'
+ << start_from << '\t' << end_from << '\t' << interval_from.strand << endl;
+
+ // now map to coordinates in the other sequence
+ const Interval interval_to = stockholm_bin.map_seq_to_seq (genome_from, start_from_seq, end_from_seq,
+ genome_to);
+
+ // check for the case of no sequence (empty interval) in the "to" genome subsequence
+ // Alignment::map_seq_to_seq returns (1, 0) if no sequence
+ if (interval_to.end < interval_to.start)
+ return Genomic_interval();
+
+ // now convert mercator_interval_to to hold the base-level mapping
+ // else add offsets w.r.t. end of the Mercator_interval
+ if (mercator_interval_to.strand == '-') {
+ mercator_interval_to.start = mercator_interval_to.end - interval_to.end;
+ mercator_interval_to.end = mercator_interval_to.end - interval_to.start;
+ }
+ // if Mercator_interval is on + strand, then just add offsets back on
+ else {
+ mercator_interval_to.end = mercator_interval_to.start + interval_to.end;
+ mercator_interval_to.start += interval_to.start;
+ }
+ // (NB: both of these transformations are derived by
+ // inverting the ones used above to set {start,end}_from_seq)
+
+ return mercator_interval_to;
+
+}
+
+GFF_database Mercator_alignment::map_gff_database
+(const std::string& genome_from, const std::string& genome_to,
+ const GFF_database& gff_db_from,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool verbose /* = true */,
+ const bool force_entry /* = false */) const {
+
+ GFF_database gff_db_to;
+
+ // initialize persistent sequence & alignment information for current bin
+ Sequence_database seq_db_bin;
+ Stockholm stockholm_bin (seq_db_bin);
+ unsigned bin = 0; // initialize to dummy 0 value
+
+ // iterate through GFF
+ for (std::vector<GFF>::const_iterator gff_from = gff_db_from.begin(); gff_from != gff_db_from.end(); ++gff_from) {
+
+ // use the alignment to find the homologous interval
+ Genomic_interval region_target = find_homologous_interval (bin,
+ stockholm_bin,
+ genome_from, gff_from->seqid,
+ gff_from->start - 1, gff_from->end - 1, // convert to 0-based coordinates
+ genome_to,
+ lazy, truncate_ok,
+ verbose);
+
+ // check that it was mapped successfully
+ // (Mercator_alignment::find_homologous_interval returns an empty value
+ // if it wasn't or if homologous subsequence is empty)
+ // NB no need to enforce lazy here, b/c find_homologous_interval does this for us
+ if (region_target.genome == "") {
+ cerr << "WARNING: No homologous sequence found (all gaps) in " << genome_to << " for: " << genome_from << '\t' << gff_from->seqid << '\t'
+ << gff_from->start - 1 << '\t' << gff_from->end - 1 << '\t' << gff_from->strand << endl;
+ // store an empty entry if requested
+ if (force_entry) {
+ GFF gff_to;
+ gff_to.source = std::string (PACKAGE) + '\\' + gff_from->source;
+ gff_to.type = gff_from->type;
+ gff_to.start = 1; // nonsense values for start and end: [1, 0]
+ gff_to.end = 0;
+ gff_db_to.store_entry (gff_to);
+ }
+ continue;
+ }
+
+ // get the Mercator_interval for the source
+ const size_t idx_source = find_mercator_interval (genome_from, gff_from->seqid,
+ gff_from->start - 1, gff_from->end - 1, // convert to 0-based coordinates
+ !truncate_ok);
+ assert (idx_source < size());
+ const Mercator_interval& interval_source = get_interval (idx_source);
+
+ // use the source interval to determine whether the source feature was
+ // reverse-complemented w.r.t. the strand in the Mercator_interval
+ // if it was, then the target feature will also be reverse-complemented
+ // w.r.t. the strand in the Mercator_interval
+ const bool is_rc = (interval_source.strand != gff_from->strand);
+
+ GFF gff_to;
+ gff_to.seqid = region_target.chromosome;
+ gff_to.source = std::string (PACKAGE) + '\\' + gff_from->source;
+ gff_to.type = gff_from->type;
+ gff_to.start = region_target.start + 1; // convert back to 1-based coordinates
+ gff_to.end = region_target.end + 1;
+ if (gff_from->strand == GFF::unknown_strand) // if the source feature had no annotated strand, then do the same for the target feature
+ gff_to.strand = GFF::unknown_strand;
+ else { // otherwise set the target strand appropriately using the homology mapping implied by the alignment
+ gff_to.strand = region_target.strand;
+ if (is_rc)
+ Sequence::complement_strand (gff_to.strand);
+ }
+ for (std::vector<std::string>::const_iterator key = gff_from->attributes_ordering.begin(); key != gff_from->attributes_ordering.end(); ++key) {
+ const std::vector<std::string>& values = gff_from->attributes_map.find (*key)->second;
+ for (std::vector<std::string>::const_iterator value = values.begin(); value != values.end(); ++value) {
+ // watch for case of quoted fields
+ if ((*value)[0] == '\"' && (*value)[value->length() - 1] == '\"') {
+ gff_to.add_value (*key, '\"' + genome_to + '\\'+ std::string (*value, 1, value->length() - 1));
+ } else if ((*value)[0] == '\'' && (*value)[value->length() - 1] == '\'') {
+ gff_to.add_value (*key, '\'' + genome_to + '\\'+ std::string (*value, 1, value->length() - 1));
+ } else {
+ gff_to.add_value (*key, genome_to + '\\'+ *value);
+ }
+ }
+ }
+
+ gff_db_to.store_entry (gff_to);
+
+ }
+
+ return gff_db_to;
+
+}
+
+Genomic_interval Mercator_alignment::map_align_to_genomic
+(const unsigned bin,
+ const Stockholm& stockholm_bin,
+ const std::string& genome,
+ const unsigned start, const unsigned end,
+ const bool rc /* = false */) const {
+
+ // check sane
+ assert (start <= end);
+ assert (end < stockholm_bin.columns());
+ assert (exists_genome (genome));
+
+ // find the Mercator_interval describing the sequence for genome in this bin
+ // check whether the passed alignment of the bin sequence has been reverse-complemented:
+ // if so, then we need to flip the strand of Mercator_interval for this bin
+ Mercator_interval mercator_interval = get_interval_by_bin (bin, genome);
+ if (rc)
+ Sequence::complement_strand (mercator_interval.strand);
+
+ // map column indices to sequence coordinates (w.r.t. stockholm_bin)
+ const Interval align_seq_coords = stockholm_bin.map_align_to_seq (genome,
+ start, end);
+
+ // now map from sequence coordinates within the alignment of the bin to genomic coordinates
+ Genomic_interval genomic_interval;
+ genomic_interval.genome = genome;
+ genomic_interval.chromosome = mercator_interval.chromosome;
+ genomic_interval.strand = mercator_interval.strand;
+
+ // check for the case of an empty interval
+ if (align_seq_coords.start > align_seq_coords.end) {
+ genomic_interval.start = 1;
+ genomic_interval.end = 0;
+ return genomic_interval;
+ }
+
+ // tricky if on the - strand
+ // (sequence has been reversed, so we need to count from right to left)
+ if (genomic_interval.strand == '-') {
+ genomic_interval.start = mercator_interval.end - align_seq_coords.end;
+ genomic_interval.end = mercator_interval.end - align_seq_coords.start;
+ }
+ // ...easier if aligned sequence is on the + strand
+ else {
+ genomic_interval.start = mercator_interval.start + align_seq_coords.start;
+ genomic_interval.end = mercator_interval.start + align_seq_coords.end;
+ }
+ // Note that the above calculations for the - strand are equivalent to:
+ // genomic_coords.start = (seqlength - 1) - align_seq_coords.end + mercator_interval.start;
+ // genomic_coords.end = (seqlength - 1) - align_seq_coords.start + mercator_interval.start;
+ // where seqlength is the ungapped sequence length of the bin.
+
+ return genomic_interval;
+
+}
+
+Interval Mercator_alignment::map_genomic_to_align
+(const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end,
+ unsigned& bin,
+ Stockholm& stockholm_bin,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool verbose /* = true */) const {
+
+ // map to sequence coordinates within the bin
+ const Interval bin_seq_coords = map_genomic_to_bin_seq (genome, chromosome,
+ start, end,
+ bin,
+ stockholm_bin,
+ lazy, truncate_ok,
+ verbose);
+
+ // catch the case of a 0-lenth interval
+ if (bin_seq_coords.length() == 0)
+ return Interval (1, 0);
+
+ // then map to alignment coordinates
+ const unsigned start_align = stockholm_bin.map_seq_to_align (genome, bin_seq_coords.start);
+ const unsigned end_align = stockholm_bin.map_seq_to_align (genome, bin_seq_coords.end);
+
+ return Interval (start_align, end_align);
+
+}
+
+Interval Mercator_alignment::map_genomic_to_bin_seq
+(const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end,
+ unsigned& bin,
+ Stockholm& stockholm_bin,
+ const bool lazy /* = false */, const bool truncate_ok /* = false */,
+ const bool verbose /* = true */) const {
+
+ // check that this is a valid genome
+ if (!exists_genome (genome)) {
+ cerr << "ERROR: No information for genome '" << genome << "'; valid genomes are:" << endl
+ << get_genomes_string() << endl;
+ exit (1);
+ }
+
+ // try to map the interval
+ const size_t idx = find_mercator_interval (genome, chromosome,
+ start, end,
+ !truncate_ok); // not strict if truncate_ok
+ if (idx == size()) {
+ if (!lazy) {
+ cerr << "ERROR: No mapping exists for: " << genome << '\t' << chromosome << '\t'
+ << start << '\t' << end << endl;
+ exit (1);
+ } else {
+ cerr << "WARNING: No mapping exists for: " << genome << '\t' << chromosome << '\t'
+ << start << '\t' << end << endl;
+ return Interval (1, 0);
+ }
+ }
+ const Mercator_interval& interval = get_interval (idx);
+ const unsigned this_bin = interval.bin;
+
+ // if this_bin isn't the passed alignment,
+ // then find and open the appropriate bin
+ if (bin != this_bin) {
+ // find & read alignment
+ read_bin_alignment (this_bin, stockholm_bin, verbose);
+ // record current bin
+ bin = this_bin;
+ }
+
+ // map sequence to alignment coordinates
+
+ // first calculate the sequence coordinates within the interval alignment
+ // (i.e., subtract off the offsets for the mapped Mercator_interval)
+ // the conditionals truncate the requested sequence as appropriate if it's not entirely
+ // contained within the interval alignment
+ unsigned start_seq, end_seq;
+
+ // if Mercator_interval is on - strand, then need to flip the interval and calculate w.r.t.
+ // the end of the mapped Mercator_interval (because the sequence in the alignment has
+ // been reverse-complemented, so it "begins" at the end of the Mercator_interval)
+ // (very tricky...)
+ if (interval.strand == '-') {
+ start_seq = static_cast<int> (interval.end - end) >= 0
+ ? interval.end - end
+ : 0;
+ end_seq = static_cast<int> (interval.end - start) >= 0
+ ? interval.end - start
+ : interval.end - interval.start;
+ }
+ // if Mercator_interval is on + strand, then just subtract offsets
+ else {
+ start_seq = static_cast<int> (start - interval.start) >= 0
+ ? start - interval.start
+ : 0;
+ end_seq = static_cast<int> (interval.end - end) >= 0
+ ? end - interval.start
+ : interval.end - interval.start;
+ }
+
+ // warn if we've truncated
+ if (static_cast<int> (start - interval.start) < 0 || static_cast<int> (interval.end - end) < 0
+ || static_cast<int> (interval.end - end) < 0 || static_cast<int> (interval.end - start) < 0)
+ cerr << "WARNING: Truncating alignment slice to mapped sequence: " << genome << '\t' << chromosome << '\t'
+ << start << '\t' << end << endl;
+
+ return Interval (start_seq, end_seq);
+
+}
diff --git a/src/seq/mercator.h b/src/seq/mercator.h
new file mode 100644
index 0000000..318854f
--- /dev/null
+++ b/src/seq/mercator.h
@@ -0,0 +1,465 @@
+
+/**
+ * \file mercator.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef SEQ_MERCATOR_INCLUDED
+#define SEQ_MERCATOR_INCLUDED
+
+#include "config.h"
+#include "util/regexp.h"
+#include "seq/alignment.h"
+#include "seq/gff.h"
+#include "seq/interval.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a single genomic interval in a mapping.
+ *
+ * Uses 0-based, fully-closed coordinates.
+ * Note that this is NOT the same as Mercator itself,
+ * which uses 0-based, half-open [start, end) coordinates.
+ * \see Mercator_map
+ */
+ struct Mercator_interval : public Genomic_interval {
+
+ public:
+
+ Mercator_interval() { }
+
+ /**
+ * \brief Constructor.
+ */
+ Mercator_interval (unsigned bin,
+ const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end, char strand)
+ : Genomic_interval (genome, chromosome,
+ start, end, strand),
+ bin (bin)
+ { }
+
+ unsigned bin; ///< Mercator bin number
+
+ /**
+ * \brief Write in Mercator format.
+ */
+ std::string to_string() const {
+ std::string str;
+ str = chromosome + '\t'
+ + Util::to_string (start) + '\t' + Util::to_string (end) + '\t'
+ + strand;
+ return str;
+ }
+
+ /**
+ * \brief Output operator.
+ */
+ friend std::ostream& operator<< (std::ostream& o, const Mercator_interval& interval) {
+ o << interval.bin << '\t'
+<< interval.genome << '\t'
+ << interval.to_string() << endl;
+ return o;
+ }
+
+ // explicitly import less_than
+ using Genomic_interval::operator<;
+
+ };
+
+ /**
+ * \brief Represent a Mercator mapping between genomes.
+ *
+ * Uses 0-based, fully-closed coordinates.
+ * Mercator uses 0-based, half-open [start, end)
+ * coordinates; the conversion is done internally by this class.
+ * If present, strips off the leading 'chr' frequently prepended
+ * to chromosome names (this helps to prevent frustrations due
+ * to, e.g., having 'chr' prepended to the chromosomes in the map
+ * file but not when calling slice.
+ */
+ struct Mercator_map {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ * \param map_dir directory for Mercator genomes and map files
+ */
+ Mercator_map (const std::string& map_dir);
+
+ /**
+ * \brief Find the Mercator_interval for a particular genomic sequence.
+ *
+ * Require that the sequence is completely or partially contained
+ * in interval.
+ * Uses a binary search over all Mercator_interval objects.
+ * \param strict interval must be completely contained within Mercator_interval
+ * \return index of Mercator_interval in __intervals, or size() if it can't be found
+ */
+ size_t find_mercator_interval (const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end,
+ const bool strict = true) const;
+
+ /**
+ * \brief Choose random Genomic_intervals from sequence in a Mercator_map.
+ *
+ * Chosen according to a uniform distribution over sequences:
+ * - choose a Mercator_interval according to the length of sequence it has for genome
+ * - choose a point within the Mercator_interval
+ * - use this point as a centroid for a Genomic_interval
+ * (note that the Genomic_interval will NOT be truncated, even if it does not
+ * fit within the containing Mercator_interval)
+ * \param genome genome to select intervals for
+ * \param length length of desired intervals
+ * \param num number of intervals desired
+ */
+ std::vector<Genomic_interval> choose_random_intervals (const std::string& genome,
+ const size_t length, const size_t num) const;
+
+ /**
+ * \brief Get a Mercator_interval by its index.
+ * \see find_mercator_interval
+ */
+ const Mercator_interval& get_interval (const size_t idx) const {
+ return __intervals[idx];
+ }
+
+ /**
+ * \brief Number of intervals.
+ *
+ * This is equal to (# of bins) * (# of genomes).
+ */
+ size_t size() const { return __intervals.size(); }
+
+ /**
+ * \brief Number of bins.
+ */
+ size_t bins() const { return __num_bins; }
+
+ /**
+ * \brief Get all Mercator_intervals for a particular genome.
+ */
+ std::vector<Mercator_interval> get_mercator_intervals (const std::string& genome) const;
+
+ /**
+ * \brief Do we have information for a particular genome?
+ */
+ bool exists_genome (const std::string& genome) const {
+ return __genome_index.find (genome) != __genome_index.end();
+ }
+
+ /**
+ * \brief Get the list of genomes in the Mercator file format.
+ */
+ std::string get_genomes_string() const;
+
+ /**
+ * \brief Get the Mercator_interval for a particular bin and genome.
+ */
+ inline const Mercator_interval& get_interval_by_bin (const unsigned bin, const std::string& genome) const;
+
+
+ protected:
+
+ /**
+ * \brief Get indices in __intervals for all Mercator_interval objects for a particular bin.
+ */
+ inline const std::vector<size_t>& get_intervals_by_bin (const unsigned bin) const;
+
+ /**
+ * \brief Get iterator to start of __intervals.
+ */
+ std::vector<Mercator_interval>::const_iterator begin() const {
+ return __intervals.begin();
+ }
+
+ /**
+ * \brief Get iterator to end of __intervals.
+ */
+ std::vector<Mercator_interval>::const_iterator end() const {
+ return __intervals.end();
+ }
+
+
+ private:
+
+ /**
+ * \brief Initialize from Mercator file.
+ * \see parse_line
+ */
+ void from_file (const std::string& genomes_filename,
+ const std::string& map_filename);
+
+ /**
+ * \brief Initialize map from bins to Mercator_interval objects.
+ *
+ * Must be called after from_file.
+ */
+ void init_bin_index();
+
+ /**
+ * \brief Parse single line of Mercator map file.
+ */
+ void parse_line (const std::string& line);
+
+
+ std::vector<std::string> __genomes; ///< map from numeric genome index to name (ordered list of genomes)
+ std::map<std::string, size_t> __genome_index; ///< map from a genome to its numeric index in the map file
+
+ size_t __num_bins; ///< number of bins in the map
+ std::vector<Mercator_interval> __intervals; ///< Mercator_interval entries
+
+ /**
+ * \brief Map from a bin and genome to the index for the corresponding Mercator_interval objects in __intervals.
+ * The appropriate index in __intervals is accessed as __bin_index[bin][__genome_index[genome]].
+ * If there is no such index (i.e., for a particular bin there is no associated interval for some genome,
+ * then the index will be the nonsense index size().
+ */
+ std::vector<std::vector<size_t> > __bin_index;
+
+ private:
+
+ static const std::string mercator_empty_interval; ///< string designating no information for a particular genome in a map file
+
+ };
+
+ /**
+ * \brief
+ *
+ * Assumes a DNA alphabet, but DOES NOT check or enforce this!
+ */
+ struct Mercator_alignment : public Mercator_map {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ * \param map_dir directory for Mercator genomes and map files
+ * \param alignments_dir directory for alignment files
+ */
+ Mercator_alignment (const std::string& map_dir,
+ const std::string& alignments_dir);
+
+ /**
+ * \brief Find and read the alignment file for a particular bin.
+ * \param bin Mercator bin
+ * \param stockholm_bin read alignment into this
+ */
+ void read_bin_alignment (const unsigned bin,
+ Stockholm& stockholm_bin,
+ const bool verbose = true) const;
+
+ /**
+ * \brief Get the subalignment for a particular genomic sequence.
+ *
+ * If requested, will return a truncated subalignment if only
+ * part of the sequence can be mapped (rather than returning nothing).
+ * If the strand is -, then the returned subalignment
+ * will be reverse-complemented.
+ * \param seq_db_subalign Sequence_database hold subalignment sequences
+ * \param lazy warn, instead of die, if the interval can't be mapped
+ * \param truncate_ok if the sequence can't all be mapped, then return a truncated subalignment
+ * \param annotate_homology_information mark up alignment with homology information for sequences (in GFF format)
+ * \return subalignment, or empty alignment if can't be found
+ * \see subalignment
+ */
+ Stockholm* slice (Sequence_database& seq_db_subalign,
+ const std::string& genome, const std::string& chromosome,
+ char strand,
+ const unsigned start, const unsigned end,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool annotate_homology_information = false,
+ const bool verbose = true) const;
+
+ /**
+ * \brief Get the subalignment for a particular genomic sequence.
+ *
+ * If requested, will return a truncated subalignment if only
+ * part of the sequence can be mapped (rather than returning nothing).
+ * If the strand is -, then the returned subalignment
+ * will be reverse-complemented (i.e., if the requested strand differs from
+ * the strand specified in the Mercator mapping, then the alignment will
+ * be reverse-complemented w.r.t. the Mercator multiple alignment).
+ * If the strand is unknown, then the + strand is assumed.
+ * Looks for an alignment of the form 'bin.{stock,stk,mfa,fasta,fa,fas}'
+ * in __alignments_dir.
+ * This method populates Sequence_database and Stockholm objects
+ * for both the entire bin alignment as well as the requested subalignment.
+ * Saving on overhead associated with reading in the bin alignment,
+ * this allows for efficient extraction of multiple sequences
+ * from the same bin.
+ * \param subalign_seq_db hold subalignment sequences
+ * \param bin Mercator bin which stockholm_bin holds the alignment for (set to 0 for dummy/unknown value)
+ * \param stockholm_bin hold Stockholm alignment for bin
+ * \param lazy warn, instead of die, if the interval can't be mapped
+ * \param truncate if the sequence can't all be mapped, then return a truncated subalignment
+ * \param annotate_homology_information mark up alignment with homology information for sequences (in GFF format)
+ * \see map_genomic_to_align
+ * \return subalignment, or empty alignment if can't be found
+ */
+ Stockholm* slice (Sequence_database& seq_db_subalign,
+ unsigned& bin,
+ Stockholm& stockholm_bin,
+ const std::string& genome, const std::string& chromosome,
+ char strand,
+ const unsigned start, const unsigned end,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool annotate_homology_information = false,
+ const bool verbose = true) const;
+
+ /**
+ * \brief Find the homologous interval according to the Mercator mapping and corresponding multiple alignment.
+ *
+ * The returned Mercator_interval DOES NOT correspond to an actual entry
+ * in the Mercator map file, but rather a sub-interval thereof.
+ * Maps genome_from -> genome_to.
+ * As always, coordinates are 0-based and fully-closed.
+ * \param genome_from genome with the specified sequence interval
+ * \param genome_to genome to find the homologous interval in
+ * \param lazy warn, instead of die, if the interval can't be mapped
+ * \param truncate if the sequence can't all be mapped, then use a truncated subalignment
+ * \return Mercator_interval specifying the homologous interval; returned value is empty if it can't be mapped or if empty subsequence (all gaps in alignment)
+ */
+ Genomic_interval find_homologous_interval
+ (const std::string& genome_from, const std::string& chromosome_from,
+ const unsigned start_from, const unsigned end_from,
+ const std::string& genome_to,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool verbose = true) const;
+
+ /**
+ * \brief Find the homologous interval according to the Mercator mapping and corresponding multiple alignment.
+ *
+ * The returned Mercator_interval DOES NOT correspond to an actual entry
+ * in the Mercator map file, but rather a sub-interval thereof.
+ * Maps genome_from -> genome_to.
+ * This method populates Sequence_database and Stockholm objects
+ * for the entire bin alignment.
+ * Saving on overhead associated with reading in the bin alignment,
+ * this allows for efficient multiple queries from the same bin.
+ * As always, coordinates are 0-based and fully-closed.
+ * \param genome_from genome with the specified sequence interval
+ * \param genome_to genome to find the homologous interval in
+ * \param lazy warn, instead of die, if the interval can't be mapped
+ * \param truncate if the sequence can't all be mapped, then use a truncated subalignment
+ * \return Mercator_interval specifying the homologous interval; returned value is empty if it can't be mapped or if empty subsequence (all gaps in alignment)
+ */
+ Genomic_interval find_homologous_interval
+ (unsigned& bin,
+ Stockholm& stockholm_bin,
+ const std::string& genome_from, const std::string& chromosome_from,
+ const unsigned start_from, const unsigned end_from,
+ const std::string& genome_to,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool verbose = true) const;
+
+ /**
+ * \brief Map the features in a GFF database to another genome.
+ *
+ * \param lazy warn, instead of die, if the interval can't be mapped
+ * \param truncate_ok if the sequence can't all be mapped, then return a truncated subalignment
+ * \param force_entry if a feature can't be mapped, then add an empty entry to the GFF file (rather than skipping it entirely)
+ */
+ GFF_database map_gff_database
+ (const std::string& genome_from, const std::string& genome_to,
+ const GFF_database& gff_db_from,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool verbose = true,
+ const bool force_entry = false) const;
+
+ /**
+ * \brief Map alignment coordinates (w.r.t. the alignment of a particular Mercator bin)
+ * to genomic coordinates for a genome.
+ *
+ * \param bin bin which we have the alignment for
+ * \param stockholm_bin the alignment of the bin
+ * \param genome genome to map coordinates for
+ * \param start 0-based column start coordinate
+ * \param end 0-based column end coordinate
+ * \param rc has the passed alignment of the bin been reverse-complemented? (if so,
+ * then appropriately deals with the necessary coordinate conversions)
+ * \return Genomic_interval representing the appropriate genomic sequence for genome,
+ * with nonsense coordinates [1, 0] if the interval is empty (no ungapped sequence).
+ */
+ Genomic_interval map_align_to_genomic
+ (const unsigned bin,
+ const Stockholm& stockholm_bin,
+ const std::string& genome,
+ const unsigned start, const unsigned end,
+ const bool rc = false) const;
+
+ /**
+ * \brief Map genomic coordinates to alignment coordinates for a particular bin.
+ *
+ * \param start 0-based genomic start coordinate
+ * \param end 0-based genomic end coordinate
+ * \param bin Mercator bin which stockholm holds the alignment for (set to 0 for dummy/unknown value)
+ if reading in a new alignment is necessary, then this function sets bin appropriately
+ * \param stockholm_bin hold Stockholm alignment for bin
+ * \return alignment column coordinates or nonsense coordinates [1, 0] if no mapping
+ */
+ Interval map_genomic_to_align
+ (const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end,
+ unsigned& bin,
+ Stockholm& stockholm_bin,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool verbose = true) const;
+
+ /**
+ * \brief Map genomic coordinates to sequence coordinates within a particular bin.
+ * \param start 0-based genomic start coordinate
+ * \param end 0-based genomic end coordinate
+ * \param bin Mercator bin which stockholm holds the alignment for (set to 0 for dummy/unknown value)
+ if reading in a new alignment is necessary, then this function sets bin appropriately
+ * \param stockholm_bin hold Stockholm alignment for bin
+ * \return alignment column coordinates or nonsense coordinates [1, 0] if no mapping
+ */
+ Interval map_genomic_to_bin_seq
+ (const std::string& genome, const std::string& chromosome,
+ const unsigned start, const unsigned end,
+ unsigned& bin,
+ Stockholm& stockholm_bin,
+ const bool lazy = false, const bool truncate_ok = false,
+ const bool verbose = true) const;
+
+
+ private:
+
+ std::string __alignments_dir; ///< directory to search for alignments
+ static const Alphabet alphabet; ///< DNA alphabet
+ std::vector<std::string> __suffixes_mfa; ///< file suffixes to search for alignments
+ std::vector<std::string> __suffixes_stockholm; ///< file suffixes to search for alignments
+
+ };
+
+ inline const std::vector<size_t>& Mercator_map::get_intervals_by_bin (const unsigned bin) const {
+ return __bin_index[bin];
+ }
+
+ inline const Mercator_interval& Mercator_map::get_interval_by_bin (const unsigned bin, const std::string& genome) const {
+
+ // check sane
+ assert (exists_genome (genome));
+ assert (bin <= bins()); // remember that the numbering of Mercator bins is 1-based
+ // and that we preserve the 1-based indexing in __bin_index
+ // (see init_bin_index)
+
+ const size_t index = __bin_index[bin][__genome_index.find (genome)->second];
+
+ // make sure that we have a valid Mercator_interval for this (bin, genome) pair
+ assert (index < size());
+
+ // make sure that we found it
+ assert ((get_interval (index).bin == bin) && (get_interval (index).genome == genome));
+
+ return get_interval (index);
+
+ }
+
+}
+
+#endif /* SEQ_MERCATOR_INCLUDED */
diff --git a/src/seq/sequence.cc b/src/seq/sequence.cc
new file mode 100644
index 0000000..7d46264
--- /dev/null
+++ b/src/seq/sequence.cc
@@ -0,0 +1,587 @@
+
+/**
+ * \file sequence.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <algorithm>
+
+#include "util/regexp.h"
+#include "math/mathematics.h"
+#include "seq/sequence.h"
+
+using namespace fsa;
+
+const std::string Sequence::fasta_seq_start = ">";
+
+// Mapping from codons to amino acids.
+// This really should be a static member variable,
+// but I kept getting annoying linker errors, so here it is.
+// Nucleotide->integer mapping is e.g. AGC => [0][3][2].
+// Stop codons are 'X'.
+const char Translated_sequence::__codon_map[4][4][4] = {
+ { { 'K', 'N', 'K', 'N' },
+ { 'T', 'T', 'T', 'T' },
+ { 'R', 'S', 'R', 'S' },
+ { 'I', 'I', 'M', 'I' } },
+ { { 'Q', 'H', 'Q', 'H' },
+ { 'P', 'P', 'P', 'P' },
+ { 'R', 'R', 'R', 'R' },
+ { 'L', 'L', 'L', 'L' } },
+ { { 'E', 'D', 'E', 'D' },
+ { 'A', 'A', 'A', 'A' },
+ { 'G', 'G', 'G', 'G' },
+ { 'V', 'V', 'V', 'V' } },
+ { { 'X', 'Y', 'X', 'Y' },
+ { 'S', 'S', 'S', 'S' },
+ { 'X', 'C', 'W', 'C' },
+ { 'L', 'F', 'L', 'F' } },
+};
+
+
+
+Sequence::Sequence (const std::string& name, const std::string& seq)
+ : name (name), seq (seq)
+{ }
+
+Sequence::Sequence (const std::string& name, const std::string& seq,
+ const std::string& info)
+ : name (name), seq (seq), info (info)
+{ }
+
+bool Sequence::detect_fasta (const std::string& filename) {
+
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ Regexp re_name ("^[ \t]*" + fasta_seq_start + "([^ \t]*)[ \t]*(.*)");
+
+ std::string line;
+ while (!filestream.eof()) {
+
+ getline (filestream, line);
+ if (re_name.Match (line.c_str())) {
+ filestream.close();
+ return true;
+ }
+
+ }
+ filestream.close();
+
+ return false;
+
+}
+
+Sequence* Sequence::subsequence (const unsigned start, const unsigned end) const {
+
+ assert (!length() || (end < length()));
+ Sequence* sequence = NULL;
+ if (end < start)
+ sequence = new Sequence (name, "");
+ else
+ sequence = new Sequence (name, seq.substr (start, end - start + 1), info);
+
+ return sequence;
+
+}
+
+void Sequence::revcomp (const Alphabet& alphabet, bool (*is_gap_char) (char) /* = NULL */) {
+
+ alphabet.revcomp (seq, is_gap_char);
+
+}
+
+Sequence Sequence::revcomp (const Alphabet& alphabet, bool (*is_gap_char) (char) /* = NULL */) const {
+
+ Sequence sequence = *this;
+ sequence.revcomp (alphabet, is_gap_char);
+ return sequence;
+
+}
+
+Translated_sequence::Translated_sequence (const Sequence& orig_seq)
+ : orig_seq (orig_seq),
+ __alphabet (DNA_alphabet()) { // impose DNA alphabet
+
+ __forward.resize (3);
+ __reverse.resize (3);
+
+ // size strings for all reading frames for speed
+ const unsigned rem = orig_seq.length() % 3;
+ const unsigned len = (orig_seq.length() - rem) / 3;
+ for (size_t frame = 0; frame < 3; ++frame) {
+ // calculate length for this frame
+ const size_t l = len - ((static_cast<int> (rem) - static_cast<int> (frame)) >= 0 ? 0 : 1); // remember possibility of overhang at end
+ __forward[frame].reserve (l);
+ __reverse[frame].reserve (l);
+ }
+
+ // forward strand
+ unsigned zero;
+ unsigned one = __alphabet.get_char_index (orig_seq.seq[0]); // initialize to "previous" values from fake last frame
+ unsigned two = __alphabet.get_char_index (orig_seq.seq[1]);
+ for (size_t i = 2; i < orig_seq.length(); ++i) {
+
+ // get amino acid
+ zero = one; // increment frame
+ one = two;
+ two = __alphabet.get_char_index (orig_seq.seq[i]); // and get new character
+ const char ch = __codon_map[zero][one][two];
+
+ // get frame and position in translated sequence
+ const unsigned frame = (i - 2) % 3; // because we begin at frame 0 but i = 2
+
+ // store character
+ __forward[frame] += ch;
+
+ }
+
+ // reverse strand
+ std::string orig_seq_revcomp = __alphabet.revcomp (orig_seq.seq);
+
+ one = __alphabet.get_char_index (orig_seq_revcomp[0]); // initialize to "previous" values from fake last frame
+ two = __alphabet.get_char_index (orig_seq_revcomp[1]);
+ for (size_t i = 2; i < orig_seq.length(); ++i) {
+
+ // get amino acid
+ zero = one; // increment frame
+ one = two;
+ two = __alphabet.get_char_index (orig_seq_revcomp[i]); // and get new character
+ const char ch = __codon_map[zero][one][two];
+
+ // get frame and position in translated sequence
+ const unsigned frame = (i - 2) % 3; // because we begin at frame 0 but i = 2
+
+ // store character
+ __reverse[frame] += ch;
+
+ }
+
+}
+
+void Sequence::init_hardmasking (size_t min_hardmask_length, bool (*is_hardmask_char) (char)) {
+
+ // mark sequence as hardmasked
+ __is_hardmasked = true;
+
+ // find hardmasked intervals
+ bool in_run = false;
+ size_t start = 0;
+ size_t len = 0;
+ for (size_t i = 0; i < seq.length(); ++i) {
+ if (is_hardmask_char (seq[i])) {
+ // if just started a run of hardmasked characters
+ if (!in_run) {
+ start = i;
+ len = 0;
+ in_run = true;
+ }
+ // increment length of run
+ ++len;
+ }
+ else {
+ // if just ended a run
+ if (in_run) {
+ // store if meets length criteria
+ if (len >= min_hardmask_length)
+ __masked_intervals.push_back (Interval (start, i - 1)); // -1 b/c now outside of run
+ in_run = false;
+ }
+ }
+ }
+
+ // check for case of ending in a run
+ if (in_run) {
+ // store if meets length criteria
+ if (len >= min_hardmask_length)
+ __masked_intervals.push_back (Interval (start, seq.length()));
+ }
+
+}
+
+Sequence Sequence::get_stripped_sequence() const {
+
+ if (!__is_hardmasked) {
+ cerr << "ERROR: Sequence isn't hardmasked." << endl;
+ exit (1);
+ }
+
+ // handle case of no masked intervals
+ if (!__masked_intervals.size())
+ return *this;
+
+ std::string stripped;
+
+ // iterate over masked intervals, avoiding them as we go
+ size_t start = 0;
+ for (std::vector<Interval>::const_iterator iter = __masked_intervals.begin(); iter != __masked_intervals.end(); ++iter) {
+ for (size_t i = start; i < iter->start; ++i)
+ stripped += seq[i];
+ start = iter->end + 1;
+ }
+ // catch the sequence past the last interval
+ for (size_t i = __masked_intervals.back().end + 1; i < seq.length(); ++i)
+ stripped += seq[i];
+
+ return Sequence (name, stripped, info);
+
+}
+
+bool Sequence::is_pos_hardmasked (const unsigned orig_pos) const {
+
+ if (!__is_hardmasked) {
+ cerr << "ERROR: Sequence isn't hardmasked." << endl;
+ exit (1);
+ }
+
+ for (std::vector<Interval>::const_iterator iter = __masked_intervals.begin(); iter != __masked_intervals.end(); ++iter) {
+ if ((orig_pos >= iter->start) && (orig_pos <= iter->end))
+ return true;
+ }
+
+ return false;
+}
+
+unsigned Sequence::map_stripped_to_orig (const unsigned pos) const {
+
+ if (!__is_hardmasked) {
+ cerr << "ERROR: Sequence isn't hardmasked." << endl;
+ exit (1);
+ }
+
+ size_t orig_pos = pos;
+ for (std::vector<Interval>::const_iterator iter = __masked_intervals.begin(); iter != __masked_intervals.end(); ++iter) {
+
+ // have we found it?
+ // (is it before this interval begins?)
+ if (orig_pos < iter->start)
+ return orig_pos;
+
+ // if position is past this masked interval,
+ // increment offset appropriately
+ if (orig_pos >= iter->start)
+ orig_pos += iter->end - iter->start + 1;
+
+ }
+
+ // check sane
+ if (orig_pos >= seq.length()) {
+ cerr << "map_stripped_to_orig: mapped " << pos << " -> " << orig_pos << "; seqlen = " << seq.length() << endl;
+ }
+ assert (orig_pos < seq.length());
+
+ return orig_pos;
+
+}
+
+unsigned Sequence::map_orig_to_stripped (const unsigned orig_pos) const {
+
+ if (!__is_hardmasked) {
+ cerr << "ERROR: Sequence isn't hardmasked." << endl;
+ exit (1);
+ }
+
+ // sanity check
+ assert (orig_pos < (*this).length());
+
+ // loop over the masked intervals,
+ // subtracting their length as we go
+ size_t pos = orig_pos;
+ for (std::vector<Interval>::const_iterator iter = __masked_intervals.begin(); iter != __masked_intervals.end(); ++iter) {
+
+ // return out-of-bounds answer if original coordinate
+ // falls within a masked interval
+ if ((orig_pos >= iter->start) && (orig_pos <= iter->end))
+ return seq.length();
+
+ // have we reached the original coordinate?
+ if (orig_pos < iter->start)
+ return pos;
+
+ pos -= iter->length();
+
+ }
+
+ return pos;
+
+}
+
+void Sequence::write_fasta (std::ostream& o) const {
+
+ o << fasta_seq_start << name
+ << (info.length() ? (' ' + info) : "") << endl
+ << seq << endl;
+
+}
+
+Sequence_database::Sequence_database (const Sequence_database& parent) {
+
+ // deep copy
+ for (std::vector<Sequence*>::const_iterator sequence = parent.__sequences.begin(); sequence != parent.__sequences.end(); ++sequence) {
+ Sequence* s = new Sequence (**sequence);
+ __sequences.push_back (s);
+ }
+
+ __sequence_index = parent.__sequence_index;
+
+}
+
+Sequence_database& Sequence_database::operator= (const Sequence_database& parent) {
+
+ // check for self-assignment
+ if (this == &parent)
+ return *this;
+
+ // clear old memory
+ this->clear();
+
+ // perform deep copy
+ for (std::vector<Sequence*>::const_iterator sequence = parent.__sequences.begin(); sequence != parent.__sequences.end(); ++sequence) {
+ Sequence* s = new Sequence (**sequence);
+ __sequences.push_back (s);
+ }
+
+ __sequence_index = parent.__sequence_index;
+
+ return *this;
+
+}
+
+Sequence_database::~Sequence_database() {
+
+ for (std::vector<Sequence*>::iterator sequence = __sequences.begin(); sequence != __sequences.end(); ++sequence)
+ delete *sequence;
+
+}
+
+void Sequence_database::read_fasta (const std::string& filename, bool (*is_gap_char) (char) /* = NULL */,
+ const bool strip_leading_chr /* = true */,
+ const bool verbose /* = true */) {
+
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ if (verbose)
+ cerr << "Reading FASTA-format sequence file '" << filename << "'...";
+
+ Regexp re_name ("^[ \t]*" + Sequence::fasta_seq_start + "([^ \t]*)[ \t]*(.*)");
+
+ std::string line;
+
+ std::vector<std::string> seqs_names;
+ std::vector<std::string> seqs;
+ std::vector<std::string> seqs_info;
+
+ bool in_seq_body = false;
+ size_t curr_idx = 0; // dummy value to prevent compiler warnings
+ while (!filestream.eof()) {
+
+ getline (filestream, line);
+
+ // are we at a name line?
+ if (re_name.Match (line.c_str())) {
+ if (re_name.SubStrings() < 1) { continue; }
+ // store name
+ const std::string name = re_name[1];
+ curr_idx = seqs_names.size();
+ seqs_names.push_back (name);
+ // store info following name, if present
+ std::string info;
+ if (re_name.SubStrings() >= 2)
+ info = re_name[2];
+ seqs_info.push_back (info);
+ // store empty sequence
+ seqs.push_back ("");
+ in_seq_body = true;
+ }
+ // if not, then we must be reading sequence data
+ else if (in_seq_body) {
+ // if this is the first line of data for this sequence
+ if (seqs.size() < seqs_names.size())
+ seqs.push_back (line);
+ else
+ seqs[curr_idx] += line;
+ }
+
+ }
+ filestream.close();
+
+ // assert sane
+ if (seqs.size() != seqs_names.size()) {
+ cerr << "ERROR: Sequence names and data don't match up. Is your FASTA file improperly formatted?" << endl;
+ exit (1);
+ }
+ assert (seqs_names.size() == seqs_info.size());
+
+ // now store
+ for (size_t i = 0; i < seqs_names.size(); ++i) {
+
+ std::string& name = seqs_names[i];
+ std::string& seq = seqs[i];
+ std::string& info = seqs_info[i];
+
+ // remove leading chr if requested and present
+ if (strip_leading_chr)
+ Util::strip_leading_chr (name);
+
+ // strip out whitespace
+ std::string::iterator last_pos = std::remove_if (seq.begin(), seq.end(),
+ isspace);
+ seq.erase (last_pos, seq.end());
+
+ // strip out gaps if requested
+ if (is_gap_char != 0) {
+ last_pos = std::remove_if (seq.begin(), seq.end(),
+ is_gap_char);
+ seq.erase (last_pos, seq.end());
+ }
+
+ // remove newline from info, if present
+ Util::chomp (info);
+
+ // store sequence
+ Sequence* sequence = new Sequence (name, seq, info);
+ add_seq (sequence);
+ }
+
+ if (verbose)
+ cerr << "done." << endl;
+
+}
+
+void Sequence_database::write_fasta (std::ostream& o) const {
+
+ for (std::vector<Sequence*>::const_iterator seq = this->begin(); seq != this->end(); ++seq)
+ (*seq)->write_fasta (o);
+
+}
+
+void Sequence_database::add_seq (Sequence* sequence) {
+
+ if (exists_seq (sequence->name)) {
+ cerr << "ERROR: Duplicate sequence name '" << sequence->name << "'; this is forbidden." << endl
+ << "Note that descriptions following the sequence names are not considered part of the names themselves." << endl;
+ exit (1);
+ }
+ __sequences.push_back (sequence);
+ __sequence_index.insert (std::make_pair (sequence->name, __sequences.size() - 1));
+
+}
+
+void Sequence_database::add_seq (const Sequence& sequence) {
+
+ if (exists_seq (sequence.name)) {
+ cerr << "ERROR: Duplicate sequence name '" << sequence.name << "'; this is forbidden." << endl
+ << "Note that descriptions following the sequence names are not considered part of the names themselves." << endl;
+ exit (1);
+ }
+
+ Sequence* sequence_p = new Sequence (sequence);
+ __sequences.push_back (sequence_p);
+ __sequence_index.insert (std::make_pair (sequence.name, __sequences.size() - 1));
+
+}
+
+void Sequence_database::revcomp (const Alphabet& alphabet, bool (*is_gap_char) (char) /* = NULL */) {
+
+ for (std::vector<Sequence*>::iterator seq = this->begin(); seq != this->end(); ++seq)
+ (*seq)->revcomp (alphabet, is_gap_char);
+
+}
+
+bool Sequence_database::matches_alphabet (const Alphabet& alphabet, const double threshold /* = 0.95 */) const {
+
+ size_t matches = 0;
+ size_t total = 0;
+
+ for (size_t i = 0; i < size(); ++i) {
+ const Sequence& sequence = get_seq (i);
+ total += sequence.length();
+
+ for (std::string::const_iterator s = sequence.seq.begin(); s != sequence.seq.end(); ++s) {
+ if (alphabet.is_nondegen_char (*s) || alphabet.is_unknown_char (*s))
+ ++matches;
+ }
+
+ }
+
+ // catch case of no sequence
+ if (total == 0)
+ return true;
+
+ const double frac = static_cast<double> (matches) / total;
+
+ if (frac >= threshold) {
+ cerr << "Sequences match a " << alphabet.name() << " alphabet." << endl;
+ return true;
+ }
+
+ return false;
+}
+
+void Sequence_database::clear() {
+
+ for (std::vector<Sequence*>::iterator sequence = __sequences.begin(); sequence != __sequences.end(); ++sequence)
+ delete *sequence;
+ __sequences.clear();
+
+ __sequence_index.clear();
+
+}
+
+size_t Sequence_database::meanlength() const {
+
+ size_t total = 0;
+ for (size_t i = 0; i < size(); ++i) {
+ const Sequence& sequence = get_seq (i);
+ total += sequence.length();
+ }
+
+ return static_cast<size_t> (total / size());
+
+}
+
+size_t Sequence_database::median_length() const {
+
+ std::vector<size_t> lengths (size());
+ for (size_t i = 0; i < size(); ++i)
+ lengths[i] = get_seq (i).length();
+
+ return Mathematics::median (lengths);
+
+}
+
+std::vector<std::string> Sequence_database::get_sequence_list() const {
+
+ std::vector<std::string> names;
+ for (std::vector<Sequence*>::const_iterator sequence = begin(); sequence != end(); ++sequence)
+ names.push_back ((*sequence)->name);
+
+ return names;
+
+}
+
+Sequence_database Sequence_database::translate() const {
+
+ Sequence_database tr_db;
+
+ // store first reading frame of forward strand
+ for (size_t i = 0; i < this->size(); ++i) {
+ const Sequence& sequence = get_seq (i);
+ Translated_sequence tr (sequence);
+ Sequence* forward = new Sequence (tr.get_forward (0));
+ tr_db.add_seq (forward);
+ }
+
+ return tr_db;
+
+}
diff --git a/src/seq/sequence.h b/src/seq/sequence.h
new file mode 100644
index 0000000..6d623b5
--- /dev/null
+++ b/src/seq/sequence.h
@@ -0,0 +1,506 @@
+
+/**
+ * \file sequence.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef SEQ_SEQUENCE_INCLUDED
+#define SEQ_SEQUENCE_INCLUDED
+
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <map>
+
+#include "util/misc.h"
+#include "seq/alphabet.h"
+#include "seq/interval.h"
+
+namespace fsa {
+
+ /**
+ * \brief Represent a single named sequence.
+ *
+ * Coordinates are 0-based.
+ * Interavls are always fully-closed, [start, end].
+ */
+ struct Sequence {
+
+ public:
+
+ std::string name; ///< sequence name
+ std::string seq; ///< sequence itself
+ std::string info; ///< free-form information which comes after the name in a FASTA file
+
+ /**
+ * \brief Default constructor.
+ */
+ Sequence() { }
+
+ /**
+ * \brief Constructor.
+ */
+ Sequence (const std::string& name, const std::string& seq);
+
+ /**
+ * \brief Constructor.
+ */
+ Sequence (const std::string& name, const std::string& seq,
+ const std::string& info);
+
+ /**
+ * \brief Detect whether a file seems to be in FASTA format.
+ */
+ static bool detect_fasta (const std::string& filename);
+
+ /**
+ * \brief Write sequence in FASTA format.
+ */
+ void write_fasta (std::ostream& o) const;
+
+ /**
+ * \brief Get sequence length.
+ */
+ inline size_t length() const { return seq.length(); }
+
+ /**
+ * \brief Append sequence data.
+ */
+ inline void append (const std::string& s) { seq += s; }
+
+ /**
+ * \brief Get subsequence.
+ *
+ */
+ Sequence* subsequence (const unsigned start, const unsigned end) const;
+
+ /**
+ * \brief Reverse-complement sequence under the passed alphabet.
+ *
+ * If requested, ignores gap characters as defined by the passed function.
+ * \param alphabet Alphabet to reverse-complement under
+ * \param is_gap_char function pointer defining a gap character
+ */
+ void revcomp (const Alphabet& alphabet, bool (*is_gap_char) (char) = NULL);
+
+ /**
+ * \brief Reverse-complement sequence under the passed alphabet.
+ */
+ Sequence revcomp (const Alphabet& alphabet, bool (*is_gap_char) (char) = NULL) const;
+
+ /**
+ * \brief Complement a strand.
+ */
+ inline static void complement_strand (char& strand);
+
+ /**
+ * \brief Initialize hardmasking by finding hardmasked intervals in original sequence.
+ *
+ * \param min_hardmask_length minimum length of hardmasked sequence to strip out
+ * \param is_hardmask_char function pointer defining a hardmasked character
+ */
+ void init_hardmasking (size_t min_hardmask_length, bool (*is_hardmask_char) (char));
+
+ /**
+ * \brief Is the sequence at a position hardmasked?
+ */
+ bool is_pos_hardmasked (const unsigned orig_pos) const;
+
+ /**
+ * \brief Map coordinates from stripped sequence back to original sequence.
+ *
+ * Uses a linear-time search over the masked intervals.
+ * NB: The coordinate mappings could be made faster with a binary search.
+ */
+ unsigned map_stripped_to_orig (const unsigned pos) const;
+
+ /**
+ * \brief Map coordinates from original sequence to stripped sequence.
+ *
+ * Uses a linear-time search over the masked intervals.
+ * Returns sequence length (out of bounds)
+ * if the coordinate falls in a masked interval.
+ */
+ unsigned map_orig_to_stripped (const unsigned pos) const;
+
+ /**
+ * \brief Strip out hardmasked sequence.
+ */
+ Sequence get_stripped_sequence() const;
+
+
+
+ static const std::string fasta_seq_start; ///< designate sequence name in FASTA files
+
+
+ private:
+
+ bool __is_hardmasked; ///< is this sequence hardmasked?
+
+ /**
+ * \brief coordinates of hardmasked intervals
+ *
+ * 0-based, fully-closed coordinates [start, end].
+ */
+ std::vector<Interval> __masked_intervals;
+
+
+ };
+
+ /**
+ * \brief Represent a translated nucleotide sequence.
+ *
+ * Assumes and enforces a non-degenerate DNA alphabet:
+ * Degenerate characters are randomized and a DNA alphabet is imposed.
+ */
+ struct Translated_sequence {
+
+ public:
+
+ /**
+ * \brief constructor
+ */
+ Translated_sequence (const Sequence& orig_seq);
+
+ /**
+ * \brief Get translated sequence on forward strand.
+ * \param frame reading frame 0, 1, 2
+ */
+ inline Sequence get_forward (const unsigned frame) const {
+ assert (frame < 3);
+ return Sequence (orig_seq.name, __forward[frame], orig_seq.info);
+ }
+
+ /**
+ * \brief Get translated sequence on reverse strand.
+ */
+ inline Sequence get_reverse (const unsigned frame) const {
+ assert (frame < 3);
+ return Sequence (orig_seq.name, __reverse[frame], orig_seq.info);
+ }
+
+ /**
+ * \brief Map a coordinate in a translated sequence back to the position in the original sequence.
+ *
+ * All coordinates are assumed to be 0-based.
+ * Maps back to the first nucleotide of the corresponding codon.
+ * \param forward true for forward strand, false for reverse
+ * \param frame reading frame (0, 1 or 2)
+ * \param pos position in translated sequence
+ * \return position in original sequence
+ */
+ inline unsigned map_coords_to_orig (const bool forward, const unsigned frame, const unsigned pos) const;
+
+ /**
+ * \brief Map an interval in a translated sequence back to the interval in the original sequence.
+ *
+ * All coordinates are assumed to be 0-based.
+ * Maps back to the first nucleotide of first corresponding codon and last nucleotide of the last codon.
+ * \param forward true for forward strand, false for reverse
+ * \param frame reading frame (0, 1 or 2)
+ * \param interval position in translated sequence
+ * \return interval in original sequence
+ */
+ inline Interval map_interval_to_orig (const bool forward, const unsigned frame, const Interval& interval) const;
+
+ private:
+
+ static const char __codon_map[4][4][4]; ///< map from codons to amino acids
+
+ const Sequence& orig_seq; ///< original sequence
+ const Alphabet __alphabet; ///< DNA alphabet
+
+ std::vector<std::string> __forward; ///< 3 reading frames of forward strand
+ std::vector<std::string> __reverse; ///< 3 reading frames of reverse strand
+
+ };
+
+ /**
+ * \brief Represent a set of sequences.
+ *
+ * This container holds all sequence data,
+ * and as such should be instantiated at the "top" of a program.
+ */
+ struct Sequence_database {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ Sequence_database() { }
+ Sequence_database (const Sequence_database& parent);
+ Sequence_database& operator= (const Sequence_database& parent);
+
+ /**
+ * \brief Destructor.
+ */
+ ~Sequence_database();
+
+ /**
+ * \brief Read a FASTA-format file.
+ *
+ * Strips out whitespace. Strips out gaps if requested with, e.g.,
+ * seq_db.read_fasta ("rob.fasta", Alignment::is_gap_char)
+ * Does NOT clear sequence data; this method can therefore be
+ * used to read a series of different files into the same Sequence_database.
+ * \param is_gap_char function pointer defining a gap character
+ * \param strip_leading_chr strips the leading 'chr', if present, from the sequence names
+ */
+ void read_fasta (const std::string& filename, bool (*is_gap_char) (char) = NULL,
+ const bool strip_leading_chr = true,
+ const bool verbose = true);
+
+ /**
+ * \brief Write in FASTA format.
+ */
+ void write_fasta (std::ostream& o) const;
+
+ /**
+ * \brief Add sequence to database.
+ */
+ void add_seq (Sequence* sequence);
+
+ /**
+ * \brief Add sequence to database.
+ *
+ * Note that this method creates a copy of the passed sequence!
+ */
+ void add_seq (const Sequence& sequence);
+
+ /**
+ * \brief Append sequence data.
+ * \param name sequence name
+ * \param seq sequence data to append
+ */
+ inline void append_seq (const std::string& name, const std::string& seq);
+
+ /**
+ * \brief Does a sequence exist in the database?
+ */
+ inline bool exists_seq (const std::string& name) const;
+
+ /**
+ * \brief Get sequence from database.
+ */
+ inline const Sequence& get_seq (const std::string& name) const;
+
+ /**
+ * \brief Get sequence from database.
+ */
+ inline Sequence& get_seq (const std::string& name);
+
+ /**
+ * \brief Get sequence from database.
+ * \param i index of sequence in database
+ */
+ inline const Sequence& get_seq (const size_t i) const;
+
+ /**
+ * \brief Get sequence from database.
+ * \param i index of sequence in database
+ */
+ inline Sequence& get_seq (const size_t i);
+
+ /**
+ * \brief Get index of sequence in database.
+ *
+ * Sequences are indexed according to the order in which they were first stored.
+ */
+ inline size_t get_seq_index (const std::string& name) const;
+
+ /**
+ * \brief Reverse-complement sequences under the passed alphabet.
+ *
+ * If requested, ignores gap characters as defined by the passed function.
+ * \param alphabet Alphabet to reverse-complement under
+ * \param is_gap_char function pointer defining a gap character
+ */
+ void revcomp (const Alphabet& alphabet, bool (*is_gap_char) (char) = NULL);
+
+ /**
+ * \brief Do the sequences appear to match a particular alphabet?
+ * \param alphabet alphabet to match against
+ * \param threshold fraction of sequence characters required to match alphabet
+ * \return match >= 0.95 to alphabet, or true if Sequence_database is empty
+ */
+ bool matches_alphabet (const Alphabet& alphabet, const double threshold = 0.95) const;
+
+ /**
+ * \brief Number of sequences in database.
+ */
+ size_t size() const { return __sequences.size(); }
+
+ /**
+ * \brief Average length of sequences in database.
+ */
+ size_t meanlength() const;
+
+ /**
+ * \brief Median length of sequences in database.
+ */
+ size_t median_length() const;
+
+ /**
+ * \brief Clear all sequence data.
+ */
+ void clear();
+
+ /**
+ * \brief Get list of names of all sequences in database.
+ */
+ std::vector<std::string> get_sequence_list() const;
+
+ /**
+ * \brief Translate all sequences.
+ *
+ * "Overhangs" (incomplete codons at the end of the sequence) are dropped.
+ * \return the translated database
+ */
+ Sequence_database translate() const;
+
+ /**
+ * \brief Get iterator to start of __sequences.
+ */
+ std::vector<Sequence*>::iterator begin() {
+ return __sequences.begin();
+ }
+
+ /**
+ * \brief Get iterator to start of __sequences.
+ */
+ std::vector<Sequence*>::const_iterator begin() const {
+ return __sequences.begin();
+ }
+
+ /**
+ * \brief Get iterator to end of __sequences.
+ */
+ std::vector<Sequence*>::iterator end() {
+ return __sequences.end();
+ }
+
+ /**
+ * \brief Get iterator to end of __sequences.
+ */
+ std::vector<Sequence*>::const_iterator end() const {
+ return __sequences.end();
+ }
+
+
+ private:
+
+ std::vector<Sequence*> __sequences; ///< sequences
+ std::map<std::string, size_t> __sequence_index; ///< lookup index in *this from sequence name
+
+ };
+
+
+
+
+ /****************************************
+ * Function definitions.
+ ****************************************/
+
+ inline void Sequence::complement_strand (char& strand) {
+
+ if (strand == '+')
+ strand = '-';
+ else if (strand == '-')
+ strand = '+';
+
+ }
+
+ inline unsigned Translated_sequence::map_coords_to_orig (const bool forward, const unsigned frame, const unsigned pos) const {
+
+ unsigned orig_pos;
+ if (forward)
+ orig_pos = (3 * pos + frame);
+ else
+ orig_pos = (orig_seq.length() - 1) - (3 * pos + frame); // - 1 because 0-based coordinates
+
+ assert (orig_pos < orig_seq.length());
+
+ return orig_pos;
+
+ }
+
+ inline Interval Translated_sequence::map_interval_to_orig (const bool forward, const unsigned frame, const Interval& interval) const {
+
+ assert (interval.start <= interval.end);
+
+ Interval orig_interval;
+ if (forward) {
+ orig_interval.start = map_coords_to_orig (forward, frame, interval.start); // first nt of first codon
+ orig_interval.end = map_coords_to_orig (forward, frame, interval.end) + 2; // last nt of last codon
+ }
+ else {
+ // for reverse strand:
+ // first nt of first codon on forward strand is last nt of last codon in revcomp'ed sequence
+ orig_interval.start = map_coords_to_orig (forward, frame, interval.end) - 2;
+ orig_interval.end = orig_interval.start + 3 * (interval.end - interval.start + 1) - 1; // remember 0-based coordinates
+ }
+
+ assert (orig_interval.start <= orig_interval.end);
+ assert (orig_interval.end < orig_seq.length());
+
+ return orig_interval;
+ }
+
+
+ inline bool Sequence_database::exists_seq (const std::string& name) const {
+
+ return (__sequence_index.find (name) != __sequence_index.end());
+
+ }
+
+ inline size_t Sequence_database::get_seq_index (const std::string& name) const {
+ assert (exists_seq (name));
+ return __sequence_index.find (name)->second;
+ }
+
+ inline const Sequence& Sequence_database::get_seq (const std::string& name) const {
+
+ assert (exists_seq (name));
+ return *__sequences[__sequence_index.find (name)->second];
+
+ }
+
+ inline Sequence& Sequence_database::get_seq (const std::string& name) {
+
+ assert (exists_seq (name));
+ return *__sequences[__sequence_index.find (name)->second];
+
+ }
+
+ inline const Sequence& Sequence_database::get_seq (const size_t i) const {
+
+ assert (i < __sequences.size());
+ return *__sequences[i];
+
+ }
+
+ inline Sequence& Sequence_database::get_seq (const size_t i) {
+
+ assert (i < __sequences.size());
+ return *__sequences[i];
+
+ }
+
+ inline void Sequence_database::append_seq (const std::string& name, const std::string& seq) {
+ if (!exists_seq (name)) {
+ Sequence* sequence = new Sequence (name, seq);
+ add_seq (sequence);
+ }
+ else
+ get_seq (name).append (seq);
+ return;
+ }
+
+}
+
+#endif /* SEQ_SEQUENCE_INCLUDED */
diff --git a/src/seq/similarity_matrix.cc b/src/seq/similarity_matrix.cc
new file mode 100644
index 0000000..0d6be11
--- /dev/null
+++ b/src/seq/similarity_matrix.cc
@@ -0,0 +1,204 @@
+
+/**
+ * \file similarity_matrix.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include <iostream>
+#include <iomanip>
+
+#include "math/mathematics.h"
+#include "seq/similarity_matrix.h"
+
+using namespace fsa;
+
+Sequence_kmer_counts::Sequence_kmer_counts (const Alphabet& alphabet,
+ const size_t k)
+ : __alphabet (alphabet),
+ __k (k),
+ __num_words (fsa::Mathematics::power_of_integer (__alphabet.size(), __k)) {
+
+ // pre-compute necessary powers of alphabet size
+ __powers_of_alphabet_size.resize (__k);
+ for (size_t i = 0; i < k; ++i)
+ __powers_of_alphabet_size[i] = Mathematics::power_of_integer (__alphabet.size(), i);
+
+}
+
+Sequence_kmer_counts::Kmer_counts Sequence_kmer_counts::compute_counts (const Sequence& sequence) const {
+
+ Sequence_kmer_counts::Kmer_counts kmer_counts;
+
+ // if the sequence is shorter than k, then return
+ if (sequence.length() < k())
+ return kmer_counts;
+
+ // iterate over positions in the sequence, storing counts as we go
+ for (size_t i = 0; i <= sequence.length() - k() + 1; ++i) {
+
+ const Sequence_kmer_counts::Kmer_index index = kmer_to_index (sequence.seq, i);
+
+ // if this word contains a character which isn't in the alphabet,
+ // then don't store any information
+ if (index == num_words())
+ continue;
+
+ // else store count
+ else
+ ++kmer_counts[index];
+
+ }
+
+ return kmer_counts;
+
+}
+
+size_t Sequence_kmer_counts::choose_minimum_word_length (const Sequence_database& seq_db,
+ const Alphabet& alphabet) {
+
+ const size_t medianlen = seq_db.median_length();
+ const size_t bestk = 1 + static_cast<size_t> (std::log (static_cast<double> (medianlen))
+ / std::log (static_cast<double> (alphabet.size())));
+
+ if (bestk > 0)
+ return bestk;
+ else
+ return 1;
+
+}
+
+Sequence_similarity_matrix::Sequence_similarity_matrix (const Sequence_database& seq_db,
+ const Alphabet& alphabet,
+ const size_t k)
+ : __seq_db (seq_db),
+ __similarities (seq_db.size(), std::vector<double> (seq_db.size(), 0.)) {
+
+ compute_kmer_similarity_matrix (seq_db,
+ alphabet,
+ k);
+
+}
+
+size_t Sequence_similarity_matrix::compute_kmer_similarity (const Sequence_kmer_counts::Kmer_counts& counts_x, const Sequence_kmer_counts::Kmer_counts& counts_y) {
+
+ size_t count = 0;
+
+ // for speed, loop over the smaller set of k-mers
+ if (counts_x.size() < counts_y.size()) {
+
+ // for each k-mer in X
+ for (Sequence_kmer_counts::Kmer_counts::const_iterator kmer_count_x = counts_x.begin(); kmer_count_x != counts_x.end(); ++kmer_count_x) {
+ Sequence_kmer_counts::Kmer_counts::const_iterator kmer_count_y = counts_y.find (kmer_count_x->first);
+ if (kmer_count_y != counts_y.end())
+ count += std::min (kmer_count_x->second, kmer_count_y->second);
+ }
+
+ }
+
+ else {
+
+ // for each k-mer in Y
+ for (Sequence_kmer_counts::Kmer_counts::const_iterator kmer_count_y = counts_y.begin(); kmer_count_y != counts_y.end(); ++kmer_count_y) {
+ Sequence_kmer_counts::Kmer_counts::const_iterator kmer_count_x = counts_x.find (kmer_count_y->first);
+ if (kmer_count_x != counts_x.end())
+ count += std::min (kmer_count_x->second, kmer_count_y->second);
+ }
+
+ }
+
+ return count;
+
+}
+
+void Sequence_similarity_matrix::write (std::ostream& o) const {
+
+ // figure out an appropriate width based on the longest sequence name
+ size_t width = 8;
+ for (size_t i = 0; i < __seq_db.size(); ++i)
+ width = std::max (width, __seq_db.get_seq (i).name.length() + 2);
+
+ // precision of floating-point output
+ const size_t precision = 3;
+
+ // write header
+ o.width (width); o << "";
+ for (size_t i = 0; i < __similarities.size(); ++i) {
+ o.width (width);
+ o << __seq_db.get_seq (i).name;
+ }
+ o << endl;
+
+ // matrix itself
+ for (size_t i = 0; i < __similarities.size(); ++i) {
+ o.width (width);
+ o << __seq_db.get_seq (i).name;
+ for (size_t j = 0; j < __similarities.size(); ++j) {
+ o.width (width);
+ if (i == j)
+ o << "";
+ else
+ o << std::setprecision (precision) << get_similarity (i, j);
+ }
+ o << endl;
+ }
+
+}
+
+void Sequence_similarity_matrix::compute_kmer_similarity_matrix (const Sequence_database& seq_db,
+ const Alphabet& alphabet,
+ const size_t k) {
+
+ // check sane
+ assert (seq_db.size() > 1);
+ assert (seq_db.matches_alphabet (alphabet));
+
+ // initialize appropriate Sequence_kmer_counts object
+ const Sequence_kmer_counts counter (alphabet, k);
+
+ // accumulate k-mer counts for each sequence
+ std::vector<Sequence_kmer_counts::Kmer_counts> kmer_counts_db (seq_db.size());
+ for (size_t i = 0; i < seq_db.size(); ++i)
+ kmer_counts_db[i] = counter.compute_counts (seq_db.get_seq (i));
+
+ // compute similarities
+ assert (__similarities.size() == seq_db.size());
+ for (size_t i = 0; i < seq_db.size(); ++i) {
+
+ // check sane
+ assert (__similarities[i].size() == seq_db.size());
+
+ // set diagonal entries to one
+ __similarities[i][i] = 1;
+
+ // catch the case of a 0-length sequence
+ if (seq_db.get_seq (i).length() == 0)
+ continue;
+
+ for (size_t j = i + 1; j < seq_db.size(); ++j) {
+
+ // catch the case of a 0-length sequence
+ if (seq_db.get_seq (j).length() == 0)
+ continue;
+
+ // compute k-mer similarity and normalize with the length of the shorter sequence
+ __similarities[i][j] = static_cast<double> (compute_kmer_similarity (kmer_counts_db[i], kmer_counts_db[j]));
+ __similarities[i][j] /=
+ (std::min (seq_db.get_seq (i).length(), seq_db.get_seq (j).length()) >= k)
+ ? std::min (seq_db.get_seq (i).length(), seq_db.get_seq (j).length()) - (k - 1)
+ : std::min (seq_db.get_seq (i).length(), seq_db.get_seq (j).length());
+
+ // matrix is symmetric
+ __similarities[j][i] = __similarities[i][j];
+
+ // check sane
+ if (__similarities[i][j] < 0.)
+ cerr << __similarities[i][j] << endl;
+ assert (__similarities[i][j] >= 0.);
+ assert (__similarities[i][j] <= 1. + Mathematics::double_very_tiny);
+
+ }
+
+ }
+
+}
diff --git a/src/seq/similarity_matrix.h b/src/seq/similarity_matrix.h
new file mode 100644
index 0000000..9746c8e
--- /dev/null
+++ b/src/seq/similarity_matrix.h
@@ -0,0 +1,198 @@
+
+/**
+ * \file similarity_matrix.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef SEQ_SIMILARITY_MATRIX_INCLUDED
+#define SEQ_SIMILARITY_MATRIX_INCLUDED
+
+#include "util/misc.h"
+#include "seq/alphabet.h"
+#include "seq/sequence.h"
+
+namespace fsa {
+
+ /**
+ * \brief Compute k-mer statistics of sequences.
+ */
+ struct Sequence_kmer_counts {
+
+ public:
+
+ typedef uintmax_t Kmer_index; ///< numerical index of a k-mer
+ typedef std::map<Kmer_index, size_t> Kmer_counts; ///< k-mer counts for a sequence
+
+ /**
+ * Constructor.
+ * \param k word length
+ */
+ Sequence_kmer_counts (const Alphabet& alphabet,
+ const size_t k);
+
+ /**
+ * \brief Compute the k-mer counts of a sequence.
+ */
+ Kmer_counts compute_counts (const Sequence& sequence) const;
+
+ /**
+ * \brief Compute the minimum word length (>= 1) appropriate for computing distances.
+ *
+ * Given a uniform distribution over characters of the alphabet, compute
+ * k = log_|A| (L) + 1, |A| = alphabet size
+ * the minimum word length such that the expected number of occurrences
+ * of a particular k-mer is < 1.
+ * The length L is the median length of the sequences.
+ */
+ static size_t choose_minimum_word_length (const Sequence_database& seq_db,
+ const Alphabet& alphabet);
+
+ /**
+ * \brief Get number of possible words.
+ *
+ * Note that this corresponds to 1 + the maximum index, e.g., a nonsense k-mer.
+ * \see kmer_to_index
+ */
+ Kmer_index num_words() const { return __num_words; }
+
+ /**
+ * \brief Length of words.
+ */
+ size_t k() const { return __k; }
+
+ private:
+
+ /**
+ * \brief Convert a substring of the passed string to the corresponding k-mer integral index.
+ *
+ * Considers the k-mer str.substr (start, __k).
+ * It is the responsibility of the calling function to ensure that the
+ * string boundaries are not overrun.
+ *
+ * \param str string to take a substring of
+ * \param start position (0-based) of the k-mer
+ * \return index or num_words() if the k-mer contains a character which is either degenerate or not in the alphabet
+ */
+ Kmer_index kmer_to_index (const std::string& str, const unsigned start) const;
+
+ Alphabet __alphabet; ///< alphabet which the k-mer are defined over
+ unsigned short __k; ///< word length
+ Kmer_index __num_words; ///< \see num_words
+
+ std::vector<size_t> __powers_of_alphabet_size; ///< \see kmer_to_index
+
+ };
+
+ /**
+ * \brief Represent a matrix of similarities between pairs of sequences based on k-mer counts.
+ */
+ struct Sequence_similarity_matrix {
+
+ public:
+
+ /**
+ * \brief Constructor.
+ */
+ Sequence_similarity_matrix (const Sequence_database& seq_db,
+ const Alphabet& alphabet,
+ const size_t k);
+
+ /**
+ * \brief Get the similarity between two sequences.
+ */
+ double get_similarity (const size_t i, const size_t j) const;
+
+ /**
+ * \brief Output method.
+ */
+ void write (std::ostream& o) const;
+
+ private:
+
+ /**
+ * \brief Compute the k-mer similarity between two sequences.
+ *
+ * Computed as:
+ * counts <- 0
+ * For each k-mer w in X
+ * counts += min (# instances of w in X, # instances of w in Y)
+ * (the outer loop is over k-mers of X or Y, depending upon which is the smaller set)
+ *
+ * \param counts_x k-mer counts for sequence X
+ * \param counts_y k-mer counts for sequence Y
+ */
+ static size_t compute_kmer_similarity (const Sequence_kmer_counts::Kmer_counts& counts_x, const Sequence_kmer_counts::Kmer_counts& counts_y);
+
+ /**
+ * \brief Compute the k-mer similarity matrix between all pairs of sequences.
+ *
+ * The similarity between two sequences is defined as the
+ * total number of shared k-mers divided by the length of the
+ * shortest sequence. We divide by the length of the shortest
+ * sequence to avoid a systematic bias towards longer sequences.
+ * Each entry in the similarity matrix therefore falls in the interval [0, 1].
+ * Sets diagonal entries (the similarities of sequences with themselves) to 1.
+ *
+ * \param seq_db sequences to consider
+ * \param alphabet alphabet over which sequences are defined
+ * \param k word length to use
+ * \see compute_kmer_similarity
+ */
+ void compute_kmer_similarity_matrix (const Sequence_database& seq_db,
+ const Alphabet& alphabet,
+ const size_t k);
+
+ const Sequence_database& __seq_db; ///< sequence data
+ std::vector<std::vector<double> > __similarities; ///< sequence similarity matrix
+
+ };
+
+ inline Sequence_kmer_counts::Kmer_index Sequence_kmer_counts::kmer_to_index (const std::string& str, const unsigned start) const {
+
+ // catch case of k = 0
+ if (k() == 0)
+ return 0;
+
+ // assert sane
+ assert (start + k() - 1 <= str.length());
+
+ Sequence_kmer_counts::Kmer_index index = 0;
+ for (size_t i = 0; i < k(); ++i) {
+
+ const char ch = str[start + i];
+
+ if (!__alphabet.is_nondegen_char (ch))
+ return num_words();
+
+ // exploit 2-bit representation of a DNA alphabet if possible (the hare)
+ if (__alphabet.size() == 4) {
+ index <<= 2; // because 2 bits per character
+ index |= __alphabet.get_char_index (ch);
+ }
+
+ // else do it with multiplication (the tortoise)
+ // (but not too slow, since we've hardcoded in powers of the alphabet size)
+ // note that the "backwards" vector indexing is so that the leftmost character,
+ // which we see first, corresponds to the largest power of the alphabet size
+ // (which is how the above bit-shifting works)
+ else
+ index += __alphabet.get_char_index (ch) * __powers_of_alphabet_size[k() - i - 1];
+
+ }
+
+ assert (index < num_words());
+
+ return index;
+
+ }
+
+ inline double Sequence_similarity_matrix::get_similarity (const size_t i, const size_t j) const {
+ assert (i < __similarities.size());
+ assert (j < __similarities.size());
+ return __similarities[i][j];
+ }
+
+}
+
+#endif /* SEQ_SIMILARITY_MATRIX_INCLUDED */
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
new file mode 100644
index 0000000..74948eb
--- /dev/null
+++ b/src/util/Makefile.am
@@ -0,0 +1,24 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+noinst_LIBRARIES = libutil.a
+libutil_a_SOURCES = \
+ dexception.cc \
+ logfile.cc \
+ memcheck.cc \
+ misc.cc \
+ opts_list.cc \
+ regexp.cc \
+ sstring.cc
+
+noinst_HEADERS = \
+ array2d.h \
+ dexception.h \
+ hash_fcn.h \
+ logfile.h \
+ logtags.h \
+ macros.h \
+ memcheck.h \
+ misc.h \
+ opts_list.h \
+ regexp.h \
+ sstring.h
diff --git a/src/util/Makefile.in b/src/util/Makefile.in
new file mode 100644
index 0000000..adde048
--- /dev/null
+++ b/src/util/Makefile.in
@@ -0,0 +1,570 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/util
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_ at AM_V@)
+am__v_AR_ = $(am__v_AR_ at AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libutil_a_AR = $(AR) $(ARFLAGS)
+libutil_a_LIBADD =
+am_libutil_a_OBJECTS = dexception.$(OBJEXT) logfile.$(OBJEXT) \
+ memcheck.$(OBJEXT) misc.$(OBJEXT) opts_list.$(OBJEXT) \
+ regexp.$(OBJEXT) sstring.$(OBJEXT)
+libutil_a_OBJECTS = $(am_libutil_a_OBJECTS)
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_ at AM_V@)
+am__v_CXX_ = $(am__v_CXX_ at AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_ at AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_ at AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(libutil_a_SOURCES)
+DIST_SOURCES = $(libutil_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src
+noinst_LIBRARIES = libutil.a
+libutil_a_SOURCES = \
+ dexception.cc \
+ logfile.cc \
+ memcheck.cc \
+ misc.cc \
+ opts_list.cc \
+ regexp.cc \
+ sstring.cc
+
+noinst_HEADERS = \
+ array2d.h \
+ dexception.h \
+ hash_fcn.h \
+ logfile.h \
+ logtags.h \
+ macros.h \
+ memcheck.h \
+ misc.h \
+ opts_list.h \
+ regexp.h \
+ sstring.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/util/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/util/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libutil.a: $(libutil_a_OBJECTS) $(libutil_a_DEPENDENCIES) $(EXTRA_libutil_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libutil.a
+ $(AM_V_AR)$(libutil_a_AR) libutil.a $(libutil_a_OBJECTS) $(libutil_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libutil.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dexception.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/logfile.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/memcheck.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/misc.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/opts_list.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/regexp.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sstring.Po at am__quote@
+
+.cc.o:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/util/array2d.h b/src/util/array2d.h
new file mode 100644
index 0000000..e6991a4
--- /dev/null
+++ b/src/util/array2d.h
@@ -0,0 +1,421 @@
+#ifndef ARRAY2D_INCLUDED
+#define ARRAY2D_INCLUDED
+
+#include <cstddef>
+#include <vector>
+#include <functional>
+#include <algorithm>
+#include "util/dexception.h"
+#include "util/logfile.h"
+
+namespace fsa {
+
+ // xy_container's must implement the following
+ // operator==
+ // swap (xy_container_type)
+ // default, copy constructors
+ // ...plus the following xy constructor...
+ // xy_container_type (int xsize, int ysize, const_reference default_val)
+ // ...and the following xy accessors...
+ // inline const_reference get_xy_or_default (int x, int y, int xsize, int ysize) const [nonperturbative]
+ // inline reference get_xy (int x, int y, int xsize, int ysize) [creates (x,y) entry if it does not exist]
+
+ template<class T>
+ struct array2d_dense_vector : std::vector<T>
+ {
+ inline array2d_dense_vector() : std::vector<T>() { }
+ inline array2d_dense_vector (const array2d_dense_vector<T>& a) : std::vector<T> (a) { }
+ inline array2d_dense_vector (int xsize, int ysize, const T& default_val) : std::vector<T> (xsize*ysize, default_val) { }
+ inline const T& get_xy_or_default (int x, int y, int xsize, int ysize) const { return (*this) [x + y * xsize]; }
+ inline T& get_xy (int x, int y, int xsize, int ysize) { return (*this) [x + y * xsize]; }
+ };
+
+ template<class T>
+ struct array2d_sparse_vector : std::vector< std::map<int,T> >
+ {
+ // typedefs
+ typedef typename std::map<int,T>::iterator map_iterator;
+ typedef typename std::map<int,T>::const_iterator const_map_iterator;
+
+ // data: default value
+ T default_val;
+
+ // methods
+ inline array2d_sparse_vector() : std::vector< std::map<int,T> >() { }
+ inline array2d_sparse_vector (const array2d_sparse_vector<T>& a) : std::vector< std::map<int,T> > (a) { }
+ inline array2d_sparse_vector (int xsize, int ysize, const T& default_val)
+ : std::vector< std::map<int,T> > (ysize),
+ default_val (default_val)
+ { }
+
+ inline const T& get_xy_or_default (int x, int y, int xsize, int ysize) const {
+ const std::map<int,T>& col = (*this)[y];
+ const_map_iterator i = col.find (x);
+ if (i == col.end())
+ return default_val;
+ return (*i).second;
+ }
+
+ inline T& get_xy (int x, int y, int xsize, int ysize) {
+ std::map<int,T>& col = (*this)[y];
+ map_iterator i = col.find (x);
+ if (i == col.end())
+ return col[x] = default_val;
+ return (*i).second;
+ }
+ };
+
+ // array2d class
+
+ /* Problems: confusingly, operator<< and operator>> output the transpose of the array, i.e. rows become columns
+ This confusion arises from the (x,y) indexing convention of arrays and the (row,col) indexing of matrices.
+ As a workaround, use write_rowcol() and read_rowcol() methods.
+ */
+
+ template <class T, class xy_container_type = array2d_dense_vector<T> >
+ class array2d
+ {
+ public:
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* pointer;
+
+ typedef ptrdiff_t difference_type;
+ typedef size_t size_type;
+
+ typedef array2d <value_type, xy_container_type> array2d_type;
+
+ private:
+ int _xsize, _ysize;
+ xy_container_type _data;
+
+ public:
+
+ std::vector<int> dim() const { std::vector<int> d(2); d[0] = _xsize; d[1] = _ysize; return d; }
+ int xsize() const { return _xsize; }
+ int ysize() const { return _ysize; }
+ int columns() const { return _xsize; }
+ int rows() const { return _ysize; }
+ int rank() const { return 2; }
+
+ bool operator== (const array2d_type& a) const
+ { return _xsize == a._xsize && _ysize == a._ysize && _data == a._data; }
+
+ // NB row/column addressing is opposite to matrices:
+ // matrices use (row,column), we use (x,y)=(column,row)
+ //
+
+ reference operator()(int x, int y)
+ {
+#ifdef DART_DEBUG
+ if (x < 0 || x >= _xsize || y < 0 || y >= _ysize)
+ DART_DEBUG_ERROR ("array2d overflow");
+#endif
+ return _data.get_xy (x, y, _xsize, _ysize);
+ }
+ const_reference operator()(int x, int y) const
+ {
+#ifdef DART_DEBUG
+ if (x < 0 || x >= _xsize || y < 0 || y >= _ysize)
+ DART_DEBUG_ERROR ("array2d overflow");
+#endif
+ return _data.get_xy_or_default (x, y, _xsize, _ysize);
+ }
+
+ reference operator[](const std::vector<int>& k) { return (*this) (k[0], k[1]); }
+ const_reference operator[](const std::vector<int>& k) const { return (*this) (k[0], k[1]); }
+
+ reference operator[](const std::pair<int, int>& k) { return (*this) (k.first, k.second); }
+ const_reference operator[](const std::pair<int, int>& k) const { return (*this) (k.first, k.second); }
+
+ reference entry (int x, int y) { return (*this) (x, y); }
+ const_reference entry (int x, int y) const { return (*this) (x, y); }
+
+ void fill (const value_type& fill_value)
+ {
+ for (int x = 0; x < xsize(); ++x)
+ for (int y = 0; y < ysize(); ++y)
+ (*this)(x,y) = fill_value;
+ }
+
+ void resize (int new_xsize, int new_ysize, const value_type& default_value)
+ {
+ array2d_type new_array (new_xsize, new_ysize, default_value);
+ for (int x = 0; x < std::min (_xsize, new_xsize); ++x)
+ for (int y = 0; y < std::min (_ysize, new_ysize); ++y)
+ new_array (x, y) = entry (x, y);
+ swap (new_array);
+ }
+
+ void swap (array2d_type& a)
+ {
+ std::swap (_xsize, a._xsize);
+ std::swap (_ysize, a._ysize);
+ _data.swap (a._data);
+ }
+
+ // iterators
+ struct xy_iterator : public std::iterator <std::forward_iterator_tag, T>
+ {
+ // data
+ int x, y;
+ array2d_type* a;
+ // methods
+ xy_iterator() : x(0), y(0), a(0) { }
+ xy_iterator (int x, int y, array2d_type* a) : x(x), y(y), a(a) { }
+ T& operator*() { return (*a)(x,y); }
+ const T& operator*() const { return (*a)(x,y); }
+ bool operator== (const xy_iterator& i) const { return y==i.y && x==i.x && a==i.a; }
+ bool operator!= (const xy_iterator& i) const { return !(*this==i); }
+ xy_iterator& operator++() { if (++x >= a->xsize()) { x = 0; ++y; } return *this; }
+ };
+
+ typedef xy_iterator iterator;
+ typedef xy_iterator const_iterator;
+
+ iterator begin() { return xy_iterator (0, 0, this); }
+ iterator end() { return xy_iterator (0, ysize(), this); }
+ const_iterator begin() const { return xy_iterator (0, 0, (array2d_type*) this); }
+ const_iterator end() const { return xy_iterator (0, ysize(), (array2d_type*) this); }
+
+ // row & column iterators
+ class Row_iterator
+ {
+ // iterator typedefs (inheriting from iterator seems to crash the compiler)
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T& reference;
+
+ // the real stuff
+ private:
+ array2d_type* _array;
+ int _row;
+ int _col_offset;
+ bool _same_row (const Row_iterator& i) const { return _array==i._array && _row==i._row; }
+ public:
+ Row_iterator (array2d_type& a, int row, int col_offset = 0) : _array(&a), _row(row), _col_offset(col_offset) { }
+ reference operator[] (int col) { return (*_array) (_row, col + _col_offset); }
+ const_reference operator[] (int col) const { return (*_array) (_row, col + _col_offset); }
+ reference operator*() { return (*this)[0]; }
+ const_reference operator*() const { return (*this)[0]; }
+ bool operator== (const Row_iterator& i) const { return _same_row(i) && _col_offset==i._col_offset; }
+ Row_iterator& operator++() { ++_col_offset; return *this; }
+ Row_iterator operator++ (int) { Row_iterator tmp = *this; ++_col_offset; return tmp; }
+ Row_iterator& operator--() { --_col_offset; return *this; }
+ Row_iterator operator-- (int) { Row_iterator tmp = *this; --_col_offset; return tmp; }
+ Row_iterator& operator+= (ptrdiff_t d) { _col_offset += d; return *this; }
+ Row_iterator& operator-= (ptrdiff_t d) { _col_offset -= d; return *this; }
+ friend Row_iterator operator+ (const Row_iterator& l, ptrdiff_t d) { Row_iterator res = l; res += d; return res; }
+ friend Row_iterator operator- (const Row_iterator& l, ptrdiff_t d) { Row_iterator res = l; res -= d; return res; }
+ ptrdiff_t operator- (const Row_iterator& i) const
+ {
+ if (!_same_row(i)) THROW fsa::Standard_exception ("Can't subtract array2d<>::Row_iterator's of different types");
+ return _col_offset - i._col_offset;
+ }
+ };
+
+ class Column_iterator
+ {
+ // iterator typedefs (inheriting from iterator seems to crash the compiler)
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T& reference;
+
+ // the real stuff
+ private:
+ array2d_type* _array;
+ int _col;
+ int _row_offset;
+ bool _same_col (const Column_iterator& i) const { return _array==i._array && _col==i._col; }
+ public:
+ Column_iterator (array2d_type& a, int col, int row_offset = 0) : _array(&a), _col(col), _row_offset(row_offset) { }
+ reference operator[] (int row) { return (*_array) (row + _row_offset, _col); }
+ const_reference operator[] (int row) const { return (*_array) (row + _row_offset, _col); }
+ reference operator*() { return (*this)[0]; }
+ const_reference operator*() const { return (*this)[0]; }
+ bool operator== (const Column_iterator& i) const { return _same_col(i) && _row_offset==i._row_offset; }
+ Column_iterator& operator++() { ++_row_offset; return *this; }
+ Column_iterator operator++ (int) { Column_iterator tmp = *this; ++_row_offset; return tmp; }
+ Column_iterator& operator--() { --_row_offset; return *this; }
+ Column_iterator operator-- (int) { Column_iterator tmp = *this; --_row_offset; return tmp; }
+ Column_iterator& operator+= (ptrdiff_t d) { _row_offset += d; return *this; }
+ Column_iterator& operator-= (ptrdiff_t d) { _row_offset -= d; return *this; }
+ friend Column_iterator operator+ (const Column_iterator& l, ptrdiff_t d) { Column_iterator res = l; res += d; return res; }
+ friend Column_iterator operator- (const Column_iterator& l, ptrdiff_t d) { Column_iterator res = l; res -= d; return res; }
+ ptrdiff_t operator- (const Column_iterator& i) const
+ {
+ if (!_same_col(i)) THROW Standard_exception ("Can't subtract array2d::Column_iterator's of different types");
+ return _row_offset - i._row_offset;
+ }
+ Column_iterator begin() const { return *this; }
+ Column_iterator end() const { return Column_iterator (_array, _col, _array->rows()); }
+ };
+
+ // row & column views
+ class Row_view
+ {
+ private:
+ Row_iterator _begin;
+ Row_iterator _end;
+ public:
+ Row_view (array2d_type& a, int row)
+ : _begin (a, row, 0), _end (a, row, a.columns())
+ { }
+
+ Row_view (array2d_type& a, int row, int begin_col, int end_col)
+ : _begin (a, row, begin_col), _end (a, row, end_col)
+ { }
+
+ const Row_iterator& begin() const { return _begin; }
+ const Row_iterator& end() const { return _end; }
+ // override operator[] to do range checking for debug compilation
+ reference operator[] (int col)
+ {
+#ifdef DART_DEBUG
+ if (col < 0 || col >= _end - _begin) DART_DEBUG_ERROR ("Row_view overflow");
+#endif /* DART_DEBUG */
+ return _begin[col];
+ }
+ const_reference operator[] (int col) const
+ {
+#ifdef DART_DEBUG
+ if (col < 0 || col >= _end - _begin) DART_DEBUG_ERROR ("Row_view overflow");
+#endif /* DART_DEBUG */
+ return _begin[col];
+ }
+ };
+
+ class Column_view
+ {
+ private:
+ Column_iterator _begin;
+ Column_iterator _end;
+ public:
+ Column_view (array2d_type& a, int col)
+ : _begin (a, col, 0), _end (a, col, a.columns())
+ { }
+
+ Column_view (array2d_type& a, int col, int begin_row, int end_row)
+ : _begin (a, col, begin_row), _end (a, col, end_row)
+ { }
+
+ const Column_iterator& begin() const { return _begin; }
+ const Column_iterator& end() const { return _end; }
+ // override operator[] to do range checking for debug compilation
+ reference operator[] (int col)
+ {
+#ifdef DART_DEBUG
+ if (col < 0 || col >= _end - _begin) DART_DEBUG_ERROR ("Column_view overflow");
+#endif /* DART_DEBUG */
+ return _begin[col];
+ }
+ const_reference operator[] (int col) const
+ {
+#ifdef DART_DEBUG
+ if (col < 0 || col >= _end - _begin) DART_DEBUG_ERROR ("Column_view overflow");
+#endif /* DART_DEBUG */
+ return _begin[col];
+ }
+ };
+
+ // row & column accessors
+
+ const Row_view row (int row) const { return Row_view (*this, row); }
+ const Row_view row (int row, int begin_col, int end_col) const { return Row_view (*this, row, begin_col, end_col); }
+
+ Row_view row (int row) { return Row_view (*this, row); }
+ Row_view row (int row, int begin_col, int end_col) { return Row_view (*this, row, begin_col, end_col); }
+
+ const Column_view column (int col) const { return Column_view (*this, col); }
+ const Column_view column (int col, int begin_row, int end_row) const { return Column_view (*this, col, begin_row, end_row); }
+
+ Column_view column (int col) { return Column_view (*this, col); }
+ Column_view column (int col, int begin_row, int end_row) { return Column_view (*this, col, begin_row, end_row); }
+
+ // misc get & set methods
+
+ void set_row (int row, const std::vector<value_type>& v)
+ {
+ for (int x = 0; x < xsize(); x++) (*this)(x,row) = v[x];
+ }
+
+ void set_column (int col, const std::vector<value_type>& v)
+ {
+ for (int y = 0; y < ysize(); y++) (*this)(col,y) = v[y];
+ }
+
+ std::vector<std::vector<value_type> > all_columns() const
+ {
+ std::vector<std::vector<value_type> > v (ysize(), std::vector<value_type> (xsize(), (value_type) 0));
+ for (int x = 0; x < xsize(); x++)
+ for (int y = 0; y < ysize(); y++)
+ v[x][y] = ((array2d_type&) *this)(x,y);
+ return v;
+ }
+
+ array2d_type transpose() const
+ {
+ array2d_type tmp (ysize(), xsize());
+ for (int x = 0; x < xsize(); x++)
+ for (int y = 0; y < ysize(); y++)
+ tmp(y,x) = (*this)(x,y);
+ return tmp;
+ }
+
+ // constructors
+ array2d() : _xsize(0), _ysize(0), _data() {}
+
+ array2d (const array2d_type& a) :
+ _xsize(a._xsize), _ysize(a._ysize), _data(a._data) {}
+
+ array2d (int xsize, int ysize, const value_type& t) :
+ _xsize(xsize), _ysize(ysize), _data(xsize, ysize, t)
+ {}
+
+ array2d (int xsize, int ysize) :
+ _xsize(xsize), _ysize(ysize), _data(xsize, ysize, value_type())
+ {}
+
+ // i/o methods
+ void write_rowcol (std::ostream& out) const
+ {
+ for (int x = 0; x < xsize(); x++)
+ for (int y = 0; y < ysize(); y++)
+ out << ((array2d_type&) *this) (x, y) << (y < ysize()-1 ? " " : "\n");
+ }
+ void read_rowcol (std::istream& in)
+ {
+ for (int x = 0; x < xsize(); x++)
+ for (int y = 0; y < ysize(); y++)
+ in >> (*this) (x, y);
+ }
+ };
+
+ template <class T, class xy_container_type>
+ std::ostream& operator<< (std::ostream& out, const array2d<T,xy_container_type>& a)
+ {
+ for (int y = 0; y < a.ysize(); y++)
+ for (int x = 0; x < a.xsize(); x++)
+ out << ((array2d<T,xy_container_type>&) a) (x, y) << (x < a.xsize()-1 ? " " : "\n");
+ return out;
+ }
+
+ template <class T, class xy_container_type>
+ std::istream& operator>> (std::istream& in, array2d<T,xy_container_type>& a)
+ {
+ for (int y = 0; y < a.ysize(); y++)
+ for (int x = 0; x < a.xsize(); x++)
+ in >> a (x, y);
+ return in;
+ }
+
+}
+
+#endif
diff --git a/src/util/dexception.cc b/src/util/dexception.cc
new file mode 100644
index 0000000..f1af7b0
--- /dev/null
+++ b/src/util/dexception.cc
@@ -0,0 +1,120 @@
+
+#include <cstdio>
+
+#include "util/dexception.h"
+#include "util/logfile.h"
+
+// uncomment the following #define to allow debugging display of the function stack
+// (finally decided against leaving this as the default behaviour: it garbled the error message too many times - ihh, 8/15/03)
+// #define __SHOW_FUNCTION_STACK__
+
+using namespace fsa;
+
+Dart_exception::Dart_exception()
+{
+ stack_trace.clear(); // dummy, redundant line of code just so we have some place to set a breakpoint
+#ifdef __SHOW_FUNCTION_STACK__
+#ifdef __GNUC__
+ // this code is VERY messy and doesn't work right, but a stack trace is a nice thing to have, even a half-working one
+ void* ret_addr[20];
+ int d = 0;
+ void* fa;
+ fa = __builtin_frame_address(0);
+ if (fa) { ret_addr[d++] = __builtin_return_address(0); fa = __builtin_frame_address(1); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(1); fa = __builtin_frame_address(2); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(2); fa = __builtin_frame_address(3); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(3); fa = __builtin_frame_address(4); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(4); fa = __builtin_frame_address(5); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(5); fa = __builtin_frame_address(6); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(6); fa = __builtin_frame_address(7); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(7); fa = __builtin_frame_address(8); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(8); fa = __builtin_frame_address(9); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(9); fa = __builtin_frame_address(10); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(10); fa = __builtin_frame_address(11); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(11); fa = __builtin_frame_address(12); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(12); fa = __builtin_frame_address(13); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(13); fa = __builtin_frame_address(14); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(14); fa = __builtin_frame_address(15); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(15); fa = __builtin_frame_address(16); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(16); fa = __builtin_frame_address(17); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(17); fa = __builtin_frame_address(18); }
+ if (fa) { ret_addr[d++] = __builtin_return_address(18); fa = __builtin_frame_address(19); }
+ if (fa) ret_addr[d++] = __builtin_return_address(19);
+ // the following line was added to work around mysterious, intermittent corruption of stack_trace...
+ // this now seems to have disappeared, but it did that once before and came back... perhaps the code is haunted?
+ stack_trace << "*** exception *** exception *** exception *** exception *** exception *** exception *** exception *** exception ***\n";
+ stack_trace << "Function stack (depth=" << d;
+ if (d == 20) stack_trace << '+';
+ stack_trace << "):";
+ for (int level = 0; level < d; ++level)
+ {
+ char hex[100]; // i assume this will never run on a >400-bit machine
+ sprintf (hex, "%.8x", ret_addr[level]);
+ stack_trace << " *0x" << hex;
+ }
+ if (d == 20) stack_trace << " ...";
+ stack_trace << '\n';
+ stack_trace << "*** exception *** exception *** exception *** exception *** exception *** exception *** exception *** exception ***\n";
+ stack_trace << '\n';
+#endif /* __GNUC__ */
+#endif /* __SHOW_FUNCTION_STACK__ */
+}
+
+Dart_exception::~Dart_exception() { }
+
+const char* Dart_exception::what() const
+{
+ sstring& what = (sstring&) _what; // cast away const
+ what.clear();
+ what << stack_trace;
+ what << details();
+ return what.c_str();
+}
+
+const char* Dart_exception::details() const
+{
+ return "unknown exception\n";
+}
+
+Standard_exception::Standard_exception (const char* m) : Dart_exception(), msg(m)
+{
+ msg.append("\n");
+}
+
+Standard_exception::Standard_exception (const sstring& m) : Dart_exception(), msg(m)
+{
+ msg.append("\n");
+}
+
+const char* Standard_exception::details() const
+{
+ return msg.c_str();
+}
+
+Format_exception::Format_exception (std::istream& in) : Dart_exception() { info = ""; setup_info (in); }
+Format_exception::Format_exception (std::istream& in, const char* prefix) : Dart_exception() { info << prefix << '\n'; setup_info (in); }
+Format_exception::Format_exception (std::istream& in, const sstring& prefix) : Dart_exception() { info << prefix << '\n'; setup_info (in); }
+
+void Format_exception::setup_info (std::istream& in)
+{
+ info << "Bad input format, somewhere before ";
+ if (in.eof()) info.append("EOF\n");
+ else
+ {
+ info.append("'");
+ char c;
+ for (int i = 0; i < 20 && !in.eof(); i++)
+ if ((c = in.get()) != '\n') { if (!in.eof()) info.push_back(c); } else info.append("\\n");
+ info.append("'\n");
+ }
+}
+
+const char* Format_exception::details() const
+{
+ return info.c_str();
+}
+
+const char* String_exception::details() const
+{
+ return msg.c_str();
+}
diff --git a/src/util/dexception.h b/src/util/dexception.h
new file mode 100644
index 0000000..a0e3e1f
--- /dev/null
+++ b/src/util/dexception.h
@@ -0,0 +1,58 @@
+// my exception class
+
+#ifndef DART_EXCEPTION_INCLUDED
+#define DART_EXCEPTION_INCLUDED
+
+#include "util/sstring.h"
+
+namespace fsa {
+
+ struct Dart_exception
+ {
+ sstring stack_trace, _what;
+
+ Dart_exception();
+ virtual ~Dart_exception();
+
+ virtual const char* details() const;
+ const char* what() const;
+ };
+
+ class Standard_exception : public Dart_exception
+ {
+ protected:
+ sstring msg;
+
+ public:
+ Standard_exception (const char* m);
+ Standard_exception (const sstring& m);
+ const char* details() const;
+ };
+
+ class Format_exception : public Dart_exception
+ {
+ protected:
+ sstring info;
+ void setup_info (std::istream& in);
+
+ public:
+ Format_exception (std::istream& in);
+ Format_exception (std::istream& in, const char* prefix);
+ Format_exception (std::istream& in, const sstring& prefix);
+ const char* details() const;
+ };
+
+ class String_exception : public Dart_exception
+ {
+ protected:
+ sstring msg;
+
+ public:
+ String_exception (const char* m, const char* arg) : Dart_exception(), msg(m) { msg.append(arg).append("\n"); }
+ String_exception (const char* m, const sstring& arg) : Dart_exception(), msg(m) { msg.append(arg).append("\n"); }
+ const char* details() const;
+ };
+
+}
+
+#endif
diff --git a/src/util/hash_fcn.h b/src/util/hash_fcn.h
new file mode 100644
index 0000000..360e1d7
--- /dev/null
+++ b/src/util/hash_fcn.h
@@ -0,0 +1,200 @@
+
+/**
+ * \file hash_fcn.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file implements Paul Hsieh's hash function,
+ * found at http://www.azillionmonkeys.com/qed/hash.html.
+ */
+
+#ifndef HASH_FCN_INCLUDED
+#define HASH_FCN_INCLUDED
+
+#include <cstring>
+#include <config.h>
+#include <stdint.h>
+
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+
+namespace fsa {
+
+ typedef unsigned short bit16_t;
+ typedef unsigned int bit32_t;
+ typedef unsigned long long bit64_t;
+
+ /// Assorted hash functions.
+ // NB: Who knows why, but I get "duplicate symbol" errors
+ // if these functions aren't wrapped up in a struct.
+ struct Hash_functions {
+
+ /// Hash for 16-bit integer.
+ /*
+ * \param key int to hash
+ */
+ static inline bit32_t bit16_t_hash (const bit16_t key) {
+ return __lh3_Wang_hash_int (bit32_t (key));
+ }
+
+ /// Hash for 32-bit integer.
+ /*
+ * \param key int to hash
+ */
+ static inline bit32_t bit32_t_hash (const bit32_t key) {
+ return __lh3_Wang_hash_int (key);
+ }
+
+ /// Hash for 64-bit integer.
+ /*
+ * \param key int to hash
+ */
+ static inline bit32_t bit64_t_hash (const bit64_t key) {
+ return bit32_t (__lh3_Jenkins_hash_64 (key));
+ }
+
+ /// Hash for two 64-bit integers.
+ /*
+ * \param first first int to hash
+ * \param second second int to hash
+ *
+ * XORs the two integers, then uses the Jenkins hash.
+ */
+ static inline bit32_t bit64_t_pair_hash (const bit64_t first, const bit64_t second) {
+ return bit32_t (__lh3_Jenkins_hash_64 (first ^ second));
+ }
+
+ /// Wang's hash function for 32-bit integers.
+ static inline bit32_t __lh3_Wang_hash_int (bit32_t key) {
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+ /// Jenkins' hash function for 64-bit integers.
+ static inline bit64_t __lh3_Jenkins_hash_64 (bit64_t key) {
+ key += ~(key << 32);
+ key ^= (key >> 22);
+ key += ~(key << 13);
+ key ^= (key >> 8);
+ key += (key << 3);
+ key ^= (key >> 15);
+ key += ~(key << 27);
+ key ^= (key >> 31);
+ return key;
+ }
+
+ /// Hsieh's hash.
+ /*
+ * \param data char array to hash
+ * \param len length of char array
+ * \see hsieh_hash_incr
+ */
+ static inline uint32_t hsieh_hash (const char* data, int len) {
+ return hsieh_hash_incr (data, len, len);
+ }
+
+ /// Hsieh's hash.
+ /*
+ * \param data char array to hash
+ * \see hsieh_hash_incr
+ */
+ static inline uint32_t hsieh_hash (const char* data) {
+ int len = std::strlen (data);
+ return hsieh_hash_incr (data, len, len);
+ }
+
+ /// Hsieh's hash for pairs.
+ /*
+ * \param first first element (char array) to hash
+ * \param second second element (char array) to hash
+ * \param len length of char array
+ * Hash first, then use that to hash second.
+ * Assumes that both first and second have identical lengths.
+ * \see hsieh_hash_incr
+ */
+ static inline uint32_t hsieh_hash_pair (const char* first, const char* second, int len) {
+ return hsieh_hash_incr (second, len, hsieh_hash_incr (first, len, 0));
+ }
+
+ /// Hsieh's hash for pairs.
+ /*
+ * \param first first element (char array) to hash
+ * \param second second element (char array) to hash
+ * Hash first, then use that to hash second.
+ * Assumes that both first and second have identical lengths.
+ * \see hsieh_hash_incr
+ */
+ static inline uint32_t hsieh_hash_pair (const char* first, const char* second) {
+ return hsieh_hash_incr (second, std::strlen (second), hsieh_hash_incr (first, std::strlen (first), 0));
+ }
+
+ /// Incremental version of Hsieh's hash.
+ /*
+ * \param data char array to hash
+ * \param len length of char array
+ * \param hash some constant
+ */
+ static inline uint32_t hsieh_hash_incr (const char* data, int len, uint32_t hash) {
+ uint32_t tmp;
+ int rem;
+
+ // the below previously was
+ // if (len <= 0 || data == NULL) return 0;
+ // -- RKB 9/27/08
+ if (len <= 0 || data == 0) return 0;
+
+ rem = len & 3;
+ len >>= 2;
+
+ /* Main loop */
+ for (;len > 0; len--) {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (uint16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem) {
+ case 3: hash += get16bits (data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof (uint16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += get16bits (data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+ }
+
+ };
+
+}
+
+#endif /* HASH_FCN_INCLUDED */
diff --git a/src/util/logfile.cc b/src/util/logfile.cc
new file mode 100644
index 0000000..167390b
--- /dev/null
+++ b/src/util/logfile.cc
@@ -0,0 +1,337 @@
+#include "util/logfile.h"
+#include "util/logtags.h"
+
+using namespace fsa;
+
+namespace fsa {
+ Log_streambuf clog_streambuf;
+ Log_stream clog_stream (clog_streambuf, 9);
+ sstring ERRSTR; /* used as a temporary variable by THROWEXPR() macro */
+}
+
+Log_streambuf::Log_streambuf()
+ : std::streambuf()
+{
+ bare_newline = true;
+ verbose_on_stderr = false;
+ log_to_stderr = true;
+ log_to_file = false;
+
+ datebuf = new char[TBUF_MAX_SZ + 1];
+ timebuf = new char[TBUF_MAX_SZ + 1];
+}
+
+Log_streambuf::~Log_streambuf()
+{
+ delete[] datebuf;
+ delete[] timebuf;
+}
+
+int Log_streambuf::overflow (int c)
+{
+ // print tags
+ if (bare_newline)
+ {
+ if (log_in_XML)
+ if (last_file_tag != file_tag)
+ print_long_XML_tag();
+ else
+ print_short_XML_tag();
+ else
+ print_tabbed_tag();
+ last_file_tag = file_tag;
+ }
+ // log the character
+ if (log_to_stdout) cout.put(c);
+ if (log_to_stderr) cerr.put(c);
+ if (log_to_file && logfile_open) logfile_stream.put(c);
+ // set (or unset) bare_newline flag
+ if (c == '\n')
+ {
+ bare_newline = TRUE;
+ if (log_to_stdout) cout.flush();
+ if (log_to_stderr) cerr.flush();
+ if (log_to_file && logfile_open) logfile_stream.flush();
+ }
+ else
+ bare_newline = FALSE;
+ // return
+ return 0;
+}
+
+void Log_streambuf::save_logfile_state()
+{
+ saved_logfile_state.push (Log_streambuf_vars (*this));
+}
+
+void Log_streambuf::restore_logfile_state()
+{
+ ((Log_streambuf_vars&) *this) = saved_logfile_state.top();
+ saved_logfile_state.pop();
+}
+
+void Log_streambuf::print_long_XML_tag()
+{
+ prepare_date_and_time();
+ newtag_buf.clear();
+ newtag_buf << '<' << CLOGXMLTAGNAME;
+ newtag_buf << " date=\"" << datebuf << "\" time=\"" << timebuf << "\" " << file_tag << "/>\n";
+ print_newtag_buf();
+}
+
+void Log_streambuf::print_short_XML_tag()
+{
+ const sstring old_datebuf (datebuf);
+ const sstring old_timebuf (timebuf);
+ prepare_date_and_time();
+ const bool date_changed = strcmp (datebuf, old_datebuf.c_str()) != 0;
+ const bool time_changed = strcmp (timebuf, old_timebuf.c_str()) != 0;
+ if (date_changed || time_changed)
+ {
+ newtag_buf.clear();
+ newtag_buf << '<' << CLOGXMLTAGNAME;
+ if (date_changed) newtag_buf << " date=\"" << datebuf << "\"";
+ if (time_changed) newtag_buf << " time=\"" << timebuf << "\"";
+ newtag_buf << "/>\n";
+ print_newtag_buf();
+ }
+}
+
+void Log_streambuf::print_tabbed_tag()
+{
+ prepare_date_and_time();
+ newtag_buf.clear();
+ newtag_buf << '[' << datebuf << ',' << timebuf << "] " << file_tag << "\t";
+ print_newtag_buf();
+}
+
+void Log_streambuf::print_newtag_buf()
+{
+ if (log_to_file && logfile_open) logfile_stream << newtag_buf;
+ if (log_to_stderr && verbose_on_stderr) cerr << newtag_buf;
+}
+
+Regexp stream_qualifier_re ("^(.*);([^;]*)$");
+Regexp bad_re ("[!#,:;]");
+Regexp level_range_re ("^(.*),([^,]*)$");
+Regexp range_re ("^(-?[0123456789]+):(-?[0123456789]+)$");
+Regexp above_re ("^(-?[0123456789]+)$");
+Regexp below_re ("^:(-?[0123456789]+)$");
+Regexp line_range_re ("^(.*)#([0123456789]+)-([0123456789]+)$");
+Regexp single_line_re ("^(.*)#([0123456789]+)$");
+Regexp pling_re ("^!(.*)$");
+Regexp filename_re ("^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]+\\.[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]+$");
+Regexp tag_re ("^[ABCDEFGHIJKLMNOPQRSTUVWXYZ][ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]+$");
+
+Log_stream::Log_directive::Log_directive (const sstring& directive_string)
+{
+ sstring d = directive_string;
+
+ // chop off the ';f' or the ';e'
+ //
+ if (stream_qualifier_re.Match (d.c_str()))
+ {
+ d = stream_qualifier_re[1];
+ const sstring qualifier = stream_qualifier_re[2];
+ if (qualifier.size() != 1) THROWEXPR ("ERROR: Bad qualifier char: '" << qualifier << "' in '" << d << "'.");
+ const char q = qualifier[0];
+ if (q != 'f' && q != 'e') { syntax_help(0); THROW Standard_exception ("ERROR: Syntax error in logging directive."); }
+ stderr_or_logfile = q == 'e' ? 1 : 2;
+ }
+ else
+ stderr_or_logfile = 3;
+
+ // chop off the ',x:y' log-level range
+ //
+ if (level_range_re.Match (d.c_str()))
+ {
+ d = level_range_re[1];
+ const sstring level_range = level_range_re[2];
+ if (range_re.Match (level_range.c_str())) { sstring l = range_re[1]; sstring h = range_re[2]; lowest_level = atoi(l.c_str()); highest_level = atoi(h.c_str()); }
+ else if (above_re.Match (level_range.c_str())) { sstring l = above_re[1]; lowest_level = atoi(l.c_str()); highest_level = +123456789; }
+ else if (below_re.Match (level_range.c_str())) { sstring h = below_re[1]; lowest_level = -123456789; highest_level = atoi(h.c_str()); }
+ else { syntax_help(0); THROW Standard_exception ("ERROR: Syntax error in logging directive."); }
+ }
+ else
+ {
+ lowest_level = -123456789;
+ highest_level = +123456789;
+ }
+ if (lowest_level > highest_level) { syntax_help(0); THROW Standard_exception ("ERROR: Syntax error in logging directive."); }
+
+ // chop off the '#x-y' line-number range
+ //
+ if (line_range_re.Match (d.c_str())) { d = line_range_re[1]; sstring s = line_range_re[2]; start_line = atoi(s.c_str()); sstring e = line_range_re[3]; end_line = atoi(e.c_str()); }
+ else if (single_line_re.Match (d.c_str())) { d = single_line_re[1]; sstring s = single_line_re[2]; start_line = end_line = atoi(s.c_str()); }
+ else { start_line = 0; end_line = +123456789; }
+ if (start_line > end_line) { syntax_help(0); THROW Standard_exception ("ERROR: Syntax error in logging directive."); }
+
+ // strip the '!' off the front
+ //
+ if (pling_re.Match (d.c_str())) { d = pling_re[1]; on = 0; }
+ else on = 1;
+
+ // if any special characters remain, then something's wrong
+ //
+ if (bad_re.Match (d.c_str())) { syntax_help(0); THROW Standard_exception ("ERROR: Syntax error in logging directive."); }
+
+ // convert '^' and '$' to whitespace
+ for_contents (sstring, d, c) if (*c == '^' || *c == '$') *c = ' ';
+
+ // if the remaining pattern fits
+ // /^[A-Za-z_]+\.[A-Za-z]+$/ (has a dot suffix => is a filename)
+ // or /^[A-Z][A-Z_0-9]+$/ (upper case variable name => is a tag),
+ // then add a space to the start and the end, to force a complete match
+ // (or in the case of filenames, add a '^' to the start and a space to the end)
+ //
+ // also add parentheses at this stage
+ //
+ const char* dc = d.c_str();
+ if (filename_re.Match(dc)) { d.insert ((sstring::size_type) 0, "^()"); d.append (" "); }
+ else if (tag_re.Match(dc)) { d.insert ((sstring::size_type) 0, " ("); d.append (") "); }
+ else { d.insert ((sstring::size_type) 0, "()"); }
+
+ filename_pattern = Regexp (d.c_str());
+}
+
+bool Log_stream::Log_directive::syntax_help (Opts_list* ol)
+{
+ cerr << "\nLogging directives have a flexible syntax. The simplest kind of directive is a tag in upper-case,\nsuch as '-log INIT', or a priority level, e.g. '-log 6'; but you can also turn on (or off) messages\nby source file, by line, and by combinations of these.\n\n";
+ cerr << "Examples include:\n\n";
+ cerr << "-log JAM turns on logging for all messages with tag 'JAM' (see -logtags or -logtaginfo for list)\n";
+ cerr << "-log 3 turns on logging for messages of priority level 3 or higher\n";
+ cerr << "-log cabin,3 turns on logging for messages of priority level 3 or higher in source files matching '*cabin*' (eg cabin.h, mycabin.cc)\n";
+ cerr << "-log cabin.h,3 turns on logging for messages of priority level 3 or higher in source file 'cabin.h' only\n";
+ cerr << "-log 'lady,3:6' turns on logging for messages from priority levels 3 to 6 in source files '*lady*'\n";
+ cerr << " (NB excluding high log levels may have the side-effect of blocking lower ones due to nested 'if' clauses in C++ code)";
+ cerr << "\n-log 'lady#1-100,3:6' turns on logging for messages from levels 3 to 6 for first 100 lines of files '*lady*'";
+ cerr << "\n-log 'lady,3:6;f' turns on logging for messages from levels 3 to 6 in files '*lady*' for logfile only\n";
+ cerr << " (suffix ';e' applies to standard error only)\n";
+ cerr << "-log '!^fire' turns off logging for all messages in source files starting with 'fire' (eg firefight.f77, fired.exe)\n";
+ cerr << "-nolog fire same as -log '!fire'\n\n";
+ exit(0);
+ return 0;
+}
+
+bool Log_stream::Log_directive::tags_help (Opts_list* ol)
+{
+ cout << all_log_tags;
+ exit(0);
+ return 1;
+}
+
+bool Log_stream::Log_directive::tags_long_help (Opts_list* ol)
+{
+ cout << all_log_tag_info;
+ exit(0);
+ return 1;
+}
+
+bool Log_stream::Log_directive::process (int level, const char* src_file, int src_line, int& stderr_ret, int& file_ret)
+{
+ if (filename_pattern.Match (src_file) && level >= lowest_level && level <= highest_level && src_line >= start_line && src_line <= end_line)
+ {
+ if (((stderr_or_logfile & 1) == 1) && stderr_ret == -1) stderr_ret = on ? 1 : 0;
+ if (((stderr_or_logfile & 2) == 2) && file_ret == -1) file_ret = on ? 1 : 0;
+ dirstr_match = filename_pattern[1];
+ return stderr_or_logfile ? 1 : 0;
+ }
+ return 0;
+}
+
+void Log_stream::add_new_directive (const char* dir)
+{
+ sstring d (dir);
+ directives.push_back (Log_directive (d));
+}
+
+void Log_stream::save_logfile_state()
+{
+ saved_logfile_state.push (Log_stream_vars (*this));
+ log_streambuf.save_logfile_state();
+}
+
+void Log_stream::restore_logfile_state()
+{
+ ((Log_stream_vars&) *this) = saved_logfile_state.top();
+ saved_logfile_state.pop();
+ log_streambuf.restore_logfile_state();
+}
+
+Log_stream::Log_stream (Log_streambuf& log_streambuf, int log_level) :
+ std::ostream (&log_streambuf),
+ log_streambuf (log_streambuf)
+{
+ log_to_stderr_mask = true;
+ log_to_file_mask = false;
+ lowest_log_level = log_level;
+ current_log_level = INITIAL_LOG_LEVEL;
+
+ file_tag_buf = new char[FILETAG_MAX_SZ + 1];
+ this->request_logging(0,__FILE__,__LINE__).CLOG_FILE_LINE << "Log opened\n";
+}
+
+Log_stream::~Log_stream()
+{
+ this->request_logging(0,__FILE__,__LINE__).CLOG_FILE_LINE << "Log closed\n";
+ clog_streambuf.close_logfile();
+ delete[] file_tag_buf;
+}
+
+
+bool Log_stream::clog_to_file (Opts_list* ol)
+{
+ sstring filename = ol->next_string();
+ clog_streambuf.open_logfile (filename);
+ clog_stream.log_to_file_only();
+ CLOG(0) << "Opened logfile " << filename << "\n";
+ return 1;
+}
+
+bool Log_stream::clog_to_stderr (Opts_list* ol)
+{
+ clog_stream.log_to_stderr_only();
+ return 1;
+}
+
+bool Log_stream::clog_everywhere (Opts_list* ol)
+{
+ sstring filename = ol->next_string();
+ clog_streambuf.open_logfile (filename);
+ clog_stream.log_everywhere();
+ CLOG(0) << "Opened logfile " << filename << "\0";
+ return 1;
+}
+
+bool Log_stream::clog_directive (Opts_list* ol)
+{
+ sstring directive_string (ol->next_string());
+ Regexp numeric_re ("^-?[0123456789]+$");
+ if (numeric_re.Match (directive_string.c_str())) clog_stream.lowest_log_level = atoi (directive_string.c_str());
+ else clog_stream.directives.push_back (Log_directive (directive_string));
+ return 1;
+}
+
+bool Log_stream::clog_negated_directive (Opts_list* ol)
+{
+ sstring directive_string (ol->next_string());
+ clog_stream.directives.push_back (Log_directive (directive_string));
+ clog_stream.directives.back().on = !clog_stream.directives.back().on;
+ return 1;
+}
+
+void Log_stream::add_opts (Opts_list& ol)
+{
+ ol.print_title ("Logging options");
+ ol.add ("-log", &Log_stream::clog_directive, " <string>\tturn on diagnostic logging (-loghelp shows syntax)");
+ ol.add ("-logfile", &Log_stream::clog_to_file, " <file>\tlog to file");
+ ol.add ("-logcopy", &Log_stream::clog_everywhere, " <file>\tlog to file and standard error");
+ ol.add ("-logtime", clog_streambuf.verbose_on_stderr = 0, "timestamp standard error (logfile stamped automatically)");
+ ol.add ("-logxml", clog_streambuf.log_in_XML = TRUE, "add XML timestamps");
+ ol.add ("-logerr", &Log_stream::clog_to_stderr, "\tlog on standard error (default)");
+ ol.add ("-nolog", &Log_stream::clog_negated_directive);
+ ol.add ("-loghelp", &Log_stream::Log_directive::syntax_help);
+ ol.add ("-logtags", &Log_stream::Log_directive::tags_help);
+ ol.add ("-logtaginfo", &Log_stream::Log_directive::tags_long_help);
+ ol.newline();
+}
diff --git a/src/util/logfile.h b/src/util/logfile.h
new file mode 100644
index 0000000..86c3f15
--- /dev/null
+++ b/src/util/logfile.h
@@ -0,0 +1,277 @@
+#ifndef LOGFILE_INCLUDED
+#define LOGFILE_INCLUDED
+
+#include <cstring>
+#include <cstdio>
+#include <ctype.h>
+#include <time.h>
+#include <fstream>
+#include <list>
+#include <map>
+#include <stack>
+
+#include "util/misc.h"
+#include "util/sstring.h"
+#include "util/macros.h"
+#include "util/opts_list.h"
+#include "util/regexp.h"
+
+#define CLOGXMLTAGNAME "log"
+#define INITIAL_LOG_LEVEL 9
+#define ERROR_LOG_LEVEL 10
+#define ERROR_TAG "ERROR"
+
+#define CLOGSTREAM clog_stream
+#define CLOGSTREAMBUF clog_streambuf
+#define CLOG_FILE_LINE file_tag(__FILE__,__LINE__,"")
+#define CLOG_FILE_LINE_TAGS(T) file_tag(__FILE__,__LINE__,"" #T "")
+
+#define CLOGREQUEST(n,STDOUT_FLAG) CLOGSTREAM.request_logging(n,__FILE__ " ",__LINE__,STDOUT_FLAG)
+#define CTAGREQUEST(n,TAGS,STDOUT_FLAG) CLOGSTREAM.request_logging(n,__FILE__ " " #TAGS " ",__LINE__,STDOUT_FLAG)
+
+#define CLOG(n) CLOGREQUEST(n,0).CLOG_FILE_LINE
+#define CTAG(n,TAGS) CTAGREQUEST(n,TAGS,0).CLOG_FILE_LINE_TAGS(TAGS)
+#define CLOGERR CLOGREQUEST(ERROR_LOG_LEVEL,0).CLOG_FILE_LINE_TAGS(ERROR_TAG)
+#define CLOGOUT CLOGREQUEST(ERROR_LOG_LEVEL,1).CLOG_FILE_LINE
+#define CL CLOGSTREAM
+#define CLOGGING(n) (CLOGREQUEST(n,0).logging() ? CLOGSTREAM.CLOG_FILE_LINE.logging() : 0)
+#define CTAGGING(n,TAGS) (CTAGREQUEST(n,TAGS,0).logging() ? CLOGSTREAM.CLOG_FILE_LINE_TAGS(TAGS).logging() : 0)
+
+// max buffer sizes
+#define TBUF_MAX_SZ 60
+#define FILETAG_MAX_SZ 400
+
+// helpful exception stuff
+
+#define THROW CLOG(7) << "Exception thrown\n", throw
+#define THROWSTR "", THROW Standard_exception (ERRSTR.c_str())
+#define THROWEXPR(EXPR) { ERRSTR.clear(); ERRSTR << EXPR; THROW Standard_exception (ERRSTR.c_str()); }
+#define THROWIFTRUE(EXPR) { if (EXPR) { ERRSTR.clear(); ERRSTR << #EXPR; THROW Standard_exception (ERRSTR.c_str()); } }
+#define THROWASSERT(EXPR) { if (!(EXPR)) { ERRSTR.clear(); ERRSTR << "ERROR: Failed assertion '" << #EXPR << "'"; THROW Standard_exception (ERRSTR.c_str()); } }
+
+namespace fsa {
+
+ // Logfile system variables
+ class Log_streambuf_vars
+ {
+ protected:
+ bool logfile_open;
+ sstring last_filename;
+ bool bare_newline;
+ sstring file_tag;
+ sstring last_file_tag;
+
+ public:
+ bool verbose_on_stderr;
+ bool log_to_stderr;
+ bool log_to_stdout;
+ bool log_to_file;
+ bool log_in_XML;
+ };
+
+ // streambuf class
+ class Log_streambuf : public std::streambuf, public Log_streambuf_vars
+ {
+ protected:
+ int overflow(int c);
+
+ private:
+
+ std::ofstream logfile_stream;
+ char* datebuf; // date string buffer
+ char* timebuf; // time string buffer
+ sstring newtag_buf;
+
+ std::stack<Log_streambuf_vars> saved_logfile_state;
+
+ inline void prepare_date_and_time()
+ {
+ const time_t t = time(NULL);
+ strftime (datebuf, TBUF_MAX_SZ, "%Y/%d/%m", localtime(&t));
+ strftime (timebuf, TBUF_MAX_SZ, "%H:%M:%S", localtime(&t));
+ }
+
+ public:
+
+ void save_logfile_state();
+ void restore_logfile_state();
+
+ inline void new_file_tag (const char* s)
+ {
+ // print a newline
+ if (!bare_newline)
+ {
+ if (log_to_file && logfile_open) logfile_stream << '\n';
+ if (log_to_stderr) cerr << '\n';
+ if (log_to_stdout) cout << '\n';
+ }
+ // update vars
+ file_tag = s;
+ bare_newline = TRUE;
+ }
+
+ void print_long_XML_tag();
+ void print_short_XML_tag();
+ void print_tabbed_tag();
+ void print_newtag_buf();
+
+ inline void close_logfile()
+ {
+ if (logfile_open)
+ logfile_stream.close();
+ logfile_open = FALSE;
+ }
+
+ inline void open_logfile(const sstring& filename)
+ {
+ if (filename != last_filename)
+ {
+ close_logfile();
+ logfile_stream.open (filename.c_str(), std::ios_base::app);
+ logfile_open = 1;
+ last_filename = filename;
+ }
+ }
+
+ Log_streambuf();
+ ~Log_streambuf();
+ };
+
+ // vars for Log_stream
+ struct Log_stream_vars
+ {
+ bool log_to_stderr_mask;
+ bool log_to_file_mask;
+ int lowest_log_level;
+ int current_log_level;
+ };
+
+ // ostream class
+ class Log_stream : public std::ostream, public Log_stream_vars
+ {
+ private:
+ Log_streambuf& log_streambuf;
+
+ char* file_tag_buf;
+
+ public:
+
+ std::stack<Log_stream_vars> saved_logfile_state;
+
+ struct Log_directive
+ {
+ sstring dirstr_match;
+ Regexp filename_pattern;
+ int start_line;
+ int end_line;
+ int lowest_level;
+ int highest_level;
+ int stderr_or_logfile; // 1 means directive applies to stderr, 2 means it applies to logfile, 3 means both
+ bool on; // true if this directive turns logging on & not off
+ bool process (int level, const char* src_file, int src_line, int& stderr_ret, int& file_ret);
+ Log_directive (const sstring& directive_string);
+
+ static bool syntax_help (Opts_list* ol);
+ static bool tags_help (Opts_list* ol);
+ static bool tags_long_help (Opts_list* ol);
+ };
+
+ std::list<Log_directive> directives;
+
+ void add_new_directive (const char* dir); // can be called from the debugger
+
+ void save_logfile_state();
+ void restore_logfile_state();
+
+ void log_to_stderr_only() { log_to_stderr_mask = 1; log_to_file_mask = 0; }
+ void log_to_file_only() { log_to_stderr_mask = 0; log_to_file_mask = 1; }
+ void log_everywhere() { log_to_stderr_mask = log_to_file_mask = 1; }
+
+ inline Log_stream& request_logging (int level, const char* src_file, int src_line, bool log_to_stdout = 0)
+ {
+ if (directives.empty())
+ {
+ log_streambuf.log_to_stderr = log_to_stderr_mask && level >= lowest_log_level && !log_to_stdout;
+ log_streambuf.log_to_file = log_to_file_mask && level >= lowest_log_level;
+ log_streambuf.log_to_stdout = log_to_stdout;
+ }
+ else
+ {
+ src_file = strip_path (src_file);
+ int stderr_flag = -1;
+ int file_flag = -1;
+ for_iterator (std::list<Log_directive>::reverse_iterator, dir, directives.rbegin(), directives.rend()) // loop backwards through directives list
+ {
+ dir->process (level, src_file, src_line, stderr_flag, file_flag);
+ if (stderr_flag != -1 && file_flag != -1)
+ {
+ if (dir->dirstr_match.size())
+ {
+ for_const_contents (sstring, dir->dirstr_match, c)
+ if (*c == ' ' || *c == '\t') // chop off whitespace
+ break;
+ }
+ break;
+ }
+ }
+ log_streambuf.log_to_stderr = log_to_stderr_mask && (stderr_flag == -1 ? level >= lowest_log_level : stderr_flag) && !log_to_stdout;
+ log_streambuf.log_to_file = log_to_file_mask && (file_flag == -1 ? level >= lowest_log_level : file_flag);
+ log_streambuf.log_to_stdout = log_to_stdout;
+ }
+ current_log_level = level;
+ return *this;
+ }
+
+ inline bool logging() { return log_streambuf.log_to_stderr || log_streambuf.log_to_file || log_streambuf.log_to_stdout; }
+
+ static inline const char* strip_path (const char* file_with_path)
+ {
+ const char* s;
+ while ((s = std::strchr (file_with_path, DIR_SEP_CHAR)) != NULL) file_with_path = s + 1;
+ return file_with_path;
+ }
+
+ inline Log_stream& file_tag (const char* src_file, int src_line, const char* tags)
+ {
+ if (log_streambuf.log_in_XML)
+ {
+ if (tags ? (std::strlen(tags) > 0) : false)
+ sprintf (file_tag_buf, "file=\"%s\" line=%d level=%d tags=\"%s\"", strip_path (src_file), src_line, current_log_level, tags);
+ else
+ sprintf (file_tag_buf, "file=\"%s\" line=%d level=%d", strip_path (src_file), src_line, current_log_level);
+ }
+ else
+ {
+ if (tags ? (std::strlen(tags) > 0) : false)
+ sprintf (file_tag_buf, "<%s#%d> <%d %s>", strip_path (src_file), src_line, current_log_level, tags);
+ else
+ sprintf (file_tag_buf, "<%s#%d> <%d>", strip_path (src_file), src_line, current_log_level);
+ }
+ log_streambuf.new_file_tag (file_tag_buf);
+ return *this;
+ }
+
+ // constructor
+ Log_stream (Log_streambuf& log_streambuf, int log_level);
+
+ // destructor
+ ~Log_stream();
+
+ static bool clog_to_file (Opts_list* ol);
+ static bool clog_to_stderr (Opts_list* ol);
+ static bool clog_everywhere (Opts_list* ol);
+ static bool clog_directive (Opts_list* ol);
+ static bool clog_negated_directive (Opts_list* ol);
+
+ static void add_opts (Opts_list& ol);
+ };
+
+ extern Log_streambuf clog_streambuf;
+ extern Log_stream clog_stream;
+
+ // the following string does nothing special except serve as a buffer for exception-throwing via the THROWSTR macro:
+ extern sstring ERRSTR;
+
+}
+
+#endif
diff --git a/src/util/logtags.h b/src/util/logtags.h
new file mode 100644
index 0000000..ec9c9d1
--- /dev/null
+++ b/src/util/logtags.h
@@ -0,0 +1,13 @@
+/* This file automatically generated by make-logtags.pl. DO NOT EDIT */
+
+#ifndef UTIL_LOGTAGS_INCLUDED
+#define UTIL_LOGTAGS_INCLUDED
+
+namespace fsa {
+
+ const char* all_log_tags = "\nANCHORING CONSTRAINTS MANAGER \nANCHORING_VERBOSE CONSTRAINTS_VERBOSE MW \nANCHORING_VERBOSE_VERBOSE DAG OPTS \nANNEALING DB REFINEMENT \nANNEALING_VERBOSE FSA SPARSEMATRIX \nANNEALING_VERBOSEs FSAEM \n";
+ const char* all_log_tag_info = "\nTag Level Module File#line\n--- ----- ------ ---------\n<none> 0 util logfile.cc#285\n 0 util logfile.cc#300\nANCHORING 9 fsa anchors.cc#934\n 9 fsa anchors.cc#936\n 9 fsa anchors.cc#938\n 9 fsa anchors.cc#1140\n [...]
+
+}
+
+#endif /* UTIL_LOGTAGS_INCLUDED */
diff --git a/src/util/macros.h b/src/util/macros.h
new file mode 100644
index 0000000..2f49d67
--- /dev/null
+++ b/src/util/macros.h
@@ -0,0 +1,84 @@
+// miscellaneous useful macros
+
+#ifndef MACROS_INCLUDED
+#define MACROS_INCLUDED
+
+#include <ctype.h>
+#include <iostream>
+
+// TRUE and FALSE
+#define TRUE 1
+#define FALSE 0
+
+// conditional char and string macros for true and false
+#define YES_OR_NO(X) ((X) ? "yes" : "no")
+#define TRUE_OR_FALSE(X) ((X) ? "true" : "false")
+#define Y_OR_N(X) ((X) ? 'y' : 'n')
+#define T_OR_F(X) ((X) ? 't' : 'f')
+
+// Container iterator macros. There are two kinds:
+// (1) template iterator macros, using "typename";
+// (2) nontemplate iterator macros, using typedefs without "typename".
+
+// Prefixes used by the iterator macros
+#define DART_ITER_TYPE _type_
+#define DART_END_ITER _end_
+#define DART_TMP_CNTNR _cntnr_
+
+// (1) template iterator macros, using "typename"
+#define template_for_contents(ContainerType, Container, Iterator) for ( typename ContainerType ::iterator Iterator = ( Container ).begin(), DART_END_ITER ## Iterator = ( Container ).end(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define template_for_const_contents(ContainerType, Container, Iterator) for ( typename ContainerType ::const_iterator Iterator = ( Container ).begin(), DART_END_ITER ## Iterator = ( Container ).end(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define template_for_reverse_contents(ContainerType, Container, Iterator) for ( typename ContainerType ::reverse_iterator Iterator = ( Container ).rbegin(), DART_END_ITER ## Iterator = ( Container ).rend(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define template_for_const_reverse_contents(ContainerType, Container, Iterator) for ( typename ContainerType ::const_reverse_iterator Iterator = ( Container ).rbegin(), DART_END_ITER ## Iterator = ( Container ).rend(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+
+// (2) nontemplate iterator macros, using typedefs without "typename"
+#define for_contents(ContainerType, Container, Iterator) for ( ContainerType ::iterator Iterator = ( Container ).begin(), DART_END_ITER ## Iterator = ( Container ).end(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define for_const_contents(ContainerType, Container, Iterator) for ( ContainerType ::const_iterator Iterator = ( Container ).begin(), DART_END_ITER ## Iterator = ( Container ).end(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define for_tmp_contents(ContainerType, ContainerExpr, Iterator) ContainerType DART_TMP_CNTNR ## Iterator = ContainerExpr; for ( ContainerType ::iterator Iterator = DART_TMP_CNTNR ## Iterator .begin(), DART_END_ITER ## Iterator = DART_TMP_CNTNR ## Iterator .end(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define for_reverse_contents(ContainerType, Container, Iterator) for ( ContainerType ::reverse_iterator Iterator = ( Container ).rbegin(), DART_END_ITER ## Iterator = ( Container ).rend(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define for_const_reverse_contents(ContainerType, Container, Iterator) for ( ContainerType ::const_reverse_iterator Iterator = ( Container ).rbegin(), DART_END_ITER ## Iterator = ( Container ).rend(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+#define for_tmp_reverse_contents(ContainerType, ContainerExpr, Iterator) ContainerType DART_TMP_CNTNR ## Iterator = ContainerExpr; for ( ContainerType ::reverse_iterator Iterator = DART_TMP_CNTNR ## Iterator .rbegin(), DART_END_ITER ## Iterator = DART_TMP_CNTNR ## Iterator .rend(); !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+// for_iterator macro
+#define for_iterator(IteratorType, Iterator, Begin, End) for ( IteratorType Iterator = Begin, DART_END_ITER ## Iterator = End; !(Iterator == DART_END_ITER ## Iterator); ++ Iterator )
+
+// "begin, end" iterator macro
+#define begin_end(Container) ( Container ).begin(), ( Container ).end()
+
+// Directory separator
+#define DIR_SEP_CHAR '/'
+
+
+// Stream tricks -- rarely if ever used
+struct Eat_white_type
+{
+ friend std::istream& operator>> (std::istream& is, Eat_white_type)
+ {
+ char c;
+ while (is.get(c)) if (!isspace (c)) { is.putback(c); break; }
+ return is;
+ }
+};
+
+#define EAT_WHITE Eat_white_type()
+
+struct Flush_type { friend std::ostream& operator<< (std::ostream& o, Flush_type) { return flush(o); } };
+
+#define FLUSH Flush_type()
+
+#ifdef DART_DEBUG
+#define DART_DEBUG_MODE_STRING "debug"
+#else
+#define DART_DEBUG_MODE_STRING "release"
+#endif
+
+#endif
diff --git a/src/util/memcheck.cc b/src/util/memcheck.cc
new file mode 100644
index 0000000..0286c34
--- /dev/null
+++ b/src/util/memcheck.cc
@@ -0,0 +1,51 @@
+
+/**
+ * \file memcheck.cc
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Colin Dewey.
+ */
+
+#include "config.h"
+#include "memcheck.h"
+
+#ifdef HAVE_STRUCT_SYSINFO_TOTALRAM
+// Memory check for Linux systems
+#include <sys/sysinfo.h>
+int total_ram() {
+ struct sysinfo info;
+ if (sysinfo(&info) == 0) {
+ unsigned long totalram = info.totalram;
+#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT
+ // info.totalram is in units of info.mem_unit bytes
+ totalram *= info.mem_unit;
+#endif
+ // Return total RAM in megabytes
+ return totalram >> 20;
+ } else {
+ return -1;
+ }
+}
+#elif HAVE_DECL_SYSCTL && HAVE_DECL_CTL_HW && HAVE_DECL_HW_PHYSMEM
+// Memory check for BSD/Darwin systems
+#include <sys/sysctl.h>
+int total_ram() {
+ // Management Information Base (MIB) codes for physical memory
+ static int mib[] = {CTL_HW, HW_PHYSMEM};
+
+ // Variable for result of physical memory query and its size
+ size_t physmem;
+ size_t len = sizeof(physmem);
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &physmem, &len, NULL, 0) == 0
+ and len == sizeof(physmem)) {
+ // sysctl returns total RAM in bytes
+ return physmem >> 20;
+ } else {
+ return -1;
+ }
+}
+#else
+int total_ram() {
+ return -1;
+}
+#endif
diff --git a/src/util/memcheck.h b/src/util/memcheck.h
new file mode 100644
index 0000000..4a0b282
--- /dev/null
+++ b/src/util/memcheck.h
@@ -0,0 +1,17 @@
+
+/**
+ * \file memcheck.h
+ * This file is part of FSA, a sequence alignment algorithm.
+ * \author Source code in this file was written by Colin Dewey.
+ */
+
+#ifndef MEMCHECK_INCLUDED
+#define MEMCHECK_INCLUDED
+
+/**
+ * \brief Returns the total system memory size in megabytes,
+ * or -1 if it cannot be determined.
+ */
+int total_ram();
+
+#endif // MEMCHECK_INCLUDED
diff --git a/src/util/misc.cc b/src/util/misc.cc
new file mode 100644
index 0000000..056975f
--- /dev/null
+++ b/src/util/misc.cc
@@ -0,0 +1,90 @@
+
+/**
+ * \file misc.cc
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#include "util/misc.h"
+#include <algorithm>
+#include <fstream>
+
+using namespace fsa;
+
+
+Regexp Util::re_chr_stripper = Regexp ("^(chr)?(.+)");
+Regexp Util::re_basename = Regexp ("^.*\\/([^\\/]+)$");
+Regexp Util::re_basename_extension = Regexp ("^(.+)\\.[^\\.]+$");
+
+bool Util::exists_file (const std::string& filename) {
+
+ struct stat fileinfo;
+ bool gotattr;
+
+ // Attempt to get the file attributes
+ int statresults = stat (filename.c_str(), &fileinfo);
+
+ if (statresults == 0) {
+ // We were able to get the file attributes
+ // so the file obviously exists.
+ gotattr = true;
+ } else {
+ // We were not able to get the file attributes.
+ // This may mean that we don't have permission to
+ // access the folder which contains this file. If you
+ // need to do that level of checking, lookup the
+ // return values of stat which will give you
+ // more details on why stat failed.
+ gotattr = false;
+
+ }
+
+ return gotattr;
+
+}
+
+size_t Util::count_newlines (const std::string& filename) {
+
+ std::ifstream filestream;
+ filestream.open (filename.c_str(), std::ios::in);
+ if (!filestream.is_open()) {
+ cerr << "ERROR: Couldn't open file '" << filename << "' for reading." << endl;
+ exit (1);
+ }
+
+ size_t num = std::count (std::istreambuf_iterator<char> (filestream), std::istreambuf_iterator<char>(),
+ '\n');
+
+ return num;
+
+}
+
+void Util::strip_leading_chr (std::string& chromosome) {
+
+ if (re_chr_stripper.Match (chromosome.c_str())) // strip off leading 'chr' if present
+ chromosome = std::string (re_chr_stripper[2]);
+
+}
+
+void Util::basename (std::string& filename,
+ const bool strip_extension /* = false */) {
+
+ // remove directory information
+ if (re_basename.Match (filename.c_str()))
+ filename = std::string (re_basename[1]);
+
+ // remove filename extension
+ if (strip_extension && re_basename_extension.Match (filename.c_str()))
+ filename = re_basename_extension[1];
+
+}
+
+bool Util::String_equal_ci::operator() (const std::string& s1, const std::string& s2) const {
+
+ return std::lexicographical_compare (s1.begin(),
+ s1.end(),
+ s2.begin(),
+ s2.end(),
+ Util::char_less_ci);
+
+}
diff --git a/src/util/misc.h b/src/util/misc.h
new file mode 100644
index 0000000..a2063f2
--- /dev/null
+++ b/src/util/misc.h
@@ -0,0 +1,390 @@
+
+/**
+ * \file misc.h
+ * This file is part of FSA.
+ * \author Source code in this file was written by Robert Bradley.
+ */
+
+#ifndef UTIL_MISC_INCLUDED
+#define UTIL_MISC_INCLUDED
+
+#include <cassert>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <sys/stat.h>
+#include <map>
+
+#include "config.h"
+#include "util/regexp.h"
+
+using std::cerr;
+using std::cout;
+using std::endl;
+
+namespace fsa {
+
+ struct Util {
+
+ public:
+
+ /**
+ * \brief Convert to a string.
+ */
+ template<typename T>
+ static std::string to_string (const T& t);
+
+ /**
+ * \brief Remove newline character, if it exists, from the end of a string.
+ */
+ static void chomp (std::string& str);
+
+ /**
+ * \brief Convert a string to upper-case.
+ */
+ static void toupper (std::string& str);
+
+ /**
+ * \brief Convert a string to lower-case.
+ */
+ static void tolower (std::string& str);
+
+ /**
+ * \brief Tokenize a string according to the specified delimiters.
+ *
+ * Code from:
+ * http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
+ */
+ static std::vector<std::string> split (const std::string& str,
+ const std::string& delimiters = " ");
+
+ /**
+ * \brief Join strings into a single string separated by delimiter.
+ */
+ template<typename T>
+ static std::string join (const std::vector<T>& items,
+ const std::string& delimiter = "");
+
+ /**
+ * \brief Search for an instance of a specified item in a vector of items.
+ * \param item list of items to search through
+ * \param query item to search for
+ */
+ template<typename T>
+ static bool contains (const std::vector<T>& items,
+ const T query);
+
+ /**
+ * \brief Add prefix to all strings in vector.
+ */
+ static std::vector<std::string> addprefix (const std::vector<std::string>& items,
+ const std::string prefix);
+
+ /**
+ * \brief Add suffix to all strings in vector.
+ */
+ static std::vector<std::string> addsuffix (const std::vector<std::string>& items,
+ const std::string suffix);
+
+ /**
+ * \brief Get keys in a map or multimap.
+ *
+ * Returns possibly-duplicate key values if T is a multimap.
+ * \param container map or multimap
+ */
+ template<typename T>
+ static std::vector<typename T::key_type> keys (const T& container);
+
+ /**
+ * \brief Get values in a map or multimap.
+ * \param container map or multimap
+ */
+ template<typename T>
+ static std::vector<typename T::mapped_type> values (const T& container);
+
+ /**
+ * \brief Strip leading 'chr' (if present) from the passed chromosome name.
+ */
+ static void strip_leading_chr (std::string& chromosome);
+
+ /**
+ * \brief Return a random number in [0, max].
+ */
+ static unsigned rand (const unsigned max);
+
+ /**
+ * \brief Return a random probability (double in [0, 1]).
+ */
+ static double prob();
+
+ /**
+ * \brief Seed random number generator.
+ */
+ static void seed_rand (const unsigned seed);
+
+ /**
+ * \brief Seed random number generate on current time.
+ */
+ static void seed_rand_on_time();
+
+ /**
+ * \brief Choose from a probability vector.
+ *
+ * Assumes that the distribution is properly normalized.
+ */
+ static size_t choose_from_distribution (const std::vector<double>& dist);
+
+ /**
+ * \brief Does a file exist?
+ *
+ * Uses stat to see if we can get the file attributes.
+ * From http://www.techbytes.ca/techbyte103.html.
+ */
+ static bool exists_file (const std::string& filename);
+
+ /**
+ * \brief Counts the number of newlines in a file.
+ * \param filename name of file
+ */
+ static size_t count_newlines (const std::string& filename);
+
+ /**
+ * \brief Remove directory information from filename.
+ *
+ * Converts, e.g., '/tmp/rob.data' to 'rob.data' or 'rob'.
+ * \param strip_extension remove extension from filename as well
+ */
+ static void basename (std::string& filename,
+ const bool strip_extension = false);
+
+ /**
+ * \brief Case-insensitive character comparison.
+ * \see String_equal_ci
+ */
+ static bool char_less_ci (const char c1, const char c2) {
+ return std::tolower (static_cast<unsigned char> (c1)) < std::tolower (static_cast<unsigned char> (c2));
+ }
+
+ /**
+ * \brief Case-insensitive string comparison.
+ *
+ * Taken from Meyers, "Effective C++" 3rd ed.
+ */
+ struct String_equal_ci {
+ public:
+ bool operator() (const std::string& s1, const std::string& s2) const;
+ };
+
+ /**
+ * \brief Function object for comparing duples.
+ *
+ * Orders by first coordinate, then second coordinate.
+ */
+ template<typename T1, typename T2>
+ struct Duple_less : std::binary_function<T1, T2, bool> {
+ public:
+ bool operator() (const std::pair<T1, T2> l, const std::pair<T1, T2> r) const {
+ if (l.first == r.first)
+ return (l.second < r.second);
+ else
+ return (l.first < r.first);
+ }
+ };
+
+ /**
+ * \brief Function object for comparing map entries based on their values.
+ *
+ * T might be, e.g., std::map<char, size_t>
+ */
+ template<typename T>
+ struct Map_value_less : std::binary_function<T, T, bool> {
+ public:
+ bool operator() (const typename T::value_type& l, const typename T::value_type& r) const {
+ return l.second < r.second;
+ }
+ };
+
+
+ private:
+
+ static Regexp re_chr_stripper; ///< \see strip_leading_chr
+ static Regexp re_basename; ///< \see basename
+ static Regexp re_basename_extension; ///< \see basename
+
+ };
+
+
+ template<typename T>
+ std::string Util::to_string (const T& t) {
+
+ std::stringstream ss;
+ ss << t;
+
+ return ss.str();
+
+ }
+
+ template<typename T>
+ std::string Util::join (const std::vector<T>& items,
+ const std::string& delimiter /* = "" */) {
+
+ std::stringstream joined;
+
+ // case the catch of no items
+ if (!items.size())
+ return joined.str();
+
+ // awkward loop structure is to avoid adding the delimiter onto the end of the string
+ typename std::vector<T>::const_iterator item;
+ for (item = items.begin(); (item + 1) != items.end(); ++item)
+ joined << *item << delimiter;
+ joined << *item;
+
+ return joined.str();
+
+ }
+
+ inline std::vector<std::string> Util::addprefix (const std::vector<std::string>& items,
+ const std::string prefix) {
+
+ std::vector<std::string> modified;
+ if (!items.size())
+ return modified;
+
+ for (std::vector<std::string>::const_iterator item = items.begin(); item != items.end(); ++item)
+ modified.push_back (prefix + *item);
+
+ return modified;
+
+ }
+
+ inline std::vector<std::string> Util::addsuffix (const std::vector<std::string>& items,
+ const std::string suffix) {
+
+ std::vector<std::string> modified;
+ if (!items.size())
+ return modified;
+
+ for (std::vector<std::string>::const_iterator item = items.begin(); item != items.end(); ++item)
+ modified.push_back (*item + suffix);
+
+ return modified;
+
+ }
+
+ template<typename T>
+ bool Util::contains (const std::vector<T>& items,
+ const T query) {
+
+ for (typename std::vector<T>::const_iterator item = items.begin(); item != items.end(); ++item) {
+ if (*item == query)
+ return true;
+ }
+
+ return false;
+
+ }
+
+ template<typename T>
+ std::vector<typename T::key_type> Util::keys (const T& container) {
+
+ std::vector<typename T::key_type> keys;
+ for (typename T::const_iterator item = container.begin(); item != container.end(); ++item)
+ keys.push_back (item->first);
+
+ return keys;
+
+ }
+
+ template<typename T>
+ std::vector<typename T::mapped_type> Util::values (const T& container) {
+
+ std::vector<typename T::mapped_type> values;
+ for (typename T::const_iterator item = container.begin(); item != container.end(); ++item)
+ values.push_back (item->second);
+
+ return values;
+
+ }
+
+ inline void Util::chomp (std::string& str) {
+
+ const int end = str.length() - 1;
+ if (end >= 0 && str[end] == '\n')
+ str.erase (end);
+
+ }
+
+ inline void Util::toupper (std::string& str) {
+
+ for (std::string::iterator s = str.begin(); s != str.end(); ++s)
+ *s = std::toupper (*s);
+
+ }
+
+ inline void Util::tolower (std::string& str) {
+
+ for (std::string::iterator s = str.begin(); s != str.end(); ++s)
+ *s = std::tolower (*s);
+
+ }
+
+ inline std::vector<std::string> Util::split (const std::string& str,
+ const std::string& delimiters /* = " " */) {
+
+ std::vector<std::string> tokens;
+
+ // Skip delimiters at beginning.
+ std::string::size_type lastpos = str.find_first_not_of (delimiters, 0);
+ // Find first "non-delimiter".
+ std::string::size_type pos = str.find_first_of (delimiters, lastpos);
+
+ while (std::string::npos != pos || std::string::npos != lastpos) {
+ // Found a token, add it to the vector.
+ tokens.push_back (str.substr (lastpos, pos - lastpos));
+ // Skip delimiters. Note the "not_of"
+ lastpos = str.find_first_not_of (delimiters, pos);
+ // Find next "non-delimiter"
+ pos = str.find_first_of (delimiters, lastpos);
+ }
+
+ return tokens;
+
+ }
+
+ inline unsigned Util::rand (const unsigned max) {
+ assert (max < RAND_MAX);
+ return std::rand() % (max + 1);
+ }
+
+ inline double Util::prob() {
+ return static_cast<double> (std::rand()) / RAND_MAX;
+ }
+
+ inline void Util::seed_rand (const unsigned seed) {
+ std::srand (seed);
+ }
+
+ inline void Util::seed_rand_on_time() {
+ std::srand (std::time (NULL));
+ }
+
+ inline size_t Util::choose_from_distribution (const std::vector<double>& dist) {
+ double prob = Util::prob();
+ for (size_t i = 0; i < dist.size() - 1; ++i) {
+ prob -= dist[i];
+ if (prob <= 0.)
+ return i;
+ }
+
+ // handle last case separately to accomodate floating-point error
+ return dist.size() - 1;
+
+ }
+
+}
+
+#endif /* UTIL_MISC_INCLUDED */
diff --git a/src/util/opts_list.cc b/src/util/opts_list.cc
new file mode 100755
index 0000000..458cd7a
--- /dev/null
+++ b/src/util/opts_list.cc
@@ -0,0 +1,433 @@
+#include <ctype.h>
+#include "util/opts_list.h"
+#include "util/macros.h"
+#include "util/logfile.h"
+
+using namespace fsa;
+
+void Opts_list::print (const char* text)
+{ options_help_text.append (text); }
+
+void Opts_list::newline()
+{ print ("\n"); }
+
+void Opts_list::print_title (const char* text)
+{
+ sstring underline (std::strlen(text), '-');
+ options_help_text << text << "\n" << underline << "\n";
+}
+
+sstring Opts_list::short_help() const
+{
+ sstring h = program_name;
+ if (short_description.size()) h << " - " << short_description << '\n';
+ if (syntax.size()) h << "\nUsage: " << program_name << " " << syntax << '\n';
+ if (short_help_text.size()) h << short_help_text << '\n';
+ return h;
+}
+
+Regexp help_tab_re ("^([^\t]+)\t+([^\t].*)$");
+sstring Opts_list::help() const
+{
+ sstring h = program_name;
+ if (short_description.size()) h << " - " << short_description << '\n';
+ if (syntax.size()) h << "Usage: " << program_name << " " << syntax << '\n';
+ if (options_help_text.size())
+ {
+ h << "\n";
+ h << "Command-line options (righthandmost options take precedence)\n";
+ h << "------------------------------------------------------------\n";
+ // split up the options_help_text by lines
+ const std::vector<sstring> help_lines = options_help_text.split ("\n", FALSE);
+ // split at tab, find max width of LHS
+ int max_lhs_width = 0;
+ for_const_contents (std::vector<sstring>, help_lines, line)
+ if (help_tab_re.Match (line->c_str()))
+ max_lhs_width = std::max (max_lhs_width, (int) help_tab_re[1].size());
+ // print out each line, again splitting tabs & aligning LHS
+ for_const_contents (std::vector<sstring>, help_lines, line)
+ if (help_tab_re.Match (line->c_str()))
+ {
+ const sstring lhs = help_tab_re[1];
+ const sstring rhs = help_tab_re[2];
+ h << lhs;
+ for (int i = (int) lhs.size(); i < max_lhs_width + 1; ++i)
+ h << ' ';
+ h << rhs << '\n';
+ }
+ else
+ h << *line << '\n';
+ h << "\n";
+ }
+ return h;
+}
+
+bool Opts_list::display_help (Opts_list* ol)
+{ cout << ol->help(); exit(0); return 1; }
+
+bool Opts_list::display_version (Opts_list* ol)
+{
+ cout << ol->program_name << ":\n" << ol->version_info;
+ exit(0);
+ return 1;
+}
+
+void Opts_list::set_expect_flag (Expect_flag& flag, const char* value_str)
+{
+ sstring value (value_str);
+ value.to_lower();
+ if (value == sstring("yes") || value == sstring("y")) flag = YES;
+ else if (value == sstring("no") || value == sstring("n")) flag = NO;
+ else if (value == sstring("auto") || value == sstring("a")) flag = AUTO;
+ else THROW Syntax_exception (*this, "expected 'yes', 'no' or 'auto'");
+}
+
+Opts_list::Opts_list (int argc, char** argv)
+ : argc(argc),
+ argv(argv),
+ alias_args(),
+ next_alias_arg (alias_args.end()),
+ init_argc(argc),
+ init_argv(argv),
+ expect_args(-1)
+{
+ program_name = next_string();
+ add ("h help -help", &display_help, "\tdisplay this message");
+ add ("v -version", &display_version, "\tdisplay version");
+ short_help_text.clear();
+ short_help_text << "Type \'" << program_name << " " << "--help\' for command-line options.";
+ SET_VERSION_INFO(*this);
+}
+
+Opts_list::~Opts_list()
+{ }
+
+bool Opts_list::more_args() const
+{
+ return next_alias_arg != alias_args.begin() || argc > 0;
+}
+
+double Opts_list::next_double()
+{
+ if (next_alias_arg != alias_args.begin())
+ {
+ const sstring& next_arg = *--next_alias_arg;
+ return next_arg.to_double();
+ }
+ if (--argc < 0) THROW Syntax_exception (*this, "missing floating-point argument");
+ return atof(*argv++);
+}
+
+int Opts_list::next_int()
+{
+ if (next_alias_arg != alias_args.begin())
+ {
+ const sstring& next_arg = *--next_alias_arg;
+ return next_arg.to_int();
+ }
+ if (--argc < 0) THROW Syntax_exception (*this, "missing integer argument");
+ return atoi(*argv++);
+}
+
+char* Opts_list::next_string()
+{
+ if (next_alias_arg != alias_args.begin())
+ {
+ const sstring& next_arg = *--next_alias_arg;
+ return (char*) next_arg.c_str(); // cast away const... hacky
+ }
+ if (--argc < 0) THROW Syntax_exception (*this, "missing string argument");
+ return *argv++;
+}
+
+void Opts_list::new_opt (const sstring& s)
+{
+ if (all_opts.find(s) != all_opts.end())
+ {
+ // print directly to cerr, as this exception is often thrown outside a clean handler
+ cerr << "Duplicate option: -" << s << "; about to throw an exception...\n";
+ cerr.flush();
+ THROWEXPR ("ERROR: Duplicate option: -" << s);
+ }
+ all_opts.insert(s);
+}
+
+sstring Opts_list::neg_opt (const sstring& s)
+{
+ sstring neg;
+ sstring::const_iterator i = s.begin();
+ while (i < s.end())
+ {
+ if (*i == '-') { neg << *i++; continue; }
+ neg << "no";
+ neg.append (i, s.end());
+ break;
+ }
+ return neg;
+}
+
+void Opts_list::add(const char*opt,bool&var,const char*desc, bool show_default, const char* negopt, const char* negdesc)
+{
+ sstring tmp (opt);
+ std::vector<sstring> v = tmp.split();
+ std::vector<sstring> negv;
+ if (negopt)
+ {
+ tmp = negopt;
+ negv = tmp.split();
+ }
+ else
+ for_contents (std::vector<sstring>, v, s)
+ negv.push_back (neg_opt (*s));
+ if (desc)
+ {
+ options_help_text << "-" << sstring::join (v,",-") << "\t";
+ int i = 0;
+ int desc_len = std::strlen(desc);
+ while (i < desc_len) if (isspace(desc[i])) options_help_text << desc[i++]; else break;
+ if (show_default && var) options_help_text << "(default) ";
+ while (i < desc_len) options_help_text << desc[i++];
+ const sstring& neg = negv.back();
+ if (show_default && var) options_help_text << " (-" << neg << " to disable)";
+ else if (negdesc) options_help_text << " (opposite of -" << neg << ")";
+ options_help_text << "\n";
+ }
+ if (negdesc)
+ {
+ options_help_text << " -" << sstring::join (negv,",-") << "\t ";
+ int i = 0;
+ int desc_len = std::strlen(negdesc);
+ while (i < desc_len) if (isspace(negdesc[i])) options_help_text << negdesc[i++]; else break;
+ if (show_default && !var) options_help_text << "(default) ";
+ while (i < desc_len) options_help_text << negdesc[i++];
+ const sstring& pos = v.back();
+ if (show_default && !var) options_help_text << " (-" << pos << " to disable)";
+ else if (desc) options_help_text << " (opposite of -" << pos << ")";
+ options_help_text << "\n";
+ }
+ for_contents (std::vector<sstring>, v, i)
+ {
+ new_opt (*i);
+ bool_opts[*i] = &var;
+ }
+ for_contents (std::vector<sstring>, negv, i)
+ {
+ new_opt (*i);
+ bool_no_opts[*i] = &var;
+ }
+}
+
+void Opts_list::add(const char*opt,int&var,const char*desc, bool show_default)
+{
+ sstring tmp (opt);
+ std::vector<sstring> v = tmp.split();
+ if (desc)
+ {
+ options_help_text << "-" << sstring::join (v,",-") << " <integer>\t" << desc;
+ if (show_default)
+ {
+ char buf[100];
+ sprintf (buf, "%d", var);
+ options_help_text << " (default is " << buf << ")";
+ }
+ options_help_text << "\n";
+ }
+ for_contents (std::vector<sstring>, v, i)
+ {
+ new_opt (*i);
+ int_opts[*i] = &var;
+ }
+}
+
+void Opts_list::add(const char*opt,double&var,const char*desc, bool show_default)
+{
+ sstring tmp (opt);
+ std::vector<sstring> v = tmp.split();
+ if (desc)
+ {
+ options_help_text << "-" << sstring::join (v,",-") << " <real>\t" << desc;
+ if (show_default)
+ {
+ char buf[100];
+ sprintf (buf, "%g", var);
+ options_help_text << " (default is " << buf << ")";
+ }
+ options_help_text << "\n";
+ }
+ for_contents (std::vector<sstring>, v, i)
+ {
+ new_opt (*i);
+ double_opts[*i] = &var;
+ }
+}
+
+void Opts_list::add (const char* opt, const char* alias, const char* desc, bool show_alias)
+{
+ sstring tmp (opt);
+ std::vector<sstring> v = tmp.split();
+ const sstring alias_str (alias);
+ if (desc)
+ {
+ options_help_text << '-' << sstring::join (v,",-") << '\t' << desc;
+ if (show_alias)
+ options_help_text << " (same as '" << alias << "')";
+ options_help_text << '\n';
+ }
+ for_contents (std::vector<sstring>, v, i)
+ {
+ new_opt (*i);
+ alias_opts[*i] = alias_str;
+ }
+}
+
+void Opts_list::add(const char*opt,Option_handler callback,const char*desc)
+{
+ sstring tmp (opt);
+ std::vector<sstring> v = tmp.split();
+ if (desc)
+ options_help_text << "-" << sstring::join (v,",-") << desc << "\n";
+ for_contents (std::vector<sstring>, v, i)
+ {
+ new_opt (*i);
+ callback_opts[*i] = callback;
+ }
+}
+
+void Opts_list::add(const char*opt,sstring&var,const char*desc, bool show_default)
+{
+ sstring tmp (opt);
+ std::vector<sstring> v = tmp.split();
+ if (desc)
+ {
+ options_help_text << "-" << sstring::join (v,",-") << " <string>\t" << desc;
+ if (show_default) options_help_text << " (default is \"" << var << "\")";
+ options_help_text << "\n";
+ }
+ for_contents (std::vector<sstring>, v, i)
+ {
+ new_opt (*i);
+ string_opts[*i] = &var;
+ }
+}
+
+std::vector<sstring> Opts_list::get_not_opts()
+{
+ std::vector<sstring> not_opts;
+ while (more_args())
+ {
+ sstring opt = next_string();
+ if (opt[0] != '-')
+ not_opts.push_back (opt);
+ else
+ {
+ opt.erase (opt.begin());
+ opt.to_lower();
+
+ if (int_opts.find(opt) != int_opts.end())
+ next_int();
+ else if (double_opts.find(opt) != double_opts.end())
+ next_double();
+ else if (string_opts.find(opt) != string_opts.end())
+ next_string();
+ else if (alias_opts.find(opt) != alias_opts.end())
+ {
+ const std::vector<sstring> alias_opts_vec = alias_opts[opt].split();
+ alias_args.insert (alias_args.begin(), alias_opts_vec.rbegin(), alias_opts_vec.rend());
+ }
+ else if (callback_opts.find(opt) != callback_opts.end())
+ {
+ (*callback_opts[opt]) (this);
+ }
+ }
+ }
+
+ // reset pointers
+ argc = init_argc;
+ argv = init_argv;
+
+ return not_opts;
+}
+
+bool Opts_list::parse()
+{
+ args.clear();
+ while (more_args())
+ {
+ sstring opt = next_string();
+
+ if (opt[0] != '-')
+ args.push_back (opt);
+ else
+ {
+ opt.erase (opt.begin());
+ opt.to_lower();
+
+ const Parse_status stat = parse_opt (opt);
+ if (stat == PARSE_OK || stat == PARSE_NOT_OK)
+ return stat == PARSE_OK;
+
+ else if (bool_opts.find(opt) != bool_opts.end())
+ *bool_opts[opt] = 1;
+
+ else if (bool_no_opts.find(opt) != bool_no_opts.end())
+ *bool_no_opts[opt] = 0;
+
+ else if (int_opts.find(opt) != int_opts.end())
+ *int_opts[opt] = next_int();
+
+ else if (double_opts.find(opt) != double_opts.end())
+ *double_opts[opt] = next_double();
+
+ else if (string_opts.find(opt) != string_opts.end())
+ *string_opts[opt] = next_string();
+
+ else if (alias_opts.find(opt) != alias_opts.end())
+ {
+ const std::vector<sstring> alias_opts_vec = alias_opts[opt].split();
+ alias_args.insert (alias_args.begin(), alias_opts_vec.rbegin(), alias_opts_vec.rend());
+ }
+
+ else if (callback_opts.find(opt) != callback_opts.end())
+ {
+ if (!(*callback_opts[opt]) (this))
+ return 0;
+ }
+
+ else
+ {
+ THROW Syntax_exception (*this, "unknown option: -", opt.c_str());
+ return 0;
+ }
+ }
+ }
+
+ if (expect_args >= 0 && (int) args.size() != expect_args)
+ THROWEXPR ("ERROR: Expected " << expect_args << " arguments, got " << args.size());
+
+ CTAG(5,OPTS) << "Parsed command line: ";
+ for (int i = 0; i < init_argc; i++) clog_stream << init_argv[i] << (i < init_argc - 1 ? " " : "\n");
+
+ bool parsed_ok = 1;
+ for_contents (std::vector<Option_handler>, post_parse_callback, callback) parsed_ok &= (*callback) (this);
+
+ return parsed_ok;
+}
+
+void Opts_list::parse_or_die()
+{
+ try
+ {
+ if (!parse()) { CLOGERR << short_help(); exit(1); }
+ }
+ catch (const Dart_exception& e)
+ {
+ cerr << short_help();
+ cerr << e.what();
+ exit(1);
+ }
+}
+
+Opts_list::Parse_status Opts_list::parse_opt (const sstring& opt)
+{
+ return UNPARSED;
+}
diff --git a/src/util/opts_list.h b/src/util/opts_list.h
new file mode 100755
index 0000000..9a1c637
--- /dev/null
+++ b/src/util/opts_list.h
@@ -0,0 +1,160 @@
+#ifndef OPTS_LIST_INCLUDED
+#define OPTS_LIST_INCLUDED
+
+#include <iostream>
+#include <cmath>
+#include <set>
+#include <map>
+#include <list>
+
+#include "util/dexception.h"
+#include "util/sstring.h"
+#include "config.h"
+
+namespace fsa {
+
+ // parser class for command line options & arguments of an executable
+ struct Opts_list {
+
+ // syntax error exception class... this is really archaic stuff
+ struct Syntax_exception : Dart_exception
+ {
+ const Opts_list& opts; // pointer to parent class
+ sstring temp; // temporary variable used by Dart_exception method
+ sstring info; // used to hold the error message
+
+ Syntax_exception (const Opts_list& opts, const char* msg) :
+ Dart_exception(), opts(opts), info(msg) {}
+ Syntax_exception (const Opts_list& opts, const char* msg1, const char* msg2) :
+ Dart_exception(), opts(opts), info(msg1) { info.append(msg2); }
+
+ // overrides Dart_exception method
+ const char* details() const
+ {
+ (sstring&) temp = "";
+ ((sstring&) temp).append("While parsing command line: ").append(info).append(".\n");
+ return temp.c_str();
+ }
+ };
+
+ // typedef for "option handlers" (callback member functions)
+ typedef bool (*Option_handler) (Opts_list*); // returns TRUE if parsed OK, FALSE if error
+
+ // type of option taking values "yes", "no" and "auto" (used in one piece of code dating from 1999, AFAIK...)
+ enum Expect_flag { YES, NO, AUTO };
+ void set_expect_flag (Expect_flag& flag, const char* value_str);
+
+ // member variables
+
+ // "current" argc and argv - these are used as pointers and are changed by the option parse code
+ int argc;
+ char** argv;
+
+ // aliased arguments
+ std::list<sstring> alias_args;
+ std::list<sstring>::iterator next_alias_arg;
+
+ // method to check if there are more args remaining
+ bool more_args() const;
+
+ // initial values of argc and argv
+ int init_argc;
+ char** init_argv;
+
+ int expect_args; // expected number of args: -1 for "any", otherwise will complain if not equal to this
+
+ // all options
+ std::set<sstring> all_opts;
+ void new_opt (const sstring& s);
+ static sstring neg_opt (const sstring& s); // puts a "no" in front of an option
+
+ // options by type
+ std::map <sstring, bool*> bool_opts;
+ std::map <sstring, bool*> bool_no_opts;
+ std::map <sstring, int*> int_opts;
+ std::map <sstring, double*> double_opts;
+ std::map <sstring, sstring*> string_opts;
+ std::map <sstring, Option_handler> callback_opts;
+ std::map <sstring, sstring> alias_opts;
+
+ // post-parse callback hooks
+ std::vector <Option_handler> post_parse_callback;
+
+ // various bits of help text
+ sstring program_name;
+ sstring short_description;
+ sstring version_info;
+ sstring syntax;
+ sstring short_help_text;
+ sstring options_help_text;
+
+ // arguments (extracted from the command line & stuck into this vector by the option-parsing code)
+ std::vector<sstring> args;
+
+ // member functions
+
+ // constructor
+ Opts_list (int argc, char** argv);
+
+ // virtual destructor
+ virtual ~Opts_list();
+
+ // builder methods to add options, with comments in help text
+ void add (const char* opt, bool& var, const char* desc = 0, bool show_default = 1, const char* negopt = 0, const char* negdesc = 0);
+ void add (const char* opt, int& var, const char* desc = 0, bool show_default = true);
+ void add (const char* opt, double& var, const char* desc = 0, bool show_default = true);
+ void add (const char* opt, sstring& var, const char* desc = 0, bool show_default = true);
+ void add (const char* opt, const char* alias, const char* desc = 0, bool show_alias = true);
+ void add (const char* opt, Option_handler callback, const char* desc = 0);
+
+ // builder methods to add comments to help text
+ void print (const char* text);
+ void newline();
+ void print_title (const char* text);
+
+ // parser methods
+ bool parse(); // returns TRUE if parsed OK
+ void parse_or_die();
+
+ // Get everything which doesn't begin with '-'
+ // (for collecting e.g. sequence filenames without parsing options).
+ // This is basically a hacked version of parse() which doesn't store
+ // bool, int, double or string option values
+ // (but alias and callback options /do/ get parsed).
+ // Pointers are reset afterwards for regular parsing with parse().
+ std::vector<sstring> get_not_opts();
+
+ // virtual parse method
+ enum Parse_status { UNPARSED = 0, PARSE_OK = 1, PARSE_NOT_OK = 2 };
+ virtual Parse_status parse_opt (const sstring& opt);
+
+ // parser helper methods
+ double next_double();
+ int next_int();
+ char* next_string();
+
+ // help text accessors
+ virtual sstring short_help() const; // prints program_name/short_description/syntax, short_help_text
+ virtual sstring help() const; // prints program_name/short_description/syntax, options_help_text
+
+ // option handler functions to display various bits of help text
+ static bool display_help (Opts_list* ol);
+ static bool display_version (Opts_list* ol);
+ };
+
+ // build macros
+#define SET_VERSION_INFO(OPTS) (OPTS).version_info.clear(); (OPTS).version_info << PACKAGE_STRING << " (" << DART_DEBUG_MODE_STRING << ") compiled " << __DATE__ << " " << __TIME__ << "\n";
+
+ //#define INIT_CONSTRUCTED_OPTS_LIST(OPTS,ARGS,SYNTAX,SHORTDESC) OPTS.short_description = (SHORTDESC); OPTS.syntax = (SYNTAX); OPTS.expect_args = (ARGS); SET_VERSION_INFO(OPTS); Rnd::add_opts(OPTS); OPTS.newline(); Log_stream::add_opts(OPTS);
+
+ // Rnd library removed 12/19/08
+ // -- RKB
+#define INIT_CONSTRUCTED_OPTS_LIST(OPTS,ARGS,SYNTAX,SHORTDESC) OPTS.short_description = (SHORTDESC); OPTS.syntax = (SYNTAX); OPTS.expect_args = (ARGS); SET_VERSION_INFO(OPTS); Log_stream::add_opts(OPTS);
+
+#define INIT_TYPED_OPTS_LIST(OPTS_TYPE,OPTS,ARGC,ARGV,ARGS,SYNTAX,SHORTDESC) OPTS_TYPE OPTS(ARGC,ARGV); INIT_CONSTRUCTED_OPTS_LIST(OPTS,ARGS,SYNTAX,SHORTDESC)
+
+#define INIT_OPTS_LIST(OPTS,ARGC,ARGV,ARGS,SYNTAX,SHORTDESC) INIT_TYPED_OPTS_LIST(Opts_list,OPTS,ARGC,ARGV,ARGS,SYNTAX,SHORTDESC)
+
+}
+
+#endif
diff --git a/src/util/regexp.cc b/src/util/regexp.cc
new file mode 100644
index 0000000..678f8c7
--- /dev/null
+++ b/src/util/regexp.cc
@@ -0,0 +1,1758 @@
+// See http://www.codeguru.com/Cpp/Cpp/string/regex/article.php/c2779/
+// for information on how to use this code.
+// -- RKB
+
+// Regexp.cc - regular expression class based on Henry Spencer's regexp code.
+// Adapted for Windows by Guy Gascoigne (see notes below)
+// Made unix-friendly by Ian Holmes ihh at lanl.gov April 30, 1999
+
+// In case this isn't obvious from the later comments this is an ALTERED
+// version of the software. If you like my changes then cool, but nearly
+// all of the functionality here is derived from Henry Spencer's original
+// work.
+//
+// This code should work correctly under both _SBCS and _UNICODE, I did
+// start working on making it work with _MBCS but gave up after a while
+// since I don't need this particular port and it's not going to be as
+// straight forward as the other two.
+//
+// The problem stems from the compiled program being stored as chars,
+// the individual items need to be wide enough to hold whatever character
+// is thrown at them, but currently they are accessed as an array of
+// whatever size integral type is appropriate. _MBCS would cause this
+// to be char, but at times it would need to be larger. This would
+// require making the program be an array of short with the appropriate
+// conversions used everywhere. Certainly it's doable, but it's a pain.
+// What's worse is that the current code will compile and run under _MBCS,
+// only breaking when it gets wide characters thrown against it.
+//
+// I've marked at least one bit of code with #pragma messages, I may not
+// get all of them, but they should be a start
+//
+// Guy Gascoigne - Piggford (ggp at bigfoot.com) Friday, February 27, 1998
+
+// EAT MY SHORTS - I took out all the casts to shorts cos they made my
+// SparcStation unhappy. ihh at lanl.gov April 30, 1999
+
+// regcomp and regexec -- regsub and regerror are elsewhere
+// @(#)regexp.c 1.3 of 18 April 87
+//
+// Copyright (c) 1986 by University of Toronto.
+// Written by Henry Spencer. Not derived from licensed software.
+//
+// Permission is granted to anyone to use this software for any
+// purpose on any computer system, and to redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The author is not responsible for the consequences of use of
+// this software, no matter how awful, even if they arise
+// from defects in it.
+//
+// 2. The origin of this software must not be misrepresented, either
+// by explicit claim or by omission.
+//
+// 3. Altered versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+// *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+// *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching
+// *** as in BSD grep and ex.
+// *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore,
+// *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \.
+// *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods,
+// *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy.
+// *** THIS IS AN ALTERED VERSION. It was altered by Geoffrey Noer,
+// *** THIS IS AN ALTERED VERSION. It was altered by Guy Gascoigne - Piggford
+// *** guy at wyrdrune.com, on 15 March 1998, porting it to C++ and converting
+// *** it to be the engine for the Regexp class
+// *** THIS IS AN ALTERED VERSION. It was altered by Ian Holmes,
+// *** ihh at fruitfly.org, on Jan 28 2000, porting it to gcc and DART's string
+// *** class (sstring)
+// *** THIS IS AN ALTERED VERSION. It was altered by Robert Bradley,
+// *** Dec 4 2008, changing the string class: sstring -> std::string.
+//
+// Beware that some of this code is subtly aware of the way operator
+// precedence is structured in regular expressions. Serious changes in
+// regular-expression syntax might require a total rethink.
+
+#include <cassert>
+#include <iostream>
+#include <string.h>
+
+#include "util/regexp.h"
+
+// The first byte of the regexp internal "program" is actually this magic
+// number; the start node begins in the second byte.
+
+const char MAGIC = ((char)'\234');
+
+// #define new DEBUG_NEW
+
+// following line commented out by ihh, December 14 2003, because gcc doesn't care for it
+// #pragma warning( disable : 4711 ) // automatic inline selected
+
+// The "internal use only" fields in regexp.h are present to pass info from
+// compile to execute that permits the execute phase to run lots faster on
+// simple cases. They are:
+//
+// regstart char that must begin a match; '\0' if none obvious
+// reganch is the match anchored (at beginning-of-line only)?
+// regmust string (pointer into program) that match must include, or NULL
+// regmlen length of regmust string
+//
+// Regstart and reganch permit very fast decisions on suitable starting
+// points for a match, cutting down the work a lot. Regmust permits fast
+// rejection of lines that cannot possibly match. The regmust tests are
+// costly enough that regcomp() supplies a regmust only if the
+// r.e. contains something potentially expensive (at present, the only
+// such thing detected is * or + at the start of the r.e., which can
+// involve a lot of backup). Regmlen is supplied because the test in
+// regexec() needs it and regcomp() is computing it anyway.
+
+// Structure for regexp "program". This is essentially a linear encoding
+// of a nondeterministic finite-state machine (aka syntax charts or
+// "railroad normal form" in parsing technology). Each node is an opcode
+// plus a "next" pointer, possibly plus an operand. "Next" pointers of
+// all nodes except BRANCH implement concatenation; a "next" pointer with
+// a BRANCH on both ends of it is connecting two alternatives. (Here we
+// have one of the subtle syntax dependencies: an individual BRANCH (as
+// opposed to a collection of them) is never concatenated with anything
+// because of operator precedence.) The operand of some types of node is
+// a literal string; for others, it is a node leading into a sub-FSM. In
+// particular, the operand of a BRANCH node is the first node of the
+// branch. (NB this is *not* a tree structure: the tail of the branch
+// connects to the thing following the set of BRANCHes.) The opcodes
+// are:
+
+enum {
+// definition number opnd? meaning
+ END = 0, // no End of program.
+ BOL = 1, // no Match beginning of line.
+ EOL = 2, // no Match end of line.
+ ANY = 3, // no Match any character.
+ ANYOF = 4, // str Match any of these.
+ ANYBUT = 5, // str Match any but one of these.
+ BRANCH = 6, // node Match this, or the next..\&.
+ BACK = 7, // no "next" ptr points backward.
+ EXACTLY = 8, // str Match this string.
+ NOTHING = 9, // no Match empty string.
+ STAR = 10, // node Match this 0 or more times.
+ PLUS = 11, // node Match this 1 or more times.
+ WORDA = 12, // no Match "" at wordchar, where prev is nonword
+ WORDZ = 13, // no Match "" at nonwordchar, where prev is word
+ OPEN = 20, // no Sub-RE starts here.
+ // OPEN+1 is number 1, etc.
+ CLOSE = 30 // no Analogous to OPEN.
+};
+
+// Opcode notes:
+//
+// BRANCH The set of branches constituting a single choice are hooked
+// together with their "next" pointers, since precedence prevents
+// anything being concatenated to any individual branch. The
+// "next" pointer of the last BRANCH in a choice points to the
+// thing following the whole choice. This is also where the
+// final "next" pointer of each individual branch points; each
+// branch starts with the operand node of a BRANCH node.
+//
+// BACK Normal "next" pointers all implicitly point forward; BACK
+// exists to make loop structures possible.
+//
+// STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+// BRANCH structures using BACK. Simple cases (one character
+// per match) are implemented with STAR and PLUS for speed
+// and to minimize recursive plunges.
+//
+// OPEN,CLOSE ...are numbered at compile time.
+
+// A node is one char of opcode followed by two chars of "next" pointer.
+// "Next" pointers are stored as two 8-bit pieces, high order first. The
+// value is a positive offset from the opcode of the node containing it.
+// An operand, if any, simply follows the node. (Note that much of the
+// code generation knows about this implicit relationship.)
+//
+// Using two bytes for the "next" pointer is vast overkill for most things,
+// but allows patterns to get big without disasters.
+
+
+enum
+{
+ REGERR_SENTINEL_VALUE = 0,
+ REGERR_NULLARG = 1, REGERR_CORRUPTED, REGERR_CORRUPTION, REGERR_CORRUPTED_POINTERS,
+ REGERR_BAD_REGREPEAT, REGERR_CORRUPTED_OPCODE, REGERR_NULL_TO_REGSUB,
+ REGERR_DAMAGED_REGEXP_REGSUB, REGERR_DAMAGED_MATCH_STRING, REGERR_NULL_TO_REGCOMP,
+ REGERR_TO_BIG, REGERR_TO_MANY_PAREN, REGERR_UNTERMINATED_PAREN, REGERR_UNMATCHED_PAREN,
+ REGERR_INTERNAL_ERROR_JUNK, REGERR_OP_COULD_BE_EMPTY, REGERR_NESTED_OP, REGERR_INVALID_RANGE,
+ REGERR_UNMATCHED_BRACE, REGERR_INTERNAL_UNEXPECTED_CHAR, REGERR_OP_FOLLOWS_NOTHING,
+ REGERR_TRAILING_ESC, REGERR_INTERNAL_STRSCSPN, REGERR_NO_REGEXP
+};
+
+struct regErr
+{
+ int m_id;
+ const char* m_err;
+} errors[] = {
+ { REGERR_NULLARG, "NULL argument to regexec" },
+ { REGERR_CORRUPTED, "corrupted regexp" },
+ { REGERR_CORRUPTION, "regexp corruption" },
+ { REGERR_CORRUPTED_POINTERS, "corrupted pointers" },
+ { REGERR_BAD_REGREPEAT, "internal error: bad call of regrepeat" },
+ { REGERR_CORRUPTED_OPCODE, "corrupted opcode" },
+ { REGERR_NULL_TO_REGSUB, "NULL parm to regsub" },
+ { REGERR_DAMAGED_REGEXP_REGSUB, "damaged regexp fed to regsub" },
+ { REGERR_DAMAGED_MATCH_STRING, "damaged match string" },
+ { REGERR_NULL_TO_REGCOMP, "NULL argument to regcomp" },
+ { REGERR_TO_BIG, "regexp too big" },
+ { REGERR_TO_MANY_PAREN, "too many ()" },
+ { REGERR_UNTERMINATED_PAREN, "unterminated ()" },
+ { REGERR_UNMATCHED_PAREN, "unmatched ()" },
+ { REGERR_INTERNAL_ERROR_JUNK, "internal error: junk on end" },
+ { REGERR_OP_COULD_BE_EMPTY, "*+ operand could be empty" },
+ { REGERR_NESTED_OP, "nested *?+" },
+ { REGERR_INVALID_RANGE, "invalid [] range" },
+ { REGERR_UNMATCHED_BRACE, "unmatched []" },
+ { REGERR_INTERNAL_UNEXPECTED_CHAR, "internal error: \\0|) unexpected" },
+ { REGERR_OP_FOLLOWS_NOTHING, "?+* follows nothing" },
+ { REGERR_TRAILING_ESC, "trailing \\" },
+ { REGERR_INTERNAL_STRSCSPN, "internal error: strcspn 0" },
+ { REGERR_NO_REGEXP, "NULL regexp" },
+ { REGERR_SENTINEL_VALUE, "Unknown error" } // must be last value
+};
+
+// Flags to be passed up and down.
+
+enum {
+ HASWIDTH = 01, // Known never to match null string.
+ SIMPLE = 02, // Simple enough to be STAR/PLUS operand.
+ SPSTART = 04, // Starts with * or +.
+ WORST = 0 // Worst case.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class CRegErrorHandler
+{
+ friend class Regexp;
+ mutable std::string m_szError;
+ static const char* FindErr( int id );
+protected:
+ void ClearErrorString() const;
+ void regerror( const char* s ) const;
+ void regerror( int id ) const;
+public:
+ CRegErrorHandler() { }
+ CRegErrorHandler( const CRegErrorHandler & reh ) : m_szError( reh.m_szError ) {}
+
+ const std::string & GetErrorString() const;
+};
+
+void CRegErrorHandler::regerror( const char* s ) const
+{
+ std::cerr << "ERROR: regerror: " << s << "\n";
+ m_szError = s;
+}
+
+void CRegErrorHandler::regerror( int id ) const
+{
+ regerror( FindErr( id ) );
+}
+
+const std::string & CRegErrorHandler::GetErrorString() const
+{
+ return m_szError;
+}
+
+void CRegErrorHandler::ClearErrorString() const
+{
+ m_szError.clear();
+}
+
+const char* CRegErrorHandler::FindErr( int id )
+{
+ struct regErr * perr;
+ for (perr = errors; perr->m_id != REGERR_SENTINEL_VALUE; perr++ )
+ if ( perr->m_id == id )
+ return perr->m_err;
+
+ return perr->m_err; // since we've fallen off the array, perr->m_id == 0
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// All of the functions required to directly access the 'program'
+class CRegProgramAccessor : public CRegErrorHandler
+{
+public:
+ static inline char OP( char* p )
+ {
+ return (*(p));
+ }
+ static inline char* OPERAND( char* p )
+ {
+ return p + 3;
+ }
+ static inline char* regnext( char* p )
+ {
+ const int offset = (((unsigned char*)p)[1] << 8) + ((unsigned char*)p)[2];
+
+ if (offset == 0)
+ return(NULL);
+
+ return((OP(p) == BACK) ? p-offset : p+offset);
+ }
+#ifdef _RE_DEBUG
+ char* CRegProgramAccessor::regprop( char* op );
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// The internal interface to the regexp, wrapping the compilation as well as the
+// execution of the regexp (matching)
+
+class regexp_internal : public CRegProgramAccessor
+{
+ friend class CRegExecutor;
+ friend class Regexp;
+
+ int m_programSize;
+ char* startp[Regexp::NSUBEXP];
+ char* endp[Regexp::NSUBEXP];
+ char regstart; // Internal use only.
+ char reganch; // Internal use only.
+ char* regmust; // Internal use only.
+ int regmlen; // Internal use only.
+ char* program;
+
+ bool status;
+ int count; // used by Regexp to manage the reference counting of regexps
+ int numSubs;
+public:
+
+ regexp_internal( const char* exp, bool iCase );
+ regexp_internal( const regexp_internal & r );
+ ~regexp_internal();
+
+ void ignoreCase( const char * in, char * out );
+
+ bool regcomp( const char* exp );
+ bool regexec( char* str );
+ bool Status() const { return status; }
+
+ std::string GetReplaceString( const char* sReplaceExp ) const;
+
+ regexp_internal * getCopy();
+
+#ifdef _RE_DEBUG
+ void regdump();
+#endif
+
+#ifdef _DEBUG
+ std::string m_originalPattern;
+ std::string m_modifiedPattern;
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Compile / Validate the regular expression - ADT
+
+class CRegCompilerBase : public CRegProgramAccessor
+{
+public:
+ CRegCompilerBase( const char* parse );
+
+ char* reg(int paren, int *flagp);
+protected:
+ char* regparse; // Input-scan pointer.
+ int regnpar; // () count.
+
+ char* regbranch(int *flagp);
+ char* regpiece(int *flagp);
+ char* regatom(int *flagp);
+ inline bool ISREPN( char c ) { return ((c) == '*' || (c) == '+' || (c) == '?'); }
+
+ virtual void regc(int c) = 0;
+ virtual char* regnode(int op) = 0;
+ virtual void reginsert(char op, char* opnd) = 0;
+ virtual void regtail(char* p, char* val) = 0;
+ virtual void regoptail(char* p, char* val) = 0;
+
+ // virtual destructor, to keep gcc happy -- added by ihh, December 14, 2003
+ virtual ~CRegCompilerBase() { }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// First pass over the expression, testing for validity and returning the
+// program size
+
+class CRegValidator : public CRegCompilerBase
+{
+public:
+ CRegValidator( const char* parse );
+
+ inline long Size() const { return regsize; }
+private:
+ long regsize; // Code size.
+ char regdummy[3]; // NOTHING, 0 next ptr
+protected:
+ char* regnode(int) { regsize += 3; return regdummy; }
+ void regc(int) { regsize++; }
+ void reginsert(char, char*) { regsize += 3; }
+ void regtail(char*, char*) { return; }
+ void regoptail(char*, char*) { return; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Second pass, actually generating the program
+
+class CRegCompiler : public CRegCompilerBase
+{
+public:
+ CRegCompiler( const char* parse, char* prog );
+private:
+ char* regcode;
+protected:
+ // regc - emit (if appropriate) a byte of code
+ void regc(int b)
+ {
+ *regcode++ = (char)b;
+ }
+ char* regnode(int op);
+ void reginsert(char op, char* opnd);
+ void regtail(char* p, char* val);
+ void regoptail(char* p, char* val);
+};
+
+// regnode - emit a node
+char* CRegCompiler::regnode(int op)
+{
+ char* const ret = regcode;
+
+ char* ptr = ret;
+ *ptr++ = (char)op;
+ *ptr++ = '\0'; // Null next pointer.
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return(ret);
+}
+
+// reginsert - insert an operator in front of already-emitted operand
+//
+// Means relocating the operand.
+void CRegCompiler::reginsert(char op, char* opnd)
+{
+ char* place;
+
+ (void) memmove(opnd+3, opnd, (size_t)((regcode - opnd)*sizeof(char)));
+ regcode += 3;
+
+ place = opnd; // Op node, where operand used to be.
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+// regtail - set the next-pointer at the end of a node chain
+void CRegCompiler::regtail(char* p, char* val)
+{
+ char* scan;
+ char* temp;
+
+ // Find last node.
+ for (scan = p; (temp = regnext(scan)) != NULL; scan = temp)
+ continue;
+
+ int next_ptr = (OP(scan) == BACK) ? scan - val : val - scan;
+ ((unsigned char*)scan)[1] = (unsigned char) (next_ptr >> 8);
+ ((unsigned char*)scan)[2] = (unsigned char) (next_ptr & 0xff);
+
+ // debugging assertion added by ihh -- December 5, 2003
+ if (regnext(scan) != val)
+ regerror( REGERR_CORRUPTED );
+}
+
+// regoptail - regtail on operand of first argument; nop if operandless
+void CRegCompiler::regoptail(char* p, char* val)
+{
+ // "Operandless" and "op != BRANCH" are synonymous in practice.
+ if (OP(p) == BRANCH)
+ regtail(OPERAND(p), val);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CRegCompilerBase::CRegCompilerBase( const char* parse )
+ : regparse( (char*)parse ),
+ regnpar(1)
+{
+}
+
+CRegValidator::CRegValidator( const char* parse )
+ : CRegCompilerBase( parse ),
+ regsize(0)
+{
+ regc(MAGIC);
+ regdummy[0] = NOTHING;
+ regdummy[1] = regdummy[2] = 0;
+}
+
+CRegCompiler::CRegCompiler( const char* parse, char* prog )
+ : CRegCompilerBase( parse ),
+ regcode(prog)
+{
+ regc(MAGIC);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+regexp_internal::regexp_internal( const char* exp, bool iCase )
+ : m_programSize(0),
+ regstart(0),
+ reganch(0),
+ regmust(0),
+ regmlen(0),
+ program(0)
+{
+#if _DEBUG
+ m_originalPattern = exp; // keep a version of the pattern for debugging
+#endif
+
+ if ( iCase )
+ {
+ char * out = new char[(strlen( exp ) * 4) + 1];
+ ignoreCase( exp, out );
+
+#if _DEBUG
+ m_modifiedPattern = out; // and the modified version if there is one
+#endif
+ status = regcomp( out );
+ delete [] out;
+ }
+ else
+ status = regcomp( exp );
+
+ count = numSubs = 0;
+}
+
+regexp_internal::regexp_internal( const regexp_internal & orig )
+ : m_programSize(orig.m_programSize),
+ regstart(orig.regstart),
+ reganch(orig.reganch),
+ regmust(0),
+ regmlen(orig.regmlen),
+ numSubs(orig.numSubs)
+{
+#if _DEBUG
+ m_originalPattern = orig.m_originalPattern;
+ m_modifiedPattern = orig.m_modifiedPattern;
+#endif
+ status = orig.status;
+ count = 0;
+ program = new char[m_programSize];
+ memcpy( program, orig.program, m_programSize * sizeof( char ) );
+ if ( orig.regmust )
+ regmust = program + ( orig.regmust - orig.program );
+
+ for ( int i = Regexp::NSUBEXP; i > 0; i--)
+ {
+ startp[i] = orig.startp[i];
+ endp[i] = orig.endp[i];
+ }
+}
+
+regexp_internal::~regexp_internal()
+{
+ delete [] program;
+}
+
+
+// regcomp - compile a regular expression into internal code
+//
+// We can't allocate space until we know how big the compiled form will
+// be, but we can't compile it (and thus know how big it is) until we've
+// got a place to put the code. So we cheat: we compile it twice, once
+// with code generation turned off and size counting turned on, and once
+// "for real". This also means that we don't allocate space until we are
+// sure that the thing really will compile successfully, and we never
+// have to move the code and thus invalidate pointers into it. (Note
+// that it has to be in one piece because free() must be able to free it
+// all.)
+//
+// Beware that the optimization-preparation code in here knows about some
+// of the structure of the compiled regexp.
+
+bool regexp_internal::regcomp(const char* exp)
+{
+ char* scan;
+ int flags;
+
+ if (exp == NULL)
+ {
+ regerror( REGERR_NULL_TO_REGCOMP );
+ return 0;
+ }
+
+ // First pass: determine size, legality.
+ CRegValidator tester( exp );
+
+ if (tester.reg(0, &flags) == NULL)
+ return false;
+
+ // Small enough for pointer-storage convention?
+ if (tester.Size() >= 0x7fffL) // Probably could be 0xffffL.
+ {
+ regerror(REGERR_TO_BIG);
+ return 0;
+ }
+
+ m_programSize = tester.Size();
+ // Allocate space.
+ program = new char[m_programSize];
+
+ CRegCompiler comp( exp, program );
+ // Second pass: emit code.
+ if (comp.reg(0, &flags) == NULL)
+ return false;
+
+ scan = program + 1; // First BRANCH.
+ if (OP(regnext(scan)) == END)
+ { // Only one top-level choice.
+ scan = OPERAND(scan);
+
+ // Starting-point info.
+ if (OP(scan) == EXACTLY)
+ regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ reganch = 1;
+
+ // If there's something expensive in the r.e., find the
+ // longest literal string that must appear and make it the
+ // regmust. Resolve ties in favor of later strings, since
+ // the regstart check works with the beginning of the r.e.
+ // and avoiding duplication strengthens checking. Not a
+ // strong reason, but sufficient in the absence of others.
+
+ if (flags&SPSTART)
+ {
+ char* longest = NULL;
+ size_t len = 0;
+
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len)
+ {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
+ }
+ regmust = longest;
+ regmlen = (int)len;
+ }
+ }
+
+ return true;
+}
+
+regexp_internal * regexp_internal::getCopy()
+{
+ return new regexp_internal( *this );
+}
+
+// reg - regular expression, i.e. main body or parenthesized thing
+//
+// Caller must absorb opening parenthesis.
+//
+// Combining parenthesis handling with the base level of regular expression
+// is a trifle forced, but the need to tie the tails of the branches to what
+// follows makes it hard to avoid.
+
+char* CRegCompilerBase::reg( int paren, int *flagp )
+{
+ char* ret = 0;
+ char* br;
+ char* ender;
+ int parno = 0;
+ int flags;
+
+ *flagp = HASWIDTH; // Tentatively.
+
+ if (paren)
+ {
+ // Make an OPEN node.
+ if (regnpar >= Regexp::NSUBEXP)
+ {
+ regerror(REGERR_TO_MANY_PAREN);
+ return NULL;
+ }
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN+parno);
+ }
+
+ // Pick up the branches, linking them together.
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ if (paren)
+ regtail(ret, br); // OPEN -> first.
+ else
+ ret = br;
+ *flagp &= ~(~flags&HASWIDTH); // Clear bit if bit 0.
+ *flagp |= flags&SPSTART;
+ while (*regparse == '|')
+ {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ regtail(ret, br); // BRANCH -> BRANCH.
+ *flagp &= ~(~flags&HASWIDTH);
+ *flagp |= flags&SPSTART;
+ }
+
+ // Make a closing node, and hook it on the end.
+ ender = regnode((paren) ? CLOSE+parno : END);
+ regtail(ret, ender);
+
+ // Hook the tails of the branches to the closing node.
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ // Check for proper termination.
+ if (paren && *regparse++ != ')')
+ {
+ regerror( REGERR_UNTERMINATED_PAREN );
+ return NULL;
+ }
+ else if (!paren && *regparse != '\0')
+ {
+ if (*regparse == ')')
+ {
+ regerror( REGERR_UNMATCHED_PAREN );
+ return NULL;
+ }
+ else
+ {
+ regerror( REGERR_INTERNAL_ERROR_JUNK );
+ return NULL;
+ }
+ // NOTREACHED
+ }
+
+ return(ret);
+}
+
+// regbranch - one alternative of an | operator
+//
+// Implements the concatenation operator.
+
+char* CRegCompilerBase::regbranch(int *flagp)
+{
+ char* ret;
+ char* chain;
+ char* latest;
+ int flags;
+ int c;
+
+ *flagp = WORST; // Tentatively.
+
+ ret = regnode(BRANCH);
+ chain = NULL;
+ while ((c = *regparse) != '\0' && c != '|' && c != ')')
+ {
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return(NULL);
+ *flagp |= flags&HASWIDTH;
+ if (chain == NULL) // First piece.
+ *flagp |= flags&SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == NULL) // Loop ran zero times.
+ (void) regnode(NOTHING);
+
+ return(ret);
+}
+
+// regpiece - something followed by possible [*+?]
+//
+// Note that the branching code sequences used for ? and the general cases
+// of * and + are somewhat optimized: they use the same NOTHING node as
+// both the endmarker for their branch list and the body of the last branch.
+// It might seem that this node could be dispensed with entirely, but the
+// endmarker role is not redundant.
+
+char* CRegCompilerBase::regpiece(int *flagp)
+{
+ char* ret;
+ char op;
+ char* next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return(NULL);
+
+ op = *regparse;
+ if (!ISREPN(op))
+ {
+ *flagp = flags;
+ return(ret);
+ }
+
+ if (!(flags&HASWIDTH) && op != '?' )
+ {
+ regerror( REGERR_OP_COULD_BE_EMPTY );
+ return NULL;
+ }
+ switch (op)
+ {
+ case '*': *flagp = WORST|SPSTART; break;
+ case '+': *flagp = WORST|SPSTART|HASWIDTH; break;
+ case '?': *flagp = WORST; break;
+ }
+
+ if (op == '*' && (flags&SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*')
+ {
+ // Emit x* as (x&|), where & means "self".
+ reginsert(BRANCH, ret); // Either x
+ regoptail(ret, regnode(BACK)); // and loop
+ regoptail(ret, ret); // back
+ regtail(ret, regnode(BRANCH)); // or
+ regtail(ret, regnode(NOTHING)); // null.
+ }
+ else if (op == '+' && (flags&SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+' )
+ {
+ // Emit x+ as x(&|), where & means "self".
+ next = regnode(BRANCH); // Either
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); // loop back
+ regtail(next, regnode(BRANCH)); // or
+ regtail(ret, regnode(NOTHING)); // null.
+ }
+ else if (op == '?' )
+ {
+ // Emit x? as (x|)
+ reginsert(BRANCH, ret); // Either x
+ regtail(ret, regnode(BRANCH)); // or
+ next = regnode(NOTHING); // null.
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISREPN(*regparse))
+ {
+ regerror( REGERR_NESTED_OP );
+ return NULL;
+ }
+
+ return(ret);
+}
+
+// regatom - the lowest level
+//
+// Optimization: gobbles an entire sequence of ordinary characters so that
+// it can turn them into a single node, which is smaller to store and
+// faster to run. Backslashed characters are exceptions, each becoming a
+// separate node; the code is simpler that way and it's not worth fixing.
+
+char* CRegCompilerBase::regatom(int * flagp)
+{
+ char* ret;
+ int flags;
+
+ *flagp = WORST; // Tentatively.
+
+ switch ( *regparse++ )
+ {
+ // FIXME: these chars only have meaning at beg/end of pat?
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ case '[':
+ {
+ int range;
+ int rangeend;
+ int c;
+
+ if (*regparse == '^')
+ { // Complement of range.
+ ret = regnode(ANYBUT);
+ regparse++;
+ }
+ else
+ ret = regnode(ANYOF);
+ if ((c = *regparse) == ']' || c == '-')
+ {
+ regc(c);
+ regparse++;
+ }
+ while ((c = *regparse++ ) != '\0' && c != ']')
+ {
+ if (c != '-')
+ regc(c);
+ else if ((c = *regparse) == ']' || c == '\0')
+ regc('-');
+ else
+ {
+ range = (char)*(regparse-2);
+ rangeend = (char)c;
+ if (range > rangeend)
+ {
+ regerror( REGERR_INVALID_RANGE );
+ return NULL;
+ }
+ for (range++; range <= rangeend; range++)
+ regc(range);
+ regparse++;
+ }
+ }
+ regc('\0');
+ if (c != ']')
+ {
+ regerror( REGERR_UNMATCHED_BRACE );
+ return NULL;
+ }
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ }
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == NULL)
+ return(NULL);
+ *flagp |= flags&(HASWIDTH|SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case ')':
+ // supposed to be caught earlier
+ regerror( REGERR_INTERNAL_UNEXPECTED_CHAR );
+ return NULL;
+ case '?':
+ case '+':
+ case '*':
+ {
+ regerror( REGERR_OP_FOLLOWS_NOTHING );
+ return NULL;
+ }
+ case '\\':
+ switch (*regparse++)
+ {
+ case '\0':
+ {
+ regerror( REGERR_TRAILING_ESC );
+ return NULL;
+ }
+ case '<':
+ ret = regnode(WORDA);
+ break;
+ case '>':
+ ret = regnode(WORDZ);
+ break;
+ /* FIXME: Someday handle \1, \2, ... */
+ default:
+ /* Handle general quoted chars in exact-match routine */
+ goto de_fault;
+ }
+ break;
+ de_fault:
+ default:
+ // Encode a string of characters to be matched exactly.
+ //
+ // This is a bit tricky due to quoted chars and due to
+ // '*', '+', and '?' taking the SINGLE char previous
+ // as their operand.
+ //
+ // On entry, the char at regparse[-1] is going to go
+ // into the string, no matter what it is. (It could be
+ // following a \ if we are entered from the '\' case.)
+ //
+ // Basic idea is to pick up a good char in ch and
+ // examine the next char. If it's *+? then we twiddle.
+ // If it's \ then we frozzle. If it's other magic char
+ // we push ch and terminate the string. If none of the
+ // above, we push ch on the string and go around again.
+ //
+ // regprev is used to remember where "the current char"
+ // starts in the string, if due to a *+? we need to back
+ // up and put the current char in a separate, 1-char, string.
+ // When regprev is NULL, ch is the only char in the
+ // string; this is used in *+? handling, and in setting
+ // flags |= SIMPLE at the end.
+ {
+ char *regprev;
+ register char ch;
+
+ regparse--; /* Look at cur char */
+ ret = regnode(EXACTLY);
+ for ( regprev = 0 ; ; ) {
+ ch = *regparse++; /* Get current char */
+ switch (*regparse) { /* look at next one */
+
+ default:
+ regc(ch); /* Add cur to string */
+ break;
+
+ case '.': case '[': case '(':
+ case ')': case '|': case '\n':
+ case '$': case '^':
+ case '\0':
+ /* FIXME, $ and ^ should not always be magic */
+ magic:
+ regc(ch); /* dump cur char */
+ goto done; /* and we are done */
+
+ case '?': case '+': case '*':
+ if (!regprev) /* If just ch in str, */
+ goto magic; /* use it */
+ /* End mult-char string one early */
+ regparse = regprev; /* Back up parse */
+ goto done;
+
+ case '\\':
+ regc(ch); /* Cur char OK */
+ switch (regparse[1]){ /* Look after \ */
+ case '\0':
+ case '<':
+ case '>':
+ /* FIXME: Someday handle \1, \2, ... */
+ goto done; /* Not quoted */
+ default:
+ /* Backup point is \, scan * point is after it. */
+ regprev = regparse;
+ regparse++;
+ continue; /* NOT break; */
+ }
+ }
+ regprev = regparse; /* Set backup point */
+ }
+ done:
+ regc('\0');
+ *flagp |= HASWIDTH;
+ if (!regprev) /* One char? */
+ *flagp |= SIMPLE;
+ }
+ break;
+ }
+
+ return(ret);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// regexec and friends
+
+// Work-variable struct for regexec().
+
+class CRegExecutor : public CRegProgramAccessor
+{
+ friend bool regexp_internal::regexec( char* str );
+
+ char* reginput; // String-input pointer.
+ char* regbol; // Beginning of input, for ^ check.
+ char* * regstartp; // Pointer to startp array.
+ char* * regendp; // Ditto for endp.
+
+ regexp_internal * prog;
+public:
+ CRegExecutor( regexp_internal * prog, char* str );
+protected:
+ bool regtry( char* str );
+ bool regmatch( char* prog );
+ size_t regrepeat( char* node );
+};
+
+CRegExecutor::CRegExecutor( regexp_internal * p, char* str )
+ : regbol( str ),
+ regstartp( p->startp ),
+ regendp( p->endp ),
+ prog(p)
+{
+}
+
+#ifdef _RE_DEBUG
+int regnarrate = 0;
+#endif
+
+// regexec - match a regexp against a string
+
+bool regexp_internal::regexec( char* str )
+{
+ // Be paranoid.
+ if ( str == NULL )
+ {
+ regerror( REGERR_NULLARG );
+ return false;
+ }
+
+ // Check validity of program.
+ if (*program != MAGIC)
+ {
+ regerror( REGERR_CORRUPTED );
+ return false;
+ }
+
+ // If there is a "must appear" string, look for it.
+ if ( regmust != NULL && strstr( str, regmust ) == NULL )
+ return false;
+
+ CRegExecutor executor( this, str );
+
+ // Simplest case: anchored match need be tried only once.
+ if ( reganch )
+ return( executor.regtry( str ) );
+
+ // Messy cases: unanchored match.
+ if ( regstart != '\0' )
+ {
+ // We know what char it must start with.
+ for ( char* s = str; s != NULL; s = strchr( s+1 , regstart ) )
+ if ( executor.regtry( s) )
+ return true;
+ return false;
+ }
+ else
+ {
+ // We don't -- general case.
+ for ( char* s = str; ! executor.regtry( s ); s++ )
+ if (*s == '\0')
+ return false;
+ }
+ return true;
+}
+
+// regtry - try match at specific point
+bool CRegExecutor::regtry( char* str )
+{
+ int i;
+ char* * stp;
+ char* * enp;
+
+ reginput = str;
+
+ stp = prog->startp;
+ enp = prog->endp;
+ for (i = Regexp::NSUBEXP; i > 0; i--)
+ {
+ *stp++ = NULL;
+ *enp++ = NULL;
+ }
+ if ( regmatch( prog->program + 1 ) )
+ {
+ prog->startp[0] = str;
+ prog->endp[0] = reginput;
+ return true;
+ }
+ else
+ return false;
+}
+
+// regmatch - main matching routine
+//
+// Conceptually the strategy is simple: check to see whether the current
+// node matches, call self recursively to see whether the rest matches,
+// and then act accordingly. In practice we make some effort to avoid
+// recursion, in particular by going through "ordinary" nodes (that don't
+// need to know whether the rest of the match failed) by a loop instead of
+// by recursion.
+
+bool CRegExecutor::regmatch( char* prog )
+{
+ char* scan; // Current node.
+ char* next; // Next node.
+
+#ifdef _RE_DEBUG
+ if (prog != NULL && regnarrate)
+ _ftprintf(stderr, "%s(\n", regprop(prog));
+#endif
+ for (scan = prog; scan != NULL; scan = next)
+ {
+#ifdef _RE_DEBUG
+ if (regnarrate)
+ _ftprintf(stderr, "%s...\n", regprop(scan));
+#endif
+ next = regnext(scan);
+
+ switch (OP(scan))
+ {
+ case BOL:
+ if (reginput != regbol)
+ return false;
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return false;
+ break;
+ case WORDA:
+ /* Must be looking at a letter, digit, or _ */
+ if ((!isalnum(*reginput)) && *reginput != '_')
+ return(0);
+ /* Prev must be BOL or nonword */
+ if (reginput > regbol &&
+ (isalnum(reginput[-1]) || reginput[-1] == '_'))
+ return(0);
+ break;
+ case WORDZ:
+ /* Must be looking at non letter, digit, or _ */
+ if (isalnum(*reginput) || *reginput == '_')
+ return(0);
+ /* We don't care what the previous char was */
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return false;
+ reginput++;
+ break;
+ case EXACTLY:
+ {
+ size_t len;
+ char* const opnd = OPERAND(scan);
+
+ // Inline the first character, for speed.
+ if (*opnd != *reginput)
+ return false;
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return false;
+ reginput += len;
+
+ break;
+ }
+ case ANYOF:
+ if (*reginput == '\0' ||
+ strchr(OPERAND(scan), *reginput) == NULL)
+ return false;
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' ||
+ strchr(OPERAND(scan), *reginput) != NULL)
+ return false;
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN+1: case OPEN+2: case OPEN+3:
+ case OPEN+4: case OPEN+5: case OPEN+6:
+ case OPEN+7: case OPEN+8: case OPEN+9:
+ {
+ const int no = OP(scan) - OPEN;
+ char* const input = reginput;
+
+ if (regmatch(next))
+ {
+ // Don't set startp if some later
+ // invocation of the same parentheses
+ // already has.
+
+ if (regstartp[no] == NULL)
+ regstartp[no] = input;
+ return true;
+ }
+ else
+ return false;
+ break;
+ }
+ case CLOSE+1: case CLOSE+2: case CLOSE+3:
+ case CLOSE+4: case CLOSE+5: case CLOSE+6:
+ case CLOSE+7: case CLOSE+8: case CLOSE+9:
+ {
+ const int no = OP(scan) - CLOSE;
+ char* const input = reginput;
+
+ if (regmatch(next))
+ {
+ // Don't set endp if some later
+ // invocation of the same parentheses
+ // already has.
+
+ if (regendp[no] == NULL)
+ regendp[no] = input;
+ return true;
+ }
+ else
+ return false;
+ break;
+ }
+ case BRANCH:
+ {
+ char* const save = reginput;
+
+ if (OP(next) != BRANCH) // No choice.
+ next = OPERAND(scan); // Avoid recursion.
+ else
+ {
+ while (OP(scan) == BRANCH)
+ {
+ if (regmatch(OPERAND(scan)))
+ return true;
+ reginput = save;
+ scan = regnext(scan);
+ }
+ return false;
+ // NOTREACHED
+ }
+ break;
+ }
+ case STAR: case PLUS:
+ {
+ const char nextch = (OP(next) == EXACTLY) ? *OPERAND(next) : '\0';
+ size_t no;
+ char* const save = reginput;
+ const size_t min = (OP(scan) == STAR) ? 0 : 1;
+
+ for (no = regrepeat(OPERAND(scan)) + 1; no > min; no--)
+ {
+ reginput = save + no - 1;
+ // If it could work, try it.
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return true;
+ }
+ return false;
+ break;
+ }
+ case END:
+ return true; // Success!
+ break;
+ default:
+ regerror( REGERR_CORRUPTION );
+ return false;
+ break;
+ }
+ }
+
+ // We get here only if there's trouble -- normally "case END" is
+ // the terminating point.
+
+ regerror( REGERR_CORRUPTED_POINTERS );
+ return false;
+}
+
+// regrepeat - report how many times something simple would match
+
+size_t CRegExecutor::regrepeat( char* node )
+{
+ size_t count;
+ char* scan;
+ char ch;
+
+ switch (OP(node))
+ {
+ case ANY:
+ return(strlen(reginput));
+ break;
+ case EXACTLY:
+ ch = *OPERAND(node);
+ count = 0;
+ for (scan = reginput; *scan == ch; scan++)
+ count++;
+ return(count);
+ break;
+ case ANYOF:
+ return(strspn(reginput, OPERAND(node)));
+ break;
+ case ANYBUT:
+ return(strcspn(reginput, OPERAND(node)));
+ break;
+ default: // Oh dear. Called inappropriately.
+ regerror( REGERR_BAD_REGREPEAT );
+ return(0); // Best compromise.
+ break;
+ }
+ // NOTREACHED
+}
+
+#ifdef _RE_DEBUG
+
+// regdump - dump a regexp onto stdout in vaguely comprehensible form
+
+void regexp_internal::regdump()
+{
+ char* s;
+ char op = EXACTLY; // Arbitrary non-END op.
+ char* next;
+
+ s = strinc(program);
+ while (op != END)
+ { // While that wasn't END last time...
+ op = OP(s);
+ _tprintf("%2d%s", s-program, regprop(s)); // Where, what.
+ next = regnext(s);
+ if (next == NULL) // Next ptr.
+ _tprintf("(0)");
+ else
+ _tprintf("(%d)", (s-program)+(next-s));
+ s += 3;
+ if (op == ANYOF || op == ANYBUT || op == EXACTLY)
+ {
+ // Literal string, where present.
+ while (*s != '\0')
+ {
+ _putchar(*s);
+ s = strinc(s);
+ }
+ s = strinc(s);
+ }
+ _putchar('\n');
+ }
+
+ // Header fields of interest.
+ if (regstart != '\0')
+ _tprintf("start `%c' ", regstart);
+ if (reganch)
+ _tprintf("anchored ");
+ if (regmust != NULL)
+ _tprintf("must have \"%s\"", regmust);
+ _tprintf("\n");
+}
+
+// regprop - printable representation of opcode
+
+#define OUTPUT(s) case s: p = s; break
+char* CRegProgramAccessor::regprop( char* op )
+{
+ char* p;
+ static char buf[50];
+
+ (void) strcpy(buf, ":");
+
+ switch (OP(op))
+ {
+ OUTPUT( BOL );
+ OUTPUT( EOL );
+ OUTPUT( ANY );
+ OUTPUT( ANYOF );
+ OUTPUT( ANYBUT );
+ OUTPUT( BRANCH );
+ OUTPUT( EXACTLY );
+ OUTPUT( NOTHING );
+ OUTPUT( BACK );
+ OUTPUT( END );
+ OUTPUT( STAR );
+ OUTPUT( PLUS );
+ OUTPUT( WORDA );
+ OUTPUT( WORDZ );
+ case OPEN+1: case OPEN+2: case OPEN+3:
+ case OPEN+4: case OPEN+5: case OPEN+6:
+ case OPEN+7: case OPEN+8: case OPEN+9:
+ _stprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+ p = NULL;
+ break;
+ case CLOSE+1: case CLOSE+2: case CLOSE+3:
+ case CLOSE+4: case CLOSE+5: case CLOSE+6:
+ case CLOSE+7: case CLOSE+8: case CLOSE+9:
+ _stprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+ p = NULL;
+ break;
+ default:
+ regerror( REGERR_CORRUPTED_OPCODE );
+ break;
+ }
+ if (p != NULL)
+ (void) strcat(buf, p);
+ return(buf);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+// constructor
+Regexp::Regexp()
+ : str(0),
+ rc(0)
+{ }
+
+Regexp::Regexp( const char* exp, bool iCase )
+ : str( 0 ),
+ rc( new regexp_internal( exp, iCase ) )
+{ }
+
+Regexp::Regexp( const std::string& exp, bool iCase )
+ : str( 0 ),
+ rc( new regexp_internal( exp.c_str(), iCase ) )
+{ }
+
+Regexp::Regexp( const Regexp &r )
+ : str(r.str),
+ m_szError(r.m_szError),
+ rc( r.rc )
+{
+ if ( rc )
+ rc->count++;
+}
+
+const Regexp & Regexp::operator=( const Regexp & r )
+{
+ if ( this != &r )
+ {
+ if ( rc && rc->count-- == 0 )
+ delete rc;
+
+ rc = r.rc;
+ if ( rc )
+ rc->count++;
+
+ str = r.str;
+ m_szError = r.m_szError;
+ }
+ return *this;
+}
+
+Regexp::~Regexp()
+{
+ if ( rc && rc->count-- == 0 )
+ delete rc;
+}
+
+bool Regexp::Match( const char * s )
+{
+ ClearErrorString();
+ str = s;
+ bool ret = false;
+ if ( rc )
+ {
+ // copy on write !
+
+ if ( rc->count )
+ {
+ rc->count--;
+ rc = rc->getCopy();
+ }
+
+ ret = rc->regexec( (char*) s );
+ int i = 0;
+ if ( ret )
+ for ( i = 0; i < Regexp::NSUBEXP && rc->startp[i] ; i++ )
+ ;
+ rc->numSubs = i - 1;
+ }
+ else
+ m_szError = CRegErrorHandler::FindErr( REGERR_NO_REGEXP );
+ return ret;
+}
+
+std::string Regexp::GetReplaceString( char* source ) const
+{
+ ClearErrorString();
+ if ( rc )
+ return rc->GetReplaceString( source );
+ else
+ m_szError = CRegErrorHandler::FindErr( REGERR_NO_REGEXP );
+ return "";
+}
+
+int Regexp::SubStrings() const
+{
+ ClearErrorString();
+ int ret = -1;
+ if ( rc )
+ ret = rc->numSubs;
+ else
+ m_szError = CRegErrorHandler::FindErr( REGERR_NO_REGEXP );
+ return ret;
+}
+
+int Regexp::SubStart( unsigned int i ) const
+{
+ ClearErrorString();
+ int ret = -1;
+ if ( rc )
+ ret = rc->startp[safeIndex(i)] - str;
+ else
+ m_szError = CRegErrorHandler::FindErr( REGERR_NO_REGEXP );
+ return ret;
+}
+
+int Regexp::SubLength( unsigned int i ) const
+{
+ ClearErrorString();
+ int ret = -1;
+ if ( rc )
+ {
+ i = safeIndex(i);
+ ret = rc->endp[i] - rc->startp[i];
+ }
+ else
+ m_szError = CRegErrorHandler::FindErr( REGERR_NO_REGEXP );
+ return ret;
+}
+
+bool Regexp::CompiledOK() const
+{
+ return rc ? rc->Status() : false;
+}
+
+#ifdef _RE_DEBUG
+void Regexp::Dump()
+{
+ if ( rc )
+ rc->regdump();
+#if defined( _DEBUG )
+ else
+ TRACE0( "No regexp to dump out\n" );
+#endif
+}
+#endif
+
+int Regexp::safeIndex( unsigned int i ) const
+{
+ return i < Regexp::NSUBEXP ? i : Regexp::NSUBEXP;
+}
+
+const std::string Regexp::operator[]( unsigned int i ) const
+{
+ ClearErrorString();
+ assert( rc );
+ if ( rc )
+ {
+ int len = SubLength(i);
+ std::string buffer (rc->startp[i], len);
+ return buffer;
+ }
+ else
+ {
+ m_szError = CRegErrorHandler::FindErr( REGERR_NO_REGEXP );
+ return "";
+ }
+}
+
+void regexp_internal::ignoreCase( const char * in, char * out )
+{
+ // copy in to out making every top level character a [Aa] set
+ bool inRange = 0;
+ while( *in )
+ {
+ if ( *in == '[' )
+ inRange = 1;
+ if ( *in == ']' )
+ inRange = 0;
+ if ( ! inRange && isalpha( *in ) )
+ {
+ *out++ = '[';
+ *out++ = (char)toupper( *in );
+ *out++ = (char)tolower( *in );
+ *out++ = ']';
+ }
+ else
+ *out++ = *in;
+ in++;
+ }
+ *out = 0;
+}
+
+// GetReplaceString - Converts a replace expression to a string
+// - perform substitutions after a regexp match
+// Returns - The resultant string
+std::string regexp_internal::GetReplaceString( const char* sReplaceExp ) const
+{
+ std::string szEmpty;
+
+ char *src = (char *)sReplaceExp;
+ char *buf = 0;
+ char c;
+ int no;
+ size_t len;
+
+ if( sReplaceExp == NULL )
+ {
+ regerror( REGERR_NULL_TO_REGSUB );
+ return szEmpty;
+ }
+ if ( *program != MAGIC)
+ {
+ regerror( REGERR_DAMAGED_REGEXP_REGSUB );
+ return szEmpty;
+ }
+
+ // First compute the length of the string
+ int replacelen = 0;
+ while ((c = *src++) != '\0')
+ {
+ if (c == '&')
+ no = 0;
+ else if (c == '\\' && isdigit(*src))
+ no = *src++ - '0';
+ else
+ no = -1;
+
+ if (no < 0)
+ {
+ // Ordinary character.
+ if (c == '\\' && (*src == '\\' || *src == '&'))
+ c = *src++;
+ replacelen++;
+ }
+ else if (startp[no] != NULL && endp[no] != NULL &&
+ endp[no] > startp[no])
+ {
+ // Get tagged expression
+ len = endp[no] - startp[no];
+ replacelen += len;
+ }
+ }
+
+ std::string szReplace (replacelen, '\0');
+
+ // Now we can create the string
+ src = (char *)sReplaceExp;
+ while ((c = *src++) != '\0')
+ {
+ if (c == '&')
+ no = 0;
+ else if (c == '\\' && isdigit(*src))
+ no = *src++ - '0';
+ else
+ no = -1;
+
+ if (no < 0)
+ {
+ // Ordinary character.
+ if (c == '\\' && (*src == '\\' || *src == '&'))
+ c = *src++;
+ szReplace.push_back(c);
+ }
+ else if (startp[no] != NULL && endp[no] != NULL &&
+ endp[no] > startp[no])
+ {
+ // Get tagged expression
+ len = endp[no] - startp[no];
+ strncpy(buf, startp[no], len);
+ buf += len;
+ if (len != 0 && *(buf-1) == '\0')
+ { /* strncpy hit NUL. */
+ regerror( REGERR_DAMAGED_MATCH_STRING );
+ return szEmpty;
+ }
+ }
+ }
+
+ return szReplace;
+}
+
+std::string Regexp::GetErrorString() const
+{
+ // make sure that if status == 0 that we have an error string
+ assert( ( ! CompiledOK() ) ? ( rc ? rc->GetErrorString() : m_szError).size() != 0 : 1 );
+ return rc ? rc->GetErrorString() : m_szError ;
+}
+
+void Regexp::ClearErrorString() const
+{
+ if ( rc )
+ rc->ClearErrorString();
+ m_szError.clear();
+}
+
diff --git a/src/util/regexp.h b/src/util/regexp.h
new file mode 100644
index 0000000..b00e53d
--- /dev/null
+++ b/src/util/regexp.h
@@ -0,0 +1,49 @@
+// Regexp.h - regular expression class based on Henry Spencer's regexp code.
+// Adapted for Windows by Guy Gascoigne (see notes in Regexp.cc)
+// Made unix-friendly by Ian Holmes ihh at lanl.gov April 30, 1999
+
+#ifndef UTIL_REGEXP_INCLUDED
+#define UTIL_REGEXP_INCLUDED
+
+#include <string>
+
+class regexp_internal; // internal interface to the regexp
+
+class Regexp // main regular expression class
+{
+public:
+ enum { NSUBEXP = 10 };
+
+ Regexp();
+ Regexp( const char* exp, bool iCase = false );
+ Regexp( const std::string& exp, bool iCase = false ); // added by Robert Bradley
+ Regexp( const Regexp &r );
+ ~Regexp();
+ const Regexp & operator=( const Regexp & r );
+
+ bool Match( const char * s );
+ int SubStrings() const;
+
+ const std::string operator[]( unsigned int i ) const;
+ int SubStart( unsigned int i ) const;
+ int SubLength( unsigned int i ) const;
+
+ std::string GetReplaceString( char* source ) const;
+
+ std::string GetErrorString() const;
+ bool CompiledOK() const;
+
+#if defined( _RE_DEBUG )
+ void Dump();
+#endif
+private:
+ const char * str; /* used to return substring offsets only */
+ mutable std::string m_szError;
+ regexp_internal * rc;
+
+ void ClearErrorString() const;
+ int safeIndex( unsigned int i ) const;
+
+};
+
+#endif /* UTIL_REGEXP_INCLUDED */
diff --git a/src/util/sstring.cc b/src/util/sstring.cc
new file mode 100644
index 0000000..2005a96
--- /dev/null
+++ b/src/util/sstring.cc
@@ -0,0 +1,159 @@
+
+#include <cstring>
+#include <algorithm>
+
+#include "util/sstring.h"
+#include "util/regexp.h"
+#include "util/macros.h"
+#include "util/logfile.h"
+
+#include "math/mathematics.h"
+
+// minimum buffer size for sstring::getline()
+#define DART_GETLINE_BUF_SIZE 100
+
+using namespace fsa;
+
+int string_with_streambuf::DART_string_streambuf::overflow(int c) { owner.push_back ((char) c); return c; }
+
+void sstring::to_lower()
+{
+ for_contents (sstring, *this, c)
+ if (*c >= 'A' && *c <= 'Z') *c += 'a' - 'A';
+}
+
+void sstring::to_upper()
+{
+ for_contents (sstring, *this, c)
+ if (*c >= 'a' && *c <= 'z') *c += 'A' - 'a';
+}
+
+std::vector<sstring> sstring::split (const char* split_chars, bool skip_empty_fields, int max_fields) const
+{
+ sstring expr;
+ expr << "^([^" << split_chars << "]*)([" << split_chars << "])(.*)";
+ Regexp parser (expr.c_str());
+
+ std::vector<sstring> result;
+ sstring tmp = *this;
+ while (--max_fields != 0 && parser.Match (tmp.c_str()))
+ {
+ if (parser[1].size() || !skip_empty_fields) result.push_back (parser[1]);
+ tmp = parser[3];
+ }
+ if (tmp.size() || !skip_empty_fields) result.push_back(tmp);
+
+ return result;
+}
+
+sstring sstring::join (const std::vector<sstring>& v, const char* sep)
+{
+ sstring result;
+ for (int i = 0; i+1 < (int) v.size(); i++) result.append(v[i]).append(sep);
+ if (v.size()) result.append(v.back());
+ return result;
+}
+
+sstring& sstring::getline (std::istream& is, size_type max_size)
+{
+ clear();
+ size_type buf_sz = std::max ((size_t) capacity(), (size_t) DART_GETLINE_BUF_SIZE);
+ const char term = '\n';
+ while (1)
+ {
+ // read from the stream, until we reach the delimiter character, or fill the buffer.
+ char buf [buf_sz];
+ is.get (buf, buf_sz, term);
+ append (buf);
+ if (is.eof())
+ break;
+ is.clear();
+ if (is.fail()) THROWEXPR ("ERROR: Couldn't clear fail bit.");
+ // read next character. If it's the delimiter, stop; otherwise, enlarge the buffer.
+ char c = '\0';
+ is.get (c);
+ push_back (c);
+ if (is.fail()) THROW Format_exception (is, "ERROR: Read failure\n");
+ if (is.eof())
+ break;
+ if (c == term)
+ {
+ is.clear();
+ break;
+ }
+ if (buf_sz >= max_size) THROW Format_exception (is, "ERROR: Line too long\n");
+ buf_sz = std::min (buf_sz * 2, max_size);
+ }
+ return *this;
+}
+
+Regexp int_regexp ("^\\-?[0-9]+$");
+int sstring::to_int_strict (const char* err_prefix) const
+{
+ if (!int_regexp.Match (c_str()))
+ THROWEXPR (err_prefix << ": " << *this);
+ return to_int();
+}
+
+Regexp nonneg_int_regexp ("^[0-9]+$");
+int sstring::to_nonneg_int_strict (const char* err_prefix) const
+{
+ if (!nonneg_int_regexp.Match (c_str()))
+ THROWEXPR (err_prefix << ": " << *this);
+ return to_int();
+}
+
+Regexp double_regexp ("^\\-?([0-9]*\\.)?[0-9]+([eE][\\+\\-]?[0-9]+)?$");
+double sstring::to_double_strict (const char* err_prefix) const
+{
+ if (!double_regexp.Match (c_str()))
+ THROWEXPR (err_prefix << ": " << *this);
+ return to_double();
+}
+
+Regexp nonneg_double_regexp ("^([0-9]*\\.)?[0-9]+([eE][\\+\\-]?[0-9]+)?$");
+double sstring::to_nonneg_double_strict (const char* err_prefix) const
+{
+ if (!nonneg_double_regexp.Match (c_str()))
+ THROWEXPR (err_prefix << ": " << *this);
+ return to_double();
+}
+
+sstring sstring::substr (int start, int len) const
+{
+ const int real_start = Mathematics::bounded_value (start, 0, (int) size());
+ const int real_end = Mathematics::bounded_value (start + len, real_start, (int) size());
+ sstring sub (begin() + real_start, begin() + real_end);
+ return sub;
+}
+
+char_string::char_string (char c) : sstring()
+{
+ add_char(c);
+}
+
+
+char_string::char_string (const char* s) : sstring()
+{
+ reserve (std::strlen (s));
+ for (; *s != '\0'; ++s) add_char(*s);
+}
+
+void char_string::add_char (char c)
+{
+ if (isprint(c))
+ *this << c;
+ else
+ {
+ char cstr[12];
+ sprintf (cstr, "\\%.3o", c);
+ *this << cstr;
+ }
+}
+
+void sstring::read_entire_file (const char* filename)
+{
+ std::ifstream sstring_stream (filename);
+ if (!sstring_stream) THROWEXPR ("ERROR: File '" << filename << "' not found.");
+ std::copy (std::istream_iterator<char> (sstring_stream), std::istream_iterator<char>(), back_inserter (*this));
+}
diff --git a/src/util/sstring.h b/src/util/sstring.h
new file mode 100644
index 0000000..355f7e5
--- /dev/null
+++ b/src/util/sstring.h
@@ -0,0 +1,131 @@
+#ifndef SSTRING_INCLUDED
+#define SSTRING_INCLUDED
+
+#include <cstdio>
+#include <string>
+#include <cstdlib>
+#include <string>
+#include <fstream>
+#include <vector>
+
+// RKB -- 5/29/08
+#include <iterator>
+
+#include "util/misc.h"
+
+// default maximum length for sstring::getline
+#define DART_MAX_LINE_SIZE 12345678
+
+namespace fsa {
+
+ // base class for sstring
+ class string_with_streambuf : public std::basic_string<char>
+ {
+ protected:
+ // streambuf prototype
+ class DART_string_streambuf : public std::streambuf
+ {
+ protected:
+ int overflow(int c);
+ public:
+ string_with_streambuf& owner;
+ DART_string_streambuf (string_with_streambuf& s) : owner(s) { }
+ };
+
+ // streambuf member
+ DART_string_streambuf sbuf;
+
+ public:
+ // constructors
+ string_with_streambuf() : std::basic_string<char>(), sbuf(*this) { }
+ string_with_streambuf (long n, const char value) : std::basic_string<char>(n,value), sbuf(*this) { }
+ string_with_streambuf (const std::basic_string<char>& x) : std::basic_string<char>(x), sbuf(*this) { }
+ string_with_streambuf (const string_with_streambuf& x) : std::basic_string<char>(x), sbuf(*this) { }
+#ifdef __STL_MEMBER_TEMPLATES
+ template <class InputIterator>
+ string_with_streambuf(InputIterator first, InputIterator last) : std::basic_string<char>(first, last), sbuf(*this) { }
+#else /* __STL_MEMBER_TEMPLATES */
+ string_with_streambuf(const_iterator first, const_iterator last) : std::basic_string<char>(first, last), sbuf(*this) { }
+#endif /* __STL_MEMBER_TEMPLATES */
+ string_with_streambuf (const char* x) : std::basic_string<char>(x), sbuf(*this) { }
+ string_with_streambuf (const char* x, size_type n) : std::basic_string<char>(x,n), sbuf(*this) { }
+ };
+
+ // sstring: DART string class
+ class sstring : public string_with_streambuf, public std::ostream
+ {
+ public:
+ sstring() : string_with_streambuf(), std::ostream(&sbuf) {}
+ sstring (size_type n, const char value = '\0') : string_with_streambuf(n,value), std::ostream(&sbuf) {}
+ sstring (int n, const char value = '\0') : string_with_streambuf(n,value), std::ostream(&sbuf) {}
+ sstring (long n, const char value = '\0') : string_with_streambuf(n,value), std::ostream(&sbuf) {}
+ sstring (const std::basic_string<char>& x) : string_with_streambuf(x), std::ostream(&sbuf) {}
+ sstring (const sstring& x) : string_with_streambuf(x), std::ostream(&sbuf) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+ template <class InputIterator>
+ sstring(InputIterator first, InputIterator last) : string_with_streambuf(first, last), std::ostream(&sbuf) {}
+#else /* __STL_MEMBER_TEMPLATES */
+ sstring(const_iterator first, const_iterator last) : string_with_streambuf(first, last), std::ostream(&sbuf) {}
+#endif /* __STL_MEMBER_TEMPLATES */
+
+ sstring (const char* x) : string_with_streambuf(x), std::ostream(&sbuf) {}
+ sstring (const char* x, size_type n) : string_with_streambuf(x,n), std::ostream(&sbuf) {}
+
+ void read_entire_file (const char* filename);
+
+ iterator end() { return ((std::basic_string<char>*) this) -> end(); }
+ const_iterator end() const { return ((const std::basic_string<char>*) this) -> end(); }
+
+ bool operator==(const std::basic_string<char>& x) const { return ((const std::basic_string<char>&) *this) == x; }
+ bool operator==(const char* x) const { return ((const std::basic_string<char>&) *this) == std::basic_string<char> (x); }
+
+ bool operator<(const std::basic_string<char>& x) const { return ((const std::basic_string<char>&) *this) < x; }
+
+ sstring& operator=(const sstring& x) { ((std::basic_string<char>&) *this) = (const std::basic_string<char>&) x; return *this; }
+ sstring& operator=(const std::basic_string<char>& x) { ((std::basic_string<char>&) *this) = x; return *this; }
+ sstring& operator=(const char* x) { ((std::basic_string<char>&) *this) = x; return *this; }
+
+ void push_back (char c) { append (1, c); }
+ void clear() { erase(); }
+ void to_lower();
+ void to_upper();
+
+ std::vector<sstring> split (const char* split_chars = " \t\n", bool skip_empty_fields = 1, int max_fields = 0) const;
+ static sstring join (const std::vector<sstring>& v, const char* sep = " ");
+
+ friend std::ostream& operator<<(std::ostream&o, const sstring& s) { return o << s.c_str(); }
+
+ sstring& getline (std::istream& is, size_type max_size = DART_MAX_LINE_SIZE);
+
+ char front() { char c = '\0'; if (size() > 0) c = *begin(); return c; }
+ char back() { char c = '\0'; if (size() > 0) c = *(end()-1); return c; }
+ char chop() { char c = '\0'; if (size() > 0) { c = back(); erase (end() - 1); } return c; }
+ char chomp (const char chomp_char = '\n') { return back() == chomp_char ? chop() : '\0'; }
+
+ int to_int() const { return atoi (c_str()); }
+ double to_double() const { return atof (c_str()); }
+
+ // strict versions of to_int() and to_double(), that do checking
+ int to_int_strict (const char* err_prefix = "Not an integer constant") const;
+ int to_nonneg_int_strict (const char* err_prefix = "Not a non-negative integer constant") const;
+ double to_double_strict (const char* err_prefix = "Not a numeric constant") const;
+ double to_nonneg_double_strict (const char* err_prefix = "Not a non-negative numeric constant") const;
+
+ sstring substr (int start, int len) const;
+
+ };
+
+ // char_string converts non-printable chars into octal
+ class char_string : public sstring
+ {
+ private:
+ void add_char (char c);
+ public:
+ char_string (char c);
+ char_string (const char* s);
+ };
+
+}
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..284b32e
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,3 @@
+AM_COLOR_TESTS=always
+TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
+TESTS = apps/isect_d.unmappable.bash apps/isect_eve.bash apps/isect_hairy.bash apps/map_eve.bash apps/map_hairy.bash apps/slice_eve.bash apps/slice_hairy.bash RV11.BBS11011.default.bash RV11.BBS11011.noindel2.bash RV11.BBS11011.nolearngap.bash RV11.BBS11011.nolearnemit-bypair.bash RV11.BBS11011.nolearnemit-all.bash RV11.BBS11011.nolearn.bash RV11.BBS11011.noregularize.bash RV11.BBS11011.refinement0.bash RV11.BBS11011.refinement1.bash RV11.BBS11011.maxsn.bash RV11.BBS11011.gapfactor0.bash [...]
diff --git a/tests/Makefile.in b/tests/Makefile.in
new file mode 100644
index 0000000..d213950
--- /dev/null
+++ b/tests/Makefile.in
@@ -0,0 +1,1198 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = tests
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/test-driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='[0;31m'; \
+ grn='[0;32m'; \
+ lgn='[1;32m'; \
+ blu='[1;34m'; \
+ mgn='[0;35m'; \
+ brg='[1m'; \
+ std='[m'; \
+ fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT at .log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXONERATE_EXEC = @EXONERATE_EXEC@
+GREP = @GREP@
+HAVE_CONDOR = @HAVE_CONDOR@
+HAVE_CONDOR_COMPILE = @HAVE_CONDOR_COMPILE@
+HAVE_JAVAC = @HAVE_JAVAC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAD_MAIN_CLASS = @MAD_MAIN_CLASS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUMMER_EXEC = @MUMMER_EXEC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_COLOR_TESTS = always
+TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
+TESTS = apps/isect_d.unmappable.bash apps/isect_eve.bash \
+ apps/isect_hairy.bash apps/map_eve.bash apps/map_hairy.bash \
+ apps/slice_eve.bash apps/slice_hairy.bash \
+ RV11.BBS11011.default.bash RV11.BBS11011.noindel2.bash \
+ RV11.BBS11011.nolearngap.bash \
+ RV11.BBS11011.nolearnemit-bypair.bash \
+ RV11.BBS11011.nolearnemit-all.bash RV11.BBS11011.nolearn.bash \
+ RV11.BBS11011.noregularize.bash RV11.BBS11011.refinement0.bash \
+ RV11.BBS11011.refinement1.bash RV11.BBS11011.maxsn.bash \
+ RV11.BBS11011.gapfactor0.bash RV11.BBS11011.gapfactor2.bash \
+ RV11.BBS11011.nodynamicweights.bash RV11.BBS11011.fast.bash \
+ RV11.BBS11011.refalign.bash RV11.BBS11011.bandwidth10.bash \
+ RV11.BBS11011.minprob0.1.bash mel-yak.11.bash all_empty.bash \
+ one_empty.bash length1.bash RV12.BBS12030.default.bash \
+ tRNA.aln1.default.bash mel-yak.233.aln1.default.bash \
+ RV12.BBS12030.noindel2.bash tRNA.aln1.nucprot.bash \
+ tRNA.aln1.loadprobs.bash RV12.BBS12030.nolearn.bash \
+ RV12.BBS12030.maxsn.bash RV12.BBS12030.refinement0.bash \
+ RV12.BBS12030.refinement1.bash \
+ RV12.BBS12030.nodynamicweights.bash tRNA.aln1.treeweights.bash \
+ mirna.refalign.bash mirna.fast.bash mirna.fast.maxsn.bash \
+ mirna.mst-min.bash mirna.mst-min.mst-max.bash \
+ mirna.mst-palm.degree.bash translated.anchored.bash \
+ RV12.BBS12030.nolearn.anchored.bash \
+ mel-yak.233.aln1.translated.bash \
+ mel-yak.233.aln1.exonerate.bash \
+ mel-yak.233.aln1.translated.exonerate.bash \
+ mel-yak.233.aln1.exonerate.mercator.bash \
+ mel-yak-sec.97.mercator.bash blanchette.seq00.exonerate.bash \
+ blanchette.seq00.exonerate.minscore50.bash \
+ blanchette.seq00.exonerate.bandwidth1000.bash
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .log .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ else \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+apps/isect_d.unmappable.bash.log: apps/isect_d.unmappable.bash
+ @p='apps/isect_d.unmappable.bash'; \
+ b='apps/isect_d.unmappable.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+apps/isect_eve.bash.log: apps/isect_eve.bash
+ @p='apps/isect_eve.bash'; \
+ b='apps/isect_eve.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+apps/isect_hairy.bash.log: apps/isect_hairy.bash
+ @p='apps/isect_hairy.bash'; \
+ b='apps/isect_hairy.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+apps/map_eve.bash.log: apps/map_eve.bash
+ @p='apps/map_eve.bash'; \
+ b='apps/map_eve.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+apps/map_hairy.bash.log: apps/map_hairy.bash
+ @p='apps/map_hairy.bash'; \
+ b='apps/map_hairy.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+apps/slice_eve.bash.log: apps/slice_eve.bash
+ @p='apps/slice_eve.bash'; \
+ b='apps/slice_eve.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+apps/slice_hairy.bash.log: apps/slice_hairy.bash
+ @p='apps/slice_hairy.bash'; \
+ b='apps/slice_hairy.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.default.bash.log: RV11.BBS11011.default.bash
+ @p='RV11.BBS11011.default.bash'; \
+ b='RV11.BBS11011.default.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.noindel2.bash.log: RV11.BBS11011.noindel2.bash
+ @p='RV11.BBS11011.noindel2.bash'; \
+ b='RV11.BBS11011.noindel2.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.nolearngap.bash.log: RV11.BBS11011.nolearngap.bash
+ @p='RV11.BBS11011.nolearngap.bash'; \
+ b='RV11.BBS11011.nolearngap.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.nolearnemit-bypair.bash.log: RV11.BBS11011.nolearnemit-bypair.bash
+ @p='RV11.BBS11011.nolearnemit-bypair.bash'; \
+ b='RV11.BBS11011.nolearnemit-bypair.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.nolearnemit-all.bash.log: RV11.BBS11011.nolearnemit-all.bash
+ @p='RV11.BBS11011.nolearnemit-all.bash'; \
+ b='RV11.BBS11011.nolearnemit-all.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.nolearn.bash.log: RV11.BBS11011.nolearn.bash
+ @p='RV11.BBS11011.nolearn.bash'; \
+ b='RV11.BBS11011.nolearn.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.noregularize.bash.log: RV11.BBS11011.noregularize.bash
+ @p='RV11.BBS11011.noregularize.bash'; \
+ b='RV11.BBS11011.noregularize.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.refinement0.bash.log: RV11.BBS11011.refinement0.bash
+ @p='RV11.BBS11011.refinement0.bash'; \
+ b='RV11.BBS11011.refinement0.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.refinement1.bash.log: RV11.BBS11011.refinement1.bash
+ @p='RV11.BBS11011.refinement1.bash'; \
+ b='RV11.BBS11011.refinement1.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.maxsn.bash.log: RV11.BBS11011.maxsn.bash
+ @p='RV11.BBS11011.maxsn.bash'; \
+ b='RV11.BBS11011.maxsn.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.gapfactor0.bash.log: RV11.BBS11011.gapfactor0.bash
+ @p='RV11.BBS11011.gapfactor0.bash'; \
+ b='RV11.BBS11011.gapfactor0.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.gapfactor2.bash.log: RV11.BBS11011.gapfactor2.bash
+ @p='RV11.BBS11011.gapfactor2.bash'; \
+ b='RV11.BBS11011.gapfactor2.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.nodynamicweights.bash.log: RV11.BBS11011.nodynamicweights.bash
+ @p='RV11.BBS11011.nodynamicweights.bash'; \
+ b='RV11.BBS11011.nodynamicweights.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.fast.bash.log: RV11.BBS11011.fast.bash
+ @p='RV11.BBS11011.fast.bash'; \
+ b='RV11.BBS11011.fast.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.refalign.bash.log: RV11.BBS11011.refalign.bash
+ @p='RV11.BBS11011.refalign.bash'; \
+ b='RV11.BBS11011.refalign.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.bandwidth10.bash.log: RV11.BBS11011.bandwidth10.bash
+ @p='RV11.BBS11011.bandwidth10.bash'; \
+ b='RV11.BBS11011.bandwidth10.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV11.BBS11011.minprob0.1.bash.log: RV11.BBS11011.minprob0.1.bash
+ @p='RV11.BBS11011.minprob0.1.bash'; \
+ b='RV11.BBS11011.minprob0.1.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak.11.bash.log: mel-yak.11.bash
+ @p='mel-yak.11.bash'; \
+ b='mel-yak.11.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+all_empty.bash.log: all_empty.bash
+ @p='all_empty.bash'; \
+ b='all_empty.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+one_empty.bash.log: one_empty.bash
+ @p='one_empty.bash'; \
+ b='one_empty.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+length1.bash.log: length1.bash
+ @p='length1.bash'; \
+ b='length1.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.default.bash.log: RV12.BBS12030.default.bash
+ @p='RV12.BBS12030.default.bash'; \
+ b='RV12.BBS12030.default.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tRNA.aln1.default.bash.log: tRNA.aln1.default.bash
+ @p='tRNA.aln1.default.bash'; \
+ b='tRNA.aln1.default.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak.233.aln1.default.bash.log: mel-yak.233.aln1.default.bash
+ @p='mel-yak.233.aln1.default.bash'; \
+ b='mel-yak.233.aln1.default.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.noindel2.bash.log: RV12.BBS12030.noindel2.bash
+ @p='RV12.BBS12030.noindel2.bash'; \
+ b='RV12.BBS12030.noindel2.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tRNA.aln1.nucprot.bash.log: tRNA.aln1.nucprot.bash
+ @p='tRNA.aln1.nucprot.bash'; \
+ b='tRNA.aln1.nucprot.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tRNA.aln1.loadprobs.bash.log: tRNA.aln1.loadprobs.bash
+ @p='tRNA.aln1.loadprobs.bash'; \
+ b='tRNA.aln1.loadprobs.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.nolearn.bash.log: RV12.BBS12030.nolearn.bash
+ @p='RV12.BBS12030.nolearn.bash'; \
+ b='RV12.BBS12030.nolearn.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.maxsn.bash.log: RV12.BBS12030.maxsn.bash
+ @p='RV12.BBS12030.maxsn.bash'; \
+ b='RV12.BBS12030.maxsn.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.refinement0.bash.log: RV12.BBS12030.refinement0.bash
+ @p='RV12.BBS12030.refinement0.bash'; \
+ b='RV12.BBS12030.refinement0.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.refinement1.bash.log: RV12.BBS12030.refinement1.bash
+ @p='RV12.BBS12030.refinement1.bash'; \
+ b='RV12.BBS12030.refinement1.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.nodynamicweights.bash.log: RV12.BBS12030.nodynamicweights.bash
+ @p='RV12.BBS12030.nodynamicweights.bash'; \
+ b='RV12.BBS12030.nodynamicweights.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+tRNA.aln1.treeweights.bash.log: tRNA.aln1.treeweights.bash
+ @p='tRNA.aln1.treeweights.bash'; \
+ b='tRNA.aln1.treeweights.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirna.refalign.bash.log: mirna.refalign.bash
+ @p='mirna.refalign.bash'; \
+ b='mirna.refalign.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirna.fast.bash.log: mirna.fast.bash
+ @p='mirna.fast.bash'; \
+ b='mirna.fast.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirna.fast.maxsn.bash.log: mirna.fast.maxsn.bash
+ @p='mirna.fast.maxsn.bash'; \
+ b='mirna.fast.maxsn.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirna.mst-min.bash.log: mirna.mst-min.bash
+ @p='mirna.mst-min.bash'; \
+ b='mirna.mst-min.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirna.mst-min.mst-max.bash.log: mirna.mst-min.mst-max.bash
+ @p='mirna.mst-min.mst-max.bash'; \
+ b='mirna.mst-min.mst-max.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mirna.mst-palm.degree.bash.log: mirna.mst-palm.degree.bash
+ @p='mirna.mst-palm.degree.bash'; \
+ b='mirna.mst-palm.degree.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+translated.anchored.bash.log: translated.anchored.bash
+ @p='translated.anchored.bash'; \
+ b='translated.anchored.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RV12.BBS12030.nolearn.anchored.bash.log: RV12.BBS12030.nolearn.anchored.bash
+ @p='RV12.BBS12030.nolearn.anchored.bash'; \
+ b='RV12.BBS12030.nolearn.anchored.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak.233.aln1.translated.bash.log: mel-yak.233.aln1.translated.bash
+ @p='mel-yak.233.aln1.translated.bash'; \
+ b='mel-yak.233.aln1.translated.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak.233.aln1.exonerate.bash.log: mel-yak.233.aln1.exonerate.bash
+ @p='mel-yak.233.aln1.exonerate.bash'; \
+ b='mel-yak.233.aln1.exonerate.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak.233.aln1.translated.exonerate.bash.log: mel-yak.233.aln1.translated.exonerate.bash
+ @p='mel-yak.233.aln1.translated.exonerate.bash'; \
+ b='mel-yak.233.aln1.translated.exonerate.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak.233.aln1.exonerate.mercator.bash.log: mel-yak.233.aln1.exonerate.mercator.bash
+ @p='mel-yak.233.aln1.exonerate.mercator.bash'; \
+ b='mel-yak.233.aln1.exonerate.mercator.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+mel-yak-sec.97.mercator.bash.log: mel-yak-sec.97.mercator.bash
+ @p='mel-yak-sec.97.mercator.bash'; \
+ b='mel-yak-sec.97.mercator.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+blanchette.seq00.exonerate.bash.log: blanchette.seq00.exonerate.bash
+ @p='blanchette.seq00.exonerate.bash'; \
+ b='blanchette.seq00.exonerate.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+blanchette.seq00.exonerate.minscore50.bash.log: blanchette.seq00.exonerate.minscore50.bash
+ @p='blanchette.seq00.exonerate.minscore50.bash'; \
+ b='blanchette.seq00.exonerate.minscore50.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+blanchette.seq00.exonerate.bandwidth1000.bash.log: blanchette.seq00.exonerate.bandwidth1000.bash
+ @p='blanchette.seq00.exonerate.bandwidth1000.bash'; \
+ b='blanchette.seq00.exonerate.bandwidth1000.bash'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+ at am__EXEEXT_TRUE@.test$(EXEEXT).log:
+ at am__EXEEXT_TRUE@ @p='$<'; \
+ at am__EXEEXT_TRUE@ $(am__set_b); \
+ at am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ at am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+ at am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ at am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am check check-TESTS check-am clean clean-generic \
+ cscopelist-am ctags-am distclean distclean-generic distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am recheck tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/version.m4 b/version.m4
new file mode 100644
index 0000000..7fa52ad
--- /dev/null
+++ b/version.m4
@@ -0,0 +1 @@
+m4_define([VERSION_NUMBER], [1.15.9])
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/fsa.git
More information about the debian-med-commit
mailing list